SQLite

Check-in [dbc65a6958]
Login

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

Overview
Comment:Merge latest trunk changes into this branch.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | reuse-schema
Files: files | file ages | folders
SHA3-256: dbc65a695877306e2add75aba2a279efbb30bfadb5339883cf74aa417f11de86
User & Date: dan 2021-05-22 15:05:02.152
Context
2021-05-27
15:24
The SQLITE_ENABLE_SHARED_SCHEMA compile-time option is on by default in the configure-generated makefile, permitting a complete test of this branch using "./configure && make test". (check-in: e867d22622 user: drh tags: reuse-schema)
2021-05-22
15:05
Merge latest trunk changes into this branch. (check-in: dbc65a6958 user: dan tags: reuse-schema)
2021-05-21
16:41
Fix a problem with SQLITE_MAX_MEMORY in malloc.c. (check-in: c18dbe2f38 user: dan tags: trunk)
2021-04-07
15:13
Update a broken assert() on this branch. (check-in: e69f29892e user: dan tags: reuse-schema)
Changes
Unified Diff Ignore Whitespace Patch
Changes to Makefile.in.
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
  $(TOP)/src/test_vfs.c \
  $(TOP)/src/test_windirent.c \
  $(TOP)/src/test_window.c \
  $(TOP)/src/test_wsd.c       \
  $(TOP)/ext/fts3/fts3_term.c \
  $(TOP)/ext/fts3/fts3_test.c  \
  $(TOP)/ext/session/test_session.c \
  $(TOP)/ext/rbu/test_rbu.c

# Statically linked extensions
#
TESTSRC += \
  $(TOP)/ext/expert/sqlite3expert.c \
  $(TOP)/ext/expert/test_expert.c \
  $(TOP)/ext/misc/amatch.c \







|







429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
  $(TOP)/src/test_vfs.c \
  $(TOP)/src/test_windirent.c \
  $(TOP)/src/test_window.c \
  $(TOP)/src/test_wsd.c       \
  $(TOP)/ext/fts3/fts3_term.c \
  $(TOP)/ext/fts3/fts3_test.c  \
  $(TOP)/ext/session/test_session.c \
  $(TOP)/ext/rbu/test_rbu.c 

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

527
528
529
530
531
532
533
  $(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


# Header files used by all library source files.
#
HDR = \
   $(TOP)/src/btree.h \
   $(TOP)/src/btreeInt.h \
   $(TOP)/src/hash.h \







|
>







519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
  $(TOP)/ext/fts3/fts3_aux.c \
  $(TOP)/ext/fts3/fts3_expr.c \
  $(TOP)/ext/fts3/fts3_term.c \
  $(TOP)/ext/fts3/fts3_tokenizer.c \
  $(TOP)/ext/fts3/fts3_write.c \
  $(TOP)/ext/async/sqlite3async.c \
  $(TOP)/ext/session/sqlite3session.c \
  $(TOP)/ext/misc/stmt.c \
  fts5.c

# Header files used by all library source files.
#
HDR = \
   $(TOP)/src/btree.h \
   $(TOP)/src/btreeInt.h \
   $(TOP)/src/hash.h \
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
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_BYTECODE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
SHELL_OPT += -DSQLITE_ENABLE_DESERIALIZE
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
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







<




<







614
615
616
617
618
619
620

621
622
623
624

625
626
627
628
629
630
631
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_BYTECODE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC

FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -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
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706

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_ENABLE_FTS5








<







691
692
693
694
695
696
697

698
699
700
701
702
703
704

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_DEBUG \
  -DSQLITE_ENABLE_DBSTAT_VTAB \
  -DSQLITE_ENABLE_BYTECODE_VTAB \
  -DSQLITE_ENABLE_RTREE \
  -DSQLITE_ENABLE_FTS4 \
  -DSQLITE_ENABLE_FTS5

1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
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_BYTECODE_VTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DESERIALIZE
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))








<







1230
1231
1232
1233
1234
1235
1236

1237
1238
1239
1240
1241
1242
1243
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_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))

1428
1429
1430
1431
1432
1433
1434



1435
1436
1437
1438
1439
1440
1441

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)




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

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







>
>
>







1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441

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)
1481
1482
1483
1484
1485
1486
1487

1488
1489
1490
1491
1492
1493
1494
	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.*


distclean:	clean
	rm -f config.h config.log config.status libtool Makefile sqlite3.pc

#
# Windows section
#







>







1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
	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

#
# Windows section
#
Changes to Makefile.msc.
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
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_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.
#







<







363
364
365
366
367
368
369

370
371
372
373
374
375
376
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_ENABLE_BYTECODE_VTAB=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.
#
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
  $(TOP)\src\test_vfs.c \
  $(TOP)\src\test_windirent.c \
  $(TOP)\src\test_window.c \
  $(TOP)\src\test_wsd.c \
  $(TOP)\ext\fts3\fts3_term.c \
  $(TOP)\ext\fts3\fts3_test.c \
  $(TOP)\ext\rbu\test_rbu.c \
  $(TOP)\ext\session\test_session.c

# Statically linked extensions.
#
TESTEXT = \
  $(TOP)\ext\expert\sqlite3expert.c \
  $(TOP)\ext\expert\test_expert.c \
  $(TOP)\ext\misc\amatch.c \







|







1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
  $(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 

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

1590
1591
1592
1593
1594
1595
1596
  $(TOP)\ext\misc\prefixes.c \
  $(TOP)\ext\misc\regexp.c \
  $(TOP)\ext\misc\remember.c \
  $(TOP)\ext\misc\series.c \
  $(TOP)\ext\misc\spellfix.c \
  $(TOP)\ext\misc\totype.c \
  $(TOP)\ext\misc\unionvtab.c \
  $(TOP)\ext\misc\wholenumber.c


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








|
>







1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
  $(TOP)\ext\misc\prefixes.c \
  $(TOP)\ext\misc\regexp.c \
  $(TOP)\ext\misc\remember.c \
  $(TOP)\ext\misc\series.c \
  $(TOP)\ext\misc\spellfix.c \
  $(TOP)\ext\misc\totype.c \
  $(TOP)\ext\misc\unionvtab.c \
  $(TOP)\ext\misc\wholenumber.c \
  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

1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
# 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_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_DESERIALIZE
FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4
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 = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c







<








<







1685
1686
1687
1688
1689
1690
1691

1692
1693
1694
1695
1696
1697
1698
1699

1700
1701
1702
1703
1704
1705
1706
# 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

!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_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000 -DSQLITE_PRINTF_PRECISION_LIMIT=1000

FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4
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 = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
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_BYTECODE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=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)







<







2386
2387
2388
2389
2390
2391
2392

2393
2394
2395
2396
2397
2398
2399
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_BYTECODE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1=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)
Changes to README.md.
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
first install Fossil version 2.0 or later.
(Source tarballs and precompiled binaries available
[here](https://www.fossil-scm.org/fossil/uv/download.html).  Fossil is
a stand-alone program.  To install, simply download or build the single 
executable file and put that file someplace on your $PATH.)
Then run commands like this:

        mkdir ~/sqlite
        cd ~/sqlite
        fossil clone https://www.sqlite.org/src sqlite.fossil
        fossil open sqlite.fossil
    
After setting up a repository using the steps above, you can always
update to the lastest version using:

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

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







|

|
|
|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
first install Fossil version 2.0 or later.
(Source tarballs and precompiled binaries available
[here](https://www.fossil-scm.org/fossil/uv/download.html).  Fossil is
a stand-alone program.  To install, simply download or build the single 
executable file and put that file someplace on your $PATH.)
Then run commands like this:

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

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

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

Or type "fossil ui" to get a web-based user interface.
Changes to VERSION.
1
3.35.3
|
1
3.36.0
Changes to autoconf/Makefile.msc.
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
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_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.
#







<







286
287
288
289
290
291
292

293
294
295
296
297
298
299
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_ENABLE_BYTECODE_VTAB=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.
#
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
# 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







<







955
956
957
958
959
960
961

962
963
964
965
966
967
968
# 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

!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
Changes to configure.
1
2
3
4
5
6
7
8
9
10
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.35.3.
#
#
# 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.


|







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.36.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
#
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
subdirs=
MFLAGS=
MAKEFLAGS=

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

# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
#ifdef HAVE_SYS_TYPES_H







|
|







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.36.0'
PACKAGE_STRING='sqlite 3.36.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''

# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
#ifdef HAVE_SYS_TYPES_H
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
  # Omit some internal or obsolete options to make the list less imposing.
  # This message is too long to be a string in the A/UX 3.1 sh.
  cat <<_ACEOF
\`configure' configures sqlite 3.35.3 to adapt to many kinds of systems.

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.







|







1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
  # Omit some internal or obsolete options to make the list less imposing.
  # This message is too long to be a string in the A/UX 3.1 sh.
  cat <<_ACEOF
\`configure' configures sqlite 3.36.0 to adapt to many kinds of systems.

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

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

Defaults for the options are specified in brackets.
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
  --build=BUILD     configure for building on BUILD [guessed]
  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
_ACEOF
fi

if test -n "$ac_init_help"; then
  case $ac_init_help in
     short | recursive ) echo "Configuration of sqlite 3.35.3:";;
   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]







|







1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
  --build=BUILD     configure for building on BUILD [guessed]
  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
_ACEOF
fi

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

Optional Features:
  --disable-option-checking  ignore unrecognized --enable/--with options
  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
    cd "$ac_pwd" || { ac_status=$?; break; }
  done
fi

test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
  cat <<\_ACEOF
sqlite configure 3.35.3
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







|







1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
    cd "$ac_pwd" || { ac_status=$?; break; }
  done
fi

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

Copyright (C) 2012 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
  exit
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

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

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

  $ $0 $@

_ACEOF
exec 5>>config.log
{







|







2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno

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

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

  $ $0 $@

_ACEOF
exec 5>>config.log
{
12374
12375
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388
test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1

cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Save the log message, to keep $0 and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.35.3, which was
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 $@







|







12374
12375
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388
test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1

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

  CONFIG_FILES    = $CONFIG_FILES
  CONFIG_HEADERS  = $CONFIG_HEADERS
  CONFIG_LINKS    = $CONFIG_LINKS
  CONFIG_COMMANDS = $CONFIG_COMMANDS
  $ $0 $@
12440
12441
12442
12443
12444
12445
12446
12447
12448
12449
12450
12451
12452
12453
12454

Report bugs to the package provider."

_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.35.3
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."








|







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

Report bugs to the package provider."

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

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

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

700
701
702
703
704
705
706
<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_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>







>







693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
<li><tt><a href='#parse_accept'>%parse_accept</a></tt>
<li><tt><a href='#parse_failure'>%parse_failure</a></tt>
<li><tt><a href='#pright'>%right</a></tt>
<li><tt><a href='#stack_overflow'>%stack_overflow</a></tt>
<li><tt><a href='#stack_size'>%stack_size</a></tt>
<li><tt><a href='#start_symbol'>%start_symbol</a></tt>
<li><tt><a href='#syntax_error'>%syntax_error</a></tt>
<li><tt><a href='#token'>%token</a></tt>
<li><tt><a href='#token_class'>%token_class</a></tt>
<li><tt><a href='#token_destructor'>%token_destructor</a></tt>
<li><tt><a href='#token_prefix'>%token_prefix</a></tt>
<li><tt><a href='#token_type'>%token_type</a></tt>
<li><tt><a href='#ptype'>%type</a></tt>
<li><tt><a href='#pwildcard'>%wildcard</a></tt>
</ul>
1074
1075
1076
1077
1078
1079
1080
1081























1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
   %start_symbol  prog
</pre>

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

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
























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

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

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

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

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

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

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








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|





|















|







1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
   %start_symbol  prog
</pre>

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

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

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

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

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

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

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


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

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

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

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

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

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

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

<p>So if the default output of Lemon looked like this:</p>
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
    #define TOKEN_AND        1
    #define TOKEN_MINUS      2
    #define TOKEN_OR         3
    #define TOKEN_PLUS       4
</pre>

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

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







|







1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
    #define TOKEN_AND        1
    #define TOKEN_MINUS      2
    #define TOKEN_OR         3
    #define TOKEN_PLUS       4
</pre>

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

<p>These directives are used to specify the data types for values
on the parser's stack associated with terminal and non-terminal
symbols.  The values of all terminal symbols must be of the same
type.  This turns out to be the same data type as the 3rd parameter
to the Parse() function generated by Lemon.  Typically, you will
make the value of a terminal symbol be a pointer to some kind of
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
the grammar designer should keep in mind that the size of the union
will be the size of its largest element.  So if you have a single
non-terminal whose data type requires 1K of storage, then your 100
entry parser stack will require 100K of heap space.  If you are willing
and able to pay that price, fine.  You just need to know.</p>

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

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







|







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

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

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

<p>When the generated parser has the choice of matching an input against
the wildcard token and some other token, the other token is always used.
Changes to ext/expert/expert1.test.
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
  eval $setup


do_setup_rec_test $tn.1 { CREATE TABLE t1(a, b, c) } {
  SELECT * FROM t1
} {
  (no new indexes)
  SCAN TABLE 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>?)
}

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<?)
}

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
}

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=?)
}

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

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
}

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

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=?)
}
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
}


# 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=?) 
}

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<?)
}

# 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=?)
}

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
}

# 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=?)
}

# 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=?) 
    INDEX 2
      SEARCH TABLE 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=?)
}
do_setup_rec_test $tn.13.2 {
  CREATE TABLE t8(a, b);
} {
  SELECT * FROM t8 ORDER BY rowid
} {
  (no new indexes)
  SCAN TABLE 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=?)
}

# 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=?)
}

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=?)
}

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
}

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

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

}

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








|








|








|








|








|









|









|








|








|







|











|








|










|








|












|
|













|

|










|







|







|














|















|
|








|








|







|







|







|







|











|










|







99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
  eval $setup


do_setup_rec_test $tn.1 { CREATE TABLE t1(a, b, c) } {
  SELECT * FROM t1
} {
  (no new indexes)
  SCAN 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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=?)
}

}

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

451
452
453
454
455
456
457
458
  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








<
451
452
453
454
455
456
457

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

finish_test

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

329

330
331
332
333
334
335
336

/*
** 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.
*/

int sqlite3_fts3_may_be_corrupt = 1;


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







>

>







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

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

/* 
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
** The number of bytes written is returned.
*/
int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
){
  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 */
  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);
  if( zCsr>zEnd ){
    return FTS_CORRUPT_VTAB;
  }
  
  while( zCsr<zEnd && (piFirst || piLast) ){
    int cmp;                      /* memcmp() result */
    int nSuffix;                  /* Size of term suffix */







|















|
|







1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
){
  int rc = SQLITE_OK;             /* Return code */
  const char *zCsr = zNode;       /* Cursor to iterate through node */
  const char *zEnd = &zCsr[nNode];/* End of interior node buffer */
  char *zBuffer = 0;              /* Buffer to load terms into */
  i64 nAlloc = 0;                 /* Size of allocated buffer */
  int isFirstTerm = 1;            /* True when processing first term on page */
  u64 iChild;                     /* Block id of child node to descend to */
  int nBuffer = 0;                /* Total term size */

  /* Skip over the 'height' varint that occurs at the start of every 
  ** interior node. Then load the blockid of the left-child of the b-tree
  ** node into variable iChild.  
  **
  ** Even if the data structure on disk is corrupted, this (reading two
  ** varints from the buffer) does not risk an overread. If zNode is a
  ** root node, then the buffer comes from a SELECT statement. SQLite does
  ** not make this guarantee explicitly, but in practice there are always
  ** either more than 20 bytes of allocated space following the nNode bytes of
  ** contents, or two zero bytes. Or, if the node is read from the %_segments
  ** table, then there are always 20 bytes of zeroed padding following the
  ** nNode bytes of content (see sqlite3Fts3ReadBlock() for details).
  */
  zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
  zCsr += sqlite3Fts3GetVarintU(zCsr, &iChild);
  if( zCsr>zEnd ){
    return FTS_CORRUPT_VTAB;
  }
  
  while( zCsr<zEnd && (piFirst || piLast) ){
    int cmp;                      /* memcmp() result */
    int nSuffix;                  /* Size of term suffix */
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
    ** 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 = 0;
    }

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

    iChild++;
  };

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

 finish_scan:
  sqlite3_free(zBuffer);
  return rc;
}









|




|






|
|







1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
    ** iChild.
    **
    ** If the interior node term is larger than the specified term, then
    ** the tree headed by iChild may contain the specified term.
    */
    cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
    if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
      *piFirst = (i64)iChild;
      piFirst = 0;
    }

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

    iChild++;
  };

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

 finish_scan:
  sqlite3_free(zBuffer);
  return rc;
}


3582
3583
3584
3585
3586
3587
3588

3589
3590
3591
3592




3593
3594
3595


3596
3597
3598
3599
3600
3601
3602
3603
}

/*
** Implementation of xBegin() method. 
*/
static int fts3BeginMethod(sqlite3_vtab *pVtab){
  Fts3Table *p = (Fts3Table*)pVtab;

  UNUSED_PARAMETER(pVtab);
  assert( p->pSegments==0 );
  assert( p->nPendingData==0 );
  assert( p->inTransaction!=1 );




  TESTONLY( p->inTransaction = 1 );
  TESTONLY( p->mxSavepoint = -1; );
  p->nLeafAdd = 0;


  return fts3SetHasStat(p);
}

/*
** 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().
*/







>




>
>
>
>
|
|
<
>
>
|







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

3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
}

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

  }
#endif
  return rc;
}

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

5135
5136
5137
5138
5139
5140
5141
  /* Allocate a MultiSegReader for each token in the expression. */
  fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);

  /* Determine which, if any, tokens in the expression should be deferred. */
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
  if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
    Fts3TokenAndCost *aTC;
    Fts3Expr **apOr;
    aTC = (Fts3TokenAndCost *)sqlite3_malloc64(
        sizeof(Fts3TokenAndCost) * nToken
      + sizeof(Fts3Expr *) * nOr * 2
    );
    apOr = (Fts3Expr **)&aTC[nToken];

    if( !aTC ){
      rc = SQLITE_NOMEM;
    }else{

      int ii;
      Fts3TokenAndCost *pTC = aTC;
      Fts3Expr **ppOr = apOr;

      fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc);
      nToken = (int)(pTC-aTC);
      nOr = (int)(ppOr-apOr);







<




<




>







5126
5127
5128
5129
5130
5131
5132

5133
5134
5135
5136

5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
  /* Allocate a MultiSegReader for each token in the expression. */
  fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);

  /* Determine which, if any, tokens in the expression should be deferred. */
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
  if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
    Fts3TokenAndCost *aTC;

    aTC = (Fts3TokenAndCost *)sqlite3_malloc64(
        sizeof(Fts3TokenAndCost) * nToken
      + sizeof(Fts3Expr *) * nOr * 2
    );


    if( !aTC ){
      rc = SQLITE_NOMEM;
    }else{
      Fts3Expr **apOr = (Fts3Expr **)&aTC[nToken];
      int ii;
      Fts3TokenAndCost *pTC = aTC;
      Fts3Expr **ppOr = apOr;

      fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc);
      nToken = (int)(pTC-aTC);
      nOr = (int)(ppOr-apOr);
Changes to ext/fts3/fts3Int.h.
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#define POS_END     (0)     /* Position-list terminator */ 

/*
** The assert_fts3_nc() macro is similar to the assert() macro, except that it
** is used for assert() conditions that are true only if it can be 
** guranteed that the database is not corrupt.
*/
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
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

/*







|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#define POS_END     (0)     /* Position-list terminator */ 

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

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

409
410
411
412
413
414
415
  }

  /* In case this cursor is being reused, close and zero it. */
  testcase(pCsr->filter.zTerm);
  sqlite3Fts3SegReaderFinish(&pCsr->csr);
  sqlite3_free((void *)pCsr->filter.zTerm);
  sqlite3_free(pCsr->aStat);

  memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);

  pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
  if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;

  if( iEq>=0 || iGe>=0 ){
    const unsigned char *zStr = sqlite3_value_text(apVal[0]);







>







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

  /* In case this cursor is being reused, close and zero it. */
  testcase(pCsr->filter.zTerm);
  sqlite3Fts3SegReaderFinish(&pCsr->csr);
  sqlite3_free((void *)pCsr->filter.zTerm);
  sqlite3_free(pCsr->aStat);
  sqlite3_free(pCsr->zStop);
  memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);

  pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
  if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;

  if( iEq>=0 || iGe>=0 ){
    const unsigned char *zStr = sqlite3_value_text(apVal[0]);
Changes to ext/fts3/fts3_snippet.c.
13
14
15
16
17
18
19




20
21
22
23
24
25
26

#include "fts3Int.h"
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

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





/*
** Characters that may appear in the second argument to matchinfo().
*/
#define FTS3_MATCHINFO_NPHRASE   'p'        /* 1 value */
#define FTS3_MATCHINFO_NCOL      'c'        /* 1 value */
#define FTS3_MATCHINFO_NDOC      'n'        /* 1 value */
#define FTS3_MATCHINFO_AVGLENGTH 'a'        /* nCol values */







>
>
>
>







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

#include "fts3Int.h"
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)

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

#ifndef SQLITE_AMALGAMATION
typedef sqlite3_int64 i64;
#endif

/*
** Characters that may appear in the second argument to matchinfo().
*/
#define FTS3_MATCHINFO_NPHRASE   'p'        /* 1 value */
#define FTS3_MATCHINFO_NCOL      'c'        /* 1 value */
#define FTS3_MATCHINFO_NDOC      'n'        /* 1 value */
#define FTS3_MATCHINFO_AVGLENGTH 'a'        /* nCol values */
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  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 */
  char *pHead;                    /* Position list data following iHead */
  int 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 */







|

|







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  SnippetPhrase *aPhrase;         /* Array of size nPhrase */
  int iCurrent;                   /* First token of current snippet */
};

struct SnippetPhrase {
  int nToken;                     /* Number of tokens in phrase */
  char *pList;                    /* Pointer to start of phrase position list */
  i64 iHead;                      /* Next value in position list */
  char *pHead;                    /* Position list data following iHead */
  i64 iTail;                      /* Next value in trailing position list */
  char *pTail;                    /* Position list data following iTail */
};

struct SnippetFragment {
  int iCol;                       /* Column snippet is extracted from */
  int iPos;                       /* Index of first token in snippet */
  u64 covered;                    /* Mask of query phrases covered */
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
** 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){
  int iVal;
  *pp += fts3GetVarint32(*pp, &iVal);
  *piPos += (iVal-2);
}

/*
** Helper function for fts3ExprIterate() (see below).







|







234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
** are encoded.
**
** When this function is called, *pp points to the start of an element of
** the list. *piPos contains the value of the previous entry in the list.
** After it returns, *piPos contains the value of the next element of the
** list and *pp is advanced to the following varint.
*/
static void fts3GetDeltaPosition(char **pp, i64 *piPos){
  int iVal;
  *pp += fts3GetVarint32(*pp, &iVal);
  *piPos += (iVal-2);
}

/*
** Helper function for fts3ExprIterate() (see below).
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
}

/*
** 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){
  char *pIter = *ppIter;
  if( pIter ){
    int iIter = *piIter;

    while( iIter<iNext ){
      if( 0==(*pIter & 0xFE) ){
        iIter = -1;
        pIter = 0;
        break;
      }







|


|







343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
}

/*
** Advance the position list iterator specified by the first two 
** arguments so that it points to the first element with a value greater
** than or equal to parameter iNext.
*/
static void fts3SnippetAdvance(char **ppIter, i64 *piIter, int iNext){
  char *pIter = *ppIter;
  if( pIter ){
    i64 iIter = *piIter;

    while( iIter<iNext ){
      if( 0==(*pIter & 0xFE) ){
        iIter = -1;
        pIter = 0;
        break;
      }
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
  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;

      while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
        int j;
        u64 mPhrase = (u64)1 << (i%64);
        u64 mPos = (u64)1 << (iCsr - iStart);
        assert( iCsr>=iStart && (iCsr - iStart)<=64 );
        assert( i>=0 );







|







429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
  u64 mCover = 0;                 /* Mask of phrases covered by this snippet */
  u64 mHighlight = 0;             /* Mask of tokens to highlight in snippet */

  for(i=0; i<pIter->nPhrase; i++){
    SnippetPhrase *pPhrase = &pIter->aPhrase[i];
    if( pPhrase->pTail ){
      char *pCsr = pPhrase->pTail;
      i64 iCsr = pPhrase->iTail;

      while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
        int j;
        u64 mPhrase = (u64)1 << (i%64);
        u64 mPos = (u64)1 << (iCsr - iStart);
        assert( iCsr>=iStart && (iCsr - iStart)<=64 );
        assert( i>=0 );
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
  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;
    pPhrase->pList = pCsr;
    fts3GetDeltaPosition(&pCsr, &iFirst);
    if( iFirst<0 ){
      rc = FTS_CORRUPT_VTAB;
    }else{
      pPhrase->pHead = pCsr;
      pPhrase->pTail = pCsr;







|







475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
  char *pCsr;
  int rc;

  pPhrase->nToken = pExpr->pPhrase->nToken;
  rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr);
  assert( rc==SQLITE_OK || pCsr==0 );
  if( pCsr ){
    i64 iFirst = 0;
    pPhrase->pList = pCsr;
    fts3GetDeltaPosition(&pCsr, &iFirst);
    if( iFirst<0 ){
      rc = FTS_CORRUPT_VTAB;
    }else{
      pPhrase->pHead = pCsr;
      pPhrase->pTail = pCsr;
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569


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

struct TermOffsetCtx {
  Fts3Cursor *pCsr;
  int iCol;                       /* Column of table to populate aTerm for */
  int iTerm;
  sqlite3_int64 iDocid;
  TermOffset *aTerm;
};

/*
** This function is an fts3ExprIterate() callback used by sqlite3Fts3Offsets().
*/
static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
  TermOffsetCtx *p = (TermOffsetCtx *)ctx;
  int nTerm;                      /* Number of tokens in phrase */
  int iTerm;                      /* For looping through nTerm phrase terms */
  char *pList;                    /* Pointer to position list for phrase */
  int iPos = 0;                   /* First position in position-list */
  int rc;

  UNUSED_PARAMETER(iPhrase);
  rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pList);
  nTerm = pExpr->pPhrase->nToken;
  if( pList ){
    fts3GetDeltaPosition(&pList, &iPos);







|
|


















|







1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573


typedef struct TermOffset TermOffset;
typedef struct TermOffsetCtx TermOffsetCtx;

struct TermOffset {
  char *pList;                    /* Position-list */
  i64 iPos;                       /* Position just read from pList */
  i64 iOff;                       /* Offset of this term from read positions */
};

struct TermOffsetCtx {
  Fts3Cursor *pCsr;
  int iCol;                       /* Column of table to populate aTerm for */
  int iTerm;
  sqlite3_int64 iDocid;
  TermOffset *aTerm;
};

/*
** This function is an fts3ExprIterate() callback used by sqlite3Fts3Offsets().
*/
static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
  TermOffsetCtx *p = (TermOffsetCtx *)ctx;
  int nTerm;                      /* Number of tokens in phrase */
  int iTerm;                      /* For looping through nTerm phrase terms */
  char *pList;                    /* Pointer to position list for phrase */
  i64 iPos = 0;                   /* First position in position-list */
  int rc;

  UNUSED_PARAMETER(iPhrase);
  rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pList);
  nTerm = pExpr->pPhrase->nToken;
  if( pList ){
    fts3GetDeltaPosition(&pList, &iPos);
Changes to ext/fts3/fts3_test.c.
581
582
583
584
585
586
587

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

601
602
603
604
605
606
607
*/
static int SQLITE_TCLAPI fts3_may_be_corrupt(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){

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

  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







>













>







581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
*/
static int SQLITE_TCLAPI fts3_may_be_corrupt(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
#ifdef SQLITE_DEBUG
  int bOld = sqlite3_fts3_may_be_corrupt;

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

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

int Sqlitetestfts3_Init(Tcl_Interp *interp){
  Tcl_CreateObjCommand(interp, "fts3_near_match", fts3_near_match_cmd, 0, 0);
  Tcl_CreateObjCommand(interp, 
      "fts3_configure_incr_load", fts3_configure_incr_load_cmd, 0, 0
Changes to ext/fts3/fts3_write.c.
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
    }
  }else{
    rc = (pLhs->aNode==0) - (pRhs->aNode==0);
  }
  if( rc==0 ){
    rc = pRhs->iIdx - pLhs->iIdx;
  }
  assert( 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:







|







1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
    }
  }else{
    rc = (pLhs->aNode==0) - (pRhs->aNode==0);
  }
  if( rc==0 ){
    rc = pRhs->iIdx - pLhs->iIdx;
  }
  assert_fts3_nc( rc!=0 );
  return rc;
}

/*
** A different comparison function for SegReader structures. In this
** version, it is assumed that each SegReader points to an entry in
** a doclist for identical terms. Comparison is made as follows:
Changes to ext/fts5/fts5_config.c.
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
  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->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







|







533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
  if( pRet==0 ) return SQLITE_NOMEM;
  memset(pRet, 0, sizeof(Fts5Config));
  pRet->db = db;
  pRet->iCookie = -1;

  nByte = nArg * (sizeof(char*) + sizeof(u8));
  pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte);
  pRet->abUnindexed = pRet->azCol ? (u8*)&pRet->azCol[nArg] : 0;
  pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1);
  pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1);
  pRet->bColumnsize = 1;
  pRet->eDetail = FTS5_DETAIL_FULL;
#ifdef SQLITE_DEBUG
  pRet->bPrefixIndex = 1;
#endif
Changes to ext/fts5/fts5_expr.c.
2408
2409
2410
2411
2412
2413
2414

2415
2416
2417
2418
2419
2420
2421
      pRet = sqlite3Fts5ParseNode(pParse, FTS5_AND, pLeft, pRight, 0);
    }
  }

  return pRet;
}


static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
  sqlite3_int64 nByte = 0;
  Fts5ExprTerm *p;
  char *zQuoted;

  /* Determine the maximum amount of space required. */
  for(p=pTerm; p; p=p->pSynonym){







>







2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
      pRet = sqlite3Fts5ParseNode(pParse, FTS5_AND, pLeft, pRight, 0);
    }
  }

  return pRet;
}

#ifdef SQLITE_TEST
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
  sqlite3_int64 nByte = 0;
  Fts5ExprTerm *p;
  char *zQuoted;

  /* Determine the maximum amount of space required. */
  for(p=pTerm; p; p=p->pSynonym){
2774
2775
2776
2777
2778
2779
2780

2781
2782
2783
2784
2785
2786

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




2804
2805
2806
2807
2808
2809
2810
    int iCode;
    int bRemoveDiacritics = 0;
    iCode = sqlite3_value_int(apVal[0]);
    if( nArg==2 ) bRemoveDiacritics = sqlite3_value_int(apVal[1]);
    sqlite3_result_int(pCtx, sqlite3Fts5UnicodeFold(iCode, bRemoveDiacritics));
  }
}


/*
** This is called during initialization to register the fts5_expr() scalar
** UDF with the SQLite handle passed as the only argument.
*/
int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){

  struct Fts5ExprFunc {
    const char *z;
    void (*x)(sqlite3_context*,int,sqlite3_value**);
  } aFunc[] = {
    { "fts5_expr",     fts5ExprFunctionHr },
    { "fts5_expr_tcl", fts5ExprFunctionTcl },
    { "fts5_isalnum",  fts5ExprIsAlnum },
    { "fts5_fold",     fts5ExprFold },
  };
  int i;
  int rc = SQLITE_OK;
  void *pCtx = (void*)pGlobal;

  for(i=0; rc==SQLITE_OK && i<ArraySize(aFunc); i++){
    struct Fts5ExprFunc *p = &aFunc[i];
    rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
  }





  /* Avoid warnings indicating that sqlite3Fts5ParserTrace() and
  ** sqlite3Fts5ParserFallback() are unused */
#ifndef NDEBUG
  (void)sqlite3Fts5ParserTrace;
#endif
  (void)sqlite3Fts5ParserFallback;







>






>

















>
>
>
>







2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
    int iCode;
    int bRemoveDiacritics = 0;
    iCode = sqlite3_value_int(apVal[0]);
    if( nArg==2 ) bRemoveDiacritics = sqlite3_value_int(apVal[1]);
    sqlite3_result_int(pCtx, sqlite3Fts5UnicodeFold(iCode, bRemoveDiacritics));
  }
}
#endif /* ifdef SQLITE_TEST */

/*
** This is called during initialization to register the fts5_expr() scalar
** UDF with the SQLite handle passed as the only argument.
*/
int sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlite3 *db){
#ifdef SQLITE_TEST
  struct Fts5ExprFunc {
    const char *z;
    void (*x)(sqlite3_context*,int,sqlite3_value**);
  } aFunc[] = {
    { "fts5_expr",     fts5ExprFunctionHr },
    { "fts5_expr_tcl", fts5ExprFunctionTcl },
    { "fts5_isalnum",  fts5ExprIsAlnum },
    { "fts5_fold",     fts5ExprFold },
  };
  int i;
  int rc = SQLITE_OK;
  void *pCtx = (void*)pGlobal;

  for(i=0; rc==SQLITE_OK && i<ArraySize(aFunc); i++){
    struct Fts5ExprFunc *p = &aFunc[i];
    rc = sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
  }
#else
  int rc = SQLITE_OK;
  UNUSED_PARAM2(pGlobal,db);
#endif

  /* Avoid warnings indicating that sqlite3Fts5ParserTrace() and
  ** sqlite3Fts5ParserFallback() are unused */
#ifndef NDEBUG
  (void)sqlite3Fts5ParserTrace;
#endif
  (void)sqlite3Fts5ParserFallback;
Changes to ext/fts5/fts5_index.c.
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
*/
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 */

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







|







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) */
  i64 iLeafOffset;                /* Byte offset within current leaf */

  /* Next method */
  void (*xNext)(Fts5Index*, Fts5SegIter*, int*);

  /* The page and offset from which the current term was read. The offset 
  ** is the offset of the first rowid in the current doclist.  */
  int iTermLeafPgno;
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
    }
    pIter->iLeafOffset = iOff;
  }
}

static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
  u8 *a = pIter->pLeaf->p;        /* Buffer to read data from */
  int 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;







|







1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
    }
    pIter->iLeafOffset = iOff;
  }
}

static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
  u8 *a = pIter->pLeaf->p;        /* Buffer to read data from */
  i64 iOff = pIter->iLeafOffset;

  ASSERT_SZLEAF_OK(pIter->pLeaf);
  if( iOff>=pIter->pLeaf->szLeaf ){
    fts5SegIterNextPage(p, pIter);
    if( pIter->pLeaf==0 ){
      if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
      return;
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
**
** 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 */
  int nNew;                       /* Bytes of new data */

  iOff += fts5GetVarint32(&a[iOff], nNew);
  if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){
    p->rc = FTS5_CORRUPT;
    return;
  }







|







1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
**
** accordingly and leaves (Fts5SegIter.iLeafOffset) set to the content of
** the first position list. The position list belonging to document 
** (Fts5SegIter.iRowid).
*/
static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
  u8 *a = pIter->pLeaf->p;        /* Buffer to read data from */
  i64 iOff = pIter->iLeafOffset;  /* Offset to read at */
  int nNew;                       /* Bytes of new data */

  iOff += fts5GetVarint32(&a[iOff], nNew);
  if( iOff+nNew>pIter->pLeaf->szLeaf || nKeep>pIter->term.n || nNew==0 ){
    p->rc = FTS5_CORRUPT;
    return;
  }
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
        if( pbNewTerm ) *pbNewTerm = 1;
      }
    }else{
      /* The following could be done by calling fts5SegIterLoadNPos(). But
      ** this block is particularly performance critical, so equivalent
      ** code is inlined.  */
      int nSz;
      assert( p->rc==SQLITE_OK );
      assert_nc( pIter->iLeafOffset<=pIter->pLeaf->nn );
      fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
      pIter->bDel = (nSz & 0x0001);
      pIter->nPos = nSz>>1;
      assert_nc( pIter->nPos>=0 );
    }
  }







<







2068
2069
2070
2071
2072
2073
2074

2075
2076
2077
2078
2079
2080
2081
        if( pbNewTerm ) *pbNewTerm = 1;
      }
    }else{
      /* The following could be done by calling fts5SegIterLoadNPos(). But
      ** this block is particularly performance critical, so equivalent
      ** code is inlined.  */
      int nSz;

      assert_nc( pIter->iLeafOffset<=pIter->pLeaf->nn );
      fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
      pIter->bDel = (nSz & 0x0001);
      pIter->nPos = nSz>>1;
      assert_nc( pIter->nPos>=0 );
    }
  }
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558

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







|






|







4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557

      assert( writer.bFirstRowidInPage==0 );
      if( pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){
        /* The entire doclist will fit on the current leaf. */
        fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist);
      }else{
        i64 iRowid = 0;
        u64 iDelta = 0;
        int iOff = 0;

        /* The entire doclist will not fit on this leaf. The following 
        ** loop iterates through the poslists that make up the current 
        ** doclist.  */
        while( p->rc==SQLITE_OK && iOff<nDoclist ){
          iOff += fts5GetVarint(&pDoclist[iOff], &iDelta);
          iRowid += iDelta;
          
          if( writer.bFirstRowidInPage ){
            fts5PutU16(&pBuf->p[0], (u16)pBuf->n);   /* first rowid on page */
            pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid);
            writer.bFirstRowidInPage = 0;
            fts5WriteDlidxAppend(p, &writer, iRowid);
5075
5076
5077
5078
5079
5080
5081

5082
5083
5084
5085
5086
5087
5088
5089

      if( pHead->iPos!=iPrev ){
        sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pHead->iPos);
      }
      nTail = pHead->iter.nPoslist - pHead->iOff;

      /* WRITEPOSLISTSIZE */

      assert( tmp.n+nTail<=nTmp );
      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 ){







>
|







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

      if( pHead->iPos!=iPrev ){
        sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pHead->iPos);
      }
      nTail = pHead->iter.nPoslist - pHead->iOff;

      /* WRITEPOSLISTSIZE */
      assert_nc( tmp.n+nTail<=nTmp );
      assert( tmp.n+nTail<=nTmp+nMerge*10 );
      if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){
        if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
        break;
      }
      fts5BufferSafeAppendVarint(&out, (tmp.n+nTail) * 2);
      fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
      if( nTail>0 ){
6222
6223
6224
6225
6226
6227
6228

6229
6230
6231
6232
6233
6234
6235

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


/*
** Decode a segment-data rowid from the %_data table. This function is
** the opposite of macro FTS5_SEGMENT_ROWID().
*/
static void fts5DecodeRowid(
  i64 iRowid,                     /* Rowid from %_data table */
  int *piSegid,                   /* OUT: Segment id */







>







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

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

#ifdef SQLITE_TEST
/*
** Decode a segment-data rowid from the %_data table. This function is
** the opposite of macro FTS5_SEGMENT_ROWID().
*/
static void fts5DecodeRowid(
  i64 iRowid,                     /* Rowid from %_data table */
  int *piSegid,                   /* OUT: Segment id */
6244
6245
6246
6247
6248
6249
6250

6251

6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268

6269

6270
6271
6272
6273
6274
6275
6276
  iRowid >>= FTS5_DATA_HEIGHT_B;

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

  *piSegid = (int)(iRowid & (((i64)1 << FTS5_DATA_ID_B) - 1));
}



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

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



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








>

>

















>

>







6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
  iRowid >>= FTS5_DATA_HEIGHT_B;

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

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

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

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

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

6284
6285
6286
6287
6288
6289
6290

6291

6292
6293
6294
6295
6296
6297
6298
      sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " {id=%d leaves=%d..%d}", 
          pSeg->iSegid, pSeg->pgnoFirst, pSeg->pgnoLast
      );
    }
    sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}");
  }
}



/*
** This is part of the fts5_decode() debugging aid.
**
** Arguments pBlob/nBlob contain a serialized Fts5Structure object. This
** function appends a human-readable representation of the same object
** to the buffer passed as the second argument. 
*/







>

>







6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
      sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " {id=%d leaves=%d..%d}", 
          pSeg->iSegid, pSeg->pgnoFirst, pSeg->pgnoLast
      );
    }
    sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}");
  }
}
#endif /* SQLITE_TEST */

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

6316

6317
6318
6319
6320
6321
6322
6323
    *pRc = rc;
    return;
  }

  fts5DebugStructure(pRc, pBuf, p);
  fts5StructureRelease(p);
}



/*
** This is part of the fts5_decode() debugging aid.
**
** Arguments pBlob/nBlob contain an "averages" record. This function 
** appends a human-readable representation of record to the buffer passed 
** as the second argument. 
*/







>

>







6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
    *pRc = rc;
    return;
  }

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

#ifdef SQLITE_TEST
/*
** This is part of the fts5_decode() debugging aid.
**
** Arguments pBlob/nBlob contain an "averages" record. This function 
** appends a human-readable representation of record to the buffer passed 
** as the second argument. 
*/
6332
6333
6334
6335
6336
6337
6338

6339

6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355

6356

6357
6358
6359
6360
6361
6362
6363
  while( i<nBlob ){
    u64 iVal;
    i += sqlite3Fts5GetVarint(&pBlob[i], &iVal);
    sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "%s%d", zSpace, (int)iVal);
    zSpace = " ";
  }
}



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



/*
** The start of buffer (a/n) contains the start of a doclist. The doclist
** may or may not finish within the buffer. This function appends a text
** representation of the part of the doclist that is present to buffer
** pBuf. 
**
** The return value is the number of bytes read from the input buffer.







>

>
















>

>







6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
  while( i<nBlob ){
    u64 iVal;
    i += sqlite3Fts5GetVarint(&pBlob[i], &iVal);
    sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "%s%d", zSpace, (int)iVal);
    zSpace = " ";
  }
}
#endif /* SQLITE_TEST */

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

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

6389

6390
6391
6392
6393
6394
6395
6396
      iDocid += iDelta;
      sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " id=%lld", iDocid);
    }
  }

  return iOff;
}



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







>

>







6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
      iDocid += iDelta;
      sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " id=%lld", iDocid);
    }
  }

  return iOff;
}
#endif /* SQLITE_TEST */

#ifdef SQLITE_TEST
/*
** This function is part of the fts5_decode() debugging function. It is 
** only ever used with detail=none tables.
**
** Buffer (pData/nData) contains a doclist in the format used by detail=none
** tables. This function appends a human-readable version of that list to
** buffer pBuf.
6423
6424
6425
6426
6427
6428
6429

6430

6431
6432
6433
6434
6435
6436
6437
        zApp = "*";
      }
    }

    sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp);
  }
}



/*
** The implementation of user-defined scalar function fts5_decode().
*/
static void fts5DecodeFunction(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args (always 2) */
  sqlite3_value **apVal           /* Function arguments */







>

>







6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
        zApp = "*";
      }
    }

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

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

6639

6640
6641
6642
6643
6644
6645
6646
  if( rc==SQLITE_OK ){
    sqlite3_result_text(pCtx, (const char*)s.p, s.n, SQLITE_TRANSIENT);
  }else{
    sqlite3_result_error_code(pCtx, rc);
  }
  fts5BufferFree(&s);
}



/*
** The implementation of user-defined scalar function fts5_rowid().
*/
static void fts5RowidFunction(
  sqlite3_context *pCtx,          /* Function call context */
  int nArg,                       /* Number of args (always 2) */
  sqlite3_value **apVal           /* Function arguments */







>

>







6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
  if( rc==SQLITE_OK ){
    sqlite3_result_text(pCtx, (const char*)s.p, s.n, SQLITE_TRANSIENT);
  }else{
    sqlite3_result_error_code(pCtx, rc);
  }
  fts5BufferFree(&s);
}
#endif /* SQLITE_TEST */

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

6673
6674
6675
6676
6677
6678
6679
6680
6681
6682

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




6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
    }else{
      sqlite3_result_error(pCtx, 
        "first arg to fts5_rowid() must be 'segment'" , -1
      );
    }
  }
}


/*
** This is called as part of registering the FTS5 module with database
** connection db. It registers several user-defined scalar functions useful
** with FTS5.
**
** If successful, SQLITE_OK is returned. If an error occurs, some other
** SQLite error code is returned instead.
*/
int sqlite3Fts5IndexInit(sqlite3 *db){

  int rc = sqlite3_create_function(
      db, "fts5_decode", 2, SQLITE_UTF8, 0, fts5DecodeFunction, 0, 0
  );

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

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




}


int sqlite3Fts5IndexReset(Fts5Index *p){
  assert( p->pStruct==0 || p->iStructVersion!=0 );
  if( fts5IndexDataVersion(p)!=p->iStructVersion ){
    fts5StructureInvalidate(p);
  }
  return fts5IndexReturn(p);
}







>










>

















>
>
>
>










6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
    }else{
      sqlite3_result_error(pCtx, 
        "first arg to fts5_rowid() must be 'segment'" , -1
      );
    }
  }
}
#endif /* SQLITE_TEST */

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

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

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


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

25

26
27
28
29
30
31
32

/*
** 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.
*/

int sqlite3_fts5_may_be_corrupt = 1;



typedef struct Fts5Auxdata Fts5Auxdata;
typedef struct Fts5Auxiliary Fts5Auxiliary;
typedef struct Fts5Cursor Fts5Cursor;
typedef struct Fts5FullTable Fts5FullTable;
typedef struct Fts5Sorter Fts5Sorter;







>

>







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

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


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

32

33
34
35
36
37
38
39

#ifdef SQLITE_ENABLE_FTS5

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


extern int sqlite3_fts5_may_be_corrupt;

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







>

>







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
*/
static int SQLITE_TCLAPI f5tMayBeCorrupt(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){

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

  return TCL_OK;
}


static unsigned int f5t_fts5HashKey(int nSlot, const char *p, int n){
  int i;
  unsigned int h = 13;







>













>







1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
*/
static int SQLITE_TCLAPI f5tMayBeCorrupt(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
#ifdef SQLITE_DEBUG
  int bOld = sqlite3_fts5_may_be_corrupt;

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

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


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










































































































































































































































































































































14594
14595
14596
14597
14598
| end x.db
}]} {}

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













































































































































































































































































































































sqlite3_fts5_may_be_corrupt 0
finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





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

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

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

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

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


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


sqlite3_fts5_may_be_corrupt 0
finish_test

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





















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

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























finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  INSERT INTO ccc(x899) SELECT rnddoc(500) FROM ii;
}

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

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

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

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

finish_test
Changes to ext/fts5/test/fts5plan.test.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  CREATE VIRTUAL TABLE f1 USING fts5(ff);
}

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

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
}

do_eqp_test 1.3 {
  SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
} {
  QUERY PLAN
  |--SCAN TABLE 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:
  `--USE TEMP B-TREE FOR ORDER BY
}

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

finish_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
  CREATE VIRTUAL TABLE f1 USING fts5(ff);
}

do_eqp_test 1.1 {
  SELECT * FROM t1, f1 WHERE f1 MATCH t1.x
} {
  QUERY PLAN
  |--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 f1 VIRTUAL TABLE INDEX 0:
  `--SCAN t1
}

do_eqp_test 1.3 {
  SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
} {
  QUERY PLAN
  |--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 f1 VIRTUAL TABLE INDEX 0:
  `--USE TEMP B-TREE FOR ORDER BY
}

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

finish_test
Changes to ext/fts5/test/fts5trigram.test.
188
189
190
191
192
193
194
195
196
197
198
199
200
201
  SELECT * FROM ci0 WHERE x LIKE ?
} {VIRTUAL TABLE INDEX 0:L0}
do_eqp_test 6.2 {
  SELECT * FROM ci0 WHERE x GLOB ?
} {VIRTUAL TABLE INDEX 0:G0}
do_eqp_test 6.3 {
  SELECT * FROM ci1 WHERE x LIKE ?
} {{SCAN TABLE ci1 VIRTUAL TABLE INDEX 0:}}
do_eqp_test 6.4 {
  SELECT * FROM ci1 WHERE x GLOB ?
} {VIRTUAL TABLE INDEX 0:G0}

finish_test








|





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

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

finish_test

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



536
537
538
539
540
541
542
  memset(pApndFile, 0, sizeof(ApndFile));
  pFile->pMethods = &apnd_io_methods;
  pApndFile->iMark = -1;    /* Append mark not yet written */

  rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
  if( rc==SQLITE_OK ){
    rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
  }
  if( rc ){
    pBaseFile->pMethods->xClose(pBaseFile);



    pFile->pMethods = 0;
    return rc;
  }
  if( apndIsOrdinaryDatabaseFile(sz, pBaseFile) ){
    /* The file being opened appears to be just an ordinary DB. Copy
    ** the base dispatch-table so this instance mimics the base VFS. 
    */







<
|
|
>
>
>







526
527
528
529
530
531
532

533
534
535
536
537
538
539
540
541
542
543
544
  memset(pApndFile, 0, sizeof(ApndFile));
  pFile->pMethods = &apnd_io_methods;
  pApndFile->iMark = -1;    /* Append mark not yet written */

  rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
  if( rc==SQLITE_OK ){
    rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);

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












582
583
584
585
586
587
588
           && 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;












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







>
>
>
>
>
>
>
>
>
>
>
>







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


691
692
693
694
695
696
697
  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);


    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;







>
>







696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
  memset(p, 0, sizeof(*p));
  pSubFile = ORIGFILE(pFile);
  pFile->pMethods = &cksm_io_methods;
  rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
  if( rc ) goto cksm_open_done;
  if( flags & SQLITE_OPEN_WAL ){
    sqlite3_file *pDb = sqlite3_database_file_object(zName);
    rc = pDb->pMethods->xFileControl(pDb, SQLITE_FCNTL_CKSM_FILE, (void*)&pDb);
    assert( rc==SQLITE_OK );
    p->pPartner = (CksmFile*)pDb;
    assert( p->pPartner->pPartner==0 );
    p->pPartner->pPartner = p;
    p->isWal = 1;
    p->computeCksm = p->pPartner->computeCksm;
  }else{
    p->isWal = 0;
Changes to ext/misc/decimal.c.
455
456
457
458
459
460
461
462
463
464
465

466
467
468
469
470
471
472
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Decimal *pA = decimal_new(context, argv[0], 0, 0);
  Decimal *pB = decimal_new(context, argv[1], 0, 0);
  UNUSED_PARAMETER(argc);
  if( pB==0 ) return;
  pB->sign = !pB->sign;
  decimal_add(pA, pB);
  decimal_result(context, pA);

  decimal_free(pA);
  decimal_free(pB);
}

/* Aggregate funcion:   decimal_sum(X)
**
** Works like sum() except that it uses decimal arithmetic for unlimited







|
|
|
|
>







455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  Decimal *pA = decimal_new(context, argv[0], 0, 0);
  Decimal *pB = decimal_new(context, argv[1], 0, 0);
  UNUSED_PARAMETER(argc);
  if( pB ){
    pB->sign = !pB->sign;
    decimal_add(pA, pB);
    decimal_result(context, pA);
  }
  decimal_free(pA);
  decimal_free(pB);
}

/* Aggregate funcion:   decimal_sum(X)
**
** Works like sum() except that it uses decimal arithmetic for unlimited
Changes to ext/misc/json1.c.
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/* 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++] = '\\';







|







295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/* Append the N-byte string in zIn to the end of the JsonString string
** under construction.  Enclose the string in "..." and escape
** any double-quotes or backslash characters contained within the
** string.
*/
static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
  u32 i;
  if( zIn==0 || ((N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0) ) return;
  p->zBuf[p->nUsed++] = '"';
  for(i=0; i<N; i++){
    unsigned char c = ((unsigned const char*)zIn)[i];
    if( c=='"' || c=='\\' ){
      json_simple_escape:
      if( (p->nUsed+N+3-i > p->nAlloc) && jsonGrow(p,N+3-i)!=0 ) return;
      p->zBuf[p->nUsed++] = '\\';
1894
1895
1896
1897
1898
1899
1900
1901
1902

1903
1904
1905
1906
1907
1908
1909
  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 ){







<

>







1894
1895
1896
1897
1898
1899
1900

1901
1902
1903
1904
1905
1906
1907
1908
1909
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr));
  if( pStr ){
    if( pStr->zBuf==0 ){
      jsonInit(pStr, ctx);
      jsonAppendChar(pStr, '[');
    }else if( pStr->nUsed>1 ){
      jsonAppendChar(pStr, ',');

    }
    pStr->pCtx = ctx;
    jsonAppendValue(pStr, argv[0]);
  }
}
static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
  JsonString *pStr;
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
  if( pStr ){
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975

1976
1977




1978
1979
1980
1981
1982
1983
1984
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
#ifdef NEVER
  /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
  ** always have been called to initalize it */
  if( NEVER(!pStr) ) return;
#endif
  z = pStr->zBuf;
  for(i=1; (c = z[i])!=',' || inStr || nNest; i++){
    if( i>=pStr->nUsed ){
      pStr->nUsed = 1;
      return;
    }
    if( c=='"' ){
      inStr = !inStr;
    }else if( c=='\\' ){
      i++;
    }else if( !inStr ){
      if( c=='{' || c=='[' ) nNest++;
      if( c=='}' || c==']' ) nNest--;
    }
  }

  pStr->nUsed -= i;      
  memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1);




}
#else
# define jsonGroupInverse 0
#endif


/*







|
<
<
<
<









>
|
|
>
>
>
>







1955
1956
1957
1958
1959
1960
1961
1962




1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
  pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
#ifdef NEVER
  /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
  ** always have been called to initalize it */
  if( NEVER(!pStr) ) return;
#endif
  z = pStr->zBuf;
  for(i=1; 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


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














39
40
41
42
43
44
45
46
47
48
49

#include <zlib.h>

#ifndef SQLITE_OMIT_VIRTUALTABLE

#ifndef SQLITE_AMALGAMATION















typedef sqlite3_int64 i64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned long u32;
#define MIN(a,b) ((a)<(b) ? (a) : (b))

#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
# define ALWAYS(X)      (1)
# define NEVER(X)       (0)
#elif !defined(NDEBUG)
# define ALWAYS(X)      ((X)?1:(assert(0),0))







>
>
>
>
>
>
>
>
>
>
>
>
>
>


|
|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

#include <zlib.h>

#ifndef SQLITE_OMIT_VIRTUALTABLE

#ifndef SQLITE_AMALGAMATION

#ifndef UINT32_TYPE
# ifdef HAVE_UINT32_T
#  define UINT32_TYPE uint32_t
# else
#  define UINT32_TYPE unsigned int
# endif
#endif
#ifndef UINT16_TYPE
# ifdef HAVE_UINT16_T
#  define UINT16_TYPE uint16_t
# else
#  define UINT16_TYPE unsigned short int
# endif
#endif
typedef sqlite3_int64 i64;
typedef unsigned char u8;
typedef UINT32_TYPE u32;           /* 4-byte unsigned integer */
typedef UINT16_TYPE u16;           /* 2-byte unsigned integer */
#define MIN(a,b) ((a)<(b) ? (a) : (b))

#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
# define ALWAYS(X)      (1)
# define NEVER(X)       (0)
#elif !defined(NDEBUG)
# define ALWAYS(X)      ((X)?1:(assert(0),0))
702
703
704
705
706
707
708


709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735

736
737
738
739
740
741
742
743
**     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 = (1980 + ((pCDS->mDate >> 9) & 0x7F));
  int M = ((pCDS->mDate >> 5) & 0x0F);
  int 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;
  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;
  }
  JD = (i64)(24*60*60) * (
      (int)(365.25 * (Y + 4716))
    + (int)(30.6001 * (M + 1))
    + D + B - 1524
  );

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

  /* Convert JD to unix timestamp (the JD epoch is 2440587.5) */

  return (u32)(JD - (i64)(24405875) * 24*60*6);
}

/*
** 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.
*/







>
>
|
|
|
<
<
|
|
|
<
<
<
<
<
|
|
|

<
|
|
<
<
|
<
<
|
<
>
|







716
717
718
719
720
721
722
723
724
725
726
727


728
729
730





731
732
733
734

735
736


737


738

739
740
741
742
743
744
745
746
747
**     Bits 00-04: day
**     Bits 05-08: month (1-12)
**     Bits 09-15: years from 1980 
**
** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
*/
static u32 zipfileMtime(ZipfileCDS *pCDS){
  int Y,M,D,X1,X2,A,B,sec,min,hr;
  i64 JDsec;
  Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
  M = ((pCDS->mDate >> 5) & 0x0F);
  D = (pCDS->mDate & 0x1F);


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





  if( M<=2 ){
    Y--;
    M += 12;
  }

  X1 = 36525*(Y+4716)/100;
  X2 = 306001*(M+1)/10000;


  A = Y/100;


  B = 2 - A + (A/4);

  JDsec = (i64)((X1 + X2 + D + B - 1524.5)*86400) + hr*3600 + min*60 + sec;
  return (u32)(JDsec - (i64)24405875*(i64)8640);
}

/*
** The opposite of zipfileMtime(). This function populates the mTime and
** mDate fields of the CDS structure passed as the first argument according
** to the UNIX timestamp value passed as the second.
*/
2166
2167
2168
2169
2170
2171
2172




2173
2174
2175
2176
2177
2178
2179
  int rc = sqlite3_create_module(db, "zipfile"  , &zipfileModule, 0);
  if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0, 
        zipfileStep, zipfileFinal
    );
  }




  return rc;
}
#else         /* SQLITE_OMIT_VIRTUALTABLE */
# define zipfileRegister(x) SQLITE_OK
#endif

#ifdef _WIN32







>
>
>
>







2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
  int rc = sqlite3_create_module(db, "zipfile"  , &zipfileModule, 0);
  if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1);
  if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0, 
        zipfileStep, zipfileFinal
    );
  }
  assert( sizeof(i64)==8 );
  assert( sizeof(u32)==4 );
  assert( sizeof(u16)==2 );
  assert( sizeof(u8)==1 );
  return rc;
}
#else         /* SQLITE_OMIT_VIRTUALTABLE */
# define zipfileRegister(x) SQLITE_OK
#endif

#ifdef _WIN32
Changes to ext/rbu/rbu1.test.
128
129
130
131
132
133
134





135
136
137
138
139
140
141
foreach {tn3 create_vfs destroy_vfs} {
  1 {} {}
  2 {
    sqlite3rbu_create_vfs -default myrbu ""
  } {
    sqlite3rbu_destroy_vfs myrbu
  }





} {

  eval $create_vfs

  foreach {tn2 cmd} {
      1 run_rbu 
      2 step_rbu 3 step_rbu_uri 4 step_rbu_state







>
>
>
>
>







128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
foreach {tn3 create_vfs destroy_vfs} {
  1 {} {}
  2 {
    sqlite3rbu_create_vfs -default myrbu ""
  } {
    sqlite3rbu_destroy_vfs myrbu
  }
  3 {
    sqlite3_register_cksumvfs
  } {
    sqlite3_unregister_cksumvfs
  }
} {

  eval $create_vfs

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


1623
1624
1625
1626
1627
1628
1629
1630
          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]=='N' ){
          bFailed = 1;
          break;
        }
        zVector = rbuMPrintf(p, "%z%s%s", zVector, zSep, zQuoted);
        zSep = ", ";
      }








>
>
|







1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
          zSelect, pIter->zTbl, zOrder
        )
    );
    if( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSel) ){
      zSep = "";
      for(iCol=0; iCol<pIter->nCol; iCol++){
        const char *zQuoted = (const char*)sqlite3_column_text(pSel, iCol);
        if( zQuoted==0 ){
          p->rc = SQLITE_NOMEM;
        }else if( zQuoted[0]=='N' ){
          bFailed = 1;
          break;
        }
        zVector = rbuMPrintf(p, "%z%s%s", zVector, zSep, zQuoted);
        zSep = ", ";
      }

4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
      ** or xOpen() to operate on the *-wal file.  */
      pFd->zWal = sqlite3_filename_wal(zName);
    }
    else if( flags & SQLITE_OPEN_WAL ){
      rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
      if( pDb ){
        if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
          /* This call is to open a *-wal file. Intead, open the *-oal. This
          ** 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;
          char *zCopy;
          if( rbuIsVacuum(pDb->pRbu) ){
            zBase = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
            zBase = sqlite3_filename_wal(zBase);
          }
          nCopy = strlen(zBase);
          zCopy = sqlite3_malloc64(nCopy+2);
          if( zCopy ){
            memcpy(zCopy, zBase, nCopy);
            zCopy[nCopy-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;







|
<
<
<
<
|
<

|
|

|
<
<
<
|
<
<
<
<
<
<







4990
4991
4992
4993
4994
4995
4996
4997




4998

4999
5000
5001
5002
5003



5004






5005
5006
5007
5008
5009
5010
5011
      ** or xOpen() to operate on the *-wal file.  */
      pFd->zWal = sqlite3_filename_wal(zName);
    }
    else if( flags & SQLITE_OPEN_WAL ){
      rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
      if( pDb ){
        if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
          /* This call is to open a *-wal file. Intead, open the *-oal. */




          size_t nOpen;

          if( rbuIsVacuum(pDb->pRbu) ){
            zOpen = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
            zOpen = sqlite3_filename_wal(zOpen);
          }
          nOpen = strlen(zOpen);



          ((char*)zOpen)[nOpen-3] = 'o';






          pFd->pRbu = pDb->pRbu;
        }
        pDb->pWalFd = pFd;
      }
    }
  }else{
    pFd->pRbu = pRbuVfs->pRbu;
Changes to ext/rtree/geopoly.c.
306
307
308
309
310
311
312




313
314
315
316
317
318
319
  GeoPoly *p = 0;
  int nByte;
  if( sqlite3_value_type(pVal)==SQLITE_BLOB
   && (nByte = sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord))
  ){
    const unsigned char *a = sqlite3_value_blob(pVal);
    int nVertex;




    nVertex = (a[1]<<16) + (a[2]<<8) + a[3];
    if( (a[0]==0 || a[0]==1)
     && (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte
    ){
      p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) );
      if( p==0 ){
        if( pRc ) *pRc = SQLITE_NOMEM;







>
>
>
>







306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
  GeoPoly *p = 0;
  int nByte;
  if( sqlite3_value_type(pVal)==SQLITE_BLOB
   && (nByte = sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord))
  ){
    const unsigned char *a = sqlite3_value_blob(pVal);
    int nVertex;
    if( a==0 ){
      sqlite3_result_error_nomem(pCtx);
      return 0;
    }
    nVertex = (a[1]<<16) + (a[2]<<8) + a[3];
    if( (a[0]==0 || a[0]==1)
     && (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte
    ){
      p = sqlite3_malloc64( sizeof(*p) + (nVertex-1)*2*sizeof(GeoCoord) );
      if( p==0 ){
        if( pRc ) *pRc = SQLITE_NOMEM;
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
    }else{
      sqlite3_free(p);
      aCoord[0].f = mnX;
      aCoord[1].f = mxX;
      aCoord[2].f = mnY;
      aCoord[3].f = mxY;
    }
  }else{
    memset(aCoord, 0, sizeof(RtreeCoord)*4);
  }
  return pOut;
}

/*
** Implementation of the geopoly_bbox(X) SQL function.







|







683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
    }else{
      sqlite3_free(p);
      aCoord[0].f = mnX;
      aCoord[1].f = mxX;
      aCoord[2].f = mnY;
      aCoord[3].f = mxY;
    }
  }else if( aCoord ){
    memset(aCoord, 0, sizeof(RtreeCoord)*4);
  }
  return pOut;
}

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

3893
3894
3895
3896

3897



3898
3899
3900
3901
3902
3903
3904
** 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]);

    sqlite3_result_int(ctx, readInt16(zBlob));



  }
}

/*
** Context object passed between the various routines that make up the
** implementation of integrity-check function rtreecheck().
*/







>




>
|
>
>
>







3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
** node always has nodeno=1, so the example above is the primary use for this
** routine.  This routine is intended for testing and analysis only.
*/
static void rtreedepth(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
  UNUSED_PARAMETER(nArg);
  if( sqlite3_value_type(apArg[0])!=SQLITE_BLOB 
   || sqlite3_value_bytes(apArg[0])<2

  ){
    sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1); 
  }else{
    u8 *zBlob = (u8 *)sqlite3_value_blob(apArg[0]);
    if( zBlob ){
      sqlite3_result_int(ctx, readInt16(zBlob));
    }else{
      sqlite3_result_error_nomem(ctx);
    }
  }
}

/*
** Context object passed between the various routines that make up the
** implementation of integrity-check function rtreecheck().
*/
Changes to ext/rtree/rtree6.test.
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  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=?)
}

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=?)
}

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=?)
}

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=?)
}
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=?)
}

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=?)
}

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 







|
|






|
|






|
|






|
|





|
|






|
|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  rtree_strategy {SELECT * FROM t1,t2 WHERE k=+ii AND x1<10}
} {C0}

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

do_execsql_test rtree6-3.1 {
  CREATE VIRTUAL TABLE t3 USING rtree(id, x1, x2, y1, y2);
  INSERT INTO t3 VALUES(NULL, 1, 1, 2, 2);
  SELECT * FROM t3 WHERE 
    x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND 
Changes to ext/rtree/rtreeC.test.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
}

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
}

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
}

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
}

do_eqp_test 1.5 {
  SELECT * FROM t, r_tree
} {
  QUERY PLAN
  |--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
  `--SCAN TABLE 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);







|
|







|
|







|
|






|
|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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 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 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 t
  `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}

do_eqp_test 1.5 {
  SELECT * FROM t, r_tree
} {
  QUERY PLAN
  |--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
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
}

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
}

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
}

do_eqp_test 2.5 {
  SELECT * FROM t, r_tree
} {
  QUERY PLAN
  |--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
  `--SCAN TABLE 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
}
do_eqp_test 3.2.2 { SELECT * FROM t2 CROSS JOIN t1 } {
  QUERY PLAN
  |--SCAN TABLE t2
  `--SCAN TABLE 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:
}
do_eqp_test 3.3.2 { SELECT * FROM t3 CROSS JOIN t1 } {
  QUERY PLAN
  |--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
  `--SCAN TABLE t1
}

#--------------------------------------------------------------------
# Test that LEFT JOINs are not reordered if the right-hand-side is
# a virtual table.
#
reset_db







|
|







|
|







|
|






|
|













|
|



|
|




|
|



|
|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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 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 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 t
  `--SCAN r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
}

do_eqp_test 2.5 {
  SELECT * FROM t, r_tree
} {
  QUERY PLAN
  |--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 t1
  `--SCAN t2
}
do_eqp_test 3.2.2 { SELECT * FROM t2 CROSS JOIN t1 } {
  QUERY PLAN
  |--SCAN t2
  `--SCAN t1
}

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

#--------------------------------------------------------------------
# Test that LEFT JOINs are not reordered if the right-hand-side is
# a virtual table.
#
reset_db
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# 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:
}

# 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=?)
}

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

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







|
|















|
|











|
|







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

#--------------------------------------------------------------------
# Test that having a second connection drop the sqlite_stat1 table
# before it is required by rtreeConnect() does not cause problems.
#
ifcapable rtree {







|
|







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

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
} {
  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
} {
  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
} {
  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
} {
  2 4
}

finish_test







|
|
|










|
|
|












|
|
|










|
|
|





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 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 xdir
  |--SCAN rt VIRTUAL TABLE INDEX 2:B0D1
  `--SCAN ydir
} {
  5 1 2 7 12 14 {}
  5 2 2 7  8 12 10
  5 4 5 5 10 10 10
}

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

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


































































































































































1048
1049
|   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}}




































































































































































finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
|   2880: ff ff ff 06 00 00 00 0c 00 00 00 01 00 00 00 0b   ................
|   2896: 00 00 00 00 00 00 00 02 40 00 00 00 00 00 00 00   ........@.......
| end crash-2e81f5dce5cbd4.db}]
  execsql { PRAGMA writable_schema = 1;}
  catchsql {UPDATE t1 SET ex= ex ISNULL}
} {1 {database disk image is malformed}}

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

ifcapable geopoly {

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

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

} ;# ifcapable geopoly

finish_test
Added ext/session/sessionsize.test.






































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# 2021 April 22
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#

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

set testprefix sessionsize

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

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

  do_test $tn "expr $sz" $szC
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

S delete

finish_test

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

45
46
47
48
49
50
51

52
53
54
55
56
57
58

/*
** Session handle structure.
*/
struct sqlite3_session {
  sqlite3 *db;                    /* Database handle session is attached to */
  char *zDb;                      /* Name of database session is attached to */

  int bEnable;                    /* True if currently recording */
  int bIndirect;                  /* True if all changes are indirect */
  int bAutoAttach;                /* True to auto-attach tables */
  int rc;                         /* Non-zero if an error has occurred */
  void *pFilterCtx;               /* First argument to pass to xTableFilter */
  int (*xTableFilter)(void *pCtx, const char *zTab);
  i64 nMalloc;                    /* Number of bytes of data allocated */

  sqlite3_value *pZeroBlob;       /* Value containing X'' */
  sqlite3_session *pNext;         /* Next session object on same db. */
  SessionTable *pTable;           /* List of attached tables */
  SessionHook hook;               /* APIs to grab new and old data with */
};

/*







>







>







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

/*
** Session handle structure.
*/
struct sqlite3_session {
  sqlite3 *db;                    /* Database handle session is attached to */
  char *zDb;                      /* Name of database session is attached to */
  int bEnableSize;                /* True if changeset_size() enabled */
  int bEnable;                    /* True if currently recording */
  int bIndirect;                  /* True if all changes are indirect */
  int bAutoAttach;                /* True to auto-attach tables */
  int rc;                         /* Non-zero if an error has occurred */
  void *pFilterCtx;               /* First argument to pass to xTableFilter */
  int (*xTableFilter)(void *pCtx, const char *zTab);
  i64 nMalloc;                    /* Number of bytes of data allocated */
  i64 nMaxChangesetSize;
  sqlite3_value *pZeroBlob;       /* Value containing X'' */
  sqlite3_session *pNext;         /* Next session object on same db. */
  SessionTable *pTable;           /* List of attached tables */
  SessionHook hook;               /* APIs to grab new and old data with */
};

/*
287
288
289
290
291
292
293
294
295

296
297
298
299
300
301
302
*/

/*
** 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" */

  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 







|
|
>







289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
*/

/*
** For each row modified during a session, there exists a single instance of
** this structure stored in a SessionTable.aChange[] hash table.
*/
struct SessionChange {
  u8 op;                          /* One of UPDATE, DELETE, INSERT */
  u8 bIndirect;                   /* True if this change is "indirect" */
  int nMaxSize;                   /* Max size of eventual changeset record */
  int nRecord;                    /* Number of bytes in buffer aRecord[] */
  u8 *aRecord;                    /* Buffer containing old.* record */
  SessionChange *pNext;           /* For hash-table collisions */
};

/*
** Write a varint with value iVal into the buffer at aBuf. Return the 
1117
1118
1119
1120
1121
1122
1123






1124
1125
1126
1127
1128
1129
1130
          pTab->abPK = abPK;
          break;
        }
      }
      if( 0==sqlite3_stricmp("sqlite_stat1", pTab->zName) ){
        pTab->bStat1 = 1;
      }






    }
  }
  return (pSession->rc || pTab->abPK==0);
}

/*
** Versions of the four methods in object SessionHook for use with the







>
>
>
>
>
>







1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
          pTab->abPK = abPK;
          break;
        }
      }
      if( 0==sqlite3_stricmp("sqlite_stat1", pTab->zName) ){
        pTab->bStat1 = 1;
      }

      if( pSession->bEnableSize ){
        pSession->nMaxChangesetSize += (
          1 + sessionVarintLen(pTab->nCol) + pTab->nCol + strlen(pTab->zName)+1
        );
      }
    }
  }
  return (pSession->rc || pTab->abPK==0);
}

/*
** Versions of the four methods in object SessionHook for use with the
1162
1163
1164
1165
1166
1167
1168

































































































1169
1170
1171
1172
1173
1174
1175
  return p->hook.xCount(p->hook.pCtx);
}
static int sessionStat1Depth(void *pCtx){
  SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx;
  return p->hook.xDepth(p->hook.pCtx);
}



































































































/*
** This function is only called from with a pre-update-hook reporting a 
** change on table pTab (attached to session pSession). The type of change
** (UPDATE, INSERT, DELETE) is specified by the first argument.
**
** Unless one is already present or an error occurs, an entry is added







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
  return p->hook.xCount(p->hook.pCtx);
}
static int sessionStat1Depth(void *pCtx){
  SessionStat1Ctx *p = (SessionStat1Ctx*)pCtx;
  return p->hook.xDepth(p->hook.pCtx);
}

static int sessionUpdateMaxSize(
  int op,
  sqlite3_session *pSession,      /* Session object pTab is attached to */
  SessionTable *pTab,             /* Table that change applies to */
  SessionChange *pC               /* Update pC->nMaxSize */
){
  i64 nNew = 2;
  if( pC->op==SQLITE_INSERT ){
    if( op!=SQLITE_DELETE ){
      int ii;
      for(ii=0; ii<pTab->nCol; ii++){
        sqlite3_value *p = 0;
        pSession->hook.xNew(pSession->hook.pCtx, ii, &p);
        sessionSerializeValue(0, p, &nNew);
      }
    }
  }else if( op==SQLITE_DELETE ){
    nNew += pC->nRecord;
    if( sqlite3_preupdate_blobwrite(pSession->db)>=0 ){
      nNew += pC->nRecord;
    }
  }else{
    int ii;
    u8 *pCsr = pC->aRecord;
    for(ii=0; ii<pTab->nCol; ii++){
      int bChanged = 1;
      int nOld = 0;
      int eType;
      sqlite3_value *p = 0;
      pSession->hook.xNew(pSession->hook.pCtx, ii, &p);
      if( p==0 ){
        return SQLITE_NOMEM;
      }

      eType = *pCsr++;
      switch( eType ){
        case SQLITE_NULL:
          bChanged = sqlite3_value_type(p)!=SQLITE_NULL;
          break;

        case SQLITE_FLOAT:
        case SQLITE_INTEGER: {
          if( eType==sqlite3_value_type(p) ){
            sqlite3_int64 iVal = sessionGetI64(pCsr);
            if( eType==SQLITE_INTEGER ){
              bChanged = (iVal!=sqlite3_value_int64(p));
            }else{
              double dVal;
              memcpy(&dVal, &iVal, 8);
              bChanged = (dVal!=sqlite3_value_double(p));
            }
          }
          nOld = 8;
          pCsr += 8;
          break;
        }

        default: {
          int nByte;
          nOld = sessionVarintGet(pCsr, &nByte);
          pCsr += nOld;
          nOld += nByte;
          assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
          if( eType==sqlite3_value_type(p) 
           && nByte==sqlite3_value_bytes(p)
           && (nByte==0 || 0==memcmp(pCsr, sqlite3_value_blob(p), nByte))
          ){
            bChanged = 0;
          }
          pCsr += nByte;
          break;
        }
      }

      if( bChanged && pTab->abPK[ii] ){
        nNew = pC->nRecord + 2;
        break;
      }

      if( bChanged ){
        nNew += 1 + nOld;
        sessionSerializeValue(0, p, &nNew);
      }else if( pTab->abPK[ii] ){
        nNew += 2 + nOld;
      }else{
        nNew += 2;
      }
    }
  }

  if( nNew>pC->nMaxSize ){
    int nIncr = nNew - pC->nMaxSize;
    pC->nMaxSize = nNew;
    pSession->nMaxChangesetSize += nIncr;
  }
  return SQLITE_OK;
}

/*
** This function is only called from with a pre-update-hook reporting a 
** change on table pTab (attached to session pSession). The type of change
** (UPDATE, INSERT, DELETE) is specified by the first argument.
**
** Unless one is already present or an error occurs, an entry is added
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
      if( sessionPreupdateEqual(pSession, pTab, pC, op) ) break;
    }

    if( pC==0 ){
      /* Create a new change object containing all the old values (if
      ** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK
      ** values (if this is an INSERT). */
      SessionChange *pChange; /* New change object */
      sqlite3_int64 nByte;    /* Number of bytes to allocate */
      int i;                  /* Used to iterate through columns */
  
      assert( rc==SQLITE_OK );
      pTab->nEntry++;
  
      /* Figure out how large an allocation is required */







<







1341
1342
1343
1344
1345
1346
1347

1348
1349
1350
1351
1352
1353
1354
      if( sessionPreupdateEqual(pSession, pTab, pC, op) ) break;
    }

    if( pC==0 ){
      /* Create a new change object containing all the old values (if
      ** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK
      ** values (if this is an INSERT). */

      sqlite3_int64 nByte;    /* Number of bytes to allocate */
      int i;                  /* Used to iterate through columns */
  
      assert( rc==SQLITE_OK );
      pTab->nEntry++;
  
      /* Figure out how large an allocation is required */
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310






1311
1312
1313
1314
1315
1316
1317
        /* This may fail if SQLite value p contains a utf-16 string that must
        ** be converted to utf-8 and an OOM error occurs while doing so. */
        rc = sessionSerializeValue(0, p, &nByte);
        if( rc!=SQLITE_OK ) goto error_out;
      }
  
      /* Allocate the change object */
      pChange = (SessionChange *)sessionMalloc64(pSession, nByte);
      if( !pChange ){
        rc = SQLITE_NOMEM;
        goto error_out;
      }else{
        memset(pChange, 0, sizeof(SessionChange));
        pChange->aRecord = (u8 *)&pChange[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);
      }

      /* Add the change to the hash-table */
      if( pSession->bIndirect || pSession->hook.xDepth(pSession->hook.pCtx) ){
        pChange->bIndirect = 1;
      }
      pChange->nRecord = nByte;
      pChange->op = op;
      pChange->pNext = pTab->apChange[iHash];
      pTab->apChange[iHash] = pChange;

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







  /* If an error has occurred, mark the session object as failed. */
 error_out:
  if( pTab->bStat1 ){
    pSession->hook = stat1.hook;
  }
  if( rc!=SQLITE_OK ){







|
|



|
|














|




|

|
|
|
|










|
>
>
>
>
>
>







1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
        /* This may fail if SQLite value p contains a utf-16 string that must
        ** be converted to utf-8 and an OOM error occurs while doing so. */
        rc = sessionSerializeValue(0, p, &nByte);
        if( rc!=SQLITE_OK ) goto error_out;
      }
  
      /* Allocate the change object */
      pC = (SessionChange *)sessionMalloc64(pSession, nByte);
      if( !pC ){
        rc = SQLITE_NOMEM;
        goto error_out;
      }else{
        memset(pC, 0, sizeof(SessionChange));
        pC->aRecord = (u8 *)&pC[1];
      }
  
      /* Populate the change object. None of the preupdate_old(),
      ** preupdate_new() or SerializeValue() calls below may fail as all
      ** required values and encodings have already been cached in memory.
      ** It is not possible for an OOM to occur in this block. */
      nByte = 0;
      for(i=0; i<pTab->nCol; i++){
        sqlite3_value *p = 0;
        if( op!=SQLITE_INSERT ){
          pSession->hook.xOld(pSession->hook.pCtx, i, &p);
        }else if( pTab->abPK[i] ){
          pSession->hook.xNew(pSession->hook.pCtx, i, &p);
        }
        sessionSerializeValue(&pC->aRecord[nByte], p, &nByte);
      }

      /* Add the change to the hash-table */
      if( pSession->bIndirect || pSession->hook.xDepth(pSession->hook.pCtx) ){
        pC->bIndirect = 1;
      }
      pC->nRecord = nByte;
      pC->op = op;
      pC->pNext = pTab->apChange[iHash];
      pTab->apChange[iHash] = pC;

    }else if( pC->bIndirect ){
      /* If the existing change is considered "indirect", but this current
      ** change is "direct", mark the change object as direct. */
      if( pSession->hook.xDepth(pSession->hook.pCtx)==0 
       && pSession->bIndirect==0 
      ){
        pC->bIndirect = 0;
      }
    }

    assert( rc==SQLITE_OK );
    if( pSession->bEnableSize ){
      rc = sessionUpdateMaxSize(op, pSession, pTab, pC);
    }
  }


  /* If an error has occurred, mark the session object as failed. */
 error_out:
  if( pTab->bStat1 ){
    pSession->hook = stat1.hook;
  }
  if( rc!=SQLITE_OK ){
2516
2517
2518
2519
2520
2521
2522
2523




2524
2525
2526
2527
2528
2529
2530
** using sqlite3_free().
*/
int sqlite3session_changeset(
  sqlite3_session *pSession,      /* Session object */
  int *pnChangeset,               /* OUT: Size of buffer at *ppChangeset */
  void **ppChangeset              /* OUT: Buffer containing changeset */
){
  return sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset, ppChangeset);




}

/*
** Streaming version of sqlite3session_changeset().
*/
int sqlite3session_changeset_strm(
  sqlite3_session *pSession,







|
>
>
>
>







2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
** using sqlite3_free().
*/
int sqlite3session_changeset(
  sqlite3_session *pSession,      /* Session object */
  int *pnChangeset,               /* OUT: Size of buffer at *ppChangeset */
  void **ppChangeset              /* OUT: Buffer containing changeset */
){
  int rc = sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset,ppChangeset);
  assert( rc || pnChangeset==0 
       || pSession->bEnableSize==0 || *pnChangeset<=pSession->nMaxChangesetSize 
  );
  return rc;
}

/*
** Streaming version of sqlite3session_changeset().
*/
int sqlite3session_changeset_strm(
  sqlite3_session *pSession,
2607
2608
2609
2610
2611
2612
2613

































2614
2615
2616
2617
2618
2619
2620

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


































/*
** Do the work for either sqlite3changeset_start() or start_strm().
*/
static int sessionChangesetStart(
  sqlite3_changeset_iter **pp,    /* OUT: Changeset iterator handle */
  int (*xInput)(void *pIn, void *pData, int *pnData),







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768

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

/*
** Configure the session object passed as the first argument.
*/
int sqlite3session_object_config(sqlite3_session *pSession, int op, void *pArg){
  int rc = SQLITE_OK;
  switch( op ){
    case SQLITE_SESSION_OBJCONFIG_SIZE: {
      int iArg = *(int*)pArg;
      if( iArg>=0 ){
        if( pSession->pTable ){
          rc = SQLITE_MISUSE;
        }else{
          pSession->bEnableSize = (iArg!=0);
        }
      }
      *(int*)pArg = pSession->bEnableSize;
      break;
    }

    default:
      rc = SQLITE_MISUSE;
  }

  return rc;
}

/*
** Return the maximum size of sqlite3session_changeset() output.
*/
sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession){
  return pSession->nMaxChangesetSize;
}

/*
** Do the work for either sqlite3changeset_start() or start_strm().
*/
static int sessionChangesetStart(
  sqlite3_changeset_iter **pp,    /* OUT: Changeset iterator handle */
  int (*xInput)(void *pIn, void *pData, int *pnData),
Changes to ext/session/sqlite3session.h.
75
76
77
78
79
80
81
































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


































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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
**
** Session objects must be deleted before the database handle to which they
** are attached is closed. Refer to the documentation for 
** [sqlite3session_create()] for details.
*/
void sqlite3session_delete(sqlite3_session *pSession);

/*
** CAPIREF: Conigure a Session Object
** METHOD: sqlite3_session
**
** This method is used to configure a session object after it has been
** created. At present the only valid value for the second parameter is
** [SQLITE_SESSION_OBJCONFIG_SIZE].
**
** Arguments for sqlite3session_object_config()
**
** The following values may passed as the the 4th parameter to
** sqlite3session_object_config().
**
** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd>
**   This option is used to set, clear or query the flag that enables
**   the [sqlite3session_changeset_size()] API. Because it imposes some
**   computational overhead, this API is disabled by default. Argument
**   pArg must point to a value of type (int). If the value is initially
**   0, then the sqlite3session_changeset_size() API is disabled. If it
**   is greater than 0, then the same API is enabled. Or, if the initial
**   value is less than zero, no change is made. In all cases the (int)
**   variable is set to 1 if the sqlite3session_changeset_size() API is
**   enabled following the current call, or 0 otherwise.
**
**   It is an error (SQLITE_MISUSE) to attempt to modify this setting after 
**   the first table has been attached to the session object.
*/
int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);

/*
*/
#define SQLITE_SESSION_OBJCONFIG_SIZE 1

/*
** CAPI3REF: Enable Or Disable A Session Object
** METHOD: sqlite3_session
**
** Enable or disable the recording of changes by a session object. When
** enabled, a session object records changes made to the database. When
319
320
321
322
323
324
325
















326
327
328
329
330
331
332
*/
int sqlite3session_changeset(
  sqlite3_session *pSession,      /* Session object */
  int *pnChangeset,               /* OUT: Size of buffer at *ppChangeset */
  void **ppChangeset              /* OUT: Buffer containing changeset */
);

















/*
** CAPI3REF: Load The Difference Between Tables Into A Session
** METHOD: sqlite3_session
**
** If it is not already attached to the session object passed as the first
** argument, this function attaches table zTbl in the same manner as the
** [sqlite3session_attach()] function. If zTbl does not exist, or if it







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
*/
int sqlite3session_changeset(
  sqlite3_session *pSession,      /* Session object */
  int *pnChangeset,               /* OUT: Size of buffer at *ppChangeset */
  void **ppChangeset              /* OUT: Buffer containing changeset */
);

/*
** CAPI3REF: Return An Upper-limit For The Size Of The Changeset
** METHOD: sqlite3_session
**
** By default, this function always returns 0. For it to return
** a useful result, the sqlite3_session object must have been configured
** to enable this API using sqlite3session_object_config() with the
** SQLITE_SESSION_OBJCONFIG_SIZE verb.
**
** When enabled, this function returns an upper limit, in bytes, for the size 
** of the changeset that might be produced if sqlite3session_changeset() were
** called. The final changeset size might be equal to or smaller than the
** size in bytes returned by this function.
*/
sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession);

/*
** CAPI3REF: Load The Difference Between Tables Into A Session
** METHOD: sqlite3_session
**
** If it is not already attached to the session object passed as the first
** argument, this function attaches table zTbl in the same manner as the
** [sqlite3session_attach()] function. If zTbl does not exist, or if it
Changes to ext/session/test_session.c.
242
243
244
245
246
247
248


249
250
251
252
253
254
255
    { "enable",       1, "BOOL",       }, /* 3 */
    { "indirect",     1, "BOOL",       }, /* 4 */
    { "isempty",      0, "",           }, /* 5 */
    { "table_filter", 1, "SCRIPT",     }, /* 6 */
    { "patchset",     0, "",           }, /* 7 */
    { "diff",         2, "FROMDB TBL", }, /* 8 */
    { "memory_used",  0, "",           }, /* 9 */


    { 0 }
  };
  int iSub;
  int rc;

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");







>
>







242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
    { "enable",       1, "BOOL",       }, /* 3 */
    { "indirect",     1, "BOOL",       }, /* 4 */
    { "isempty",      0, "",           }, /* 5 */
    { "table_filter", 1, "SCRIPT",     }, /* 6 */
    { "patchset",     0, "",           }, /* 7 */
    { "diff",         2, "FROMDB TBL", }, /* 8 */
    { "memory_used",  0, "",           }, /* 9 */
    { "changeset_size", 0, "",         }, /* 10 */
    { "object_config_size", 1, "INTEGER", }, /* 11 */
    { 0 }
  };
  int iSub;
  int rc;

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























360
361
362
363
364
365
366
    }

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























  }

  return TCL_OK;
}

static void SQLITE_TCLAPI test_session_del(void *clientData){
  TestSession *p = (TestSession*)clientData;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

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

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

  return TCL_OK;
}

static void SQLITE_TCLAPI test_session_del(void *clientData){
  TestSession *p = (TestSession*)clientData;
378
379
380
381
382
383
384

385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404







405
406
407
408
409
410
411
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3 *db;
  Tcl_CmdInfo info;
  int rc;                         /* sqlite3session_create() return code */
  TestSession *p;                 /* New wrapper object */


  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);
  }








  Tcl_CreateObjCommand(
      interp, Tcl_GetString(objv[1]), test_session_cmd, (ClientData)p,
      test_session_del
  );
  Tcl_SetObjResult(interp, objv[1]);
  return TCL_OK;
}







>




















>
>
>
>
>
>
>







403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3 *db;
  Tcl_CmdInfo info;
  int rc;                         /* sqlite3session_create() return code */
  TestSession *p;                 /* New wrapper object */
  int iArg = -1;

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

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

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

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

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

445
446
447
448
449
450
451
  $(TOP)/ext/fts3/fts3_aux.c \
  $(TOP)/ext/fts3/fts3_expr.c \
  $(TOP)/ext/fts3/fts3_tokenizer.c \
  $(TOP)/ext/fts3/fts3_write.c \
  $(TOP)/ext/async/sqlite3async.c \
  $(TOP)/ext/misc/stmt.c \
  $(TOP)/ext/session/sqlite3session.c \
  $(TOP)/ext/session/test_session.c


# Header files used by all library source files.
#
HDR = \
   $(TOP)/src/btree.h \
   $(TOP)/src/btreeInt.h \
   $(TOP)/src/hash.h \







|
>







437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
  $(TOP)/ext/fts3/fts3_aux.c \
  $(TOP)/ext/fts3/fts3_expr.c \
  $(TOP)/ext/fts3/fts3_tokenizer.c \
  $(TOP)/ext/fts3/fts3_write.c \
  $(TOP)/ext/async/sqlite3async.c \
  $(TOP)/ext/misc/stmt.c \
  $(TOP)/ext/session/sqlite3session.c \
  $(TOP)/ext/session/test_session.c \
  fts5.c

# Header files used by all library source files.
#
HDR = \
   $(TOP)/src/btree.h \
   $(TOP)/src/btreeInt.h \
   $(TOP)/src/hash.h \
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000
FUZZCHECK_OPT += -DSQLITE_ENABLE_DESERIALIZE
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
DBFUZZ_OPT =
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ







<







537
538
539
540
541
542
543

544
545
546
547
548
549
550
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -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
DBFUZZ_OPT =
KV_OPT = -DSQLITE_THREADSAFE=0 -DSQLITE_DIRECT_OVERFLOW_READ
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
	$(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_ENABLE_DESERIALIZE \
  -DSQLITE_DEBUG \
  -DSQLITE_ENABLE_DBSTAT_VTAB \
  -DSQLITE_ENABLE_BYTECODE_VTAB \
  -DSQLITE_ENABLE_RTREE \
  -DSQLITE_ENABLE_FTS4 \
  -DSQLITE_ENABLE_FTS5








<







589
590
591
592
593
594
595

596
597
598
599
600
601
602
	$(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

1078
1079
1080
1081
1082
1083
1084



1085
1086
1087
1088
1089
1090
1091
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)




# 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








>
>
>







1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
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

1140
1141
1142
1143
1144
1145
1146

	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








>
1142
1143
1144
1145
1146
1147
1148
1149
	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
Changes to src/alter.c.
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN).
** If the table is a system table, this function leaves an error message
** in pParse->zErr (system tables may not be altered) and returns non-zero.
**
** Or, if zName is not a system table, zero is returned.
*/
static int isAlterableTable(Parse *pParse, Table *pTab){
  if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) 
#ifndef SQLITE_OMIT_VIRTUALTABLE

   || ( (pTab->tabFlags & TF_Shadow)!=0
        && sqlite3ReadOnlyShadowTables(pParse->db)
   )
#endif
  ){
    sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
    return 1;







|

>







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN).
** If the table is a system table, this function leaves an error message
** in pParse->zErr (system tables may not be altered) and returns non-zero.
**
** Or, if zName is not a system table, zero is returned.
*/
static int isAlterableTable(Parse *pParse, Table *pTab){
  if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
#ifndef SQLITE_OMIT_VIRTUALTABLE
   || (pTab->tabFlags & TF_Eponymous)!=0
   || ( (pTab->tabFlags & TF_Shadow)!=0
        && sqlite3ReadOnlyShadowTables(pParse->db)
   )
#endif
  ){
    sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
    return 1;
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
























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

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
























    );
  }
}

/*
** Generate code to reload the schema for database iDb. And, if iDb!=1, for
** the temp database as well.







|







|

|








|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
** objects unusable.
*/
static void renameTestSchema(
  Parse *pParse,                  /* Parse context */
  const char *zDb,                /* Name of db to verify schema of */
  int bTemp,                      /* True if this is the temp db */
  const char *zWhen,              /* "when" part of error message */
  int bNoDQS                      /* Do not allow DQS in the schema */
){
  pParse->colNamesSet = 1;
  sqlite3NestedParse(pParse, 
      "SELECT 1 "
      "FROM \"%w\"." DFLT_SCHEMA_TABLE " "
      "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
      " AND sql NOT LIKE 'create virtual%%'"
      " AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %d)=NULL ",
      zDb,
      zDb, bTemp, zWhen, bNoDQS
  );

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

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

/*
** Generate code to reload the schema for database iDb. And, if iDb!=1, for
** the temp database as well.
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
  ** as required.  */
  if( iDb!=1 ){
    sqlite3NestedParse(pParse, 
        "UPDATE sqlite_temp_schema SET "
            "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
            "tbl_name = "
              "CASE WHEN tbl_name=%Q COLLATE nocase AND "
              "  sqlite_rename_test(%Q, sql, type, name, 1, 'after rename',0) "
              "THEN %Q ELSE tbl_name END "
            "WHERE type IN ('view', 'trigger')"
        , zDb, zTabName, zName, zTabName, zDb, zName);
  }

  /* If this is a virtual table, invoke the xRename() function if
  ** one is defined. The xRename() callback will modify the names







|







258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
  ** as required.  */
  if( iDb!=1 ){
    sqlite3NestedParse(pParse, 
        "UPDATE sqlite_temp_schema SET "
            "sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
            "tbl_name = "
              "CASE WHEN tbl_name=%Q COLLATE nocase AND "
              "  sqlite_rename_test(%Q, sql, type, name, 1, 'after rename', 0) "
              "THEN %Q ELSE tbl_name END "
            "WHERE type IN ('view', 'trigger')"
        , zDb, zTabName, zName, zTabName, zDb, zName);
  }

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




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





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







>
>
>
>







616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
  for(iCol=0; iCol<pTab->nCol; iCol++){
    if( 0==sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break;
  }
  if( iCol==pTab->nCol ){
    sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
    goto exit_rename_column;
  }

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

  /* Do the rename operation using a recursive UPDATE statement that
  ** uses the sqlite_rename_column() SQL function to compute the new
  ** CREATE statement text for the sqlite_schema table.
  */
  sqlite3MayAbort(pParse);
  zNew = sqlite3NameFromToken(db, pNew);
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
      "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) "
      "WHERE type IN ('trigger', 'view')",
      zDb, pTab->zName, iCol, zNew, bQuote
  );

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

 exit_rename_column:
  sqlite3SrcListDelete(db, pSrc);
  sqlite3DbFree(db, zOld);
  sqlite3DbFree(db, zNew);
  return;
}







|







650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
      "sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) "
      "WHERE type IN ('trigger', 'view')",
      zDb, pTab->zName, iCol, zNew, bQuote
  );

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

 exit_rename_column:
  sqlite3SrcListDelete(db, pSrc);
  sqlite3DbFree(db, zOld);
  sqlite3DbFree(db, zNew);
  return;
}
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
/*
** Walker callback used by sqlite3RenameExprUnmap().
*/
static int renameUnmapSelectCb(Walker *pWalker, Select *p){
  Parse *pParse = pWalker->pParse;
  int i;
  if( pParse->nErr ) return WRC_Abort;
  if( NEVER(p->selFlags & SF_View) ) return WRC_Prune;
  if( ALWAYS(p->pEList) ){
    ExprList *pList = p->pEList;
    for(i=0; i<pList->nExpr; i++){
      if( pList->a[i].zEName && pList->a[i].eEName==ENAME_NAME ){
        sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName);
      }
    }







|







831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
/*
** Walker callback used by sqlite3RenameExprUnmap().
*/
static int renameUnmapSelectCb(Walker *pWalker, Select *p){
  Parse *pParse = pWalker->pParse;
  int i;
  if( pParse->nErr ) return WRC_Abort;
  if( p->selFlags & SF_View ) return WRC_Prune;
  if( ALWAYS(p->pEList) ){
    ExprList *pList = p->pEList;
    for(i=0; i<pList->nExpr; i++){
      if( pList->a[i].zEName && pList->a[i].eEName==ENAME_NAME ){
        sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName);
      }
    }
886
887
888
889
890
891
892
893


894
895
896
897
898
899
900
*/
static RenameToken *renameTokenFind(
  Parse *pParse, 
  struct RenameCtx *pCtx, 
  void *pPtr
){
  RenameToken **pp;
  assert( pPtr!=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;







|
>
>







915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
*/
static RenameToken *renameTokenFind(
  Parse *pParse, 
  struct RenameCtx *pCtx, 
  void *pPtr
){
  RenameToken **pp;
  if( NEVER(pPtr==0) ){
    return 0;
  }
  for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){
    if( (*pp)->p==pPtr ){
      RenameToken *pToken = *pp;
      if( pCtx ){
        *pp = pToken->pNext;
        pToken->pNext = pCtx->pList;
        pCtx->pList = pToken;
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
** is initialized by this function before it is used.
*/
static int renameParseSql(
  Parse *p,                       /* Memory to use for Parse object */
  const char *zDb,                /* Name of schema SQL belongs to */
  sqlite3 *db,                    /* Database handle */
  const char *zSql,               /* SQL to parse */
  int bTemp,                      /* True if SQL is from temp schema */
  const char *zDropColumn         /* Name of column being dropped */
){
  int rc;
  char *zErr = 0;

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

  /* Parse the SQL statement passed as the first argument. If no error
  ** occurs and the parse does not result in a new table, index or
  ** trigger object, the database must be corrupt. */
  memset(p, 0, sizeof(Parse));
  p->eParseMode = PARSE_MODE_RENAME;
  p->db = db;







|
<





<
<
<
<







1076
1077
1078
1079
1080
1081
1082
1083

1084
1085
1086
1087
1088




1089
1090
1091
1092
1093
1094
1095
** is initialized by this function before it is used.
*/
static int renameParseSql(
  Parse *p,                       /* Memory to use for Parse object */
  const char *zDb,                /* Name of schema SQL belongs to */
  sqlite3 *db,                    /* Database handle */
  const char *zSql,               /* SQL to parse */
  int bTemp                       /* True if SQL is from temp schema */

){
  int rc;
  char *zErr = 0;

  db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);





  /* Parse the SQL statement passed as the first argument. If no error
  ** occurs and the parse does not result in a new table, index or
  ** trigger object, the database must be corrupt. */
  memset(p, 0, sizeof(Parse));
  p->eParseMode = PARSE_MODE_RENAME;
  p->db = db;
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
    for(pToken=p->pRename; pToken; pToken=pToken->pNext){
      assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] );
    }
  }
#endif

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

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







<







1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
    for(pToken=p->pRename; pToken; pToken=pToken->pNext){
      assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] );
    }
  }
#endif

  db->init.iDb = 0;

  return rc;
}

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


1122

1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135




1136


1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153



1154
1155
1156
1157
1158
1159

















1160
1161
1162
1163
1164
1165
1166
  const char *zNew,               /* New token text */
  int bQuote                      /* True to always quote token */
){
  int nNew = sqlite3Strlen30(zNew);
  int nSql = sqlite3Strlen30(zSql);
  sqlite3 *db = sqlite3_context_db_handle(pCtx);
  int rc = SQLITE_OK;
  char *zQuot;
  char *zOut;
  int 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);
  }
  if( bQuote ){
    zNew = zQuot;




    nNew = nQuot;


  }

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



      if( sqlite3IsIdChar(*pBest->t.z) ){
        nReplace = nNew;
        zReplace = zNew;
      }else{
        nReplace = nQuot;
        zReplace = zQuot;

















      }

      iOff = pBest->t.z - zSql;
      if( pBest->t.n!=nReplace ){
        memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n], 
            nOut - (iOff + pBest->t.n)
        );







|

|
>
>

>
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
|
>
>




|
|
<
<





<
<


>
>
>
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176


1177
1178
1179
1180
1181


1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
  const char *zNew,               /* New token text */
  int bQuote                      /* True to always quote token */
){
  int nNew = sqlite3Strlen30(zNew);
  int nSql = sqlite3Strlen30(zSql);
  sqlite3 *db = sqlite3_context_db_handle(pCtx);
  int rc = SQLITE_OK;
  char *zQuot = 0;
  char *zOut;
  int nQuot = 0;
  char *zBuf1 = 0;
  char *zBuf2 = 0;

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

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

  /* At this point pRename->pList contains a list of RenameToken objects
  ** corresponding to all tokens in the input SQL that must be replaced
  ** with the new column name, or with single-quoted versions of themselves. 
  ** All that remains is to construct and return the edited SQL string. */


  if( zOut ){
    int nOut = nSql;
    memcpy(zOut, zSql, nSql);
    while( pRename->pList ){
      int iOff;                   /* Offset of token to replace in zOut */


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

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

      iOff = pBest->t.z - zSql;
      if( pBest->t.n!=nReplace ){
        memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n], 
            nOut - (iOff + pBest->t.n)
        );
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
  zOld = pTab->aCol[iCol].zName;
  memset(&sCtx, 0, sizeof(sCtx));
  sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol);

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

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







|







1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
  zOld = pTab->aCol[iCol].zName;
  memset(&sCtx, 0, sizeof(sCtx));
  sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol);

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

  /* Find tokens that need to be replaced. */
  memset(&sWalker, 0, sizeof(Walker));
  sWalker.pParse = &sParse;
  sWalker.xExprCallback = renameColumnExprCb;
  sWalker.xSelectCallback = renameColumnSelectCb;
  sWalker.u.pRename = &sCtx;
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
** Walker select callback used by "RENAME TABLE". 
*/
static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
  int i;
  RenameCtx *p = pWalker->u.pRename;
  SrcList *pSrc = pSelect->pSrc;
  if( pSelect->selFlags & SF_View ) return WRC_Prune;
  if( pSrc==0 ){
    assert( pWalker->pParse->db->mallocFailed );
    return WRC_Abort;
  }
  for(i=0; i<pSrc->nSrc; i++){
    SrcItem *pItem = &pSrc->a[i];
    if( pItem->pTab==p->pTab ){
      renameTokenFind(pWalker->pParse, p, pItem->zName);







|







1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
** Walker select callback used by "RENAME TABLE". 
*/
static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
  int i;
  RenameCtx *p = pWalker->u.pRename;
  SrcList *pSrc = pSelect->pSrc;
  if( pSelect->selFlags & SF_View ) return WRC_Prune;
  if( NEVER(pSrc==0) ){
    assert( pWalker->pParse->db->mallocFailed );
    return WRC_Abort;
  }
  for(i=0; i<pSrc->nSrc; i++){
    SrcItem *pItem = &pSrc->a[i];
    if( pItem->pTab==p->pTab ){
      renameTokenFind(pWalker->pParse, p, pItem->zName);
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
    sCtx.pTab = sqlite3FindTable(db, zOld, zDb);
    memset(&sWalker, 0, sizeof(Walker));
    sWalker.pParse = &sParse;
    sWalker.xExprCallback = renameTableExprCb;
    sWalker.xSelectCallback = renameTableSelectCb;
    sWalker.u.pRename = &sCtx;

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

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

        if( pTab->pSelect ){







|







1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
    sCtx.pTab = sqlite3FindTable(db, zOld, zDb);
    memset(&sWalker, 0, sizeof(Walker));
    sWalker.pParse = &sParse;
    sWalker.xExprCallback = renameTableExprCb;
    sWalker.xSelectCallback = renameTableSelectCb;
    sWalker.u.pRename = &sCtx;

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

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

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

















































































































1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743

1744
1745
1746


1747

1748
1749
1750
1751
1752
1753
1754
#ifndef SQLITE_OMIT_AUTHORIZATION
    db->xAuth = xAuth;
#endif
  }

  return;
}


















































































































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

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

  UNUSED_PARAMETER(NotUsed);

  if( zDb && zInput ){
    int rc;
    Parse sParse;


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

    if( rc==SQLITE_OK ){
      if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
        NameContext sNC;
        memset(&sNC, 0, sizeof(sNC));
        sNC.pParse = &sParse;
        sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC);
        if( sParse.nErr ) rc = sParse.rc;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














|


















|







>



>
>
|
>







1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
#ifndef SQLITE_OMIT_AUTHORIZATION
    db->xAuth = xAuth;
#endif
  }

  return;
}

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

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

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

  sqlite3BtreeEnterAll(db);

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

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

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

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

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

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

  sqlite3BtreeLeaveAll(db);
}

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

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

  UNUSED_PARAMETER(NotUsed);

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

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

  UNUSED_PARAMETER(NotUsed);
  rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1, 0);
  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;
  }







|







1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989

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

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

1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936

1937
1938



1939



1940
1941
1942
1943
1944
1945

1946
1947
1948
1949



1950

1951
1952
1953
1954
1955
1956
1957
1958
1959
1960

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

1980
1981
1982
1983
  }

  /* Edit the sqlite_schema table */
  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
  assert( iDb>=0 );
  zDb = db->aDb[iDb].zDbSName;
  renameTestSchema(pParse, zDb, iDb==1, "", 0);

  sqlite3NestedParse(pParse, 
      "UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
      "sql = sqlite_drop_column(%d, sql, %d) "
      "WHERE (type=='table' AND tbl_name=%Q COLLATE nocase)"
      , zDb, iDb, iCol, pTab->zName
  );

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

  /* Edit rows of table on disk */
  if( pParse->nErr==0 && (pTab->aCol[iCol].colFlags & COLFLAG_VIRTUAL)==0 ){
    int i;
    int addr;
    int reg;
    int regRec;
    Index *pPk = 0;
    int nField = 0;               /* Number of non-virtual columns after drop */
    int iCur;
    Vdbe *v = sqlite3GetVdbe(pParse);
    iCur = pParse->nTab++;
    sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
    addr = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
    reg = ++pParse->nMem;
    pParse->nMem += pTab->nCol;
    if( HasRowid(pTab) ){
      sqlite3VdbeAddOp2(v, OP_Rowid, iCur, reg);

    }else{
      pPk = sqlite3PrimaryKeyIndex(pTab);



    }



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

          regOut = reg+1+iPos-(iPos>iColPos);
        }else{
          regOut = reg+1+nField;
        }



        sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);

        nField++;
      }
    }
    regRec = reg + pTab->nCol;
    sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec);
    if( pPk ){
      sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol);
    }else{
      sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg);
    }


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

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

/*
** Register built-in functions used to help implement ALTER TABLE
*/
void sqlite3AlterFunctions(void){
  static FuncDef aAlterTableFuncs[] = {
    INTERNAL_FUNCTION(sqlite_rename_column,  9, renameColumnFunc),
    INTERNAL_FUNCTION(sqlite_rename_table,   7, renameTableFunc),
    INTERNAL_FUNCTION(sqlite_rename_test,    7, renameTableTest),
    INTERNAL_FUNCTION(sqlite_drop_column,    3, dropColumnFunc),

  };
  sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
}
#endif  /* SQLITE_ALTER_TABLE */







>









|















<


>


>
>
>
|
>
>
>






>




>
>
>
|
>



<






>



















>




2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101

2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132

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

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

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

  /* Edit rows of table on disk */
  if( pParse->nErr==0 && (pTab->aCol[iCol].colFlags & COLFLAG_VIRTUAL)==0 ){
    int i;
    int addr;
    int reg;
    int regRec;
    Index *pPk = 0;
    int nField = 0;               /* Number of non-virtual columns after drop */
    int iCur;
    Vdbe *v = sqlite3GetVdbe(pParse);
    iCur = pParse->nTab++;
    sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
    addr = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
    reg = ++pParse->nMem;

    if( HasRowid(pTab) ){
      sqlite3VdbeAddOp2(v, OP_Rowid, iCur, reg);
      pParse->nMem += pTab->nCol;
    }else{
      pPk = sqlite3PrimaryKeyIndex(pTab);
      pParse->nMem += pPk->nColumn;
      for(i=0; i<pPk->nKeyCol; i++){
        sqlite3VdbeAddOp3(v, OP_Column, iCur, i, reg+i+1);
      }
      nField = pPk->nKeyCol;
    }
    regRec = ++pParse->nMem;
    for(i=0; i<pTab->nCol; i++){
      if( i!=iCol && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
        int regOut;
        if( pPk ){
          int iPos = sqlite3TableColumnToIndex(pPk, i);
          int iColPos = sqlite3TableColumnToIndex(pPk, iCol);
          if( iPos<pPk->nKeyCol ) continue;
          regOut = reg+1+iPos-(iPos>iColPos);
        }else{
          regOut = reg+1+nField;
        }
        if( i==pTab->iPKey ){
          sqlite3VdbeAddOp2(v, OP_Null, 0, regOut);
        }else{
          sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
        }
        nField++;
      }
    }

    sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec);
    if( pPk ){
      sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol);
    }else{
      sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg);
    }
    sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION);

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

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

/*
** Register built-in functions used to help implement ALTER TABLE
*/
void sqlite3AlterFunctions(void){
  static FuncDef aAlterTableFuncs[] = {
    INTERNAL_FUNCTION(sqlite_rename_column,  9, renameColumnFunc),
    INTERNAL_FUNCTION(sqlite_rename_table,   7, renameTableFunc),
    INTERNAL_FUNCTION(sqlite_rename_test,    7, renameTableTest),
    INTERNAL_FUNCTION(sqlite_drop_column,    3, dropColumnFunc),
    INTERNAL_FUNCTION(sqlite_rename_quotefix,2, renameQuotefixFunc),
  };
  sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
}
#endif  /* SQLITE_ALTER_TABLE */
Changes to src/attach.c.
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

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







|







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

  UNUSED_PARAMETER(NotUsed);
  zFile = (const char *)sqlite3_value_text(argv[0]);
  zName = (const char *)sqlite3_value_text(argv[1]);
  if( zFile==0 ) zFile = "";
  if( zName==0 ) zName = "";

#ifndef SQLITE_OMIT_DESERIALIZE
# define REOPEN_AS_MEMDB(db)  (db->init.reopenMemdb)
#else
# define REOPEN_AS_MEMDB(db)  (0)
#endif

  if( REOPEN_AS_MEMDB(db) ){
    /* This is not a real ATTACH.  Instead, this routine is being called
461
462
463
464
465
466
467

468
469
470
471
472
473
474
475


476
477
478
479
480
481
482
  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 && 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->pSchema = pFix->pSchema;
      pItem->fg.fromDDL = 1;
    }
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
    if( sqlite3WalkExpr(&pFix->w, pList->a[i].pOn) ) return WRC_Abort;
#endif
  }







>
|
|
|
|
|
|
|
|
>
>







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
  sqlite3 *db = pFix->pParse->db;
  int iDb = sqlite3FindDbName(db, pFix->zDb);
  SrcList *pList = pSelect->pSrc;

  if( NEVER(pList==0) ) return WRC_Continue;
  for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
    if( pFix->bTemp==0 ){
      if( pItem->zDatabase ){
        if( iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
          sqlite3ErrorMsg(pFix->pParse,
              "%s %T cannot reference objects in database %s",
              pFix->zType, pFix->pName, pItem->zDatabase);
          return WRC_Abort;
        }
        sqlite3DbFree(db, pItem->zDatabase);
        pItem->zDatabase = 0;
        pItem->fg.notCte = 1;
      }
      pItem->pSchema = pFix->pSchema;
      pItem->fg.fromDDL = 1;
    }
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
    if( sqlite3WalkExpr(&pFix->w, pList->a[i].pOn) ) return WRC_Abort;
#endif
  }
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
  pFix->pSchema = db->aDb[iDb].pSchema;
  pFix->zType = zType;
  pFix->pName = pName;
  pFix->bTemp = (iDb==1);
  pFix->w.pParse = pParse;
  pFix->w.xExprCallback = fixExprCb;
  pFix->w.xSelectCallback = fixSelectCb;
  pFix->w.xSelectCallback2 = 0;
  pFix->w.walkerDepth = 0;
  pFix->w.eCode = 0;
  pFix->w.u.pFix = pFix;
}

/*
** The following set of routines walk through the parse tree and assign







|







511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
  pFix->pSchema = db->aDb[iDb].pSchema;
  pFix->zType = zType;
  pFix->pName = pName;
  pFix->bTemp = (iDb==1);
  pFix->w.pParse = pParse;
  pFix->w.xExprCallback = fixExprCb;
  pFix->w.xSelectCallback = fixSelectCb;
  pFix->w.xSelectCallback2 = sqlite3WalkWinDefnDummyCallback;
  pFix->w.walkerDepth = 0;
  pFix->w.eCode = 0;
  pFix->w.u.pFix = pFix;
}

/*
** The following set of routines walk through the parse tree and assign
570
571
572
573
574
575
576
577

578

579
580
581
582
583
584

585
586
587
588
589
590
591
592
593
     || sqlite3WalkExpr(&pFix->w, pStep->pWhere) 
     || sqlite3WalkExprList(&pFix->w, pStep->pExprList)
     || sqlite3FixSrcList(pFix, pStep->pFrom)
    ){
      return 1;
    }
#ifndef SQLITE_OMIT_UPSERT
    if( pStep->pUpsert ){

      Upsert *pUp = pStep->pUpsert;

      if( sqlite3WalkExprList(&pFix->w, pUp->pUpsertTarget)
       || sqlite3WalkExpr(&pFix->w, pUp->pUpsertTargetWhere)
       || sqlite3WalkExprList(&pFix->w, pUp->pUpsertSet)
       || sqlite3WalkExpr(&pFix->w, pUp->pUpsertWhere)
      ){
        return 1;

      }
    }
#endif
    pStep = pStep->pNext;
  }

  return 0;
}
#endif







<
>
|
>
|
|
|
|
|
|
>









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
     || sqlite3WalkExpr(&pFix->w, pStep->pWhere) 
     || sqlite3WalkExprList(&pFix->w, pStep->pExprList)
     || sqlite3FixSrcList(pFix, pStep->pFrom)
    ){
      return 1;
    }
#ifndef SQLITE_OMIT_UPSERT

    {
      Upsert *pUp;
      for(pUp=pStep->pUpsert; pUp; pUp=pUp->pNextUpsert){
        if( sqlite3WalkExprList(&pFix->w, pUp->pUpsertTarget)
         || sqlite3WalkExpr(&pFix->w, pUp->pUpsertTargetWhere)
         || sqlite3WalkExprList(&pFix->w, pUp->pUpsertSet)
         || sqlite3WalkExpr(&pFix->w, pUp->pUpsertWhere)
        ){
          return 1;
        }
      }
    }
#endif
    pStep = pStep->pNext;
  }

  return 0;
}
#endif
Changes to src/btree.c.
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
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( 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;







|







543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
static void invalidateIncrblobCursors(
  Btree *pBtree,          /* The database file to check */
  Pgno pgnoRoot,          /* The table that might be changing */
  i64 iRow,               /* The rowid that might be changing */
  int isClearTable        /* True if all rows are being deleted */
){
  BtCursor *p;
  assert( pBtree->hasIncrblobCur );
  assert( sqlite3BtreeHoldsMutex(pBtree) );
  pBtree->hasIncrblobCur = 0;
  for(p=pBtree->pBt->pCursor; p; p=p->pNext){
    if( (p->curFlags & BTCF_Incrblob)!=0 ){
      pBtree->hasIncrblobCur = 1;
      if( p->pgnoRoot==pgnoRoot && (isClearTable || p->info.nKey==iRow) ){
        p->eState = CURSOR_INVALID;
1444
1445
1446
1447
1448
1449
1450

1451
1452
1453
1454
1455
1456
1457
  int cbrk;                  /* Offset to the cell content area */
  int nCell;                 /* Number of cells on the page */
  unsigned char *data;       /* The page data */
  unsigned char *temp;       /* Temp area for cell content */
  unsigned char *src;        /* Source of content */
  int iCellFirst;            /* First allowable cell index */
  int iCellLast;             /* Last possible cell index */


  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
  assert( pPage->pBt!=0 );
  assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );
  assert( pPage->nOverflow==0 );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  temp = 0;







>







1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
  int cbrk;                  /* Offset to the cell content area */
  int nCell;                 /* Number of cells on the page */
  unsigned char *data;       /* The page data */
  unsigned char *temp;       /* Temp area for cell content */
  unsigned char *src;        /* Source of content */
  int iCellFirst;            /* First allowable cell index */
  int iCellLast;             /* Last possible cell index */
  int iCellStart;            /* First cell offset in input */

  assert( sqlite3PagerIswriteable(pPage->pDbPage) );
  assert( pPage->pBt!=0 );
  assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );
  assert( pPage->nOverflow==0 );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  temp = 0;
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510

1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
        }
        if( iFree2 ){
          if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage);
          sz2 = get2byte(&data[iFree2+2]);
          if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
          memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
          sz += sz2;
        }else if( NEVER(iFree+sz>usableSize) ){
          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;

  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);
    if( temp==0 ){
      int x;
      if( cbrk==pc ) continue;
      temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
      x = get2byte(&data[hdr+5]);
      memcpy(&temp[x], &data[x], (cbrk+size) - x);
      src = temp;
    }
    memcpy(&data[cbrk], &src[pc], size);
  }
  data[hdr+7] = 0;

 defragment_out:







|


















>









|


|


|


|




<


<
|







1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535

1536
1537

1538
1539
1540
1541
1542
1543
1544
1545
        }
        if( iFree2 ){
          if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage);
          sz2 = get2byte(&data[iFree2+2]);
          if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
          memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
          sz += sz2;
        }else if( iFree+sz>usableSize ){
          return SQLITE_CORRUPT_PAGE(pPage);
        }

        cbrk = top+sz;
        assert( cbrk+(iFree-top) <= usableSize );
        memmove(&data[cbrk], &data[top], iFree-top);
        for(pAddr=&data[cellOffset]; pAddr<pEnd; pAddr+=2){
          pc = get2byte(pAddr);
          if( pc<iFree ){ put2byte(pAddr, pc+sz); }
          else if( pc<iFree2 ){ put2byte(pAddr, pc+sz2); }
        }
        goto defragment_out;
      }
    }
  }

  cbrk = usableSize;
  iCellLast = usableSize - 4;
  iCellStart = get2byte(&data[hdr+5]);
  for(i=0; i<nCell; i++){
    u8 *pAddr;     /* The i-th cell pointer */
    pAddr = &data[cellOffset + i*2];
    pc = get2byte(pAddr);
    testcase( pc==iCellFirst );
    testcase( pc==iCellLast );
    /* These conditions have already been verified in btreeInitPage()
    ** if PRAGMA cell_size_check=ON.
    */
    if( pc<iCellStart || pc>iCellLast ){
      return SQLITE_CORRUPT_PAGE(pPage);
    }
    assert( pc>=iCellStart && pc<=iCellLast );
    size = pPage->xCellSize(pPage, &src[pc]);
    cbrk -= size;
    if( cbrk<iCellStart || pc+size>usableSize ){
      return SQLITE_CORRUPT_PAGE(pPage);
    }
    assert( cbrk+size<=usableSize && cbrk>=iCellStart );
    testcase( cbrk+size==usableSize );
    testcase( pc+size==usableSize );
    put2byte(pAddr, cbrk);
    if( temp==0 ){

      if( cbrk==pc ) continue;
      temp = sqlite3PagerTempSpace(pPage->pBt->pPager);

      memcpy(&temp[iCellStart], &data[iCellStart], (cbrk+size) - iCellStart);
      src = temp;
    }
    memcpy(&data[cbrk], &src[pc], size);
  }
  data[hdr+7] = 0;

 defragment_out:
5390
5391
5392
5393
5394
5395
5396
5397


5398
5399
5400
5401
5402
5403
5404
#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
    *pRes = 0;
    return SQLITE_OK;
  }

  rc = moveToRoot(pCur);







|
>
>







5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
#ifdef SQLITE_DEBUG
    /* This block serves to assert() that the cursor really does point 
    ** to the last entry in the b-tree. */
    int ii;
    for(ii=0; ii<pCur->iPage; ii++){
      assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
    }
    assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
    testcase( pCur->ix!=pCur->pPage->nCell-1 );
    /* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
    assert( pCur->pPage->leaf );
#endif
    *pRes = 0;
    return SQLITE_OK;
  }

  rc = moveToRoot(pCur);
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
          }
        }else{
          closest = 0;
        }

        iPage = get4byte(&aData[8+closest*4]);
        testcase( iPage==mxPage );
        if( iPage>mxPage ){
          rc = SQLITE_CORRUPT_PGNO(iTrunk);
          goto end_allocate_page;
        }
        testcase( iPage==mxPage );
        if( !searchList 
         || (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE)) 
        ){







|







6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
          }
        }else{
          closest = 0;
        }

        iPage = get4byte(&aData[8+closest*4]);
        testcase( iPage==mxPage );
        if( iPage>mxPage || iPage<2 ){
          rc = SQLITE_CORRUPT_PGNO(iTrunk);
          goto end_allocate_page;
        }
        testcase( iPage==mxPage );
        if( !searchList 
         || (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE)) 
        ){
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
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
** size information about the cell in pInfo.
*/
static int clearCell(
  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 ){
    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);







|
<

|











<
|
<
<







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
static void freePage(MemPage *pPage, int *pRC){
  if( (*pRC)==SQLITE_OK ){
    *pRC = freePage2(pPage->pBt, pPage, pPage->pgno);
  }
}

/*
** Free the overflow pages associated with the given Cell.

*/
static SQLITE_NOINLINE int clearCellOverflow(
  MemPage *pPage,          /* The page that contains the Cell */
  unsigned char *pCell,    /* First byte of the Cell */
  CellInfo *pInfo          /* Size information about the cell */
){
  BtShared *pBt;
  Pgno ovflPgno;
  int rc;
  int nOvfl;
  u32 ovflPageSize;

  assert( sqlite3_mutex_held(pPage->pBt->mutex) );

  assert( pInfo->nLocal!=pInfo->nPayload );


  testcase( pCell + pInfo->nSize == pPage->aDataEnd );
  testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd );
  if( pCell + pInfo->nSize > pPage->aDataEnd ){
    /* Cell extends past end of page */
    return SQLITE_CORRUPT_PAGE(pPage);
  }
  ovflPgno = get4byte(pCell + pInfo->nSize - 4);
6486
6487
6488
6489
6490
6491
6492















6493
6494
6495
6496
6497
6498
6499
      sqlite3PagerUnref(pOvfl->pDbPage);
    }
    if( rc ) return rc;
    ovflPgno = iNext;
  }
  return SQLITE_OK;
}
















/*
** Create the byte sequence used to represent a cell on page pPage
** and write that byte sequence into pCell[].  Overflow pages are
** allocated and filled in as necessary.  The calling procedure
** is responsible for making sure sufficient space has been allocated
** for pCell[].







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
      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[].
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
  pSrcEnd = pCArray->apEnd[k];

  pData = pEnd;
  while( 1/*exit by break*/ ){
    u8 *pCell = pCArray->apCell[i];
    u16 sz = pCArray->szCell[i];
    assert( sz>0 );
    if( SQLITE_WITHIN(pCell,aData,pEnd) ){
      if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
      pCell = &pTmp[pCell - aData];
    }else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
           && (uptr)(pCell)<(uptr)pSrcEnd
    ){
      return SQLITE_CORRUPT_BKPT;
    }

    pData -= sz;
    put2byte(pCellptr, (pData - aData));
    pCellptr += 2;
    if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
    memcpy(pData, pCell, sz);
    assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
    testcase( sz!=pPg->xCellSize(pPg,pCell) )
    i++;
    if( i>=iEnd ) break;
    if( pCArray->ixNx[k]<=i ){
      k++;
      pSrcEnd = pCArray->apEnd[k];
    }
  }







|












|

<







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
  pSrcEnd = pCArray->apEnd[k];

  pData = pEnd;
  while( 1/*exit by break*/ ){
    u8 *pCell = pCArray->apCell[i];
    u16 sz = pCArray->szCell[i];
    assert( sz>0 );
    if( SQLITE_WITHIN(pCell,aData+j,pEnd) ){
      if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
      pCell = &pTmp[pCell - aData];
    }else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
           && (uptr)(pCell)<(uptr)pSrcEnd
    ){
      return SQLITE_CORRUPT_BKPT;
    }

    pData -= sz;
    put2byte(pCellptr, (pData - aData));
    pCellptr += 2;
    if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
    memmove(pData, pCell, sz);
    assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );

    i++;
    if( i>=iEnd ) break;
    if( pCArray->ixNx[k]<=i ){
      k++;
      pSrcEnd = pCArray->apEnd[k];
    }
  }
7163
7164
7165
7166
7167
7168
7169
7170


7171
7172
7173
7174
7175
7176
7177
      if( pFree!=(pCell + sz) ){
        if( pFree ){
          assert( pFree>aData && (pFree - aData)<65536 );
          freeSpace(pPg, (u16)(pFree - aData), szFree);
        }
        pFree = pCell;
        szFree = sz;
        if( pFree+sz>pEnd ) return 0;


      }else{
        pFree = pCell;
        szFree += sz;
      }
      nRet++;
    }
  }







|
>
>







7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
      if( pFree!=(pCell + sz) ){
        if( pFree ){
          assert( pFree>aData && (pFree - aData)<65536 );
          freeSpace(pPg, (u16)(pFree - aData), szFree);
        }
        pFree = pCell;
        szFree = sz;
        if( pFree+sz>pEnd ){
          return 0;
        }
      }else{
        pFree = pCell;
        szFree += sz;
      }
      nRet++;
    }
  }
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
      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 );
        /* 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







|







7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
      assert( iSpace1 <= (int)pBt->pageSize );
      memcpy(pTemp, apDiv[i], sz);
      b.apCell[b.nCell] = pTemp+leafCorrection;
      assert( leafCorrection==0 || leafCorrection==4 );
      b.szCell[b.nCell] = b.szCell[b.nCell] - leafCorrection;
      if( !pOld->leaf ){
        assert( leafCorrection==0 );
        assert( pOld->hdrOffset==0 || CORRUPT_DB );
        /* The right pointer of the child page pOld becomes the left
        ** pointer of the divider cell */
        memcpy(b.apCell[b.nCell], &pOld->aData[8], 4);
      }else{
        assert( leafCorrection==4 );
        while( b.szCell[b.nCell]<4 ){
          /* Do not allow any cells smaller than 4 bytes. If a smaller cell
8139
8140
8141
8142
8143
8144
8145

8146
8147
8148
8149
8150
8151
8152
  }

  /* Insert new divider cells into pParent. */
  for(i=0; i<nNew-1; i++){
    u8 *pCell;
    u8 *pTemp;
    int sz;

    MemPage *pNew = apNew[i];
    j = cntNew[i];

    assert( j<nMaxCells );
    assert( b.apCell[j]!=0 );
    pCell = b.apCell[j];
    sz = b.szCell[j] + leafCorrection;







>







8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
  }

  /* Insert new divider cells into pParent. */
  for(i=0; i<nNew-1; i++){
    u8 *pCell;
    u8 *pTemp;
    int sz;
    u8 *pSrcEnd;
    MemPage *pNew = apNew[i];
    j = cntNew[i];

    assert( j<nMaxCells );
    assert( b.apCell[j]!=0 );
    pCell = b.apCell[j];
    sz = b.szCell[j] + leafCorrection;
8182
8183
8184
8185
8186
8187
8188






8189
8190
8191
8192
8193
8194
8195
        assert(leafCorrection==4);
        sz = pParent->xCellSize(pParent, pCell);
      }
    }
    iOvflSpace += sz;
    assert( sz<=pBt->maxLocal+23 );
    assert( iOvflSpace <= (int)pBt->pageSize );






    insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc);
    if( rc!=SQLITE_OK ) goto balance_cleanup;
    assert( sqlite3PagerIswriteable(pParent->pDbPage) );
  }

  /* Now update the actual sibling pages. The order in which they are updated
  ** is important, as this code needs to avoid disrupting any page from which







>
>
>
>
>
>







8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
        assert(leafCorrection==4);
        sz = pParent->xCellSize(pParent, pCell);
      }
    }
    iOvflSpace += sz;
    assert( sz<=pBt->maxLocal+23 );
    assert( iOvflSpace <= (int)pBt->pageSize );
    for(k=0; b.ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
    pSrcEnd = b.apEnd[k];
    if( SQLITE_WITHIN(pSrcEnd, pCell, pCell+sz) ){
      rc = SQLITE_CORRUPT_BKPT;
      goto balance_cleanup;
    }
    insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc);
    if( rc!=SQLITE_OK ) goto balance_cleanup;
    assert( sqlite3PagerIswriteable(pParent->pDbPage) );
  }

  /* Now update the actual sibling pages. The order in which they are updated
  ** is important, as this code needs to avoid disrupting any page from which
8724
8725
8726
8727
8728
8729
8730








8731
8732
8733
8734
8735
8736

8737

8738
8739
8740
8741
8742
8743
8744
  ** that the cursor is already where it needs to be and returns without
  ** doing any work. To avoid thwarting these optimizations, it is important
  ** not to clear the cursor here.
  */
  if( pCur->curFlags & BTCF_Multiple ){
    rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
    if( rc ) return rc;








  }

  if( pCur->pKeyInfo==0 ){
    assert( pX->pKey==0 );
    /* If this is an insert into a table b-tree, invalidate any incrblob 
    ** cursors open on the row being replaced */

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







>
>
>
>
>
>
>
>






>
|
>







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
  ** that the cursor is already where it needs to be and returns without
  ** doing any work. To avoid thwarting these optimizations, it is important
  ** not to clear the cursor here.
  */
  if( pCur->curFlags & BTCF_Multiple ){
    rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
    if( rc ) return rc;
    if( loc && pCur->iPage<0 ){
      /* This can only happen if the schema is corrupt such that there is more
      ** than one table or index with the same root page as used by the cursor.
      ** Which can only happen if the SQLITE_NoSchemaError flag was set when
      ** the schema was loaded. This cannot be asserted though, as a user might
      ** set the flag, load the schema, and then unset the flag.  */
      return SQLITE_CORRUPT_BKPT;
    }
  }

  if( pCur->pKeyInfo==0 ){
    assert( pX->pKey==0 );
    /* If this is an insert into a table b-tree, invalidate any incrblob 
    ** cursors open on the row being replaced */
    if( p->hasIncrblobCur ){
      invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
    }

    /* If BTREE_SAVEPOSITION is set, the cursor must already be pointing 
    ** to a row with the same key as the new entry being inserted.
    */
#ifdef SQLITE_DEBUG
    if( flags & BTREE_SAVEPOSITION ){
      assert( pCur->curFlags & BTCF_ValidNKey );
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
        BtreePayload x2;
        x2.pData = pX->pKey;
        x2.nData = pX->nKey;
        x2.nZero = 0;
        return btreeOverwriteCell(pCur, &x2);
      }
    }

  }
  assert( pCur->eState==CURSOR_VALID 
       || (pCur->eState==CURSOR_INVALID && loc)
       || CORRUPT_DB );

  pPage = pCur->pPage;
  assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
  assert( pPage->leaf || !pPage->intKey );
  if( pPage->nFree<0 ){
    if( pCur->eState>CURSOR_INVALID ){
      rc = SQLITE_CORRUPT_BKPT;
    }else{
      rc = btreeComputeFreeSpace(pPage);
    }
    if( rc ) return rc;
  }








<









|







8842
8843
8844
8845
8846
8847
8848

8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
8865
        BtreePayload x2;
        x2.pData = pX->pKey;
        x2.nData = pX->nKey;
        x2.nZero = 0;
        return btreeOverwriteCell(pCur, &x2);
      }
    }

  }
  assert( pCur->eState==CURSOR_VALID 
       || (pCur->eState==CURSOR_INVALID && loc)
       || CORRUPT_DB );

  pPage = pCur->pPage;
  assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
  assert( pPage->leaf || !pPage->intKey );
  if( pPage->nFree<0 ){
    if( NEVER(pCur->eState>CURSOR_INVALID) ){
      rc = SQLITE_CORRUPT_BKPT;
    }else{
      rc = btreeComputeFreeSpace(pPage);
    }
    if( rc ) return rc;
  }

8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878
8879
    if( rc ){
      goto end_insert;
    }
    oldCell = findCell(pPage, idx);
    if( !pPage->leaf ){
      memcpy(newCell, oldCell, 4);
    }
    rc = clearCell(pPage, oldCell, &info);
    testcase( pCur->curFlags & BTCF_ValidOvfl );
    invalidateOverflowCache(pCur);
    if( info.nSize==szNew && info.nLocal==info.nPayload 
     && (!ISAUTOVACUUM || szNew<pPage->minLocal)
    ){
      /* Overwrite the old cell with the new if they are the same size.
      ** We could also try to do this if the old cell is smaller, then add







|







8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
    if( rc ){
      goto end_insert;
    }
    oldCell = findCell(pPage, idx);
    if( !pPage->leaf ){
      memcpy(newCell, oldCell, 4);
    }
    BTREE_CLEAR_CELL(rc, pPage, oldCell, info);
    testcase( pCur->curFlags & BTCF_ValidOvfl );
    invalidateOverflowCache(pCur);
    if( info.nSize==szNew && info.nLocal==info.nPayload 
     && (!ISAUTOVACUUM || szNew<pPage->minLocal)
    ){
      /* Overwrite the old cell with the new if they are the same size.
      ** We could also try to do this if the old cell is smaller, then add
9102
9103
9104
9105
9106
9107
9108

9109
9110
9111
9112
9113
9114
9115
9116
9117
9118
  assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
  assert( pCur->curFlags & BTCF_WriteFlag );
  assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
  assert( !hasReadConflicts(p, pCur->pgnoRoot) );
  assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
  if( pCur->eState==CURSOR_REQUIRESEEK ){
    rc = btreeRestoreCursorPosition(pCur);

    if( rc ) return rc;
  }
  assert( pCur->eState==CURSOR_VALID );

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








>
|

|







9132
9133
9134
9135
9136
9137
9138
9139
9140
9141
9142
9143
9144
9145
9146
9147
9148
9149
  assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
  assert( pCur->curFlags & BTCF_WriteFlag );
  assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
  assert( !hasReadConflicts(p, pCur->pgnoRoot) );
  assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
  if( pCur->eState==CURSOR_REQUIRESEEK ){
    rc = btreeRestoreCursorPosition(pCur);
    assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
    if( rc || pCur->eState!=CURSOR_VALID ) return rc;
  }
  assert( CORRUPT_DB || pCur->eState==CURSOR_VALID );

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

9157
9158
9159
9160
9161
9162
9163
9164
9165
9166
9167
9168
9169
9170
9171
9172
9173
9174
9175
9176
9177
9178
9179
9180
  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 ){
    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);
  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







|








|







9188
9189
9190
9191
9192
9193
9194
9195
9196
9197
9198
9199
9200
9201
9202
9203
9204
9205
9206
9207
9208
9209
9210
9211
  if( pCur->curFlags & BTCF_Multiple ){
    rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
    if( rc ) return rc;
  }

  /* If this is a delete operation to remove a row from a table b-tree,
  ** invalidate any incrblob cursors open on the row being deleted.  */
  if( pCur->pKeyInfo==0 && p->hasIncrblobCur ){
    invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
  }

  /* Make the page containing the entry to be deleted writable. Then free any
  ** overflow pages associated with the entry and finally remove the cell
  ** itself from within the page.  */
  rc = sqlite3PagerWrite(pPage->pDbPage);
  if( rc ) return rc;
  BTREE_CLEAR_CELL(rc, pPage, pCell, info);
  dropCell(pPage, iCellIdx, info.nSize, &rc);
  if( rc ) return rc;

  /* If the cell deleted was not located on a leaf page, then the cursor
  ** is currently pointing to the largest entry in the sub-tree headed
  ** by the child-page of the cell that was just deleted from an internal
  ** node. The cell from the leaf node needs to be moved to the internal
9453
9454
9455
9456
9457
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467
  hdr = pPage->hdrOffset;
  for(i=0; i<pPage->nCell; i++){
    pCell = findCell(pPage, i);
    if( !pPage->leaf ){
      rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
      if( rc ) goto cleardatabasepage_out;
    }
    rc = clearCell(pPage, pCell, &info);
    if( rc ) goto cleardatabasepage_out;
  }
  if( !pPage->leaf ){
    rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
    if( rc ) goto cleardatabasepage_out;
  }else if( pnChange ){
    assert( pPage->intKey || CORRUPT_DB );







|







9484
9485
9486
9487
9488
9489
9490
9491
9492
9493
9494
9495
9496
9497
9498
  hdr = pPage->hdrOffset;
  for(i=0; i<pPage->nCell; i++){
    pCell = findCell(pPage, i);
    if( !pPage->leaf ){
      rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
      if( rc ) goto cleardatabasepage_out;
    }
    BTREE_CLEAR_CELL(rc, pPage, pCell, info);
    if( rc ) goto cleardatabasepage_out;
  }
  if( !pPage->leaf ){
    rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
    if( rc ) goto cleardatabasepage_out;
  }else if( pnChange ){
    assert( pPage->intKey || CORRUPT_DB );
9501
9502
9503
9504
9505
9506
9507

9508

9509
9510
9511
9512
9513
9514
9515

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

    invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);

    rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
  }
  sqlite3BtreeLeave(p);
  return rc;
}

/*







>
|
>







9532
9533
9534
9535
9536
9537
9538
9539
9540
9541
9542
9543
9544
9545
9546
9547
9548

  rc = saveAllCursors(pBt, (Pgno)iTable, 0);

  if( SQLITE_OK==rc ){
    /* Invalidate all incrblob cursors open on table iTable (assuming iTable
    ** is the root of a table b-tree - if it is not, the following call is
    ** a no-op).  */
    if( p->hasIncrblobCur ){
      invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
    }
    rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
  }
  sqlite3BtreeLeave(p);
  return rc;
}

/*
Changes to src/build.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
** 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(
  Parse *pParse,     /* Parsing context */
  int iDb,           /* Index of the database containing the table to lock */
  Pgno iTab,         /* Root page number of the table to be locked */
  u8 isWriteLock,    /* True for a write lock */
  const char *zName  /* Name of the table to be locked */
){
  Parse *pToplevel;
  int i;
  int nBytes;
  TableLock *p;
  assert( iDb>=0 );

  if( iDb==1 ) return;
  if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
  pToplevel = sqlite3ParseToplevel(pParse);
  for(i=0; i<pToplevel->nTableLock; i++){
    p = &pToplevel->aTableLock[i];
    if( p->iDb==iDb && p->iTab==iTab ){
      p->isWriteLock = (p->isWriteLock || isWriteLock);
      return;
    }







|












<
<







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61


62
63
64
65
66
67
68
** The table to be locked has root page iTab and is found in database iDb.
** A read or a write lock can be taken depending on isWritelock.
**
** This routine just records the fact that the lock is desired.  The
** code to make the lock occur is generated by a later call to
** codeTableLocks() which occurs during sqlite3FinishCoding().
*/
static SQLITE_NOINLINE void lockTable(
  Parse *pParse,     /* Parsing context */
  int iDb,           /* Index of the database containing the table to lock */
  Pgno iTab,         /* Root page number of the table to be locked */
  u8 isWriteLock,    /* True for a write lock */
  const char *zName  /* Name of the table to be locked */
){
  Parse *pToplevel;
  int i;
  int nBytes;
  TableLock *p;
  assert( iDb>=0 );



  pToplevel = sqlite3ParseToplevel(pParse);
  for(i=0; i<pToplevel->nTableLock; i++){
    p = &pToplevel->aTableLock[i];
    if( p->iDb==iDb && p->iTab==iTab ){
      p->isWriteLock = (p->isWriteLock || isWriteLock);
      return;
    }
80
81
82
83
84
85
86











87
88
89
90
91
92
93
    p->isWriteLock = isWriteLock;
    p->zLockName = zName;
  }else{
    pToplevel->nTableLock = 0;
    sqlite3OomFault(pToplevel->db);
  }
}












/*
** Code an OP_TableLock instruction for each table locked by the
** statement (configured by calls to sqlite3TableLock()).
*/
static void codeTableLocks(Parse *pParse){
  int i;







>
>
>
>
>
>
>
>
>
>
>







78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
    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;
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464

  p = sqlite3FindTable(db, zName, zDbase);
  if( p==0 ){
#ifndef SQLITE_OMIT_VIRTUALTABLE
    /* If zName is the not the name of a table in the schema created using
    ** CREATE, then check to see if it is the name of an virtual table that
    ** can be an eponymous virtual table. */
    if( pParse->disableVtab==0 ){
      Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
      if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
        pMod = sqlite3PragmaVtabRegister(db, zName);
      }
      if( pMod ){
        if( IsSharedSchema(db) && pParse->nErr==0 ){
          int bDummy = 0;







|







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

  p = sqlite3FindTable(db, zName, zDbase);
  if( p==0 ){
#ifndef SQLITE_OMIT_VIRTUALTABLE
    /* If zName is the not the name of a table in the schema created using
    ** CREATE, then check to see if it is the name of an virtual table that
    ** can be an eponymous virtual table. */
    if( pParse->disableVtab==0 && db->init.busy==0 ){
      Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
      if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
        pMod = sqlite3PragmaVtabRegister(db, zName);
      }
      if( pMod ){
        if( IsSharedSchema(db) && pParse->nErr==0 ){
          int bDummy = 0;
1067
1068
1069
1070
1071
1072
1073

















1074
1075
1076
1077
1078
1079
1080
    return pTab->nNVCol + i - n;
  }else{
    /* iCol is a normal or stored column */
    return n;
  }
}
#endif


















/*
** Begin constructing a new table representation in memory.  This is
** the first of several action routines that get called in response
** to a CREATE TABLE statement.  In particular, this routine is called
** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp
** flag is true if the table should be stored in the auxiliary database







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    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
1167
1168
1169
1170
1171
1172
1173

1174
1175
1176
1177
1178
1179
1180
    pTable = sqlite3FindTable(db, zName, zDb);
    if( pTable ){
      if( !noErr ){
        sqlite3ErrorMsg(pParse, "table %T already exists", pName);
      }else{
        assert( !db->init.busy || CORRUPT_DB );
        sqlite3CodeVerifySchema(pParse, iDb);

      }
      goto begin_table_error;
    }
    if( sqlite3FindIndex(db, zName, zDb)!=0 ){
      sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
      goto begin_table_error;
    }







>







1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
    pTable = sqlite3FindTable(db, zName, zDb);
    if( pTable ){
      if( !noErr ){
        sqlite3ErrorMsg(pParse, "table %T already exists", pName);
      }else{
        assert( !db->init.busy || CORRUPT_DB );
        sqlite3CodeVerifySchema(pParse, iDb);
        sqlite3ForceNotReadOnly(pParse);
      }
      goto begin_table_error;
    }
    if( sqlite3FindIndex(db, zName, zDb)!=0 ){
      sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
      goto begin_table_error;
    }
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
  pTable->nRowLogEst = sqlite3LogEst(SQLITE_DEFAULT_ROWEST);
#else
  pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
#endif
  assert( pParse->pNewTable==0 );
  pParse->pNewTable = pTable;

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

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







<
<
<
<
<
<
<
<
<
<
<







1222
1223
1224
1225
1226
1227
1228











1229
1230
1231
1232
1233
1234
1235
  pTable->nRowLogEst = sqlite3LogEst(SQLITE_DEFAULT_ROWEST);
#else
  pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
#endif
  assert( pParse->pNewTable==0 );
  pParse->pNewTable = pTable;












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

1361
1362
1363
1364
1365
1366
1367
  testcase( pParse->earlyCleanup );
  if( db->mallocFailed ) return;
  pRet->retTrig.zName = RETURNING_TRIGGER_NAME;
  pRet->retTrig.op = TK_RETURNING;
  pRet->retTrig.tr_tm = TRIGGER_AFTER;
  pRet->retTrig.bReturning = 1;
  pRet->retTrig.pSchema = db->aDb[1].pSchema;

  pRet->retTrig.step_list = &pRet->retTStep;
  pRet->retTStep.op = TK_RETURNING;
  pRet->retTStep.pTrig = &pRet->retTrig;
  pRet->retTStep.pExprList = pList;
  pHash = &(db->aDb[1].pSchema->trigHash);
  assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 || pParse->nErr );
  if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig)







>







1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
  testcase( pParse->earlyCleanup );
  if( db->mallocFailed ) return;
  pRet->retTrig.zName = RETURNING_TRIGGER_NAME;
  pRet->retTrig.op = TK_RETURNING;
  pRet->retTrig.tr_tm = TRIGGER_AFTER;
  pRet->retTrig.bReturning = 1;
  pRet->retTrig.pSchema = db->aDb[1].pSchema;
  pRet->retTrig.pTabSchema = db->aDb[1].pSchema;
  pRet->retTrig.step_list = &pRet->retTStep;
  pRet->retTStep.op = TK_RETURNING;
  pRet->retTStep.pTrig = &pRet->retTrig;
  pRet->retTStep.pExprList = pList;
  pHash = &(db->aDb[1].pSchema->trigHash);
  assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 || pParse->nErr );
  if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig)
2212
2213
2214
2215
2216
2217
2218
2219



2220
2221
2222
2223
2224
2225
2226
2227
2228



2229
2230
2231
2232
2233
2234
2235
  */
  if( pTab->iPKey>=0 ){
    ExprList *pList;
    Token ipkToken;
    sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName);
    pList = sqlite3ExprListAppend(pParse, 0, 
                  sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
    if( pList==0 ) return;



    if( IN_RENAME_OBJECT ){
      sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey);
    }
    pList->a[0].sortFlags = pParse->iPkSortOrder;
    assert( pParse->pNewTable==pTab );
    pTab->iPKey = -1;
    sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
                       SQLITE_IDXTYPE_PRIMARYKEY);
    if( db->mallocFailed || pParse->nErr ) return;



    pPk = sqlite3PrimaryKeyIndex(pTab);
    assert( pPk->nKeyCol==1 );
  }else{
    pPk = sqlite3PrimaryKeyIndex(pTab);
    assert( pPk!=0 );

    /*







|
>
>
>








|
>
>
>







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
  */
  if( pTab->iPKey>=0 ){
    ExprList *pList;
    Token ipkToken;
    sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName);
    pList = sqlite3ExprListAppend(pParse, 0, 
                  sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
    if( pList==0 ){
      pTab->tabFlags &= ~TF_WithoutRowid;
      return;
    }
    if( IN_RENAME_OBJECT ){
      sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey);
    }
    pList->a[0].sortFlags = pParse->iPkSortOrder;
    assert( pParse->pNewTable==pTab );
    pTab->iPKey = -1;
    sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
                       SQLITE_IDXTYPE_PRIMARYKEY);
    if( db->mallocFailed || pParse->nErr ){
      pTab->tabFlags &= ~TF_WithoutRowid;
      return;
    }
    pPk = sqlite3PrimaryKeyIndex(pTab);
    assert( pPk->nKeyCol==1 );
  }else{
    pPk = sqlite3PrimaryKeyIndex(pTab);
    assert( pPk!=0 );

    /*
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
  sqlite3 *db = pParse->db; /* The database connection */
  int iDb;                  /* Database in which the table lives */
  Index *pIdx;              /* An implied index of the table */

  if( pEnd==0 && pSelect==0 ){
    return;
  }
  assert( !db->mallocFailed );
  p = pParse->pNewTable;
  if( p==0 ) return;

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








<







2448
2449
2450
2451
2452
2453
2454

2455
2456
2457
2458
2459
2460
2461
  sqlite3 *db = pParse->db; /* The database connection */
  int iDb;                  /* Database in which the table lives */
  Index *pIdx;              /* An implied index of the table */

  if( pEnd==0 && pSelect==0 ){
    return;
  }

  p = pParse->pNewTable;
  if( p==0 ) return;

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

2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
    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 ){
      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
        );







|







2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
    sqlite3DbFree(db, zStmt);
    sqlite3ChangeCookie(pParse, iDb);

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

2680
2681
2682
2683
2684
2685
2686
2687











2688
2689
2690
2691
2692
2693
2694

  /* Add the table to the in-memory representation of the database.
  */
  if( db->init.busy ){
    Table *pOld;
    Schema *pSchema = p->pSchema;
    assert( sqlite3SchemaMutexHeld(db, iDb, 0) );

    pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, p);
    if( pOld ){
      assert( p==pOld );  /* Malloc must have failed inside HashInsert() */
      sqlite3OomFault(db);
      return;
    }
    pParse->pNewTable = 0;
    db->mDbFlags |= DBFLAG_SchemaChange;











  }

#ifndef SQLITE_OMIT_ALTERTABLE
  if( !pSelect && !p->pSelect ){
    assert( pCons && pEnd );
    if( pCons->z==0 ){
      pCons = pEnd;







>








>
>
>
>
>
>
>
>
>
>
>







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

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

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

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










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










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

  /* Make a copy of the entire SELECT statement that defines the view.
  ** This will force all the Expr.token.z values to be dynamically







>
>
>
>
>
>
>
>
>
>







2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
  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
3200
3201
3202
3203
3204
3205
3206

3207


3208
3209
3210
3211
3212
3213
3214
  if( !IsSharedSchema(db) && sqlite3ReadSchema(pParse) ) goto exit_drop_table;
  if( noErr ) db->suppressErr++;
  assert( isView==0 || isView==LOCATE_VIEW );
  pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
  if( noErr ) db->suppressErr--;

  if( pTab==0 ){

    if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);


    goto exit_drop_table;
  }
  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
  assert( iDb>=0 && iDb<db->nDb );
  sqlite3SchemaWritable(pParse, iDb);

  /* If pTab is a virtual table, call ViewGetColumnNames() to ensure







>
|
>
>







3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
  if( !IsSharedSchema(db) && sqlite3ReadSchema(pParse) ) goto exit_drop_table;
  if( noErr ) db->suppressErr++;
  assert( isView==0 || isView==LOCATE_VIEW );
  pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
  if( noErr ) db->suppressErr--;

  if( pTab==0 ){
    if( noErr ){
      sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
      sqlite3ForceNotReadOnly(pParse);
    }
    goto exit_drop_table;
  }
  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
  assert( iDb>=0 && iDb<db->nDb );
  sqlite3SchemaWritable(pParse, iDb);

  /* If pTab is a virtual table, call ViewGetColumnNames() to ensure
3771
3772
3773
3774
3775
3776
3777

3778
3779
3780
3781
3782
3783
3784
      }
      if( sqlite3FindIndex(db, zName, pDb->zDbSName)!=0 ){
        if( !ifNotExist ){
          sqlite3ErrorMsg(pParse, "index %s already exists", zName);
        }else{
          assert( !db->init.busy );
          sqlite3CodeVerifySchema(pParse, iDb);

        }
        goto exit_create_index;
      }
    }
  }else{
    int n;
    Index *pLoop;







>







3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
      }
      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;
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
  ** 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) );







|







4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
  ** 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) );
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295

4296
4297
4298
4299
4300
4301
4302
  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);
    }else{
      sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);

    }
    pParse->checkSchema = 1;
    goto exit_drop_index;
  }
  if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){
    sqlite3ErrorMsg(pParse, "index associated with UNIQUE "
      "or PRIMARY KEY constraint cannot be dropped", 0);







|


>







4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
  assert( pName->nSrc==1 );
  if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
    goto exit_drop_index;
  }
  pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
  if( pIndex==0 ){
    if( !ifExists ){
      sqlite3ErrorMsg(pParse, "no such index: %S", pName->a);
    }else{
      sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
      sqlite3ForceNotReadOnly(pParse);
    }
    pParse->checkSchema = 1;
    goto exit_drop_index;
  }
  if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){
    sqlite3ErrorMsg(pParse, "index associated with UNIQUE "
      "or PRIMARY KEY constraint cannot be dropped", 0);
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616

/*
** Assign VdbeCursor index numbers to all tables in a SrcList
*/
void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
  int i;
  SrcItem *pItem;
  assert(pList || pParse->db->mallocFailed );
  if( pList ){
    for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
      if( pItem->iCursor>=0 ) continue;
      pItem->iCursor = pParse->nTab++;
      if( pItem->pSelect ){
        sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
      }
    }







|
|







4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665

/*
** Assign VdbeCursor index numbers to all tables in a SrcList
*/
void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
  int i;
  SrcItem *pItem;
  assert( pList || pParse->db->mallocFailed );
  if( ALWAYS(pList) ){
    for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
      if( pItem->iCursor>=0 ) continue;
      pItem->iCursor = pParse->nTab++;
      if( pItem->pSelect ){
        sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
      }
    }
Changes to src/ctime.c.
54
55
56
57
58
59
60

61
62

63
64
65
66
67
68
69
#endif
#if SQLITE_4_BYTE_ALIGNED_MALLOC
  "4_BYTE_ALIGNED_MALLOC",
#endif
#if SQLITE_64BIT_STATS
  "64BIT_STATS",
#endif

#if SQLITE_ALLOW_COVERING_INDEX_SCAN
  "ALLOW_COVERING_INDEX_SCAN",

#endif
#if SQLITE_ALLOW_URI_AUTHORITY
  "ALLOW_URI_AUTHORITY",
#endif
#ifdef SQLITE_BITMASK_TYPE
  "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
#endif







>
|
|
>







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#endif
#if SQLITE_4_BYTE_ALIGNED_MALLOC
  "4_BYTE_ALIGNED_MALLOC",
#endif
#if SQLITE_64BIT_STATS
  "64BIT_STATS",
#endif
#ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
# if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
  "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
# endif
#endif
#if SQLITE_ALLOW_URI_AUTHORITY
  "ALLOW_URI_AUTHORITY",
#endif
#ifdef SQLITE_BITMASK_TYPE
  "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
#endif
117
118
119
120
121
122
123

124
125

126
127
128
129
130
131
132
#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

#if SQLITE_DEFAULT_MEMSTATUS
  "DEFAULT_MEMSTATUS",

#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







>
|
|
>







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#endif
#ifdef SQLITE_DEFAULT_LOCKING_MODE
  "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
#endif
#ifdef SQLITE_DEFAULT_LOOKASIDE
  "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE),
#endif
#ifdef SQLITE_DEFAULT_MEMSTATUS
# if SQLITE_DEFAULT_MEMSTATUS != 1
  "DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS),
# endif
#endif
#ifdef SQLITE_DEFAULT_MMAP_SIZE
  "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
#endif
#ifdef SQLITE_DEFAULT_PAGE_SIZE
  "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE),
#endif
192
193
194
195
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
#endif
#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
  "ENABLE_BATCH_ATOMIC_WRITE",
#endif
#if SQLITE_ENABLE_BYTECODE_VTAB
  "ENABLE_BYTECODE_VTAB",
#endif
#if SQLITE_ENABLE_CEROD
  "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
#endif
#if SQLITE_ENABLE_COLUMN_METADATA
  "ENABLE_COLUMN_METADATA",
#endif
#if SQLITE_ENABLE_COLUMN_USED_MASK
  "ENABLE_COLUMN_USED_MASK",
#endif
#if SQLITE_ENABLE_COSTMULT
  "ENABLE_COSTMULT",
#endif
#if SQLITE_ENABLE_CURSOR_HINTS
  "ENABLE_CURSOR_HINTS",



#endif
#if SQLITE_ENABLE_DBSTAT_VTAB
  "ENABLE_DBSTAT_VTAB",
#endif
#if SQLITE_ENABLE_EXPENSIVE_ASSERT
  "ENABLE_EXPENSIVE_ASSERT",
#endif
#if SQLITE_ENABLE_FTS1
  "ENABLE_FTS1",
#endif
#if SQLITE_ENABLE_FTS2
  "ENABLE_FTS2",
#endif
#if SQLITE_ENABLE_FTS3
  "ENABLE_FTS3",
#endif
#if SQLITE_ENABLE_FTS3_PARENTHESIS
  "ENABLE_FTS3_PARENTHESIS",
#endif







|













>
>
>







|
|
<
<
<







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
#endif
#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
  "ENABLE_BATCH_ATOMIC_WRITE",
#endif
#if SQLITE_ENABLE_BYTECODE_VTAB
  "ENABLE_BYTECODE_VTAB",
#endif
#ifdef SQLITE_ENABLE_CEROD
  "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
#endif
#if SQLITE_ENABLE_COLUMN_METADATA
  "ENABLE_COLUMN_METADATA",
#endif
#if SQLITE_ENABLE_COLUMN_USED_MASK
  "ENABLE_COLUMN_USED_MASK",
#endif
#if SQLITE_ENABLE_COSTMULT
  "ENABLE_COSTMULT",
#endif
#if SQLITE_ENABLE_CURSOR_HINTS
  "ENABLE_CURSOR_HINTS",
#endif
#if SQLITE_ENABLE_DBPAGE_VTAB
  "ENABLE_DBPAGE_VTAB",
#endif
#if SQLITE_ENABLE_DBSTAT_VTAB
  "ENABLE_DBSTAT_VTAB",
#endif
#if SQLITE_ENABLE_EXPENSIVE_ASSERT
  "ENABLE_EXPENSIVE_ASSERT",
#endif
#if SQLITE_ENABLE_EXPLAIN_COMMENTS
  "ENABLE_EXPLAIN_COMMENTS",



#endif
#if SQLITE_ENABLE_FTS3
  "ENABLE_FTS3",
#endif
#if SQLITE_ENABLE_FTS3_PARENTHESIS
  "ENABLE_FTS3_PARENTHESIS",
#endif
275
276
277
278
279
280
281



282
283
284
285
286
287
288
  "ENABLE_MULTIPLEX",
#endif
#if SQLITE_ENABLE_NORMALIZE
  "ENABLE_NORMALIZE",
#endif
#if SQLITE_ENABLE_NULL_TRIM
  "ENABLE_NULL_TRIM",



#endif
#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
  "ENABLE_OVERSIZE_CELL_CHECK",
#endif
#if SQLITE_ENABLE_PREUPDATE_HOOK
  "ENABLE_PREUPDATE_HOOK",
#endif







>
>
>







279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
  "ENABLE_MULTIPLEX",
#endif
#if SQLITE_ENABLE_NORMALIZE
  "ENABLE_NORMALIZE",
#endif
#if SQLITE_ENABLE_NULL_TRIM
  "ENABLE_NULL_TRIM",
#endif
#if SQLITE_ENABLE_OFFSET_SQL_FUNC
  "ENABLE_OFFSET_SQL_FUNC",
#endif
#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
  "ENABLE_OVERSIZE_CELL_CHECK",
#endif
#if SQLITE_ENABLE_PREUPDATE_HOOK
  "ENABLE_PREUPDATE_HOOK",
#endif
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
#endif
#if SQLITE_ENABLE_SORTER_REFERENCES
  "ENABLE_SORTER_REFERENCES",
#endif
#if SQLITE_ENABLE_SQLLOG
  "ENABLE_SQLLOG",
#endif
#if defined(SQLITE_ENABLE_STAT4)
  "ENABLE_STAT4",
#endif
#if SQLITE_ENABLE_STMTVTAB
  "ENABLE_STMTVTAB",
#endif
#if SQLITE_ENABLE_STMT_SCANSTATUS
  "ENABLE_STMT_SCANSTATUS",







|







316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
#endif
#if SQLITE_ENABLE_SORTER_REFERENCES
  "ENABLE_SORTER_REFERENCES",
#endif
#if SQLITE_ENABLE_SQLLOG
  "ENABLE_SQLLOG",
#endif
#if SQLITE_ENABLE_STAT4
  "ENABLE_STAT4",
#endif
#if SQLITE_ENABLE_STMTVTAB
  "ENABLE_STMTVTAB",
#endif
#if SQLITE_ENABLE_STMT_SCANSTATUS
  "ENABLE_STMT_SCANSTATUS",
363
364
365
366
367
368
369

370
371

372
373
374
375
376
377
378
#endif
#if SQLITE_FTS5_NO_WITHOUT_ROWID
  "FTS5_NO_WITHOUT_ROWID",
#endif
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
  "HAVE_ISNAN",
#endif

#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX
  "HOMEGROWN_RECURSIVE_MUTEX",

#endif
#if SQLITE_IGNORE_AFP_LOCK_ERRORS
  "IGNORE_AFP_LOCK_ERRORS",
#endif
#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
  "IGNORE_FLOCK_LOCK_ERRORS",
#endif







>
|
|
>







370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
#endif
#if SQLITE_FTS5_NO_WITHOUT_ROWID
  "FTS5_NO_WITHOUT_ROWID",
#endif
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
  "HAVE_ISNAN",
#endif
#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
# if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1
  "HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX),
# endif
#endif
#if SQLITE_IGNORE_AFP_LOCK_ERRORS
  "IGNORE_AFP_LOCK_ERRORS",
#endif
#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
  "IGNORE_FLOCK_LOCK_ERRORS",
#endif
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
#endif
#if SQLITE_MMAP_READWRITE
  "MMAP_READWRITE",
#endif
#if SQLITE_MUTEX_NOOP
  "MUTEX_NOOP",
#endif
#if SQLITE_MUTEX_NREF
  "MUTEX_NREF",
#endif
#if SQLITE_MUTEX_OMIT
  "MUTEX_OMIT",
#endif
#if SQLITE_MUTEX_PTHREADS
  "MUTEX_PTHREADS",
#endif
#if SQLITE_MUTEX_W32







<
<
<







471
472
473
474
475
476
477



478
479
480
481
482
483
484
#endif
#if SQLITE_MMAP_READWRITE
  "MMAP_READWRITE",
#endif
#if SQLITE_MUTEX_NOOP
  "MUTEX_NOOP",
#endif



#if SQLITE_MUTEX_OMIT
  "MUTEX_OMIT",
#endif
#if SQLITE_MUTEX_PTHREADS
  "MUTEX_PTHREADS",
#endif
#if SQLITE_MUTEX_W32
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548



549
550
551
552
553
554
555
#endif
#if SQLITE_OMIT_CONFLICT_CLAUSE
  "OMIT_CONFLICT_CLAUSE",
#endif
#if SQLITE_OMIT_CTE
  "OMIT_CTE",
#endif
#if SQLITE_OMIT_DATETIME_FUNCS
  "OMIT_DATETIME_FUNCS",
#endif
#if SQLITE_OMIT_DECLTYPE
  "OMIT_DECLTYPE",
#endif
#if SQLITE_OMIT_DEPRECATED
  "OMIT_DEPRECATED",



#endif
#if SQLITE_OMIT_DISKIO
  "OMIT_DISKIO",
#endif
#if SQLITE_OMIT_EXPLAIN
  "OMIT_EXPLAIN",
#endif







|







>
>
>







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
#endif
#if SQLITE_OMIT_CONFLICT_CLAUSE
  "OMIT_CONFLICT_CLAUSE",
#endif
#if SQLITE_OMIT_CTE
  "OMIT_CTE",
#endif
#if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT)
  "OMIT_DATETIME_FUNCS",
#endif
#if SQLITE_OMIT_DECLTYPE
  "OMIT_DECLTYPE",
#endif
#if SQLITE_OMIT_DEPRECATED
  "OMIT_DEPRECATED",
#endif
#if SQLITE_OMIT_DESERIALIZE
  "OMIT_DESERIALIZE",
#endif
#if SQLITE_OMIT_DISKIO
  "OMIT_DISKIO",
#endif
#if SQLITE_OMIT_EXPLAIN
  "OMIT_EXPLAIN",
#endif
569
570
571
572
573
574
575



576
577
578
579
580
581
582
  "OMIT_HEX_INTEGER",
#endif
#if SQLITE_OMIT_INCRBLOB
  "OMIT_INCRBLOB",
#endif
#if SQLITE_OMIT_INTEGRITY_CHECK
  "OMIT_INTEGRITY_CHECK",



#endif
#if SQLITE_OMIT_LIKE_OPTIMIZATION
  "OMIT_LIKE_OPTIMIZATION",
#endif
#if SQLITE_OMIT_LOAD_EXTENSION
  "OMIT_LOAD_EXTENSION",
#endif







>
>
>







578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
  "OMIT_HEX_INTEGER",
#endif
#if SQLITE_OMIT_INCRBLOB
  "OMIT_INCRBLOB",
#endif
#if SQLITE_OMIT_INTEGRITY_CHECK
  "OMIT_INTEGRITY_CHECK",
#endif
#if SQLITE_OMIT_INTROSPECTION_PRAGMAS
  "OMIT_INTROSPECTION_PRAGMAS",
#endif
#if SQLITE_OMIT_LIKE_OPTIMIZATION
  "OMIT_LIKE_OPTIMIZATION",
#endif
#if SQLITE_OMIT_LOAD_EXTENSION
  "OMIT_LOAD_EXTENSION",
#endif
633
634
635
636
637
638
639

640
641

642
643
644
645
646
647
648
#endif
#if SQLITE_OMIT_TEMPDB
  "OMIT_TEMPDB",
#endif
#if SQLITE_OMIT_TEST_CONTROL
  "OMIT_TEST_CONTROL",
#endif

#if SQLITE_OMIT_TRACE
  "OMIT_TRACE",

#endif
#if SQLITE_OMIT_TRIGGER
  "OMIT_TRIGGER",
#endif
#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION
  "OMIT_TRUNCATE_OPTIMIZATION",
#endif







>
|
|
>







645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
#endif
#if SQLITE_OMIT_TEMPDB
  "OMIT_TEMPDB",
#endif
#if SQLITE_OMIT_TEST_CONTROL
  "OMIT_TEST_CONTROL",
#endif
#ifdef SQLITE_OMIT_TRACE
# if SQLITE_OMIT_TRACE != 1
  "OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE),
# endif
#endif
#if SQLITE_OMIT_TRIGGER
  "OMIT_TRIGGER",
#endif
#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION
  "OMIT_TRUNCATE_OPTIMIZATION",
#endif
669
670
671
672
673
674
675

676
677

678
679
680
681
682
683
684
#endif
#if SQLITE_PCACHE_SEPARATE_HEADER
  "PCACHE_SEPARATE_HEADER",
#endif
#if SQLITE_PERFORMANCE_TRACE
  "PERFORMANCE_TRACE",
#endif

#if SQLITE_POWERSAFE_OVERWRITE
  "POWERSAFE_OVERWRITE",

#endif
#if SQLITE_PREFER_PROXY_LOCKING
  "PREFER_PROXY_LOCKING",
#endif
#if SQLITE_PROXY_DEBUG
  "PROXY_DEBUG",
#endif







>
|
|
>







683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
#endif
#if SQLITE_PCACHE_SEPARATE_HEADER
  "PCACHE_SEPARATE_HEADER",
#endif
#if SQLITE_PERFORMANCE_TRACE
  "PERFORMANCE_TRACE",
#endif
#ifdef SQLITE_POWERSAFE_OVERWRITE
# if SQLITE_POWERSAFE_OVERWRITE != 1
  "POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE),
# endif
#endif
#if SQLITE_PREFER_PROXY_LOCKING
  "PREFER_PROXY_LOCKING",
#endif
#if SQLITE_PROXY_DEBUG
  "PROXY_DEBUG",
#endif
705
706
707
708
709
710
711



712
713
714
715
716
717
718
719
#endif
#ifdef SQLITE_STMTJRNL_SPILL
  "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
#endif
#if SQLITE_SUBSTR_COMPATIBILITY
  "SUBSTR_COMPATIBILITY",
#endif



#if SQLITE_SYSTEM_MALLOC
  "SYSTEM_MALLOC",
#endif
#if SQLITE_TCL
  "TCL",
#endif
#ifdef SQLITE_TEMP_STORE
  "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),







>
>
>
|







721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
#endif
#ifdef SQLITE_STMTJRNL_SPILL
  "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
#endif
#if SQLITE_SUBSTR_COMPATIBILITY
  "SUBSTR_COMPATIBILITY",
#endif
#if (!defined(SQLITE_WIN32_MALLOC) \
     && !defined(SQLITE_ZERO_MALLOC) \
     && !defined(SQLITE_MEMDEBUG) \
    ) || defined(SQLITE_SYSTEM_MALLOC)
  "SYSTEM_MALLOC",
#endif
#if SQLITE_TCL
  "TCL",
#endif
#ifdef SQLITE_TEMP_STORE
  "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
Changes to src/expr.c.
48
49
50
51
52
53
54




55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
    assert( pExpr->op==TK_COLLATE
         || pExpr->op==TK_IF_NULL_ROW
         || (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) );
    pExpr = pExpr->pLeft;
    assert( pExpr!=0 );
  }
  op = pExpr->op;




  if( op==TK_SELECT ){
    assert( pExpr->flags&EP_xIsSelect );
    assert( pExpr->x.pSelect!=0 );
    assert( pExpr->x.pSelect->pEList!=0 );
    assert( pExpr->x.pSelect->pEList->a[0].pExpr!=0 );
    return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
  }
  if( op==TK_REGISTER ) op = pExpr->op2;
#ifndef SQLITE_OMIT_CAST
  if( op==TK_CAST ){
    assert( !ExprHasProperty(pExpr, EP_IntValue) );
    return sqlite3AffinityType(pExpr->u.zToken, 0);
  }
#endif
  if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->y.pTab ){
    return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
  }
  if( op==TK_SELECT_COLUMN ){
    assert( pExpr->pLeft->flags&EP_xIsSelect );
    return sqlite3ExprAffinity(
        pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
    );
  }
  if( op==TK_VECTOR ){







>
>
>
>







<






<
<
<







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71



72
73
74
75
76
77
78
    assert( pExpr->op==TK_COLLATE
         || pExpr->op==TK_IF_NULL_ROW
         || (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) );
    pExpr = pExpr->pLeft;
    assert( pExpr!=0 );
  }
  op = pExpr->op;
  if( op==TK_REGISTER ) op = pExpr->op2;
  if( (op==TK_COLUMN || op==TK_AGG_COLUMN) && pExpr->y.pTab ){
    return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
  }
  if( op==TK_SELECT ){
    assert( pExpr->flags&EP_xIsSelect );
    assert( pExpr->x.pSelect!=0 );
    assert( pExpr->x.pSelect->pEList!=0 );
    assert( pExpr->x.pSelect->pEList->a[0].pExpr!=0 );
    return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
  }

#ifndef SQLITE_OMIT_CAST
  if( op==TK_CAST ){
    assert( !ExprHasProperty(pExpr, EP_IntValue) );
    return sqlite3AffinityType(pExpr->u.zToken, 0);
  }
#endif



  if( op==TK_SELECT_COLUMN ){
    assert( pExpr->pLeft->flags&EP_xIsSelect );
    return sqlite3ExprAffinity(
        pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
    );
  }
  if( op==TK_VECTOR ){
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
*/
Expr *sqlite3ExprAddCollateToken(
  Parse *pParse,           /* Parsing context */
  Expr *pExpr,             /* Add the "COLLATE" clause to this expression */
  const Token *pCollName,  /* Name of collating sequence */
  int dequote              /* True to dequote pCollName */
){
  assert( pExpr!=0 || pParse->db->mallocFailed );
  if( pExpr==0 ) return 0;
  if( pExpr->op==TK_VECTOR ){
    ExprList *pList = pExpr->x.pList;
    if( ALWAYS(pList!=0) ){
      int i;
      for(i=0; i<pList->nExpr; i++){
        pList->a[i].pExpr = sqlite3ExprAddCollateToken(pParse,pList->a[i].pExpr,
                                                       pCollName, dequote);
      }
    }
  }else if( pCollName->n>0 ){
    Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote);
    if( pNew ){
      pNew->pLeft = pExpr;
      pNew->flags |= EP_Collate|EP_Skip;
      pExpr = pNew;
    }
  }







<
<
<
<
<
<
<
<
<
<
<
|







91
92
93
94
95
96
97











98
99
100
101
102
103
104
105
*/
Expr *sqlite3ExprAddCollateToken(
  Parse *pParse,           /* Parsing context */
  Expr *pExpr,             /* Add the "COLLATE" clause to this expression */
  const Token *pCollName,  /* Name of collating sequence */
  int dequote              /* True to dequote pCollName */
){











  if( pCollName->n>0 ){
    Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote);
    if( pNew ){
      pNew->pLeft = pExpr;
      pNew->flags |= EP_Collate|EP_Skip;
      pExpr = pNew;
    }
  }
607
608
609
610
611
612
613

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

636
637
638
639

640
641
642
643
644

645
646

647
648
649
650
651
652
653
654
655










656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674

675



676
677
678
679
680
681
682
  Expr *pLeft = pExpr->pLeft;
  Expr *pRight = pExpr->pRight;
  int nLeft = sqlite3ExprVectorSize(pLeft);
  int i;
  int regLeft = 0;
  int regRight = 0;
  u8 opx = op;

  int addrDone = sqlite3VdbeMakeLabel(pParse);
  int isCommuted = ExprHasProperty(pExpr,EP_Commuted);

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

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


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


  for(i=0; 1 /*Loop exits by "break"*/; i++){
    int regFree1 = 0, regFree2 = 0;
    Expr *pL, *pR; 
    int r1, r2;
    assert( i>=0 && i<nLeft );

    r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, &regFree1);
    r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, &regFree2);

    codeCompare(pParse, pL, pR, opx, r1, r2, dest, 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( 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);
      p5 |= SQLITE_KEEPNULL;
    }else{
      assert( op==TK_LT || op==TK_GT || op==TK_LE || op==TK_GE );
      sqlite3VdbeAddOp2(v, OP_ElseNotEq, 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;
    }
  }

  sqlite3VdbeResolveLabel(v, addrDone);



}

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







>



















<
|
|
>




>





>


>
|








>
>
>
>
>
>
>
>
>
>




<
<
<
|
<


|
<
<
<
<



>

>
>
>







596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622

623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662



663

664
665
666




667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
  Expr *pLeft = pExpr->pLeft;
  Expr *pRight = pExpr->pRight;
  int nLeft = sqlite3ExprVectorSize(pLeft);
  int i;
  int regLeft = 0;
  int regRight = 0;
  u8 opx = op;
  int addrCmp = 0;
  int addrDone = sqlite3VdbeMakeLabel(pParse);
  int isCommuted = ExprHasProperty(pExpr,EP_Commuted);

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


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

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

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



      sqlite3VdbeAddOp2(v, OP_NotNull, dest, addrDone); VdbeCoverage(v);

    }else{
      assert( op==TK_LT || op==TK_GT || op==TK_LE || op==TK_GE );
      sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone);




      if( i==nLeft-2 ) opx = op;
    }
  }
  sqlite3VdbeJumpHere(v, addrCmp);
  sqlite3VdbeResolveLabel(v, addrDone);
  if( op==TK_NE ){
    sqlite3VdbeAddOp2(v, OP_Not, dest, dest);
  }
}

#if SQLITE_MAX_EXPR_DEPTH>0
/*
** Check that argument nHeight is less than or equal to the maximum
** expression depth allowed. If it is not, leave an error message in
** pParse.
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
  if( pLeft==0  ){
    return pRight;
  }else if( pRight==0 ){
    return pLeft;
  }else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight)) 
         && !IN_RENAME_OBJECT
  ){
    sqlite3ExprDelete(db, pLeft);
    sqlite3ExprDelete(db, pRight);
    return sqlite3Expr(db, TK_INTEGER, "0");
  }else{
    return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
  }
}

/*







|
|







953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
  if( pLeft==0  ){
    return pRight;
  }else if( pRight==0 ){
    return pLeft;
  }else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight)) 
         && !IN_RENAME_OBJECT
  ){
    sqlite3ExprDeferredDelete(pParse, pLeft);
    sqlite3ExprDeferredDelete(pParse, pRight);
    return sqlite3Expr(db, TK_INTEGER, "0");
  }else{
    return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
  }
}

/*
1152
1153
1154
1155
1156
1157
1158
















1159
1160
1161
1162
1163
1164
1165
    sqlite3DbFreeNN(db, p);
  }
}
void sqlite3ExprDelete(sqlite3 *db, Expr *p){
  if( p ) sqlite3ExprDeleteNN(db, p);
}

















/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
** expression.
*/
void sqlite3ExprUnmapAndDelete(Parse *pParse, Expr *p){
  if( p ){
    if( IN_RENAME_OBJECT ){
      sqlite3RenameExprUnmap(pParse, p);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
    sqlite3DbFreeNN(db, p);
  }
}
void sqlite3ExprDelete(sqlite3 *db, Expr *p){
  if( p ) sqlite3ExprDeleteNN(db, p);
}


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

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

1301
1302
1303
1304
1305
1306
1307
  assert( dupFlags==0 || dupFlags==EXPRDUP_REDUCE );
  assert( pzBuffer==0 || dupFlags==EXPRDUP_REDUCE );

  /* Figure out where to write the new Expr structure. */
  if( pzBuffer ){
    zAlloc = *pzBuffer;
    staticFlag = EP_Static;

  }else{
    zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags));
    staticFlag = 0;
  }
  pNew = (Expr *)zAlloc;

  if( pNew ){







>







1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
  assert( dupFlags==0 || dupFlags==EXPRDUP_REDUCE );
  assert( pzBuffer==0 || dupFlags==EXPRDUP_REDUCE );

  /* Figure out where to write the new Expr structure. */
  if( pzBuffer ){
    zAlloc = *pzBuffer;
    staticFlag = EP_Static;
    assert( zAlloc!=0 );
  }else{
    zAlloc = sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags));
    staticFlag = 0;
  }
  pNew = (Expr *)zAlloc;

  if( pNew ){
1372
1373
1374
1375
1376
1377
1378
1379

1380
1381
1382
1383
1384
1385
1386
        *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 );

        }else{
          pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
        }
        pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
      }
    }
  }







|
>







1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
        *pzBuffer = zAlloc;
      }
    }else{
      if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
        if( pNew->op==TK_SELECT_COLUMN ){
          pNew->pLeft = p->pLeft;
          assert( p->iColumn==0 || p->pRight==0 );
          assert( p->pRight==0  || p->pRight==p->pLeft
                                || ExprHasProperty(p->pLeft, EP_Subquery) );
        }else{
          pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
        }
        pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
      }
    }
  }
1474
1475
1476
1477
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493

1494
1495
1496
1497
1498
1499
1500
  int i;
  Expr *pPriorSelectCol = 0;
  assert( db!=0 );
  if( p==0 ) return 0;
  pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
  if( pNew==0 ) return 0;
  pNew->nExpr = p->nExpr;

  pItem = pNew->a;
  pOldItem = p->a;
  for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
    Expr *pOldExpr = pOldItem->pExpr;
    Expr *pNewExpr;
    pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
    if( pOldExpr 
     && pOldExpr->op==TK_SELECT_COLUMN
     && (pNewExpr = pItem->pExpr)!=0 
    ){
      assert( pNewExpr->iColumn==0 || i>0 );
      if( pNewExpr->iColumn==0 ){
        assert( pOldExpr->pLeft==pOldExpr->pRight );

        pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
      }else{
        assert( i>0 );
        assert( pItem[-1].pExpr!=0 );
        assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 );
        assert( pPriorSelectCol==pItem[-1].pExpr->pLeft );
        pNewExpr->pLeft = pPriorSelectCol;







>












|
>







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
  int i;
  Expr *pPriorSelectCol = 0;
  assert( db!=0 );
  if( p==0 ) return 0;
  pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
  if( pNew==0 ) return 0;
  pNew->nExpr = p->nExpr;
  pNew->nAlloc = p->nAlloc;
  pItem = pNew->a;
  pOldItem = p->a;
  for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
    Expr *pOldExpr = pOldItem->pExpr;
    Expr *pNewExpr;
    pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
    if( pOldExpr 
     && pOldExpr->op==TK_SELECT_COLUMN
     && (pNewExpr = pItem->pExpr)!=0 
    ){
      assert( pNewExpr->iColumn==0 || i>0 );
      if( pNewExpr->iColumn==0 ){
        assert( pOldExpr->pLeft==pOldExpr->pRight
             || ExprHasProperty(pOldExpr->pLeft, EP_Subquery) );
        pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
      }else{
        assert( i>0 );
        assert( pItem[-1].pExpr!=0 );
        assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 );
        assert( pPriorSelectCol==pItem[-1].pExpr->pLeft );
        pNewExpr->pLeft = pPriorSelectCol;
1616
1617
1618
1619
1620
1621
1622








1623
1624
1625
1626
1627
1628
1629
    pNew->pWith = withDup(db, p->pWith);
#ifndef SQLITE_OMIT_WINDOWFUNC
    pNew->pWin = 0;
    pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
    if( p->pWin && db->mallocFailed==0 ) gatherSelectWindows(pNew);
#endif
    pNew->selId = p->selId;








    *pp = pNew;
    pp = &pNew->pPrior;
    pNext = pNew;
  }

  return pRet;
}







>
>
>
>
>
>
>
>







1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
    pNew->pWith = withDup(db, p->pWith);
#ifndef SQLITE_OMIT_WINDOWFUNC
    pNew->pWin = 0;
    pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
    if( p->pWin && db->mallocFailed==0 ) gatherSelectWindows(pNew);
#endif
    pNew->selId = p->selId;
    if( db->mallocFailed ){
      /* Any prior OOM might have left the Select object incomplete.
      ** Delete the whole thing rather than allow an incomplete Select
      ** to be used by the code generator. */
      pNew->pNext = 0;
      sqlite3SelectDelete(db, pNew);
      break;
    }
    *pp = pNew;
    pp = &pNew->pPrior;
    pNext = pNew;
  }

  return pRet;
}
1646
1647
1648
1649
1650
1651
1652

1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663

1664
1665

1666
1667










1668

1669
1670
1671



1672

1673



1674












1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
** 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.
*/

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;
  sqlite3 *db = pParse->db;
  assert( db!=0 );
  if( pList==0 ){
    pList = sqlite3DbMallocRawNN(db, sizeof(ExprList) );
    if( pList==0 ){

      goto no_mem;
    }

    pList->nExpr = 0;
  }else if( (pList->nExpr & (pList->nExpr-1))==0 ){










    ExprList *pNew;

    pNew = sqlite3DbRealloc(db, pList, 
         sizeof(*pList)+(2*(sqlite3_int64)pList->nExpr-1)*sizeof(pList->a[0]));
    if( pNew==0 ){



      goto no_mem;

    }



    pList = pNew;












  }
  pItem = &pList->a[pList->nExpr++];
  assert( offsetof(struct ExprList_item,zEName)==sizeof(pItem->pExpr) );
  assert( offsetof(struct ExprList_item,pExpr)==0 );
  memset(&pItem->zEName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zEName));
  pItem->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)







>
|
|
<



|
|
<
|
|
>
|
|
>
|
|
>
>
>
>
>
>
>
>
>
>
|
>
|
|
|
>
>
>
|
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>


<
<
|


<
<
<
<
<
<







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
** is a power of two.  That is true for sqlite3ExprListAppend() returns
** but is not necessarily true from the return value of sqlite3ExprListDup().
**
** If a memory allocation error occurs, the entire list is freed and
** NULL is returned.  If non-NULL is returned, then it is guaranteed
** that the new entry was successfully appended.
*/
static const struct ExprList_item zeroItem = {0};
SQLITE_NOINLINE ExprList *sqlite3ExprListAppendNew(
  sqlite3 *db,            /* Database handle.  Used for memory allocation */

  Expr *pExpr             /* Expression to be appended. Might be NULL */
){
  struct ExprList_item *pItem;
  ExprList *pList;


  pList = sqlite3DbMallocRawNN(db, sizeof(ExprList)+sizeof(pList->a[0])*4 );
  if( pList==0 ){
    sqlite3ExprDelete(db, pExpr);
    return 0;
  }
  pList->nAlloc = 4;
  pList->nExpr = 1;
  pItem = &pList->a[0];
  *pItem = zeroItem;
  pItem->pExpr = pExpr;
  return pList;
}
SQLITE_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++];


  *pItem = zeroItem;
  pItem->pExpr = pExpr;
  return pList;






}

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

2300
2301

2302
2303
2304
2305
2306
2307
2308
** 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;

  while( p->op==TK_UPLUS || p->op==TK_UMINUS ){
    p = p->pLeft;

  }
  op = p->op;
  if( op==TK_REGISTER ) op = p->op2;
  switch( op ){
    case TK_INTEGER:
    case TK_STRING:
    case TK_FLOAT:







>


>







2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
** be a small performance hit but is otherwise harmless.  On the other
** hand, a false negative (returning FALSE when the result could be NULL)
** will likely result in an incorrect answer.  So when in doubt, return
** TRUE.
*/
int sqlite3ExprCanBeNull(const Expr *p){
  u8 op;
  assert( p!=0 );
  while( p->op==TK_UPLUS || p->op==TK_UMINUS ){
    p = p->pLeft;
    assert( p!=0 );
  }
  op = p->op;
  if( op==TK_REGISTER ) op = p->op2;
  switch( op ){
    case TK_INTEGER:
    case TK_STRING:
    case TK_FLOAT:
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
** 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( 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;







|







3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
** 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)!=0 && !pParse->db->mallocFailed ){
    if( nVector!=pIn->x.pSelect->pEList->nExpr ){
      sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector);
      return 1;
    }
  }else if( nVector!=1 ){
    sqlite3VectorErrorMsg(pParse, pIn->pLeft);
    return 1;
3335
3336
3337
3338
3339
3340
3341

3342
3343
3344
3345
3346
3347
3348
    destStep2 = destIfFalse;
  }else{
    destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse);
  }
  if( pParse->nErr ) goto sqlite3ExprCodeIN_finished;
  for(i=0; i<nVector; i++){
    Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);

    if( sqlite3ExprCanBeNull(p) ){
      sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
      VdbeCoverage(v);
    }
  }

  /* Step 3.  The LHS is now known to be non-NULL.  Do the binary search







>







3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
    destStep2 = destIfFalse;
  }else{
    destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse);
  }
  if( pParse->nErr ) goto sqlite3ExprCodeIN_finished;
  for(i=0; i<nVector; i++){
    Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
    if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
    if( sqlite3ExprCanBeNull(p) ){
      sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
      VdbeCoverage(v);
    }
  }

  /* Step 3.  The LHS is now known to be non-NULL.  Do the binary search
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
      return target;
    }
    default: {
      /* Make NULL the default case so that if a bug causes an illegal
      ** Expr node to be passed into this function, it will be handled
      ** sanely and not crash.  But keep the assert() to bring the problem
      ** to the attention of the developers. */
      assert( op==TK_NULL );
      sqlite3VdbeAddOp2(v, OP_Null, 0, target);
      return target;
    }
#ifndef SQLITE_OMIT_BLOB_LITERAL
    case TK_BLOB: {
      int n;
      const char *z;







|







4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
      return target;
    }
    default: {
      /* Make NULL the default case so that if a bug causes an illegal
      ** Expr node to be passed into this function, it will be handled
      ** sanely and not crash.  But keep the assert() to bring the problem
      ** to the attention of the developers. */
      assert( op==TK_NULL || pParse->db->mallocFailed );
      sqlite3VdbeAddOp2(v, OP_Null, 0, target);
      return target;
    }
#ifndef SQLITE_OMIT_BLOB_LITERAL
    case TK_BLOB: {
      int n;
      const char *z;
4026
4027
4028
4029
4030
4031
4032

4033
4034

4035
4036
4037
4038
4039
4040
4041





4042
4043
4044
4045
4046
4047
4048
    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);

        codeCompare(pParse, pLeft, pExpr->pRight, op,
            r1, r2, inReg, SQLITE_STOREP2 | 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);





        testcase( regFree1==0 );
        testcase( regFree2==0 );
      }
      break;
    }
    case TK_AND:
    case TK_OR:







>
|
<
>







>
>
>
>
>







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
    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, r1, r2,

            sqlite3VdbeCurrentAddr(v)+2, p5,
            ExprHasProperty(pExpr,EP_Commuted));
        assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
        assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
        assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
        assert(TK_GE==OP_Ge); testcase(op==OP_Ge); VdbeCoverageIf(v,op==OP_Ge);
        assert(TK_EQ==OP_Eq); testcase(op==OP_Eq); VdbeCoverageIf(v,op==OP_Eq);
        assert(TK_NE==OP_Ne); testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
        if( p5==SQLITE_NULLEQ ){
          sqlite3VdbeAddOp2(v, OP_Integer, 0, inReg);
        }else{
          sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, inReg, r2);
        }
        testcase( regFree1==0 );
        testcase( regFree2==0 );
      }
      break;
    }
    case TK_AND:
    case TK_OR:
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
    assert( pExpr->op==TK_AGG_COLUMN || pExpr->op==TK_AGG_FUNCTION );
    if( pExpr->op==TK_AGG_COLUMN ){
      assert( iAgg>=0 && iAgg<pAggInfo->nColumn );
      if( pAggInfo->aCol[iAgg].pCExpr==pExpr ){
        pExpr = sqlite3ExprDup(db, pExpr, 0);
        if( pExpr ){
          pAggInfo->aCol[iAgg].pCExpr = pExpr;
          pParse->pConstExpr = 
             sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
        }
      }
    }else{
      assert( iAgg>=0 && iAgg<pAggInfo->nFunc );
      if( pAggInfo->aFunc[iAgg].pFExpr==pExpr ){
        pExpr = sqlite3ExprDup(db, pExpr, 0);
        if( pExpr ){
          pAggInfo->aFunc[iAgg].pFExpr = pExpr;
          pParse->pConstExpr = 
             sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
        }
      }
    }
  }
  return WRC_Continue;
}








<
|








<
|







5836
5837
5838
5839
5840
5841
5842

5843
5844
5845
5846
5847
5848
5849
5850
5851

5852
5853
5854
5855
5856
5857
5858
5859
    assert( pExpr->op==TK_AGG_COLUMN || pExpr->op==TK_AGG_FUNCTION );
    if( pExpr->op==TK_AGG_COLUMN ){
      assert( iAgg>=0 && iAgg<pAggInfo->nColumn );
      if( pAggInfo->aCol[iAgg].pCExpr==pExpr ){
        pExpr = sqlite3ExprDup(db, pExpr, 0);
        if( pExpr ){
          pAggInfo->aCol[iAgg].pCExpr = pExpr;

          sqlite3ExprDeferredDelete(pParse, pExpr);
        }
      }
    }else{
      assert( iAgg>=0 && iAgg<pAggInfo->nFunc );
      if( pAggInfo->aFunc[iAgg].pFExpr==pExpr ){
        pExpr = sqlite3ExprDup(db, pExpr, 0);
        if( pExpr ){
          pAggInfo->aFunc[iAgg].pFExpr = pExpr;

          sqlite3ExprDeferredDelete(pParse, pExpr);
        }
      }
    }
  }
  return WRC_Continue;
}

Changes to src/func.c.
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
  v1 = sqlite3_value_double(argv[1]);
  x = (double(*)(double,double))sqlite3_user_data(context);
  ans = x(v0, v1);
  sqlite3_result_double(context, ans);
}

/*
** Implementation of 2-argument SQL math functions:
**
**   power(X,Y)  - Compute X to the Y-th power
*/
static void piFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  assert( argc==0 );







|
<
<







2067
2068
2069
2070
2071
2072
2073
2074


2075
2076
2077
2078
2079
2080
2081
  v1 = sqlite3_value_double(argv[1]);
  x = (double(*)(double,double))sqlite3_user_data(context);
  ans = x(v0, v1);
  sqlite3_result_double(context, ans);
}

/*
** Implementation of 0-argument pi() function.


*/
static void piFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  assert( argc==0 );
Changes to src/global.c.
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

























60



61
62
63
64
65
66
67
    126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
    144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
    162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
    180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
    198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
    216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
    234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
    252,253,254,255
#endif
#ifdef SQLITE_EBCDIC
      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, /* 0x */
     16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */
     32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 2x */
     48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */
     64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */
     80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */
     96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 6x */
    112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 7x */
    128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */
    144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, /* 9x */
    160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */
    176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */
    192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */
    208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */
    224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */
    240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */
#endif

























};




/*
** The following 256 byte lookup table is used to support SQLites built-in
** equivalents to the following standard library functions:
**
**   isspace()                        0x01
**   isalpha()                        0x02







|



















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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,
#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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
   0,                         /* xSqllog */
   0,                         /* pSqllogArg */
#endif
#ifdef SQLITE_VDBE_COVERAGE
   0,                         /* xVdbeBranch */
   0,                         /* pVbeBranchArg */
#endif
#ifdef SQLITE_ENABLE_DESERIALIZE
   SQLITE_MEMDB_DEFAULT_MAXSIZE,   /* mxMemdbSize */
#endif
#ifndef SQLITE_UNTESTABLE
   0,                         /* xTestCallback */
#endif
   0,                         /* bLocaltimeFault */
   0x7ffffffe,                /* iOnceResetThreshold */







|







275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
   0,                         /* xSqllog */
   0,                         /* pSqllogArg */
#endif
#ifdef SQLITE_VDBE_COVERAGE
   0,                         /* xVdbeBranch */
   0,                         /* pVbeBranchArg */
#endif
#ifndef SQLITE_OMIT_DESERIALIZE
   SQLITE_MEMDB_DEFAULT_MAXSIZE,   /* mxMemdbSize */
#endif
#ifndef SQLITE_UNTESTABLE
   0,                         /* xTestCallback */
#endif
   0,                         /* bLocaltimeFault */
   0x7ffffffe,                /* iOnceResetThreshold */
Changes to src/insert.c.
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
    Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab;

    /* Verify that the sqlite_sequence table exists and is an ordinary
    ** rowid table with exactly two columns.
    ** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */
    if( pSeqTab==0
     || !HasRowid(pSeqTab)
     || IsVirtual(pSeqTab)
     || pSeqTab->nCol!=2
    ){
      pParse->nErr++;
      pParse->rc = SQLITE_CORRUPT_SEQUENCE;
      return 0;
    }








|







354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
    Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab;

    /* Verify that the sqlite_sequence table exists and is an ordinary
    ** rowid table with exactly two columns.
    ** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */
    if( pSeqTab==0
     || !HasRowid(pSeqTab)
     || NEVER(IsVirtual(pSeqTab))
     || pSeqTab->nCol!=2
    ){
      pParse->nErr++;
      pParse->rc = SQLITE_CORRUPT_SEQUENCE;
      return 0;
    }

813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
      }
      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);
          pParse->checkSchema = 1;
          goto insert_cleanup;
        }
      }
    }
  }








|







813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
      }
      if( j>=pTab->nCol ){
        if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){
          ipkColumn = i;
          bIdListInOrder = 0;
        }else{
          sqlite3ErrorMsg(pParse, "table %S has no column named %s",
              pTabList->a, pColumn->a[i].zName);
          pParse->checkSchema = 1;
          goto insert_cleanup;
        }
      }
    }
  }

941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
      for(i=0; i<pTab->nCol; i++){
        if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
      }
    }
    if( nColumn!=(pTab->nCol-nHidden) ){
      sqlite3ErrorMsg(pParse, 
         "table %S has %d columns but %d values were supplied",
         pTabList, 0, pTab->nCol-nHidden, nColumn);
     goto insert_cleanup;
    }
  }
  if( pColumn!=0 && nColumn!=pColumn->nId ){
    sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
    goto insert_cleanup;
  }







|







941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
      for(i=0; i<pTab->nCol; i++){
        if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
      }
    }
    if( nColumn!=(pTab->nCol-nHidden) ){
      sqlite3ErrorMsg(pParse, 
         "table %S has %d columns but %d values were supplied",
         pTabList->a, pTab->nCol-nHidden, nColumn);
     goto insert_cleanup;
    }
  }
  if( pColumn!=0 && nColumn!=pColumn->nId ){
    sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
    goto insert_cleanup;
  }
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270







1271
1272
1273
1274
1275
1276
1277
      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 bUseSeek;     /* True to use OPFLAG_SEEKRESULT */
      sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
          regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert
      );
      sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);

      /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE
      ** constraints or (b) there are no triggers and this table is not a
      ** parent table in a foreign key constraint. It is safe to set the
      ** flag in the second case as if any REPLACE constraint is hit, an
      ** OP_Delete or OP_IdxDelete instruction will be executed on each 
      ** cursor that is disturbed. And these instructions both clear the
      ** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT
      ** functionality.  */
      bUseSeek = (isReplace==0 || !sqlite3VdbeHasSubProgram(v));
      sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
          regIns, aRegIdx, 0, appendFlag, bUseSeek
      );
    }







  }

  /* Update the count of rows that are inserted
  */
  if( regRowCount ){
    sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
  }







|



















>
>
>
>
>
>
>







1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
      sqlite3VtabMakeWritable(pParse, pTab);
      sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
      sqlite3VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
      sqlite3MayAbort(pParse);
    }else
#endif
    {
      int isReplace = 0;/* Set to true if constraints may cause a replace */
      int bUseSeek;     /* True to use OPFLAG_SEEKRESULT */
      sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
          regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert
      );
      sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);

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

  /* Update the count of rows that are inserted
  */
  if( regRowCount ){
    sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
  }
Changes to src/main.c.
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
    if( sqlite3GlobalConfig.isPCacheInit==0 ){
      rc = sqlite3PcacheInitialize();
    }
    if( rc==SQLITE_OK ){
      sqlite3GlobalConfig.isPCacheInit = 1;
      rc = sqlite3OsInit();
    }
#ifdef SQLITE_ENABLE_DESERIALIZE
    if( rc==SQLITE_OK ){
      rc = sqlite3MemdbInit();
    }
#endif
    if( rc==SQLITE_OK ){
      sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, 
          sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);







|







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
    if( sqlite3GlobalConfig.isPCacheInit==0 ){
      rc = sqlite3PcacheInitialize();
    }
    if( rc==SQLITE_OK ){
      sqlite3GlobalConfig.isPCacheInit = 1;
      rc = sqlite3OsInit();
    }
#ifndef SQLITE_OMIT_DESERIALIZE
    if( rc==SQLITE_OK ){
      rc = sqlite3MemdbInit();
    }
#endif
    if( rc==SQLITE_OK ){
      sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, 
          sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
        iVal = SQLITE_DEFAULT_SORTERREF_SIZE;
      }
      sqlite3GlobalConfig.szSorterRef = (u32)iVal;
      break;
    }
#endif /* SQLITE_ENABLE_SORTER_REFERENCES */

#ifdef SQLITE_ENABLE_DESERIALIZE
    case SQLITE_CONFIG_MEMDB_MAXSIZE: {
      sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlite3_int64);
      break;
    }
#endif /* SQLITE_ENABLE_DESERIALIZE */

    default: {
      rc = SQLITE_ERROR;
      break;
    }
  }
  va_end(ap);







|




|







716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
        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);
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
  sqlite3_mutex_leave(db->mutex);
  return iTxn;
}

/*
** Two variations on the public interface for closing a database
** connection. The sqlite3_close() version returns SQLITE_BUSY and
** leaves the connection option if there are unfinalized prepared
** 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); }







|







1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
  sqlite3_mutex_leave(db->mutex);
  return iTxn;
}

/*
** Two variations on the public interface for closing a database
** connection. The sqlite3_close() version returns SQLITE_BUSY and
** leaves the connection 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); }
1892
1893
1894
1895
1896
1897
1898




1899
1900
1901
1902
1903
1904
1905
      sqlite3ErrorWithMsg(db, SQLITE_BUSY, 
        "unable to delete/modify user-function due to active statements");
      assert( !db->mallocFailed );
      return SQLITE_BUSY;
    }else{
      sqlite3ExpirePreparedStatements(db, 0);
    }




  }

  p = sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1);
  assert(p || db->mallocFailed);
  if( !p ){
    return SQLITE_NOMEM_BKPT;
  }







>
>
>
>







1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
      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;
  }
Changes to src/malloc.c.
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
** 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);







<







157
158
159
160
161
162
163

164
165
166
167
168
169
170
** Initialize the memory allocation subsystem.
*/
int sqlite3MallocInit(void){
  int rc;
  if( sqlite3GlobalConfig.m.xMalloc==0 ){
    sqlite3MemSetDefault();
  }

  mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
  if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
      || sqlite3GlobalConfig.nPage<=0 ){
    sqlite3GlobalConfig.pPage = 0;
    sqlite3GlobalConfig.szPage = 0;
  }
  rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
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
** 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

/*
** Forward declaration of objects used by this utility
*/
typedef struct sqlite3_vfs MemVfs;
typedef struct MemFile MemFile;


/* Access to a lower-level VFS that (might) implement dynamic loading,
** access to randomness, etc.
*/
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))







/* An open file */





























struct MemFile {
  sqlite3_file base;              /* IO methods */
  sqlite3_int64 sz;               /* Size of the file */
  sqlite3_int64 szAlloc;          /* Space allocated to aData */
  sqlite3_int64 szMax;            /* Maximum allowed size of the file */
  unsigned char *aData;           /* content of the file */

  int nMmap;                      /* Number of memory mapped pages */
  unsigned mFlags;                /* Flags */










  int eLock;                      /* Most recent lock against this file */
};












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







|






>






>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<




>


>
>
>
>
>
>
>
>
>
>



>
>
>
>
>
>
>
>
>
>
>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
** This file implements an in-memory VFS. A database is held as a contiguous
** block of memory.
**
** This file also implements interface sqlite3_serialize() and
** sqlite3_deserialize().
*/
#include "sqliteInt.h"
#ifndef SQLITE_OMIT_DESERIALIZE

/*
** Forward declaration of objects used by this utility
*/
typedef struct sqlite3_vfs MemVfs;
typedef struct MemFile MemFile;
typedef struct MemStore MemStore;

/* Access to a lower-level VFS that (might) implement dynamic loading,
** access to randomness, etc.
*/
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))

/* Storage for a memdb file.
**
** An memdb object can be shared or separate.  Shared memdb objects can be
** used by more than one database connection.  Mutexes are used by shared
** memdb objects to coordinate access.  Separate memdb objects are only
** connected to a single database connection and do not require additional
** mutexes.
**
** Shared memdb objects have .zFName!=0 and .pMutex!=0.  They are created
** using "file:/name?vfs=memdb".  The first character of the name must be
** "/" or else the object will be a separate memdb object.  All shared
** memdb objects are stored in memdb_g.apMemStore[] in an arbitrary order.
**
** Separate memdb objects are created using a name that does not begin
** with "/" or using sqlite3_deserialize().
**
** Access rules for shared MemStore objects:
**
**   *  .zFName is initialized when the object is created and afterwards
**      is unchanged until the object is destroyed.  So it can be accessed
**      at any time as long as we know the object is not being destroyed,
**      which means while either the SQLITE_MUTEX_STATIC_VFS1 or
**      .pMutex is held or the object is not part of memdb_g.apMemStore[].
**
**   *  Can .pMutex can only be changed while holding the 
**      SQLITE_MUTEX_STATIC_VFS1 mutex or while the object is not part
**      of memdb_g.apMemStore[].
**
**   *  Other fields can only be changed while holding the .pMutex mutex
**      or when the .nRef is less than zero and the object is not part of
**      memdb_g.apMemStore[].
**
**   *  The .aData pointer has the added requirement that it can can only
**      be changed (for resizing) when nMmap is zero.
**      
*/
struct MemStore {

  sqlite3_int64 sz;               /* Size of the file */
  sqlite3_int64 szAlloc;          /* Space allocated to aData */
  sqlite3_int64 szMax;            /* Maximum allowed size of the file */
  unsigned char *aData;           /* content of the file */
  sqlite3_mutex *pMutex;          /* Used by shared stores only */
  int nMmap;                      /* Number of memory mapped pages */
  unsigned mFlags;                /* Flags */
  int nRdLock;                    /* Number of readers */
  int nWrLock;                    /* Number of writers.  (Always 0 or 1) */
  int nRef;                       /* Number of users of this MemStore */
  char *zFName;                   /* The filename for shared stores */
};

/* An open file */
struct MemFile {
  sqlite3_file base;              /* IO methods */
  MemStore *pStore;               /* The storage */
  int eLock;                      /* Most recent lock against this file */
};

/*
** File-scope variables for holding the memdb files that are accessible
** to multiple database connections in separate threads.
**
** Must hold SQLITE_MUTEX_STATIC_VFS1 to access any part of this object.
*/
static struct MemFS {
  int nMemStore;                  /* Number of shared MemStore objects */
  MemStore **apMemStore;          /* Array of all shared MemStore objects */
} memdb_g;

/*
** Methods for MemFile
*/
static int memdbClose(sqlite3_file*);
static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
91
92
93
94
95
96
97
98



99
100
101
102
103
104
105
  memdbDlError,                /* xDlError */
  memdbDlSym,                  /* xDlSym */
  memdbDlClose,                /* xDlClose */
  memdbRandomness,             /* xRandomness */
  memdbSleep,                  /* xSleep */
  0, /* memdbCurrentTime, */   /* xCurrentTime */
  memdbGetLastError,           /* xGetLastError */
  memdbCurrentTimeInt64        /* xCurrentTimeInt64 */



};

static const sqlite3_io_methods memdb_io_methods = {
  3,                              /* iVersion */
  memdbClose,                      /* xClose */
  memdbRead,                       /* xRead */
  memdbWrite,                      /* xWrite */







|
>
>
>







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  memdbDlError,                /* xDlError */
  memdbDlSym,                  /* xDlSym */
  memdbDlClose,                /* xDlClose */
  memdbRandomness,             /* xRandomness */
  memdbSleep,                  /* xSleep */
  0, /* memdbCurrentTime, */   /* xCurrentTime */
  memdbGetLastError,           /* xGetLastError */
  memdbCurrentTimeInt64,       /* xCurrentTimeInt64 */
  0,                           /* xSetSystemCall */
  0,                           /* xGetSystemCall */
  0,                           /* xNextSystemCall */
};

static const sqlite3_io_methods memdb_io_methods = {
  3,                              /* iVersion */
  memdbClose,                      /* xClose */
  memdbRead,                       /* xRead */
  memdbWrite,                      /* xWrite */
116
117
118
119
120
121
122



















123
124
125
126

127
128
129
130
131
132
133

























134
135






136
137
138
139
140
141
142
143
144
145
146
147
148
149

150
151
152

153
154
155

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

189





190
191
192
193
194

195
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
  0,                               /* xShmLock */
  0,                               /* xShmBarrier */
  0,                               /* xShmUnmap */
  memdbFetch,                      /* xFetch */
  memdbUnfetch                     /* xUnfetch */
};






















/*
** Close an memdb-file.

**
** The pData pointer is owned by the application, so there is nothing
** to free.  Unless the SQLITE_DESERIALIZE_FREEONCLOSE flag is set,
** in which case we own the pData pointer and need to free it.
*/
static int memdbClose(sqlite3_file *pFile){
  MemFile *p = (MemFile *)pFile;

























  if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
    sqlite3_free(p->aData);






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

  if( iOfst+iAmt>p->sz ){
    memset(zBuf, 0, iAmt);
    if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);

    return SQLITE_IOERR_SHORT_READ;
  }
  memcpy(zBuf, p->aData+iOfst, iAmt);

  return SQLITE_OK;
}

/*
** Try to enlarge the memory allocation to hold at least sz bytes
*/
static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){
  unsigned char *pNew;
  if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
    return SQLITE_FULL;
  }
  if( newSz>p->szMax ){
    return SQLITE_FULL;
  }
  newSz *= 2;
  if( newSz>p->szMax ) newSz = p->szMax;
  pNew = sqlite3Realloc(p->aData, newSz);
  if( pNew==0 ) return SQLITE_NOMEM;
  p->aData = pNew;
  p->szAlloc = newSz;
  return SQLITE_OK;
}

/*
** Write data to an memdb-file.
*/
static int memdbWrite(
  sqlite3_file *pFile,
  const void *z,
  int iAmt,
  sqlite_int64 iOfst
){
  MemFile *p = (MemFile *)pFile;

  if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ) return SQLITE_READONLY;





  if( iOfst+iAmt>p->sz ){
    int rc;
    if( iOfst+iAmt>p->szAlloc
     && (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
    ){

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

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

/*
** Sync an memdb-file.
*/
static int memdbSync(sqlite3_file *pFile, int 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;

  *pSize = p->sz;

  return SQLITE_OK;
}

/*
** Lock an memdb-file.
*/
static int memdbLock(sqlite3_file *pFile, int eLock){
  MemFile *p = (MemFile *)pFile;




  if( eLock>SQLITE_LOCK_SHARED 
   && (p->mFlags & SQLITE_DESERIALIZE_READONLY)!=0
  ){
    return SQLITE_READONLY;





  }



















  p->eLock = eLock;

  return SQLITE_OK;
}

#if 0 /* Never used because memdbAccess() always returns false */
/*

** Check if another file-handle holds a RESERVED lock on an memdb-file.
*/
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;
  int rc = SQLITE_NOTFOUND;

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

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

  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;

  if( iOfst+iAmt>p->sz ){
    *pp = 0;
  }else{
    p->nMmap++;
    *pp = (void*)(p->aData + iOfst);
  }

  return SQLITE_OK;
}

/* Release a memory-mapped page */
static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
  MemFile *p = (MemFile *)pFile;



  p->nMmap--;

  return SQLITE_OK;
}

/*
** Open an mem file handle.
*/
static int memdbOpen(
  sqlite3_vfs *pVfs,
  const char *zName,
  sqlite3_file *pFile,
  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;
  pFile->pMethods = &memdb_io_methods;
  p->szMax = sqlite3GlobalConfig.mxMemdbSize;
  return SQLITE_OK;
}

#if 0 /* Only used to delete rollback journals, super-journals, and WAL
      ** files, none of which exist in memdb.  So this routine is never used */
/*
** Delete the file located at zPath. If the dirSync argument is true,







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>
|
<
<
<


|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>













|
>



>



>






|










|














|
>
|
>
>
>
>
>





>






>











|
>
>
|
>
>
|
>
>
|






>
>







|
>

>







|
>
>
>
>
|
|
<
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|


|

>
|






>





|

>

















>
















>













|
>






>





|
>
>
>

>









|



|
>
>

|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>


|
|







176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
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
  0,                               /* xShmLock */
  0,                               /* xShmBarrier */
  0,                               /* xShmUnmap */
  memdbFetch,                      /* xFetch */
  memdbUnfetch                     /* xUnfetch */
};

/*
** Enter/leave the mutex on a MemStore
*/
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
static void memdbEnter(MemStore *p){
  UNUSED_PARAMETER(p);
}
static void memdbLeave(MemStore *p){
  UNUSED_PARAMETER(p);
}
#else
static void memdbEnter(MemStore *p){
  sqlite3_mutex_enter(p->pMutex);
}
static void memdbLeave(MemStore *p){
  sqlite3_mutex_leave(p->pMutex);
}
#endif



/*
** Close an memdb-file.
** Free the underlying MemStore object when its refcount drops to zero
** or less.



*/
static int memdbClose(sqlite3_file *pFile){
  MemStore *p = ((MemFile*)pFile)->pStore;
  if( p->zFName ){
    int i;
#ifndef SQLITE_MUTEX_OMIT
    sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
#endif
    sqlite3_mutex_enter(pVfsMutex);
    for(i=0; ALWAYS(i<memdb_g.nMemStore); i++){
      if( memdb_g.apMemStore[i]==p ){
        memdbEnter(p);
        if( p->nRef==1 ){
          memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore];
          if( memdb_g.nMemStore==0 ){
            sqlite3_free(memdb_g.apMemStore);
            memdb_g.apMemStore = 0;
          }
        }
        break;
      }
    }
    sqlite3_mutex_leave(pVfsMutex);
  }else{
    memdbEnter(p);
  }
  p->nRef--;
  if( p->nRef<=0 ){
    if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
      sqlite3_free(p->aData);
    }
    memdbLeave(p);
    sqlite3_mutex_free(p->pMutex);
    sqlite3_free(p);
  }else{
    memdbLeave(p);
  }
  return SQLITE_OK;
}

/*
** Read data from an memdb-file.
*/
static int memdbRead(
  sqlite3_file *pFile, 
  void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  MemStore *p = ((MemFile*)pFile)->pStore;
  memdbEnter(p);
  if( iOfst+iAmt>p->sz ){
    memset(zBuf, 0, iAmt);
    if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
    memdbLeave(p);
    return SQLITE_IOERR_SHORT_READ;
  }
  memcpy(zBuf, p->aData+iOfst, iAmt);
  memdbLeave(p);
  return SQLITE_OK;
}

/*
** Try to enlarge the memory allocation to hold at least sz bytes
*/
static int memdbEnlarge(MemStore *p, sqlite3_int64 newSz){
  unsigned char *pNew;
  if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
    return SQLITE_FULL;
  }
  if( newSz>p->szMax ){
    return SQLITE_FULL;
  }
  newSz *= 2;
  if( newSz>p->szMax ) newSz = p->szMax;
  pNew = sqlite3Realloc(p->aData, newSz);
  if( pNew==0 ) return SQLITE_IOERR_NOMEM;
  p->aData = pNew;
  p->szAlloc = newSz;
  return SQLITE_OK;
}

/*
** Write data to an memdb-file.
*/
static int memdbWrite(
  sqlite3_file *pFile,
  const void *z,
  int iAmt,
  sqlite_int64 iOfst
){
  MemStore *p = ((MemFile*)pFile)->pStore;
  memdbEnter(p);
  if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
    /* Can't happen: memdbLock() will return SQLITE_READONLY before
    ** reaching this point */
    memdbLeave(p);
    return SQLITE_IOERR_WRITE;
  }
  if( iOfst+iAmt>p->sz ){
    int rc;
    if( iOfst+iAmt>p->szAlloc
     && (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
    ){
      memdbLeave(p);
      return rc;
    }
    if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
    p->sz = iOfst+iAmt;
  }
  memcpy(p->aData+iOfst, z, iAmt);
  memdbLeave(p);
  return SQLITE_OK;
}

/*
** Truncate an memdb-file.
**
** In rollback mode (which is always the case for memdb, as it does not
** support WAL mode) the truncate() method is only used to reduce
** the size of a file, never to increase the size.
*/
static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
  MemStore *p = ((MemFile*)pFile)->pStore;
  int rc = SQLITE_OK;
  memdbEnter(p);
  if( NEVER(size>p->sz) ){
    rc = SQLITE_FULL;
  }else{
    p->sz = size; 
  }
  memdbLeave(p);
  return rc;
}

/*
** Sync an memdb-file.
*/
static int memdbSync(sqlite3_file *pFile, int flags){
  UNUSED_PARAMETER(pFile);
  UNUSED_PARAMETER(flags);
  return SQLITE_OK;
}

/*
** Return the current file-size of an memdb-file.
*/
static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
  MemStore *p = ((MemFile*)pFile)->pStore;
  memdbEnter(p);
  *pSize = p->sz;
  memdbLeave(p);
  return SQLITE_OK;
}

/*
** Lock an memdb-file.
*/
static int memdbLock(sqlite3_file *pFile, int eLock){
  MemFile *pThis = (MemFile*)pFile;
  MemStore *p = pThis->pStore;
  int rc = SQLITE_OK;
  if( eLock==pThis->eLock ) return SQLITE_OK;
  memdbEnter(p);
  if( eLock>SQLITE_LOCK_SHARED ){
    if( p->mFlags & SQLITE_DESERIALIZE_READONLY ){

      rc = SQLITE_READONLY;
    }else if( pThis->eLock<=SQLITE_LOCK_SHARED ){
      if( p->nWrLock ){
        rc = SQLITE_BUSY;
      }else{
        p->nWrLock = 1;
      }
    }
  }else if( eLock==SQLITE_LOCK_SHARED ){
    if( pThis->eLock > SQLITE_LOCK_SHARED ){
      assert( p->nWrLock==1 );
      p->nWrLock = 0;
    }else if( p->nWrLock ){
      rc = SQLITE_BUSY;
    }else{
      p->nRdLock++;
    }
  }else{
    assert( eLock==SQLITE_LOCK_NONE );
    if( pThis->eLock>SQLITE_LOCK_SHARED ){    
      assert( p->nWrLock==1 );
      p->nWrLock = 0;
    }
    assert( p->nRdLock>0 );
    p->nRdLock--;
  }
  if( rc==SQLITE_OK ) pThis->eLock = eLock;
  memdbLeave(p);
  return rc;
}

#if 0
/*
** This interface is only used for crash recovery, which does not
** occur on an in-memory database.
*/
static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
  *pResOut = 0;
  return SQLITE_OK;
}
#endif


/*
** File control method. For custom operations on an memdb-file.
*/
static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
  MemStore *p = ((MemFile*)pFile)->pStore;
  int rc = SQLITE_NOTFOUND;
  memdbEnter(p);
  if( op==SQLITE_FCNTL_VFSNAME ){
    *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
    rc = SQLITE_OK;
  }
  if( op==SQLITE_FCNTL_SIZE_LIMIT ){
    sqlite3_int64 iLimit = *(sqlite3_int64*)pArg;
    if( iLimit<p->sz ){
      if( iLimit<0 ){
        iLimit = p->szMax;
      }else{
        iLimit = p->sz;
      }
    }
    p->szMax = iLimit;
    *(sqlite3_int64*)pArg = iLimit;
    rc = SQLITE_OK;
  }
  memdbLeave(p);
  return rc;
}

#if 0  /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */
/*
** Return the sector-size in bytes for an memdb-file.
*/
static int memdbSectorSize(sqlite3_file *pFile){
  return 1024;
}
#endif

/*
** Return the device characteristic flags supported by an memdb-file.
*/
static int memdbDeviceCharacteristics(sqlite3_file *pFile){
  UNUSED_PARAMETER(pFile);
  return SQLITE_IOCAP_ATOMIC | 
         SQLITE_IOCAP_POWERSAFE_OVERWRITE |
         SQLITE_IOCAP_SAFE_APPEND |
         SQLITE_IOCAP_SEQUENTIAL;
}

/* Fetch a page of a memory-mapped file */
static int memdbFetch(
  sqlite3_file *pFile,
  sqlite3_int64 iOfst,
  int iAmt,
  void **pp
){
  MemStore *p = ((MemFile*)pFile)->pStore;
  memdbEnter(p);
  if( iOfst+iAmt>p->sz ){
    *pp = 0;
  }else{
    p->nMmap++;
    *pp = (void*)(p->aData + iOfst);
  }
  memdbLeave(p);
  return SQLITE_OK;
}

/* Release a memory-mapped page */
static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
  MemStore *p = ((MemFile*)pFile)->pStore;
  UNUSED_PARAMETER(iOfst);
  UNUSED_PARAMETER(pPage);
  memdbEnter(p);
  p->nMmap--;
  memdbLeave(p);
  return SQLITE_OK;
}

/*
** Open an mem file handle.
*/
static int memdbOpen(
  sqlite3_vfs *pVfs,
  const char *zName,
  sqlite3_file *pFd,
  int flags,
  int *pOutFlags
){
  MemFile *pFile = (MemFile*)pFd;
  MemStore *p = 0;
  int szName;
  if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
    return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFd, flags, pOutFlags);
  }
  memset(pFile, 0, sizeof(*p));
  szName = sqlite3Strlen30(zName);
  if( szName>1 && zName[0]=='/' ){
    int i;
#ifndef SQLITE_MUTEX_OMIT
    sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
#endif
    sqlite3_mutex_enter(pVfsMutex);
    for(i=0; i<memdb_g.nMemStore; i++){
      if( strcmp(memdb_g.apMemStore[i]->zFName,zName)==0 ){
        p = memdb_g.apMemStore[i];
        break;
      }
    }
    if( p==0 ){
      MemStore **apNew;
      p = sqlite3Malloc( sizeof(*p) + szName + 3 );
      if( p==0 ){
        sqlite3_mutex_leave(pVfsMutex);
        return SQLITE_NOMEM;
      }
      apNew = sqlite3Realloc(memdb_g.apMemStore,
                             sizeof(apNew[0])*(memdb_g.nMemStore+1) );
      if( apNew==0 ){
        sqlite3_free(p);
        sqlite3_mutex_leave(pVfsMutex);
        return SQLITE_NOMEM;
      }
      apNew[memdb_g.nMemStore++] = p;
      memdb_g.apMemStore = apNew;
      memset(p, 0, sizeof(*p));
      p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE|SQLITE_DESERIALIZE_FREEONCLOSE;
      p->szMax = sqlite3GlobalConfig.mxMemdbSize;
      p->zFName = (char*)&p[1];
      memcpy(p->zFName, zName, szName+1);
      p->pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
      if( p->pMutex==0 ){
        memdb_g.nMemStore--;
        sqlite3_free(p);
        sqlite3_mutex_leave(pVfsMutex);
        return SQLITE_NOMEM;
      }
      p->nRef = 1;
      memdbEnter(p);
    }else{
      memdbEnter(p);
      p->nRef++;
    }
    sqlite3_mutex_leave(pVfsMutex);
  }else{
    p = sqlite3Malloc( sizeof(*p) );
    if( p==0 ){
      return SQLITE_NOMEM;
    }
    memset(p, 0, sizeof(*p));
    p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
    p->szMax = sqlite3GlobalConfig.mxMemdbSize;
  }
  pFile->pStore = p;
  assert( pOutFlags!=0 );  /* True because flags==SQLITE_OPEN_MAIN_DB */
  *pOutFlags = flags | SQLITE_OPEN_MEMORY;
  pFd->pMethods = &memdb_io_methods;
  memdbLeave(p);
  return SQLITE_OK;
}

#if 0 /* Only used to delete rollback journals, super-journals, and WAL
      ** files, none of which exist in memdb.  So this routine is never used */
/*
** Delete the file located at zPath. If the dirSync argument is true,
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
*/
static int memdbAccess(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int flags, 
  int *pResOut
){



  *pResOut = 0;
  return SQLITE_OK;
}

/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (INST_MAX_PATHNAME+1) bytes.
*/
static int memdbFullPathname(
  sqlite3_vfs *pVfs, 
  const char *zPath, 
  int nOut, 
  char *zOut
){

  sqlite3_snprintf(nOut, zOut, "%s", zPath);
  return SQLITE_OK;
}

/*
** Open the dynamic library located at zPath and return a handle.
*/







>
>
>















>







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
*/
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.
*/
454
455
456
457
458
459
460

461
462
463




464
465
466
467
468
469
470

/*
** Translate a database connection pointer and schema name into a
** MemFile pointer.
*/
static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
  MemFile *p = 0;

  int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
  if( rc ) return 0;
  if( p->base.pMethods!=&memdb_io_methods ) return 0;




  return p;
}

/*
** Return the serialization of a database
*/
unsigned char *sqlite3_serialize(







>



>
>
>
>







685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706

/*
** 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(
492
493
494
495
496
497
498


499
500
501
502
503
504
505
506
507
508
509
510
511

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


    if( piSize ) *piSize = p->sz;
    if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
      pOut = p->aData;
    }else{
      pOut = sqlite3_malloc64( p->sz );
      if( pOut ) memcpy(pOut, p->aData, p->sz);
    }
    return pOut;
  }
  pBt = db->aDb[iDb].pBt;
  if( pBt==0 ) return 0;
  szPage = sqlite3BtreeGetPageSize(pBt);
  zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);







>
>
|

|

|
|







728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749

  if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
  p = memdbFromDbSchema(db, zSchema);
  iDb = sqlite3FindDbName(db, zSchema);
  if( piSize ) *piSize = -1;
  if( iDb<0 ) return 0;
  if( p ){
    MemStore *pStore = p->pStore;
    assert( pStore->pMutex==0 );
    if( piSize ) *piSize = pStore->sz;
    if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
      pOut = pStore->aData;
    }else{
      pOut = sqlite3_malloc64( pStore->sz );
      if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
    }
    return pOut;
  }
  pBt = db->aDb[iDb].pBt;
  if( pBt==0 ) return 0;
  szPage = sqlite3BtreeGetPageSize(pBt);
  zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
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
    rc = SQLITE_ERROR;
    goto end_deserialize;
  }
  p = memdbFromDbSchema(db, zSchema);
  if( p==0 ){
    rc = SQLITE_ERROR;
  }else{

    p->aData = pData;
    pData = 0;
    p->sz = szDb;
    p->szAlloc = szBuf;
    p->szMax = szBuf;
    if( p->szMax<sqlite3GlobalConfig.mxMemdbSize ){
      p->szMax = sqlite3GlobalConfig.mxMemdbSize;
    }
    p->mFlags = mFlags;
    rc = SQLITE_OK;
  }

end_deserialize:
  sqlite3_finalize(pStmt);
  if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
    sqlite3_free(pData);
  }
  sqlite3_mutex_leave(db->mutex);
  return rc;
}

/* 
** This routine is called when the extension is loaded.
** Register the new VFS.
*/
int sqlite3MemdbInit(void){
  sqlite3_vfs *pLower = sqlite3_vfs_find(0);
  int sz = pLower->szOsFile;
  memdb_vfs.pAppData = pLower;
  /* The following conditional can only be true when compiled for
  ** Windows x86 and SQLITE_MAX_MMAP_SIZE=0.  We always leave
  ** it in, to be safe, but it is marked as NO_TEST since there
  ** is no way to reach it under most builds. */
  if( sz<sizeof(MemFile) ) sz = sizeof(MemFile); /*NO_TEST*/
  memdb_vfs.szOsFile = sz;
  return sqlite3_vfs_register(&memdb_vfs, 0);
}
#endif /* SQLITE_ENABLE_DESERIALIZE */







>
|

|
|
|
|
|

|


















|









|
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
    rc = SQLITE_ERROR;
    goto end_deserialize;
  }
  p = memdbFromDbSchema(db, zSchema);
  if( p==0 ){
    rc = SQLITE_ERROR;
  }else{
    MemStore *pStore = p->pStore;
    pStore->aData = pData;
    pData = 0;
    pStore->sz = szDb;
    pStore->szAlloc = szBuf;
    pStore->szMax = szBuf;
    if( pStore->szMax<sqlite3GlobalConfig.mxMemdbSize ){
      pStore->szMax = sqlite3GlobalConfig.mxMemdbSize;
    }
    pStore->mFlags = mFlags;
    rc = SQLITE_OK;
  }

end_deserialize:
  sqlite3_finalize(pStmt);
  if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
    sqlite3_free(pData);
  }
  sqlite3_mutex_leave(db->mutex);
  return rc;
}

/* 
** This routine is called when the extension is loaded.
** Register the new VFS.
*/
int sqlite3MemdbInit(void){
  sqlite3_vfs *pLower = sqlite3_vfs_find(0);
  unsigned int sz = pLower->szOsFile;
  memdb_vfs.pAppData = pLower;
  /* The following conditional can only be true when compiled for
  ** Windows x86 and SQLITE_MAX_MMAP_SIZE=0.  We always leave
  ** it in, to be safe, but it is marked as NO_TEST since there
  ** is no way to reach it under most builds. */
  if( sz<sizeof(MemFile) ) sz = sizeof(MemFile); /*NO_TEST*/
  memdb_vfs.szOsFile = sz;
  return sqlite3_vfs_register(&memdb_vfs, 0);
}
#endif /* SQLITE_OMIT_DESERIALIZE */
Changes to src/os.c.
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut);
  assert( rc==SQLITE_OK || pFile->pMethods==0 );
  return rc;
}
int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  DO_OS_MALLOC_TEST(0);
  assert( dirSync==0 || dirSync==1 );
  return pVfs->xDelete(pVfs, zPath, dirSync);
}
int sqlite3OsAccess(
  sqlite3_vfs *pVfs,
  const char *zPath,
  int flags,
  int *pResOut
){







|







225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut);
  assert( rc==SQLITE_OK || pFile->pMethods==0 );
  return rc;
}
int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
  DO_OS_MALLOC_TEST(0);
  assert( dirSync==0 || dirSync==1 );
  return pVfs->xDelete!=0 ? pVfs->xDelete(pVfs, zPath, dirSync) : SQLITE_OK;
}
int sqlite3OsAccess(
  sqlite3_vfs *pVfs,
  const char *zPath,
  int flags,
  int *pResOut
){
Changes to src/os_unix.c.
3947
3948
3949
3950
3951
3952
3953

3954
3955
3956
3957
3958
3959
3960
  }else{
    pFile->ctrlFlags |= mask;
  }
}

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


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







>







3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
  }else{
    pFile->ctrlFlags |= mask;
  }
}

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

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




4070
4071
4072
4073
4074
4075
4076
#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
    case SQLITE_FCNTL_SET_LOCKPROXYFILE:
    case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
      return proxyFileControl(id,op,pArg);
    }
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */




  }
  return SQLITE_NOTFOUND;
}

/*
** If pFd->sectorSize is non-zero when this function is called, it is a
** no-op. Otherwise, the values of pFd->sectorSize and 







>
>
>
>







4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
    case SQLITE_FCNTL_SET_LOCKPROXYFILE:
    case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
      return proxyFileControl(id,op,pArg);
    }
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */

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

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


































4314
4315
4316
4317
4318
4319
4320
};

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



































/*
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
**
** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
** otherwise.
*/







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

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

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

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

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

  return rc;
}


/*
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
**
** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
** otherwise.
*/
8024
8025
8026
8027
8028
8029
8030
















8031
8032
8033
8034
8035
8036
8037
  assert( ArraySize(aSyscall)==29 );

  /* Register all VFSes defined in the aVfs[] array */
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
    sqlite3_vfs_register(&aVfs[i], i==0);
  }
  unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
















  return SQLITE_OK; 
}

/*
** Shutdown the operating system interface.
**
** Some operating systems might need to do some cleanup in this routine,







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
  assert( ArraySize(aSyscall)==29 );

  /* Register all VFSes defined in the aVfs[] array */
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
    sqlite3_vfs_register(&aVfs[i], i==0);
  }
  unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);

  /* Validate lock assumptions */
  assert( SQLITE_SHM_NLOCK==8 );  /* Number of available locks */
  assert( UNIX_SHM_BASE==120  );  /* Start of locking area */
  /* Locks:
  **    WRITE       UNIX_SHM_BASE      120
  **    CKPT        UNIX_SHM_BASE+1    121
  **    RECOVER     UNIX_SHM_BASE+2    122
  **    READ-0      UNIX_SHM_BASE+3    123
  **    READ-1      UNIX_SHM_BASE+4    124
  **    READ-2      UNIX_SHM_BASE+5    125
  **    READ-3      UNIX_SHM_BASE+6    126
  **    READ-4      UNIX_SHM_BASE+7    127
  **    DMS         UNIX_SHM_BASE+8    128
  */
  assert( UNIX_SHM_DMS==128   );  /* Byte offset of the deadman-switch */
  return SQLITE_OK; 
}

/*
** Shutdown the operating system interface.
**
** Some operating systems might need to do some cleanup in this routine,
Changes to src/pager.c.
3932
3933
3934
3935
3936
3937
3938
3939

3940
3941
3942
3943
3944
3945
3946
**
** 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->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







|
>







3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
**
** This function is only called right before committing a transaction.
** Once this function has been called, the transaction must either be
** rolled back or committed. It is not safe to call this function and
** then continue writing to the database.
*/
void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
  assert( pPager->dbSize>=nPage || CORRUPT_DB );
  testcase( pPager->dbSize<nPage );
  assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
  pPager->dbSize = nPage;

  /* At one point the code here called assertTruncateConstraint() to
  ** ensure that all pages being truncated away by this operation are,
  ** if one or more savepoints are open, present in the savepoint 
  ** journal so that they can be restored if the savepoint is rolled
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
  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
  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 */







|







4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
  void (*xReinit)(DbPage*) /* Function to reinitialize pages */
){
  u8 *pPtr;
  Pager *pPager = 0;       /* Pager object to allocate and return */
  int rc = SQLITE_OK;      /* Return code */
  int tempFile = 0;        /* True for temp files (incl. in-memory files) */
  int memDb = 0;           /* True if this is an in-memory file */
#ifndef SQLITE_OMIT_DESERIALIZE
  int memJM = 0;           /* Memory journal mode */
#else
# define memJM 0
#endif
  int readOnly = 0;        /* True if this is a read-only file */
  int journalFileSize;     /* Bytes to allocate for each journal fd */
  char *zPathname = 0;     /* Full path to database file */
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878

  /* 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;
#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:







|







4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879

  /* Open the pager file.
  */
  if( zFilename && zFilename[0] ){
    int fout = 0;                    /* VFS flags returned by xOpen() */
    rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
    assert( !memDb );
#ifndef SQLITE_OMIT_DESERIALIZE
    memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
#endif
    readOnly = (fout&SQLITE_OPEN_READONLY)!=0;

    /* If the file was successfully opened for read/write access,
    ** choose a default page size in case we have to create the
    ** database file. The default page size is the maximum of:
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
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) ){
    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) ){







|







5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
  int rc = SQLITE_OK;

  if( pPager->errCode ) return pPager->errCode;
  assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR );
  pPager->subjInMemory = (u8)subjInMemory;

  if( pPager->eState==PAGER_READER ){
    assert( pPager->pInJournal==0 );

    if( pagerUseWal(pPager) ){
      /* If the pager is configured to use locking_mode=exclusive, and an
      ** exclusive lock on the database is not already held, obtain it now.
      */
      if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){
Changes to src/parse.y.
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
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;}
%endif  SQLITE_OMIT_TEMPDB
temp(A) ::= .      {A = 0;}
create_table_args ::= LP columnlist conslist_opt(X) RP(E) table_options(F). {
  sqlite3EndTable(pParse,&X,&E,F,0);
}
create_table_args ::= AS select(S). {
  sqlite3EndTable(pParse,0,0,0,S);







|







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
createkw(A) ::= CREATE(A).  {disableLookaside(pParse);}

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

1804



1805
1806
1807
1808
1809
1810
1811


%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). {

  O->pFilter = F;



  A = O;
}
filter_over(A) ::= over_clause(O). {
  A = O;
}
filter_over(A) ::= filter_clause(F). {
  A = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));







>
|
>
>
>







1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815


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

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

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  sqlite3 *db = pData->db;
  int iDb = pData->iDb;

  assert( argc==5 );
  UNUSED_PARAMETER2(NotUsed, argc);
  assert( sqlite3_mutex_held(db->mutex) );
  db->mDbFlags |= DBFLAG_EncodingFixed;

  pData->nInitRow++;
  if( db->mallocFailed ){
    corruptSchema(pData, argv, 0);
    return 1;
  }

  assert( iDb>=0 && iDb<db->nDb );
  if( argv==0 ) return 0;   /* Might happen if EMPTY_RESULT_CALLBACKS are on */
  if( argv[3]==0 ){
    corruptSchema(pData, argv, 0);
  }else if( argv[4]
         && 'c'==sqlite3UpperToLower[(unsigned char)argv[4][0]]
         && 'r'==sqlite3UpperToLower[(unsigned char)argv[4][1]] ){
    /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
    ** But because db->init.busy is set to 1, no VDBE code is generated







>







<







128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
  sqlite3 *db = pData->db;
  int iDb = pData->iDb;

  assert( argc==5 );
  UNUSED_PARAMETER2(NotUsed, argc);
  assert( sqlite3_mutex_held(db->mutex) );
  db->mDbFlags |= DBFLAG_EncodingFixed;
  if( argv==0 ) return 0;   /* Might happen if EMPTY_RESULT_CALLBACKS are on */
  pData->nInitRow++;
  if( db->mallocFailed ){
    corruptSchema(pData, argv, 0);
    return 1;
  }

  assert( iDb>=0 && iDb<db->nDb );

  if( argv[3]==0 ){
    corruptSchema(pData, argv, 0);
  }else if( argv[4]
         && 'c'==sqlite3UpperToLower[(unsigned char)argv[4][0]]
         && 'r'==sqlite3UpperToLower[(unsigned char)argv[4][1]] ){
    /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
    ** But because db->init.busy is set to 1, no VDBE code is generated
445
446
447
448
449
450
451
452
453
454
455
456
457
458


459
460
461
462
463
464
465
466
467
      sqlite3AnalysisLoad(db, iDb);
    }
#endif
  }
  if( db->mallocFailed ){
    rc = SQLITE_NOMEM_BKPT;
    sqlite3ResetAllSchemasOfConnection(db);
  }
  if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){
    /* Black magic: If the SQLITE_NoSchemaError flag is set, then consider
    ** the schema loaded, even if errors occurred. In this situation the 
    ** current sqlite3_prepare() operation will fail, but the following one
    ** will attempt to compile the supplied statement against whatever subset
    ** of the schema was loaded before the error occurred. The primary


    ** purpose of this is to allow access to the sqlite_schema table
    ** even when its contents have been corrupted.
    */
    DbSetProperty(db, iDb, DB_SchemaLoaded);
    rc = SQLITE_OK;
  }

  if( rc==SQLITE_OK && iDb!=1 && IsSharedSchema(db) ){
    rc = sqlite3SchemaConnect(db, iDb, initData.cksum);







|

|
|
|
|
|
>
>
|
|







445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
      sqlite3AnalysisLoad(db, iDb);
    }
#endif
  }
  if( db->mallocFailed ){
    rc = SQLITE_NOMEM_BKPT;
    sqlite3ResetAllSchemasOfConnection(db);
  }else
  if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){
    /* Hack: If the SQLITE_NoSchemaError flag is set, then consider
    ** the schema loaded, even if errors (other than OOM) occurred. In
    ** this situation the current sqlite3_prepare() operation will fail,
    ** but the following one will attempt to compile the supplied statement
    ** against whatever subset of the schema was loaded before the error
    ** occurred.
    **
    ** The primary purpose of this is to allow access to the sqlite_schema
    ** table even when its contents have been corrupted.
    */
    DbSetProperty(db, iDb, DB_SchemaLoaded);
    rc = SQLITE_OK;
  }

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

611
612
613
614
615
616
617
    /* If there is not already a read-only (or read-write) transaction opened
    ** on the b-tree database, open one now. If a transaction is opened, it 
    ** will be closed immediately after reading the meta-value. */
    if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_NONE ){
      rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
      if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
        sqlite3OomFault(db);

      }
      if( rc!=SQLITE_OK ) return;
      openedTransaction = 1;
    }

    /* Read the schema cookie from the database. If it does not match the 
    ** value stored as part of the in-memory schema representation,







>







606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
    /* If there is not already a read-only (or read-write) transaction opened
    ** on the b-tree database, open one now. If a transaction is opened, it 
    ** will be closed immediately after reading the meta-value. */
    if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_NONE ){
      rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
      if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
        sqlite3OomFault(db);
        pParse->rc = SQLITE_NOMEM;
      }
      if( rc!=SQLITE_OK ) return;
      openedTransaction = 1;
    }

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

846
847
848
849
850
851
852
  }

  if( db->init.busy==0 ){
    sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags);
  }
  if( db->mallocFailed ){
    sParse.rc = SQLITE_NOMEM_BKPT;

  }
  if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){
    if( sParse.checkSchema ){
      schemaIsValid(&sParse);
    }
    if( sParse.pVdbe ){
      sqlite3VdbeFinalize(sParse.pVdbe);







>







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

  if( db->init.busy==0 ){
    sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags);
  }
  if( db->mallocFailed ){
    sParse.rc = SQLITE_NOMEM_BKPT;
    sParse.checkSchema = 0;
  }
  if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){
    if( sParse.checkSchema ){
      schemaIsValid(&sParse);
    }
    if( sParse.pVdbe ){
      sqlite3VdbeFinalize(sParse.pVdbe);
Changes to src/printf.c.
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#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 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 */








|







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 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
  {  '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 },
  {  'r', 10, 1, etORDINAL,    0,  0 },
};







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








|


>
>
>
>
>
>







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  {  'i', 10, 1, etDECIMAL,    0,  0 },
  {  'n',  0, 0, etSIZE,       0,  0 },
  {  '%',  0, 0, etPERCENT,    0,  0 },
  {  'p', 16, 0, etPOINTER,    0,  1 },

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

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

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

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865



866
867
868
869
870





871
872
873
874
875
876
877
        assert( bArgList==0 );
        if( pToken && pToken->n ){
          sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
        }
        length = width = 0;
        break;
      }
      case etSRCLIST: {
        SrcList *pSrc;
        int k;
        SrcItem *pItem;
        if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
        pSrc = va_arg(ap, SrcList*);
        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);





        length = width = 0;
        break;
      }
      default: {
        assert( xtype==etINVALID );
        return;
      }







|
<
<


|
<
<

<
>
>
>
|
|
|
|
|
>
>
>
>
>







855
856
857
858
859
860
861
862


863
864
865


866

867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
        assert( bArgList==0 );
        if( pToken && pToken->n ){
          sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
        }
        length = width = 0;
        break;
      }
      case etSRCITEM: {


        SrcItem *pItem;
        if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
        pItem = va_arg(ap, SrcItem*);


        assert( bArgList==0 );

        if( pItem->zAlias && !flag_altform2 ){
          sqlite3_str_appendall(pAccum, pItem->zAlias);
        }else if( pItem->zName ){
          if( pItem->zDatabase ){
            sqlite3_str_appendall(pAccum, pItem->zDatabase);
            sqlite3_str_append(pAccum, ".", 1);
          }
          sqlite3_str_appendall(pAccum, pItem->zName);
        }else if( pItem->zAlias ){
          sqlite3_str_appendall(pAccum, pItem->zAlias);
        }else if( ALWAYS(pItem->pSelect) ){
          sqlite3_str_appendf(pAccum, "SUBQUERY %u", pItem->pSelect->selId);
        }
        length = width = 0;
        break;
      }
      default: {
        assert( xtype==etINVALID );
        return;
      }
Changes to src/resolve.c.
77
78
79
80
81
82
83


84

85
86
87
88
89
90
91
  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( pDup!=0 ){

    incrAggFunctionDepth(pDup, nSubquery);
    if( pExpr->op==TK_COLLATE ){
      pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
    }

    /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This 
    ** prevents ExprDelete() from deleting the Expr structure itself,







>
>
|
>







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  sqlite3 *db;           /* The database connection */

  assert( iCol>=0 && iCol<pEList->nExpr );
  pOrig = pEList->a[iCol].pExpr;
  assert( pOrig!=0 );
  db = pParse->db;
  pDup = sqlite3ExprDup(db, pOrig, 0);
  if( db->mallocFailed ){
    sqlite3ExprDelete(db, pDup);
    pDup = 0;
  }else{
    incrAggFunctionDepth(pDup, nSubquery);
    if( pExpr->op==TK_COLLATE ){
      pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
    }

    /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This 
    ** prevents ExprDelete() from deleting the Expr structure itself,
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
    memcpy(pExpr, pDup, sizeof(*pExpr));
    if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
      assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
      pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
      pExpr->flags |= EP_MemToken;
    }
    if( ExprHasProperty(pExpr, EP_WinFunc) ){
      if( pExpr->y.pWin!=0 ){
        pExpr->y.pWin->pOwner = pExpr;
      }else{
        assert( db->mallocFailed );
      }
    }
    sqlite3DbFree(db, pDup);
  }
}









|

<
<







102
103
104
105
106
107
108
109
110


111
112
113
114
115
116
117
    memcpy(pExpr, pDup, sizeof(*pExpr));
    if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
      assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
      pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
      pExpr->flags |= EP_MemToken;
    }
    if( ExprHasProperty(pExpr, EP_WinFunc) ){
      if( ALWAYS(pExpr->y.pWin!=0) ){
        pExpr->y.pWin->pOwner = pExpr;


      }
    }
    sqlite3DbFree(db, pDup);
  }
}


372
373
374
375
376
377
378







379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
    */
    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( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){
          pExpr->iTable = 1;
          pTab = pParse->pTriggerTab;
        }else if( op!=TK_INSERT && zTab && sqlite3StrICmp("old",zTab)==0 ){
          pExpr->iTable = 0;
          pTab = pParse->pTriggerTab;
        }else if( pParse->bReturning && (pNC->ncFlags & NC_UBaseReg)!=0 ){
          pExpr->iTable = op!=TK_DELETE;
          pTab = pParse->pTriggerTab;
        }
      }
#endif /* SQLITE_OMIT_TRIGGER */
#ifndef SQLITE_OMIT_UPSERT
      if( (pNC->ncFlags & NC_UUpsert)!=0 && zTab!=0 ){
        Upsert *pUpsert = pNC->uNC.pUpsert;
        if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){







>
>
>
>
>
>
>
|





<
<
<







373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392



393
394
395
396
397
398
399
    */
    if( cnt==0 && zDb==0 ){
      pTab = 0;
#ifndef SQLITE_OMIT_TRIGGER
      if( pParse->pTriggerTab!=0 ){
        int op = pParse->eTriggerOp;
        assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
        if( pParse->bReturning ){
          if( (pNC->ncFlags & NC_UBaseReg)!=0
           && (zTab==0 || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0)
          ){
            pExpr->iTable = op!=TK_DELETE;
            pTab = pParse->pTriggerTab;
          }
        }else if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){
          pExpr->iTable = 1;
          pTab = pParse->pTriggerTab;
        }else if( op!=TK_INSERT && zTab && sqlite3StrICmp("old",zTab)==0 ){
          pExpr->iTable = 0;
          pTab = pParse->pTriggerTab;



        }
      }
#endif /* SQLITE_OMIT_TRIGGER */
#ifndef SQLITE_OMIT_UPSERT
      if( (pNC->ncFlags & NC_UUpsert)!=0 && zTab!=0 ){
        Upsert *pUpsert = pNC->uNC.pUpsert;
        if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){
490
491
492
493
494
495
496

497
498
499
500
501
502
503
504
505
    **
    ** 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( (pNC->ncFlags & NC_UEList)!=0
     && cnt==0
     && zTab==0
    ){
      pEList = pNC->uNC.pEList;
      assert( pEList!=0 );
      for(j=0; j<pEList->nExpr; j++){
        char *zAs = pEList->a[j].zEName;
        if( pEList->a[j].eEName==ENAME_NAME







>
|
<







495
496
497
498
499
500
501
502
503

504
505
506
507
508
509
510
    **
    ** The ability to use an output result-set column in the WHERE, GROUP BY,
    ** or HAVING clauses, or as part of a larger expression in the ORDER BY
    ** clause is not standard SQL.  This is a (goofy) SQLite extension, that
    ** is supported for backwards compatibility only. Hence, we issue a warning
    ** on sqlite3_log() whenever the capability is used.
    */
    if( cnt==0
     && (pNC->ncFlags & NC_UEList)!=0

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







<














<
<
<
<
<







560
561
562
563
564
565
566

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





581
582
583
584
585
586
587
  ** Because no reference was made to outer contexts, the pNC->nRef
  ** fields are not changed in any context.
  */
  if( cnt==0 && zTab==0 ){
    assert( pExpr->op==TK_ID );
    if( ExprHasProperty(pExpr,EP_DblQuoted)
     && areDoubleQuotedStringsEnabled(db, pTopNC)

    ){
      /* 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;
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
      sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
    }else if( zTab ){
      sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
    }else{
      sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
    }
    pParse->checkSchema = 1;
    pTopNC->nErr++;
  }

  /* If a column from a table in pSrcList is referenced, then record
  ** this fact in the pSrcList.a[].colUsed bitmask.  Column 0 causes
  ** bit 0 to be set.  Column 1 sets bit 1.  And so forth.  Bit 63 is
  ** set if the 63rd or any subsequent column is used.
  **







|







604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
      sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
    }else if( zTab ){
      sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
    }else{
      sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
    }
    pParse->checkSchema = 1;
    pTopNC->nNcErr++;
  }

  /* If a column from a table in pSrcList is referenced, then record
  ** this fact in the pSrcList.a[].colUsed bitmask.  Column 0 causes
  ** bit 0 to be set.  Column 1 sets bit 1.  And so forth.  Bit 63 is
  ** set if the 63rd or any subsequent column is used.
  **
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
          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++;
            }
          }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







|







911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
          ExprSetProperty(pExpr, EP_Unlikely);
          if( n==2 ){
            pExpr->iTable = exprProbability(pList->a[1].pExpr);
            if( pExpr->iTable<0 ){
              sqlite3ErrorMsg(pParse,
                "second argument to likelihood() must be a "
                "constant between 0.0 and 1.0");
              pNC->nNcErr++;
            }
          }else{
            /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is
            ** equivalent to likelihood(X, 0.0625).
            ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is
            ** short-hand for likelihood(X,0.0625).
            ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
#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++;
            }
            pExpr->op = TK_NULL;
            return WRC_Prune;
          }
        }
#endif
        if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){







|







933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
#ifndef SQLITE_OMIT_AUTHORIZATION
        {
          int auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0,pDef->zName,0);
          if( auth!=SQLITE_OK ){
            if( auth==SQLITE_DENY ){
              sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
                                      pDef->zName);
              pNC->nNcErr++;
            }
            pExpr->op = TK_NULL;
            return WRC_Prune;
          }
        }
#endif
        if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
          || (pDef->xValue==0 && pDef->xInverse==0)
          || (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize)
        );
        if( pDef && pDef->xValue==0 && pWin ){
          sqlite3ErrorMsg(pParse, 
              "%.*s() may not be used as a window function", nId, zId
          );
          pNC->nErr++;
        }else if( 
              (is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
           || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pWin)
           || (is_agg && pWin && (pNC->ncFlags & NC_AllowWin)==0)
        ){
          const char *zType;
          if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pWin ){
            zType = "window";
          }else{
            zType = "aggregate";
          }
          sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId);
          pNC->nErr++;
          is_agg = 0;
        }
#else
        if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){
          sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId);
          pNC->nErr++;
          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++;
        }else if( wrong_num_args ){
          sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
               nId, zId);
          pNC->nErr++;
        }
#ifndef SQLITE_OMIT_WINDOWFUNC
        else if( is_agg==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
          sqlite3ErrorMsg(pParse, 
              "FILTER may not be used with non-aggregate %.*s()", 
              nId, zId
          );
          pNC->nErr++;
        }
#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







|












|





|









|



|







|







989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
          || (pDef->xValue==0 && pDef->xInverse==0)
          || (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize)
        );
        if( pDef && pDef->xValue==0 && pWin ){
          sqlite3ErrorMsg(pParse, 
              "%.*s() may not be used as a window function", nId, zId
          );
          pNC->nNcErr++;
        }else if( 
              (is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
           || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pWin)
           || (is_agg && pWin && (pNC->ncFlags & NC_AllowWin)==0)
        ){
          const char *zType;
          if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pWin ){
            zType = "window";
          }else{
            zType = "aggregate";
          }
          sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId);
          pNC->nNcErr++;
          is_agg = 0;
        }
#else
        if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){
          sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId);
          pNC->nNcErr++;
          is_agg = 0;
        }
#endif
        else if( no_such_func && pParse->db->init.busy==0
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
                  && pParse->explain==0
#endif
        ){
          sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
          pNC->nNcErr++;
        }else if( wrong_num_args ){
          sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
               nId, zId);
          pNC->nNcErr++;
        }
#ifndef SQLITE_OMIT_WINDOWFUNC
        else if( is_agg==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
          sqlite3ErrorMsg(pParse, 
              "FILTER may not be used with non-aggregate %.*s()", 
              nId, zId
          );
          pNC->nNcErr++;
        }
#endif
        if( is_agg ){
          /* Window functions may not be arguments of aggregate functions.
          ** Or arguments of other window functions. But aggregate functions
          ** may be arguments for window functions.  */
#ifndef SQLITE_OMIT_WINDOWFUNC
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270

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








|
|







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

  /* Resolve all names in the ORDER BY term expression
  */
  memset(&nc, 0, sizeof(nc));
  nc.pParse = pParse;
  nc.pSrcList = pSelect->pSrc;
  nc.uNC.pEList = pEList;
  nc.ncFlags = NC_AllowAgg|NC_UEList|NC_NoSelect;
  nc.nNcErr = 0;
  db = pParse->db;
  savedSuppErr = db->suppressErr;
  if( IN_RENAME_OBJECT==0 ) db->suppressErr = 1;
  rc = sqlite3ResolveExprNames(&nc, pE);
  db->suppressErr = savedSuppErr;
  if( rc ) return 0;

1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
){
  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;
  nResult = pSelect->pEList->nExpr;
  pParse = pNC->pParse;
  for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
    Expr *pE = pItem->pExpr;
    Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pE);
    if( NEVER(pE2==0) ) continue;
    if( zType[0]!='G' ){







|







1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
){
  int i, j;                      /* Loop counters */
  int iCol;                      /* Column number */
  struct ExprList_item *pItem;   /* A term of the ORDER BY clause */
  Parse *pParse;                 /* Parsing context */
  int nResult;                   /* Number of terms in the result set */

  assert( pOrderBy!=0 );
  nResult = pSelect->pEList->nExpr;
  pParse = pNC->pParse;
  for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
    Expr *pE = pItem->pExpr;
    Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pE);
    if( NEVER(pE2==0) ) continue;
    if( zType[0]!='G' ){
1605
1606
1607
1608
1609
1610
1611

1612

1613
1614
1615
1616
1617
1618
1619

  isCompound = p->pPrior!=0;
  nCompound = 0;
  pLeftmost = p;
  while( p ){
    assert( (p->selFlags & SF_Expanded)!=0 );
    assert( (p->selFlags & SF_Resolved)==0 );

    p->selFlags |= SF_Resolved;


    /* Resolve the expressions in the LIMIT and OFFSET clauses. These
    ** are not allowed to refer to any names, so pass an empty NameContext.
    */
    memset(&sNC, 0, sizeof(sNC));
    sNC.pParse = pParse;
    sNC.pWinSelect = p;







>

>







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

  isCompound = p->pPrior!=0;
  nCompound = 0;
  pLeftmost = p;
  while( p ){
    assert( (p->selFlags & SF_Expanded)!=0 );
    assert( (p->selFlags & SF_Resolved)==0 );
    assert( db->suppressErr==0 ); /* SF_Resolved not set if errors suppressed */
    p->selFlags |= SF_Resolved;


    /* Resolve the expressions in the LIMIT and OFFSET clauses. These
    ** are not allowed to refer to any names, so pass an empty NameContext.
    */
    memset(&sNC, 0, sizeof(sNC));
    sNC.pParse = pParse;
    sNC.pWinSelect = p;
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704





1705

1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716













1717
1718
1719
1720
1721
1722
1723
    if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
      assert( NC_MinMaxAgg==SF_MinMaxAgg );
      p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg);
    }else{
      sNC.ncFlags &= ~NC_AllowAgg;
    }
  
    /* If a HAVING clause is present, then there must be a GROUP BY clause.
    */
    if( p->pHaving && !pGroupBy ){
      sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
      return WRC_Abort;
    }
  
    /* Add the output column list to the name-context before parsing the
    ** other expressions in the SELECT statement. This is so that
    ** expressions in the WHERE clause (etc.) can refer to expressions by
    ** aliases in the result set.
    **
    ** Minor point: If this is the case, then the expression will be
    ** re-evaluated for each reference to it.
    */
    assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert|NC_UBaseReg))==0 );
    sNC.uNC.pEList = p->pEList;
    sNC.ncFlags |= NC_UEList;





    if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;

    if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;

    /* Resolve names in table-valued-function arguments */
    for(i=0; i<p->pSrc->nSrc; i++){
      SrcItem *pItem = &p->pSrc->a[i];
      if( pItem->fg.isTabFunc
       && sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg) 
      ){
        return WRC_Abort;
      }
    }














    /* The ORDER BY and GROUP BY clauses may not refer to terms in
    ** outer queries 
    */
    sNC.pNext = 0;
    sNC.ncFlags |= NC_AllowAgg|NC_AllowWin;








<
<
<
<
<
<
<











>
>
>
>
>
|
>











>
>
>
>
>
>
>
>
>
>
>
>
>







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
    if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
      assert( NC_MinMaxAgg==SF_MinMaxAgg );
      p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg);
    }else{
      sNC.ncFlags &= ~NC_AllowAgg;
    }
  







    /* Add the output column list to the name-context before parsing the
    ** other expressions in the SELECT statement. This is so that
    ** expressions in the WHERE clause (etc.) can refer to expressions by
    ** aliases in the result set.
    **
    ** Minor point: If this is the case, then the expression will be
    ** re-evaluated for each reference to it.
    */
    assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert|NC_UBaseReg))==0 );
    sNC.uNC.pEList = p->pEList;
    sNC.ncFlags |= NC_UEList;
    if( p->pHaving ){
      if( !pGroupBy ){
        sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
        return WRC_Abort;
      }
      if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
    }
    if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;

    /* Resolve names in table-valued-function arguments */
    for(i=0; i<p->pSrc->nSrc; i++){
      SrcItem *pItem = &p->pSrc->a[i];
      if( pItem->fg.isTabFunc
       && sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg) 
      ){
        return WRC_Abort;
      }
    }

#ifndef SQLITE_OMIT_WINDOWFUNC
    if( IN_RENAME_OBJECT ){
      Window *pWin;
      for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
        if( sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
         || sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
        ){
          return WRC_Abort;
        }
      }
    }
#endif

    /* The ORDER BY and GROUP BY clauses may not refer to terms in
    ** outer queries 
    */
    sNC.pNext = 0;
    sNC.ncFlags |= NC_AllowAgg|NC_AllowWin;

1738
1739
1740
1741
1742
1743
1744

1745
1746
1747
1748
1749
1750
1751
1752
    ** 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( 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;
    }







>
|







1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
    ** the compound have been resolved.
    **
    ** If there is an ORDER BY clause on a term of a compound-select other
    ** than the right-most term, then that is a syntax error.  But the error
    ** is not detected until much later, and so we need to go ahead and
    ** resolve those symbols on the incorrect ORDER BY for consistency.
    */
    if( p->pOrderBy!=0
     && isCompound<=nCompound  /* Defer right-most ORDER BY of a compound */
     && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER")
    ){
      return WRC_Abort;
    }
    if( db->mallocFailed ){
      return WRC_Abort;
    }
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
          sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
              "the GROUP BY clause");
          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

    /* If this is part of a compound SELECT, check that it has the right
    ** number of expressions in the select list. */
    if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
      sqlite3SelectWrongNumTermsError(pParse, p->pNext);
      return WRC_Abort;
    }








<
<
<
<
<
<
<
<
<
<
<
<
<







1780
1781
1782
1783
1784
1785
1786













1787
1788
1789
1790
1791
1792
1793
          sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
              "the GROUP BY clause");
          return WRC_Abort;
        }
      }
    }














    /* If this is part of a compound SELECT, check that it has the right
    ** number of expressions in the select list. */
    if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
      sqlite3SelectWrongNumTermsError(pParse, p->pNext);
      return WRC_Abort;
    }

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
  Walker w;

  if( pExpr==0 ) return SQLITE_OK;
  savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
  pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
  w.pParse = pNC->pParse;
  w.xExprCallback = resolveExprStep;
  w.xSelectCallback = resolveSelectStep;
  w.xSelectCallback2 = 0;
  w.u.pNC = pNC;
#if SQLITE_MAX_EXPR_DEPTH>0
  w.pParse->nHeight += pExpr->nHeight;
  if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
    return SQLITE_ERROR;
  }
#endif
  sqlite3WalkExpr(&w, pExpr);
#if SQLITE_MAX_EXPR_DEPTH>0
  w.pParse->nHeight -= pExpr->nHeight;
#endif
  assert( EP_Agg==NC_HasAgg );
  assert( EP_Win==NC_HasWin );
  testcase( pNC->ncFlags & NC_HasAgg );
  testcase( pNC->ncFlags & NC_HasWin );
  ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
  pNC->ncFlags |= savedHasAgg;
  return pNC->nErr>0 || w.pParse->nErr>0;
}

/*
** 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.
*/







|


















|







1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
  Walker w;

  if( pExpr==0 ) return SQLITE_OK;
  savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
  pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
  w.pParse = pNC->pParse;
  w.xExprCallback = resolveExprStep;
  w.xSelectCallback = (pNC->ncFlags & NC_NoSelect) ? 0 : resolveSelectStep;
  w.xSelectCallback2 = 0;
  w.u.pNC = pNC;
#if SQLITE_MAX_EXPR_DEPTH>0
  w.pParse->nHeight += pExpr->nHeight;
  if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
    return SQLITE_ERROR;
  }
#endif
  sqlite3WalkExpr(&w, pExpr);
#if SQLITE_MAX_EXPR_DEPTH>0
  w.pParse->nHeight -= pExpr->nHeight;
#endif
  assert( EP_Agg==NC_HasAgg );
  assert( EP_Win==NC_HasWin );
  testcase( pNC->ncFlags & NC_HasAgg );
  testcase( pNC->ncFlags & NC_HasWin );
  ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
  pNC->ncFlags |= savedHasAgg;
  return pNC->nNcErr>0 || w.pParse->nErr>0;
}

/*
** Resolve all names for all expression in an expression list.  This is
** just like sqlite3ResolveExprNames() except that it works for an expression
** list rather than a single expression.
*/
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
    testcase( pNC->ncFlags & NC_HasAgg );
    testcase( pNC->ncFlags & NC_HasWin );
    if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin) ){
      ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
      savedHasAgg |= pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
      pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
    }
    if( pNC->nErr>0 || w.pParse->nErr>0 ) return WRC_Abort;
  }
  pNC->ncFlags |= savedHasAgg;
  return WRC_Continue;
}

/*
** Resolve all names in all expressions of a SELECT and in all







|







1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
    testcase( pNC->ncFlags & NC_HasAgg );
    testcase( pNC->ncFlags & NC_HasWin );
    if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin) ){
      ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
      savedHasAgg |= pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
      pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
    }
    if( w.pParse->nErr>0 ) return WRC_Abort;
  }
  pNC->ncFlags |= savedHasAgg;
  return WRC_Continue;
}

/*
** Resolve all names in all expressions of a SELECT and in all
Changes to src/select.c.
737
738
739
740
741
742
743
744
745
746

747
748








749








750

















751
752
753

754
755






756





757







































































758
759
760
761
762
763
764
765
766
767






768





769
770
771
772
773
774
775
  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.
**








** A jump to addrRepeat is made and the N+1 values are popped from the








** stack if the top N elements are not distinct.

















*/
static void codeDistinct(
  Parse *pParse,     /* Parsing and code generating context */

  int iTab,          /* A sorting index used to test for distinctness */
  int addrRepeat,    /* Jump to here if not distinct */






  int N,             /* Number of elements */





  int iMem           /* First element */







































































){
  Vdbe *v;
  int r1;

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





}

#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 







|
|
|
>
|

>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|

>


>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
<
|
|
<
<
|
|
|
>
>
>
>
>
>
|
>
>
>
>
>







737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875


876
877


878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
  if( iOffset>0 ){
    sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v);
    VdbeComment((v, "OFFSET"));
  }
}

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

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

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

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

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

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

  return iRet;
}

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


  if( eTnctType==WHERE_DISTINCT_UNIQUE || eTnctType==WHERE_DISTINCT_ORDERED ){
    Vdbe *v = pParse->pVdbe;


    sqlite3VdbeChangeToNoop(v, iOpenEphAddr);
    if( sqlite3VdbeGetOp(v, iOpenEphAddr+1)->opcode==OP_Explain ){
      sqlite3VdbeChangeToNoop(v, iOpenEphAddr+1);
    }
    if( eTnctType==WHERE_DISTINCT_ORDERED ){
      /* Change the OP_OpenEphemeral to an OP_Null that sets the MEM_Cleared 
      ** bit on the first register of the previous value.  This will cause the
      ** OP_Ne added in codeDistinct() to always fail on the first iteration of
      ** the loop even if the first row is all NULLs.  */
      VdbeOp *pOp = sqlite3VdbeGetOp(v, iOpenEphAddr);
      pOp->opcode = OP_Null;
      pOp->p1 = 1;
      pOp->p2 = iVal;
    }
  }
}

#ifdef SQLITE_ENABLE_SORTER_REFERENCES
/*
** This function is called as part of inner-loop generation for a SELECT
** statement with an ORDER BY that is not optimized by an index. It 
** determines the expressions, if any, that the sorter-reference 
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
  }

  /* 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 ){
      case WHERE_DISTINCT_ORDERED: {
        VdbeOp *pOp;            /* No longer required OpenEphemeral instr. */
        int iJump;              /* Jump destination */
        int regPrev;            /* Previous row content */

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

        /* 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);
        pOp = sqlite3VdbeGetOp(v, pDistinct->addrTnct);
        pOp->opcode = OP_Null;
        pOp->p1 = 1;
        pOp->p2 = regPrev;
        pOp = 0;  /* Ensure pOp is not used after sqlite3VdbeAddOp() */

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

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

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

  switch( eDest ){
    /* In this mode, write each query result to the key of the temporary







|
<
<
<
<
|
<
<
|
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1133
1134
1135
1136
1137
1138
1139
1140




1141


1142
1143






1144




































1145
1146
1147
1148
1149
1150
1151
  }

  /* If the DISTINCT keyword was present on the SELECT statement
  ** and this row has been seen before, then do not make this row
  ** part of the result.
  */
  if( hasDistinct ){
    int eType = pDistinct->eTnctType;




    int iTab = pDistinct->tabTnct;


    assert( nResultCol==p->pEList->nExpr );
    iTab = codeDistinct(pParse, eType, iTab, iContinue, p->pEList, regResult);






    fixDistinctOpenEph(pParse, eType, iTab, pDistinct->addrTnct);




































    if( pSort==0 ){
      codeOffset(v, p->iOffset, iContinue);
    }
  }

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






1735
1736
1737
1738
1739
1740
1741

      assert( pTab && pExpr->y.pTab==pTab );
      if( pS ){
        /* The "table" is actually a sub-select or a view in the FROM clause
        ** of the SELECT statement. Return the declaration type and origin
        ** data for the result-set column of the sub-select.
        */
        if( iCol>=0 && iCol<pS->pEList->nExpr ){






          /* If iCol 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;







|
>
>
>
>
>
>







1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823

      assert( pTab && pExpr->y.pTab==pTab );
      if( pS ){
        /* The "table" is actually a sub-select or a view in the FROM clause
        ** of the SELECT statement. Return the declaration type and origin
        ** data for the result-set column of the sub-select.
        */
        if( iCol<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;
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
**                              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(
  Parse *pParse,      /* Parser context */
  Select *pSelect     /* Generate column names for this SELECT statement */
){
  Vdbe *v = pParse->pVdbe;
  int i;
  Table *pTab;
  SrcList *pTabList;







|







1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
**                              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.
*/
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;
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
** 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()
*/
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 */
){







|







2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
** The only guarantee that SQLite makes about column names is that if the
** column has an AS clause assigning it a name, that will be the name used.
** That is the only documented guarantee.  However, countless applications
** developed over the years have made baseless assumptions about column names
** and will break if those assumptions changes.  Hence, use extreme caution
** when modifying this routine to avoid breaking legacy.
**
** See Also: sqlite3GenerateColumnNames()
*/
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 */
){
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
#endif

    /* Generate code for the left and right SELECT statements.
    */
    switch( p->op ){
      case TK_ALL: {
        int addr = 0;
        int nLimit;
        assert( !pPrior->pLimit );
        pPrior->iLimit = p->iLimit;
        pPrior->iOffset = p->iOffset;
        pPrior->pLimit = p->pLimit;

        rc = sqlite3Select(pParse, pPrior, &dest);
        pPrior->pLimit = 0;
        if( rc ){
          goto multi_select_end;
        }
        p->pPrior = 0;
        p->iLimit = pPrior->iLimit;
        p->iOffset = pPrior->iOffset;
        if( p->iLimit ){
          addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
          VdbeComment((v, "Jump ahead if LIMIT reached"));
          if( p->iOffset ){
            sqlite3VdbeAddOp3(v, OP_OffsetLimit,
                              p->iLimit, p->iOffset+1, p->iOffset);
          }
        }
        ExplainQueryPlan((pParse, 1, "UNION ALL"));

        rc = sqlite3Select(pParse, p, &dest);
        testcase( rc!=SQLITE_OK );
        pDelete = p->pPrior;
        p->pPrior = pPrior;
        p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
        if( p->pLimit
         && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)







|




>

















>







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

    /* Generate code for the left and right SELECT statements.
    */
    switch( p->op ){
      case TK_ALL: {
        int addr = 0;
        int nLimit = 0;  /* Initialize to suppress harmless compiler warning */
        assert( !pPrior->pLimit );
        pPrior->iLimit = p->iLimit;
        pPrior->iOffset = p->iOffset;
        pPrior->pLimit = p->pLimit;
        SELECTTRACE(1, pParse, p, ("multiSelect UNION ALL left...\n"));
        rc = sqlite3Select(pParse, pPrior, &dest);
        pPrior->pLimit = 0;
        if( rc ){
          goto multi_select_end;
        }
        p->pPrior = 0;
        p->iLimit = pPrior->iLimit;
        p->iOffset = pPrior->iOffset;
        if( p->iLimit ){
          addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
          VdbeComment((v, "Jump ahead if LIMIT reached"));
          if( p->iOffset ){
            sqlite3VdbeAddOp3(v, OP_OffsetLimit,
                              p->iLimit, p->iOffset+1, p->iOffset);
          }
        }
        ExplainQueryPlan((pParse, 1, "UNION ALL"));
        SELECTTRACE(1, pParse, p, ("multiSelect UNION ALL right...\n"));
        rc = sqlite3Select(pParse, p, &dest);
        testcase( rc!=SQLITE_OK );
        pDelete = p->pPrior;
        p->pPrior = pPrior;
        p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
        if( p->pLimit
         && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
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
        }
          
  
        /* Code the SELECT statements to our left
        */
        assert( !pPrior->pOrderBy );
        sqlite3SelectDestInit(&uniondest, priorOp, unionTab);

        rc = sqlite3Select(pParse, pPrior, &uniondest);
        if( rc ){
          goto multi_select_end;
        }
  
        /* Code the current SELECT statement
        */
        if( p->op==TK_EXCEPT ){
          op = SRT_Except;
        }else{
          assert( p->op==TK_UNION );
          op = SRT_Union;
        }
        p->pPrior = 0;
        pLimit = p->pLimit;
        p->pLimit = 0;
        uniondest.eDest = op;
        ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
                          sqlite3SelectOpName(p->op)));

        rc = sqlite3Select(pParse, p, &uniondest);
        testcase( rc!=SQLITE_OK );
        assert( p->pOrderBy==0 );
        pDelete = p->pPrior;
        p->pPrior = pPrior;
        p->pOrderBy = 0;
        if( p->op==TK_UNION ){







>



















>







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
        }
          
  
        /* Code the SELECT statements to our left
        */
        assert( !pPrior->pOrderBy );
        sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
        SELECTTRACE(1, pParse, p, ("multiSelect EXCEPT/UNION left...\n"));
        rc = sqlite3Select(pParse, pPrior, &uniondest);
        if( rc ){
          goto multi_select_end;
        }
  
        /* Code the current SELECT statement
        */
        if( p->op==TK_EXCEPT ){
          op = SRT_Except;
        }else{
          assert( p->op==TK_UNION );
          op = SRT_Union;
        }
        p->pPrior = 0;
        pLimit = p->pLimit;
        p->pLimit = 0;
        uniondest.eDest = op;
        ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
                          sqlite3SelectOpName(p->op)));
        SELECTTRACE(1, pParse, p, ("multiSelect EXCEPT/UNION right...\n"));
        rc = sqlite3Select(pParse, p, &uniondest);
        testcase( rc!=SQLITE_OK );
        assert( p->pOrderBy==0 );
        pDelete = p->pPrior;
        p->pPrior = pPrior;
        p->pOrderBy = 0;
        if( p->op==TK_UNION ){
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->addrOpenEphm[0] = addr;
        findRightmost(p)->selFlags |= SF_UsesEphemeral;
        assert( p->pEList );
  
        /* Code the SELECTs to our left into temporary table "tab1".
        */
        sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);

        rc = sqlite3Select(pParse, pPrior, &intersectdest);
        if( rc ){
          goto multi_select_end;
        }
  
        /* Code the current SELECT into temporary table "tab2"
        */
        addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
        assert( p->addrOpenEphm[1] == -1 );
        p->addrOpenEphm[1] = addr;
        p->pPrior = 0;
        pLimit = p->pLimit;
        p->pLimit = 0;
        intersectdest.iSDParm = tab2;
        ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
                          sqlite3SelectOpName(p->op)));

        rc = sqlite3Select(pParse, p, &intersectdest);
        testcase( rc!=SQLITE_OK );
        pDelete = p->pPrior;
        p->pPrior = pPrior;
        if( p->nSelectRow>pPrior->nSelectRow ){
          p->nSelectRow = pPrior->nSelectRow;
        }







>
















>







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
        p->addrOpenEphm[0] = addr;
        findRightmost(p)->selFlags |= SF_UsesEphemeral;
        assert( p->pEList );
  
        /* Code the SELECTs to our left into temporary table "tab1".
        */
        sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
        SELECTTRACE(1, pParse, p, ("multiSelect INTERSECT left...\n"));
        rc = sqlite3Select(pParse, pPrior, &intersectdest);
        if( rc ){
          goto multi_select_end;
        }
  
        /* Code the current SELECT into temporary table "tab2"
        */
        addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
        assert( p->addrOpenEphm[1] == -1 );
        p->addrOpenEphm[1] = addr;
        p->pPrior = 0;
        pLimit = p->pLimit;
        p->pLimit = 0;
        intersectdest.iSDParm = tab2;
        ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
                          sqlite3SelectOpName(p->op)));
        SELECTTRACE(1, pParse, p, ("multiSelect INTERSECT right...\n"));
        rc = sqlite3Select(pParse, p, &intersectdest);
        testcase( rc!=SQLITE_OK );
        pDelete = p->pPrior;
        p->pPrior = pPrior;
        if( p->nSelectRow>pPrior->nSelectRow ){
          p->nSelectRow = pPrior->nSelectRow;
        }
3458
3459
3460
3461
3462
3463
3464



3465
3466
3467
3468
3469
3470
3471
  /* Reassembly the compound query so that it will be freed correctly
  ** by the calling function */
  if( p->pPrior ){
    sqlite3SelectDelete(db, p->pPrior);
  }
  p->pPrior = pPrior;
  pPrior->pNext = p;




  /*** TBD:  Insert subroutine calls to close cursors on incomplete
  **** subqueries ****/
  ExplainQueryPlanPop(pParse);
  return pParse->nErr!=0;
}
#endif







>
>
>







3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
  /* Reassembly the compound query so that it will be freed correctly
  ** by the calling function */
  if( p->pPrior ){
    sqlite3SelectDelete(db, p->pPrior);
  }
  p->pPrior = pPrior;
  pPrior->pNext = p;

  sqlite3ExprListDelete(db, pPrior->pOrderBy);
  pPrior->pOrderBy = 0;

  /*** TBD:  Insert subroutine calls to close cursors on incomplete
  **** subqueries ****/
  ExplainQueryPlanPop(pParse);
  return pParse->nErr!=0;
}
#endif
3513
3514
3515
3516
3517
3518
3519

3520
3521
3522


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




3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
  ){
    pExpr->iRightJoinTable = pSubst->iNewTable;
  }
  if( pExpr->op==TK_COLUMN
   && pExpr->iTable==pSubst->iTable
   && !ExprHasProperty(pExpr, EP_FixedCol)
  ){

    if( pExpr->iColumn<0 ){
      pExpr->op = TK_NULL;
    }else{


      Expr *pNew;
      Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
      Expr ifNullRow;
      assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr );
      assert( pExpr->pRight==0 );
      if( sqlite3ExprIsVector(pCopy) ){
        sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
      }else{
        sqlite3 *db = pSubst->pParse->db;
        if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){
          memset(&ifNullRow, 0, sizeof(ifNullRow));
          ifNullRow.op = TK_IF_NULL_ROW;
          ifNullRow.pLeft = pCopy;
          ifNullRow.iTable = pSubst->iNewTable;
          ifNullRow.flags = EP_IfNullRow;
          pCopy = &ifNullRow;
        }
        testcase( ExprHasProperty(pCopy, EP_Subquery) );
        pNew = sqlite3ExprDup(db, pCopy, 0);




        if( pNew && pSubst->isLeftJoin ){
          ExprSetProperty(pNew, EP_CanBeNull);
        }
        if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){
          sqlite3SetJoinExpr(pNew, pExpr->iRightJoinTable);
        }
        sqlite3ExprDelete(db, pExpr);
        pExpr = pNew;

        /* Ensure that the expression now has an implicit collation sequence,
        ** just as it did when it was a column of a view or sub-query. */
        if( pExpr ){
          if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){
            CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
            pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr, 
                (pColl ? pColl->zName : "BINARY")
            );
          }
          ExprClearProperty(pExpr, EP_Collate);
        }
      }
    }
  }else{
    if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){
      pExpr->iTable = pSubst->iNewTable;
    }
    pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);







>


|
>
>



















>
>
>
>
|


|







<
|
|
|
|
|
|
|
<







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

        /* Ensure that the expression now has an implicit collation sequence,
        ** just as it did when it was a column of a view or sub-query. */

        if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){
          CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
          pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr, 
              (pColl ? pColl->zName : "BINARY")
          );
        }
        ExprClearProperty(pExpr, EP_Collate);

      }
    }
  }else{
    if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){
      pExpr->iTable = pSubst->iNewTable;
    }
    pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);
3673
3674
3675
3676
3677
3678
3679



3680
3681
3682
3683
3684
3685
3686
3687
  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;



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








>
>
>
|







3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
  int iExcept                     /* FROM clause item to skip */
){
  int i;
  SrcItem *pItem;
  for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
    if( i!=iExcept ){
      Select *p;
      if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor]==0 ){
        aCsrMap[pItem->iCursor] = pParse->nTab++;
      }
      pItem->iCursor = aCsrMap[pItem->iCursor];
      for(p=pItem->pSelect; p; p=p->pPrior){
        srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
      }
    }
  }
}

4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
    p->pOrderBy = pOrderBy;
    p->op = TK_ALL;
    pSubitem->pTab = pItemTab;
    if( pNew==0 ){
      p->pPrior = pPrior;
    }else{
      pNew->selId = ++pParse->nSelect;
      if( aCsrMap && db->mallocFailed==0 ){
        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"







|







4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
    p->pOrderBy = pOrderBy;
    p->op = TK_ALL;
    pSubitem->pTab = pItemTab;
    if( pNew==0 ){
      p->pPrior = pPrior;
    }else{
      pNew->selId = ++pParse->nSelect;
      if( aCsrMap && ALWAYS(db->mallocFailed==0) ){
        renumberCursors(pParse, pNew, iFrom, aCsrMap);
      }
      pNew->pPrior = pPrior;
      if( pPrior ) pPrior->pNext = pNew;
      pNew->pNext = p;
      p->pPrior = pNew;
      SELECTTRACE(2,pParse,p,("compound-subquery flattener"
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
** 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( pExpr->op==TK_AND ){
    findConstInWhere(pConst, pExpr->pRight);
    findConstInWhere(pConst, pExpr->pLeft);
    return;
  }
  if( pExpr->op!=TK_EQ ) return;







|







4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
** Find all terms of COLUMN=VALUE or VALUE=COLUMN in pExpr where VALUE
** is a constant expression and where the term must be true because it
** is part of the AND-connected terms of the expression.  For each term
** found, add it to the pConst structure.
*/
static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
  Expr *pRight, *pLeft;
  if( NEVER(pExpr==0) ) return;
  if( ExprHasProperty(pExpr, EP_FromJoin) ) return;
  if( pExpr->op==TK_AND ){
    findConstInWhere(pConst, pExpr->pRight);
    findConstInWhere(pConst, pExpr->pLeft);
    return;
  }
  if( pExpr->op!=TK_EQ ) return;
4908
4909
4910
4911
4912
4913
4914

4915
4916
4917
4918
4919
4920
4921
    int i;
    for(i=0; i<p->nCte; i++){
      if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
        *ppContext = p;
        return &p->a[i];
      }
    }

  }
  return 0;
}

/* The code generator maintains a stack of active WITH clauses
** with the inner-most WITH clause being at the top of the stack.
**







>







5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
    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.
**
4967
4968
4969
4970
4971
4972
4973








4974
4975
4976
4977
4978
4979
4980
    /* There are no WITH clauses in the stack.  No match is possible */
    return 0;
  }
  if( pFrom->zDatabase!=0 ){
    /* The FROM term contains a schema qualifier (ex: main.t1) and so
    ** it cannot possibly be a CTE reference. */
    return 0;








  }
  pCte = searchWith(pParse->pWith, pFrom, &pWith);
  if( pCte ){
    sqlite3 *db = pParse->db;
    Table *pTab;
    ExprList *pEList;
    Select *pSel;







>
>
>
>
>
>
>
>







5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
    /* There are no WITH clauses in the stack.  No match is possible */
    return 0;
  }
  if( pFrom->zDatabase!=0 ){
    /* The FROM term contains a schema qualifier (ex: main.t1) and so
    ** it cannot possibly be a CTE reference. */
    return 0;
  }
  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;
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
** 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){
  Parse *pParse = pWalker->pParse;
  if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){
    With *pWith = findRightmost(p)->pWith;
    if( pWith!=0 ){
      assert( pParse->pWith==pWith || pParse->nErr );
      pParse->pWith = pWith->pOuter;
    }
  }
}
#else
#define selectPopWith 0
#endif

/*
** The SrcList_item structure passed as the second argument represents a
** sub-query in the FROM clause of a SELECT statement. This function
** allocates and populates the SrcList_item.pTab object. If successful,
** SQLITE_OK is returned. Otherwise, if an OOM error is encountered,







|









<
<







5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240


5241
5242
5243
5244
5245
5246
5247
** 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. 
*/
void sqlite3SelectPopWith(Walker *pWalker, Select *p){
  Parse *pParse = pWalker->pParse;
  if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){
    With *pWith = findRightmost(p)->pWith;
    if( pWith!=0 ){
      assert( pParse->pWith==pWith || pParse->nErr );
      pParse->pWith = pWith->pOuter;
    }
  }
}


#endif

/*
** The SrcList_item structure passed as the second argument represents a
** sub-query in the FROM clause of a SELECT statement. This function
** allocates and populates the SrcList_item.pTab object. If successful,
** SQLITE_OK is returned. Otherwise, if an OOM error is encountered,
5154
5155
5156
5157
5158
5159
5160


5161




5162
5163
5164
5165
5166
5167
5168
  }else{
    pTab->zName = sqlite3MPrintf(pParse->db, "subquery_%u", pSel->selId);
  }
  while( pSel->pPrior ){ pSel = pSel->pPrior; }
  sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
  pTab->iPKey = -1;
  pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );


  pTab->tabFlags |= TF_Ephemeral;





  return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
}

/*
** This routine is a Walker callback for "expanding" a SELECT statement.
** "Expanding" means to do the following:







>
>
|
>
>
>
>







5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
  }else{
    pTab->zName = sqlite3MPrintf(pParse->db, "subquery_%u", pSel->selId);
  }
  while( pSel->pPrior ){ pSel = pSel->pPrior; }
  sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
  pTab->iPKey = -1;
  pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
  /* The usual case - do not allow ROWID on a subquery */
  pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
#else
  pTab->tabFlags |= TF_Ephemeral;  /* Legacy compatibility mode */
#endif


  return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
}

/*
** This routine is a Walker callback for "expanding" a SELECT statement.
** "Expanding" means to do the following:
5208
5209
5210
5211
5212
5213
5214









5215
5216
5217
5218
5219
5220
5221
  }
  if( pWalker->eCode ){
    /* Renumber selId because it has been copied from a view */
    p->selId = ++pParse->nSelect;
  }
  pTabList = p->pSrc;
  pEList = p->pEList;









  sqlite3WithPush(pParse, p->pWith, 0);

  /* Make sure cursor numbers have been assigned to all entries in
  ** the FROM clause of the SELECT statement.
  */
  sqlite3SrcListAssignCursors(pParse, pTabList);








>
>
>
>
>
>
>
>
>







5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
  }
  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);

5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
  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.eCode = 0;
  sqlite3WalkSelect(&w, pSelect);
}


#ifndef SQLITE_OMIT_SUBQUERY
/*







|







5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
  w.pParse = pParse;
  if( OK_IF_ALWAYS_TRUE(pParse->hasCompound) ){
    w.xSelectCallback = convertCompoundSelectToSubquery;
    w.xSelectCallback2 = 0;
    sqlite3WalkSelect(&w, pSelect);
  }
  w.xSelectCallback = selectExpander;
  w.xSelectCallback2 = sqlite3SelectPopWith;
  w.eCode = 0;
  sqlite3WalkSelect(&w, pSelect);
}


#ifndef SQLITE_OMIT_SUBQUERY
/*
5641
5642
5643
5644
5645
5646
5647
5648
5649


5650
5651
5652
5653
5654
5655
5656
      assert( !ExprHasProperty(pE, EP_xIsSelect) );
      if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
        sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
           "argument");
        pFunc->iDistinct = -1;
      }else{
        KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0);
        sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
                          (char*)pKeyInfo, P4_KEYINFO);


      }
    }
  }
}

/*
** Invoke the OP_AggFinalize opcode for every aggregate function







|
|
>
>







5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
      assert( !ExprHasProperty(pE, EP_xIsSelect) );
      if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
        sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
           "argument");
        pFunc->iDistinct = -1;
      }else{
        KeyInfo *pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0);
        pFunc->iDistAddr = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, 
            pFunc->iDistinct, 0, 0, (char*)pKeyInfo, P4_KEYINFO);
        ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s(DISTINCT)",
                          pFunc->pFunc->zName));
      }
    }
  }
}

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





5682
5683
5684
5685
5686
5687
5688
** the current cursor position.
**
** If regAcc is non-zero and there are no min() or max() aggregates
** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator
** registers if register regAcc contains 0. The caller will take care
** of setting and clearing regAcc.
*/
static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){





  Vdbe *v = pParse->pVdbe;
  int i;
  int regHit = 0;
  int addrHitTest = 0;
  struct AggInfo_func *pF;
  struct AggInfo_col *pC;








|
>
>
>
>
>







5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
** the current cursor position.
**
** If regAcc is non-zero and there are no min() or max() aggregates
** in pAggInfo, then only populate the pAggInfo->nAccumulator accumulator
** registers if register regAcc contains 0. The caller will take care
** of setting and clearing regAcc.
*/
static void updateAccumulator(
  Parse *pParse, 
  int regAcc, 
  AggInfo *pAggInfo,
  int eDistinctType
){
  Vdbe *v = pParse->pVdbe;
  int i;
  int regHit = 0;
  int addrHitTest = 0;
  struct AggInfo_func *pF;
  struct AggInfo_col *pC;

5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
      nArg = pList->nExpr;
      regAgg = sqlite3GetTempRange(pParse, nArg);
      sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP);
    }else{
      nArg = 0;
      regAgg = 0;
    }
    if( pF->iDistinct>=0 ){
      if( addrNext==0 ){ 
        addrNext = sqlite3VdbeMakeLabel(pParse);
      }
      testcase( nArg==0 );  /* Error condition */
      testcase( nArg>1 );   /* Also an error */
      codeDistinct(pParse, pF->iDistinct, addrNext, 1, 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++){







|



|
<
|







5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859

5860
5861
5862
5863
5864
5865
5866
5867
      nArg = pList->nExpr;
      regAgg = sqlite3GetTempRange(pParse, nArg);
      sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP);
    }else{
      nArg = 0;
      regAgg = 0;
    }
    if( pF->iDistinct>=0 && pList ){
      if( addrNext==0 ){ 
        addrNext = sqlite3VdbeMakeLabel(pParse);
      }
      pF->iDistinct = codeDistinct(pParse, eDistinctType, 

          pF->iDistinct, addrNext, pList, regAgg);
    }
    if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
      CollSeq *pColl = 0;
      struct ExprList_item *pItem;
      int j;
      assert( pList!=0 );  /* pList!=0 if pF->pFunc has NEEDCOLL */
      for(j=0, pItem=pList->a; !pColl && j<nArg; j++, pItem++){
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
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",
        pTab->zName,
        bCover ? " USING COVERING INDEX " : "",
        bCover ? pIdx->zName : ""
    );
  }
}
#else







|







5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
static void explainSimpleCount(
  Parse *pParse,                  /* Parse context */
  Table *pTab,                    /* Table being queried */
  Index *pIdx                     /* Index used to optimize scan, or NULL */
){
  if( pParse->explain==2 ){
    int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
    sqlite3VdbeExplain(pParse, 0, "SCAN %s%s%s",
        pTab->zName,
        bCover ? " USING COVERING INDEX " : "",
        bCover ? pIdx->zName : ""
    );
  }
}
#else
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
        );
        goto select_end;
      }
    }
  }

  if( pDest->eDest==SRT_Output ){
    generateColumnNames(pParse, p);
  }

#ifndef SQLITE_OMIT_WINDOWFUNC
  rc = sqlite3WindowRewrite(pParse, p);
  if( rc ){
    assert( db->mallocFailed || pParse->nErr>0 );
    goto select_end;
  }
#if SELECTTRACE_ENABLED
  if( p->pWin && (sqlite3SelectTrace & 0x108)!=0 ){
    SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
    sqlite3TreeViewSelect(0, p, 0);







|



|
<







6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227

6228
6229
6230
6231
6232
6233
6234
        );
        goto select_end;
      }
    }
  }

  if( pDest->eDest==SRT_Output ){
    sqlite3GenerateColumnNames(pParse, p);
  }

#ifndef SQLITE_OMIT_WINDOWFUNC
  if( sqlite3WindowRewrite(pParse, p) ){

    assert( db->mallocFailed || pParse->nErr>0 );
    goto select_end;
  }
#if SELECTTRACE_ENABLED
  if( p->pWin && (sqlite3SelectTrace & 0x108)!=0 ){
    SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
    sqlite3TreeViewSelect(0, p, 0);
6220
6221
6222
6223
6224
6225
6226
6227

6228
6229
6230
6231
6232
6233
6234
#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

   && OptimizationEnabled(db, SQLITE_PropagateConst)
   && propagateConstants(pParse, p)
  ){
#if SELECTTRACE_ENABLED
    if( sqlite3SelectTrace & 0x100 ){
      SELECTTRACE(0x100,pParse,p,("After constant propagation:\n"));
      sqlite3TreeViewSelect(0, p, 0);







|
>







6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
#endif

  /* Do the WHERE-clause constant propagation optimization if this is
  ** a join.  No need to speed time on this operation for non-join queries
  ** as the equivalent optimization will be handled by query planner in
  ** sqlite3WhereBegin().
  */
  if( p->pWhere!=0
   && p->pWhere->op==TK_AND
   && OptimizationEnabled(db, SQLITE_PropagateConst)
   && propagateConstants(pParse, p)
  ){
#if SELECTTRACE_ENABLED
    if( sqlite3SelectTrace & 0x100 ){
      SELECTTRACE(0x100,pParse,p,("After constant propagation:\n"));
      sqlite3TreeViewSelect(0, p, 0);
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
      /* 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));
      pItem->addrFillSub = addrTop;
      sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
      ExplainQueryPlan((pParse, 1, "CO-ROUTINE %u", pSub->selId));
      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);







|


|







6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
      /* Implement a co-routine that will return a single row of the result
      ** set on each invocation.
      */
      int addrTop = sqlite3VdbeCurrentAddr(v)+1;
     
      pItem->regReturn = ++pParse->nMem;
      sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
      VdbeComment((v, "%!S", pItem));
      pItem->addrFillSub = addrTop;
      sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
      ExplainQueryPlan((pParse, 1, "CO-ROUTINE %!S", pItem));
      sqlite3Select(pParse, pSub, &dest);
      pItem->pTab->nRowLogEst = pSub->nSelectRow;
      pItem->fg.viaCoroutine = 1;
      pItem->regResult = dest.iSdst;
      sqlite3VdbeEndCoroutine(v, pItem->regReturn);
      sqlite3VdbeJumpHere(v, addrTop-1);
      sqlite3ClearTempRegCache(pParse);
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
      topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
      pItem->addrFillSub = topAddr+1;
      if( pItem->fg.isCorrelated==0 ){
        /* If the subquery is not correlated and if we are not inside of
        ** a trigger, then we only need to compute the value of the subquery
        ** once. */
        onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
        VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
      }else{
        VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
      }
      sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
      ExplainQueryPlan((pParse, 1, "MATERIALIZE %u", pSub->selId));
      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);
      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;







|

|


|




|







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
      topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
      pItem->addrFillSub = topAddr+1;
      if( pItem->fg.isCorrelated==0 ){
        /* If the subquery is not correlated and if we are not inside of
        ** a trigger, then we only need to compute the value of the subquery
        ** once. */
        onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
        VdbeComment((v, "materialize %!S", pItem));
      }else{
        VdbeNoopComment((v, "materialize %!S", pItem));
      }
      sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
      ExplainQueryPlan((pParse, 1, "MATERIALIZE %!S", pItem));
      sqlite3Select(pParse, pSub, &dest);
      pItem->pTab->nRowLogEst = pSub->nSelectRow;
      if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
      retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
      VdbeComment((v, "end %!S", pItem));
      sqlite3VdbeChangeP1(v, topAddr, retAddr);
      sqlite3ClearTempRegCache(pParse);
      if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){
        CteUse *pCteUse = pItem->u2.pCteUse;
        pCteUse->addrM9e = pItem->addrFillSub;
        pCteUse->regRtn = pItem->regReturn;
        pCteUse->iCur = pItem->iCursor;
6758
6759
6760
6761
6762
6763
6764














6765
6766
6767
6768
6769
6770
6771
      int addrOutputRow;  /* Start of subroutine that outputs a result row */
      int regOutputRow;   /* Return address register for output subroutine */
      int addrSetAbort;   /* Set the abort flag and return */
      int addrTopOfLoop;  /* Top of the input loop */
      int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
      int addrReset;      /* Subroutine for resetting the accumulator */
      int regReset;       /* Return address register for reset subroutine */















      /* If there is a GROUP BY clause we might need a sorting index to
      ** implement it.  Allocate that sorting index now.  If it turns out
      ** that we do not need it after all, the OP_SorterOpen instruction
      ** will be converted into a Noop.  
      */
      pAggInfo->sortingIdx = pParse->nTab++;







>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
      int addrOutputRow;  /* Start of subroutine that outputs a result row */
      int regOutputRow;   /* Return address register for output subroutine */
      int addrSetAbort;   /* Set the abort flag and return */
      int addrTopOfLoop;  /* Top of the input loop */
      int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
      int addrReset;      /* Subroutine for resetting the accumulator */
      int regReset;       /* Return address register for reset subroutine */
      ExprList *pDistinct = 0;
      u16 distFlag = 0;
      int eDist = WHERE_DISTINCT_NOOP;

      if( pAggInfo->nFunc==1 
       && pAggInfo->aFunc[0].iDistinct>=0
       && pAggInfo->aFunc[0].pFExpr->x.pList
      ){
        Expr *pExpr = pAggInfo->aFunc[0].pFExpr->x.pList->a[0].pExpr;
        pExpr = sqlite3ExprDup(db, pExpr, 0);
        pDistinct = sqlite3ExprListDup(db, pGroupBy, 0);
        pDistinct = sqlite3ExprListAppend(pParse, pDistinct, pExpr);
        distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
      }

      /* If there is a GROUP BY clause we might need a sorting index to
      ** implement it.  Allocate that sorting index now.  If it turns out
      ** that we do not need it after all, the OP_SorterOpen instruction
      ** will be converted into a Noop.  
      */
      pAggInfo->sortingIdx = pParse->nTab++;
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804




6805
6806
6807
6808
6809
6810
6811
      /* 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
      );
      if( pWInfo==0 ) goto select_end;




      SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
      if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
        /* The optimizer is able to deliver rows in group by order so
        ** we do not have to sort.  The OP_OpenEphemeral table will be
        ** cancelled later because we still need to use the pKeyInfo
        */
        groupBySort = 0;







|
|

|
>
>
>
>







6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
      /* Begin a loop that will extract all source rows in GROUP BY order.
      ** This might involve two separate loops with an OP_Sort in between, or
      ** it might be a single loop that uses an index to extract information
      ** in the right order to begin with.
      */
      sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
      SELECTTRACE(1,pParse,p,("WhereBegin\n"));
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct,
          WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0) | distFlag, 0
      );
      if( pWInfo==0 ){
        sqlite3ExprListDelete(db, pDistinct);
        goto select_end;
      }
      eDist = sqlite3WhereIsDistinct(pWInfo);
      SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
      if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
        /* The optimizer is able to deliver rows in group by order so
        ** we do not have to sort.  The OP_OpenEphemeral table will be
        ** cancelled later because we still need to use the pKeyInfo
        */
        groupBySort = 0;
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
      sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
      VdbeComment((v, "reset accumulator"));

      /* Update the aggregate accumulators based on the content of
      ** the current row
      */
      sqlite3VdbeJumpHere(v, addr1);
      updateAccumulator(pParse, iUseFlag, pAggInfo);
      sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
      VdbeComment((v, "indicate data in accumulator"));

      /* End of the loop
      */
      if( groupBySort ){
        sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop);
        VdbeCoverage(v);
      }else{
        SELECTTRACE(1,pParse,p,("WhereEnd\n"));
        sqlite3WhereEnd(pWInfo);
        sqlite3VdbeChangeToNoop(v, addrSortingIdx);
      }


      /* Output the final row of result
      */
      sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
      VdbeComment((v, "output final row"));

      /* Jump over the subroutines







|













>







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
      sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
      VdbeComment((v, "reset accumulator"));

      /* Update the aggregate accumulators based on the content of
      ** the current row
      */
      sqlite3VdbeJumpHere(v, addr1);
      updateAccumulator(pParse, iUseFlag, pAggInfo, eDist);
      sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
      VdbeComment((v, "indicate data in accumulator"));

      /* End of the loop
      */
      if( groupBySort ){
        sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop);
        VdbeCoverage(v);
      }else{
        SELECTTRACE(1,pParse,p,("WhereEnd\n"));
        sqlite3WhereEnd(pWInfo);
        sqlite3VdbeChangeToNoop(v, addrSortingIdx);
      }
      sqlite3ExprListDelete(db, pDistinct);

      /* Output the final row of result
      */
      sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
      VdbeComment((v, "output final row"));

      /* Jump over the subroutines
6971
6972
6973
6974
6975
6976
6977
6978




6979
6980
6981
6982
6983
6984
6985
      /* Generate a subroutine that will reset the group-by accumulator
      */
      sqlite3VdbeResolveLabel(v, addrReset);
      resetAccumulator(pParse, pAggInfo);
      sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
      VdbeComment((v, "indicate accumulator empty"));
      sqlite3VdbeAddOp1(v, OP_Return, regReset);
     




    } /* endif pGroupBy.  Begin aggregate queries without GROUP BY: */
    else {
      Table *pTab;
      if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){
        /* If isSimpleCount() returns a pointer to a Table structure, then
        ** the SQL statement is of the form:
        **







|
>
>
>
>







7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
      /* Generate a subroutine that will reset the group-by accumulator
      */
      sqlite3VdbeResolveLabel(v, addrReset);
      resetAccumulator(pParse, pAggInfo);
      sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
      VdbeComment((v, "indicate accumulator empty"));
      sqlite3VdbeAddOp1(v, OP_Return, regReset);

      if( eDist!=WHERE_DISTINCT_NOOP ){
        struct AggInfo_func *pF = &pAggInfo->aFunc[0];
        fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
      }
    } /* endif pGroupBy.  Begin aggregate queries without GROUP BY: */
    else {
      Table *pTab;
      if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){
        /* If isSimpleCount() returns a pointer to a Table structure, then
        ** the SQL statement is of the form:
        **
7035
7036
7037
7038
7039
7040
7041



7042
7043
7044
7045
7046
7047
7048
          sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
        }
        sqlite3VdbeAddOp2(v, OP_Count, iCsr, pAggInfo->aFunc[0].iMem);
        sqlite3VdbeAddOp1(v, OP_Close, iCsr);
        explainSimpleCount(pParse, pTab, pBest);
      }else{
        int regAcc = 0;           /* "populate accumulators" flag */




        /* If there are accumulator registers but no min() or max() functions
        ** without FILTER clauses, allocate register regAcc. Register regAcc
        ** will contain 0 the first time the inner loop runs, and 1 thereafter.
        ** The code generated by updateAccumulator() uses this to ensure
        ** that the accumulator registers are (a) updated only once if
        ** there are no min() or max functions or (b) always updated for the







>
>
>







7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
          sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
        }
        sqlite3VdbeAddOp2(v, OP_Count, iCsr, pAggInfo->aFunc[0].iMem);
        sqlite3VdbeAddOp1(v, OP_Close, iCsr);
        explainSimpleCount(pParse, pTab, pBest);
      }else{
        int regAcc = 0;           /* "populate accumulators" flag */
        ExprList *pDistinct = 0;
        u16 distFlag = 0;
        int eDist;

        /* If there are accumulator registers but no min() or max() functions
        ** without FILTER clauses, allocate register regAcc. Register regAcc
        ** will contain 0 the first time the inner loop runs, and 1 thereafter.
        ** The code generated by updateAccumulator() uses this to ensure
        ** that the accumulator registers are (a) updated only once if
        ** there are no min() or max functions or (b) always updated for the
7058
7059
7060
7061
7062
7063
7064



7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088

7089





7090
7091
7092
7093
7094
7095
7096
              break;
            }
          }
          if( i==pAggInfo->nFunc ){
            regAcc = ++pParse->nMem;
            sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
          }



        }

        /* This case runs if the aggregate has no GROUP BY clause.  The
        ** processing is much simpler since there is only a single row
        ** of output.
        */
        assert( p->pGroupBy==0 );
        resetAccumulator(pParse, pAggInfo);

        /* If this query is a candidate for the min/max optimization, then
        ** minMaxFlag will have been previously set to either
        ** WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX and pMinMaxOrderBy will
        ** be an appropriate ORDER BY expression for the optimization.
        */
        assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 );
        assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 );

        SELECTTRACE(1,pParse,p,("WhereBegin\n"));
        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
                                   0, minMaxFlag, 0);
        if( pWInfo==0 ){
          goto select_end;
        }
        SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));

        updateAccumulator(pParse, regAcc, pAggInfo);





        if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
        if( minMaxFlag ){
          sqlite3WhereMinMaxOptEarlyOut(v, pWInfo);
        }
        SELECTTRACE(1,pParse,p,("WhereEnd\n"));
        sqlite3WhereEnd(pWInfo);
        finalizeAggFunctions(pParse, pAggInfo);







>
>
>



















|




>
|
>
>
>
>
>







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
              break;
            }
          }
          if( i==pAggInfo->nFunc ){
            regAcc = ++pParse->nMem;
            sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
          }
        }else if( pAggInfo->nFunc==1 && pAggInfo->aFunc[0].iDistinct>=0 ){
          pDistinct = pAggInfo->aFunc[0].pFExpr->x.pList;
          distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
        }

        /* This case runs if the aggregate has no GROUP BY clause.  The
        ** processing is much simpler since there is only a single row
        ** of output.
        */
        assert( p->pGroupBy==0 );
        resetAccumulator(pParse, pAggInfo);

        /* If this query is a candidate for the min/max optimization, then
        ** minMaxFlag will have been previously set to either
        ** WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX and pMinMaxOrderBy will
        ** be an appropriate ORDER BY expression for the optimization.
        */
        assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 );
        assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 );

        SELECTTRACE(1,pParse,p,("WhereBegin\n"));
        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
                                   pDistinct, minMaxFlag|distFlag, 0);
        if( pWInfo==0 ){
          goto select_end;
        }
        SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
        eDist = sqlite3WhereIsDistinct(pWInfo);
        updateAccumulator(pParse, regAcc, pAggInfo, eDist);
        if( eDist!=WHERE_DISTINCT_NOOP ){
          struct AggInfo_func *pF = &pAggInfo->aFunc[0];
          fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
        }

        if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
        if( minMaxFlag ){
          sqlite3WhereMinMaxOptEarlyOut(v, pWInfo);
        }
        SELECTTRACE(1,pParse,p,("WhereEnd\n"));
        sqlite3WhereEnd(pWInfo);
        finalizeAggFunctions(pParse, pAggInfo);
7127
7128
7129
7130
7131
7132
7133


7134
7135
7136
7137
7138
7139
7140
  ** set the return code to 1. Otherwise 0. */
  rc = (pParse->nErr>0);

  /* Control jumps to here if an error is encountered above, or upon
  ** successful coding of the SELECT.
  */
select_end:


  sqlite3ExprListDelete(db, pMinMaxOrderBy);
#ifdef SQLITE_DEBUG
  if( pAggInfo && !db->mallocFailed ){
    for(i=0; i<pAggInfo->nColumn; i++){
      Expr *pExpr = pAggInfo->aCol[i].pCExpr;
      assert( pExpr!=0 );
      assert( pExpr->pAggInfo==pAggInfo );







>
>







7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
  ** set the return code to 1. Otherwise 0. */
  rc = (pParse->nErr>0);

  /* Control jumps to here if an error is encountered above, or upon
  ** successful coding of the SELECT.
  */
select_end:
  assert( db->mallocFailed==0 || db->mallocFailed==1 );
  pParse->nErr += db->mallocFailed;
  sqlite3ExprListDelete(db, pMinMaxOrderBy);
#ifdef SQLITE_DEBUG
  if( pAggInfo && !db->mallocFailed ){
    for(i=0; i<pAggInfo->nColumn; i++){
      Expr *pExpr = pAggInfo->aCol[i].pCExpr;
      assert( pExpr!=0 );
      assert( pExpr->pAggInfo==pAggInfo );
Changes to src/shell.c.in.
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
  sqlite3_exec(p->db,
    "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
    "  key TEXT PRIMARY KEY,\n"
    "  value ANY\n"
    ") 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);
}

/*







|







2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
  sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
  sqlite3_exec(p->db,
    "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
    "  key TEXT PRIMARY KEY,\n"
    "  value\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);
}

/*
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
  "       -x     Send output as CSV to a spreadsheet (same as \".excel\")",
#ifdef SQLITE_DEBUG
  ".oom ?--repeat M? ?N?    Simulate an OOM error on the N-th allocation",
#endif 
  ".open ?OPTIONS? ?FILE?   Close existing database and reopen FILE",
  "     Options:",
  "        --append        Use appendvfs to append database to the end of FILE",
#ifdef SQLITE_ENABLE_DESERIALIZE
  "        --deserialize   Load into memory useing 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",







|
|







3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
  "       -x     Send output as CSV to a spreadsheet (same as \".excel\")",
#ifdef SQLITE_DEBUG
  ".oom ?--repeat M? ?N?    Simulate an OOM error on the N-th allocation",
#endif 
  ".open ?OPTIONS? ?FILE?   Close existing database and reopen FILE",
  "     Options:",
  "        --append        Use appendvfs to append database to the end of FILE",
#ifndef SQLITE_OMIT_DESERIALIZE
  "        --deserialize   Load into memory using sqlite3_deserialize()",
  "        --hexdb         Load the output of \"dbtotxt\" as an in-memory db",
  "        --maxsize N     Maximum size for --hexdb or --deserialized database",
#endif
  "        --new           Initialize FILE to an empty database",
  "        --nofollow      Do not follow symbolic links",
  "        --readonly      Open FILE readonly",
  "        --zip           FILE is a ZIP archive",
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
      rc = SHELL_OPEN_ZIPFILE;
    }
  }
  fclose(f);
  return rc;  
}

#ifdef SQLITE_ENABLE_DESERIALIZE
/*
** Reconstruct an in-memory database using the output from the "dbtotxt"
** program.  Read content from the file in p->zDbFilename.  If p->zDbFilename
** is 0, then read from standard input.
*/
static unsigned char *readHexDb(ShellState *p, int *pnData){
  unsigned char *a = 0;







|







4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
      rc = SHELL_OPEN_ZIPFILE;
    }
  }
  fclose(f);
  return rc;  
}

#ifndef SQLITE_OMIT_DESERIALIZE
/*
** Reconstruct an in-memory database using the output from the "dbtotxt"
** program.  Read content from the file in p->zDbFilename.  If p->zDbFilename
** is 0, then read from standard input.
*/
static unsigned char *readHexDb(ShellState *p, int *pnData){
  unsigned char *a = 0;
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
    }
    p->lineno = nLine;
  }
  sqlite3_free(a);
  utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
  return 0;
}
#endif /* SQLITE_ENABLE_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.
*/







|







4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
    }
    p->lineno = nLine;
  }
  sqlite3_free(a);
  utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
  return 0;
}
#endif /* SQLITE_OMIT_DESERIALIZE */

/*
** Scalar function "shell_int32". The first argument to this function
** must be a blob. The second a non-negative integer. This function
** reads and returns a 32-bit big-endian integer from byte
** offset (4*<arg2>) of the blob.
*/
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
#endif
    if( p->openMode==SHELL_OPEN_ZIPFILE ){
      char *zSql = sqlite3_mprintf(
         "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
      sqlite3_exec(p->db, zSql, 0, 0, 0);
      sqlite3_free(zSql);
    }
#ifdef SQLITE_ENABLE_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);







|







4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
#endif
    if( p->openMode==SHELL_OPEN_ZIPFILE ){
      char *zSql = sqlite3_mprintf(
         "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
      sqlite3_exec(p->db, zSql, 0, 0, 0);
      sqlite3_free(zSql);
    }
#ifndef SQLITE_OMIT_DESERIALIZE
    else
    if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
      int rc;
      int nData = 0;
      unsigned char *aData;
      if( p->openMode==SHELL_OPEN_DESERIALIZE ){
        aData = (unsigned char*)readFile(p->zDbFilename, &nData);
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
  const char *zSql =
  "SELECT "
    "     'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
    "  || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
    "  || fkey_collate_clause("
    "       f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
    ", "
    "     'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('"
    "  || group_concat('*=?', ' AND ') || ')'"
    ", "
    "     s.name  || '(' || group_concat(f.[from],  ', ') || ')'"
    ", "
    "     f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
    ", "
    "     'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
    "  || ' ON ' || quote(s.name) || '('"
    "  || group_concat(quote(f.[from]) ||"
    "        fkey_collate_clause("
    "          f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
    "  || ');'"
    ", "
    "     f.[table] "
    "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
    "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
    "GROUP BY s.name, f.id "
    "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
  ;
  const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)";

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







|



















|







5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
  const char *zSql =
  "SELECT "
    "     'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
    "  || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
    "  || fkey_collate_clause("
    "       f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
    ", "
    "     'SEARCH ' || s.name || ' USING COVERING INDEX*('"
    "  || group_concat('*=?', ' AND ') || ')'"
    ", "
    "     s.name  || '(' || group_concat(f.[from],  ', ') || ')'"
    ", "
    "     f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
    ", "
    "     'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
    "  || ' ON ' || quote(s.name) || '('"
    "  || group_concat(quote(f.[from]) ||"
    "        fkey_collate_clause("
    "          f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
    "  || ');'"
    ", "
    "     f.[table] "
    "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
    "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
    "GROUP BY s.name, f.id "
    "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
  ;
  const char *zGlobIPK = "SEARCH * USING INTEGER PRIMARY KEY (rowid=?)";

  for(i=2; i<nArg; i++){
    int n = strlen30(azArg[i]);
    if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
      bVerbose = 1;
    }
    else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
6725
6726
6727
6728
6729
6730
6731

6732
6733
6734
6735
6736
6737
6738
  int rc = *pRc;
  if( rc==SQLITE_OK ){
    char *zErr = 0;
    rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
    if( rc!=SQLITE_OK ){
      raw_printf(stderr, "SQL error: %s\n", zErr);
    }

    *pRc = rc;
  }
}

/*
** Like shellExec(), except that zFmt is a printf() style format string.
*/







>







6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
  int rc = *pRc;
  if( rc==SQLITE_OK ){
    char *zErr = 0;
    rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
    if( rc!=SQLITE_OK ){
      raw_printf(stderr, "SQL error: %s\n", zErr);
    }
    sqlite3_free(zErr);
    *pRc = rc;
  }
}

/*
** Like shellExec(), except that zFmt is a printf() style format string.
*/
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
      sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
      raw_printf(p->out, "%s\n", zBuf);
    }
  }else

  if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
    ShellState data;
    char *zErrMsg = 0;
    int doStats = 0;
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.cMode = data.mode = MODE_Semi;
    if( nArg==2 && optionMatch(azArg[1], "indent") ){
      data.cMode = data.mode = MODE_Pretty;
      nArg = 1;







<







8261
8262
8263
8264
8265
8266
8267

8268
8269
8270
8271
8272
8273
8274
      sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
      raw_printf(p->out, "%s\n", zBuf);
    }
  }else

  if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
    ShellState data;

    int doStats = 0;
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.cMode = data.mode = MODE_Semi;
    if( nArg==2 && optionMatch(azArg[1], "indent") ){
      data.cMode = data.mode = MODE_Pretty;
      nArg = 1;
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
    rc = sqlite3_exec(p->db,
       "SELECT sql FROM"
       "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
       "     FROM sqlite_schema UNION ALL"
       "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
       "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
       "ORDER BY rowid",
       callback, &data, &zErrMsg
    );
    if( rc==SQLITE_OK ){
      sqlite3_stmt *pStmt;
      rc = sqlite3_prepare_v2(p->db,
               "SELECT rowid FROM sqlite_schema"
               " WHERE name GLOB 'sqlite_stat[134]'",
               -1, &pStmt, 0);
      doStats = sqlite3_step(pStmt)==SQLITE_ROW;
      sqlite3_finalize(pStmt);
    }
    if( doStats==0 ){
      raw_printf(p->out, "/* No STAT tables available */\n");
    }else{
      raw_printf(p->out, "ANALYZE sqlite_schema;\n");
      sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_schema'",
                   callback, &data, &zErrMsg);
      data.cMode = data.mode = MODE_Insert;
      data.zDestTable = "sqlite_stat1";
      shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);
      data.zDestTable = "sqlite_stat4";
      shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
      raw_printf(p->out, "ANALYZE sqlite_schema;\n");
    }
  }else

  if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
    if( nArg==2 ){
      p->showHeader = booleanValue(azArg[1]);







|















|


|

|







8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
    rc = sqlite3_exec(p->db,
       "SELECT sql FROM"
       "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
       "     FROM sqlite_schema UNION ALL"
       "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
       "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
       "ORDER BY rowid",
       callback, &data, 0
    );
    if( rc==SQLITE_OK ){
      sqlite3_stmt *pStmt;
      rc = sqlite3_prepare_v2(p->db,
               "SELECT rowid FROM sqlite_schema"
               " WHERE name GLOB 'sqlite_stat[134]'",
               -1, &pStmt, 0);
      doStats = sqlite3_step(pStmt)==SQLITE_ROW;
      sqlite3_finalize(pStmt);
    }
    if( doStats==0 ){
      raw_printf(p->out, "/* No STAT tables available */\n");
    }else{
      raw_printf(p->out, "ANALYZE sqlite_schema;\n");
      sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_schema'",
                   callback, &data, 0);
      data.cMode = data.mode = MODE_Insert;
      data.zDestTable = "sqlite_stat1";
      shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
      data.zDestTable = "sqlite_stat4";
      shell_exec(&data, "SELECT * FROM sqlite_stat4", 0);
      raw_printf(p->out, "ANALYZE sqlite_schema;\n");
    }
  }else

  if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
    if( nArg==2 ){
      p->showHeader = booleanValue(azArg[1]);
8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
8966
8967
8968
8969
8970
8971
8972
8973
8974
        p->openMode = SHELL_OPEN_APPENDVFS;
      }else if( optionMatch(z, "readonly") ){
        p->openMode = SHELL_OPEN_READONLY;
      }else if( optionMatch(z, "sharedschema") ){
        p->openMode = SHELL_OPEN_SHAREDSCHEMA;
      }else if( optionMatch(z, "nofollow") ){
        p->openFlags |= SQLITE_OPEN_NOFOLLOW;
#ifdef SQLITE_ENABLE_DESERIALIZE
      }else if( optionMatch(z, "deserialize") ){
        p->openMode = SHELL_OPEN_DESERIALIZE;
      }else if( optionMatch(z, "hexdb") ){
        p->openMode = SHELL_OPEN_HEXDB;
      }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
        p->szMax = integerValue(azArg[++iName]);
#endif /* SQLITE_ENABLE_DESERIALIZE */
      }else if( z[0]=='-' ){
        utf8_printf(stderr, "unknown option: %s\n", z);
        rc = 1;
        goto meta_command_exit;
      }else if( zNewFilename ){
        utf8_printf(stderr, "extra argument: \"%s\"\n", z);
        rc = 1;







|






|







8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
8966
8967
8968
8969
8970
8971
8972
8973
8974
        p->openMode = SHELL_OPEN_APPENDVFS;
      }else if( optionMatch(z, "readonly") ){
        p->openMode = SHELL_OPEN_READONLY;
      }else if( optionMatch(z, "sharedschema") ){
        p->openMode = SHELL_OPEN_SHAREDSCHEMA;
      }else if( optionMatch(z, "nofollow") ){
        p->openFlags |= SQLITE_OPEN_NOFOLLOW;
#ifndef SQLITE_OMIT_DESERIALIZE
      }else if( optionMatch(z, "deserialize") ){
        p->openMode = SHELL_OPEN_DESERIALIZE;
      }else if( optionMatch(z, "hexdb") ){
        p->openMode = SHELL_OPEN_HEXDB;
      }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
        p->szMax = integerValue(azArg[++iName]);
#endif /* SQLITE_OMIT_DESERIALIZE */
      }else if( z[0]=='-' ){
        utf8_printf(stderr, "unknown option: %s\n", z);
        rc = 1;
        goto meta_command_exit;
      }else if( zNewFilename ){
        utf8_printf(stderr, "extra argument: \"%s\"\n", z);
        rc = 1;
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
  "   -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_ENABLE_DESERIALIZE)
  "   -deserialize         open the database using sqlite3_deserialize()\n"
#endif
  "   -echo                print commands before execution\n"
  "   -init FILENAME       read/process named file\n"
  "   -[no]header          turn headers on or off\n"
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
  "   -heap SIZE           Size of heap for memsys3 or memsys5\n"
#endif
  "   -help                show this message\n"
  "   -html                set output mode to HTML\n"
  "   -interactive         force interactive I/O\n"
  "   -json                set output mode to 'json'\n"
  "   -line                set output mode to 'line'\n"
  "   -list                set output mode to 'list'\n"
  "   -lookaside SIZE N    use N entries of SZ bytes for lookaside memory\n"
  "   -markdown            set output mode to 'markdown'\n"
#if defined(SQLITE_ENABLE_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







|
















|







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
  "   -ascii               set output mode to 'ascii'\n"
  "   -bail                stop after hitting an error\n"
  "   -batch               force batch I/O\n"
  "   -box                 set output mode to 'box'\n"
  "   -column              set output mode to 'column'\n"
  "   -cmd COMMAND         run \"COMMAND\" before reading stdin\n"
  "   -csv                 set output mode to 'csv'\n"
#if !defined(SQLITE_OMIT_DESERIALIZE)
  "   -deserialize         open the database using sqlite3_deserialize()\n"
#endif
  "   -echo                print commands before execution\n"
  "   -init FILENAME       read/process named file\n"
  "   -[no]header          turn headers on or off\n"
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
  "   -heap SIZE           Size of heap for memsys3 or memsys5\n"
#endif
  "   -help                show this message\n"
  "   -html                set output mode to HTML\n"
  "   -interactive         force interactive I/O\n"
  "   -json                set output mode to 'json'\n"
  "   -line                set output mode to 'line'\n"
  "   -list                set output mode to 'list'\n"
  "   -lookaside SIZE N    use N entries of SZ bytes for lookaside memory\n"
  "   -markdown            set output mode to 'markdown'\n"
#if !defined(SQLITE_OMIT_DESERIALIZE)
  "   -maxsize N           maximum size for a --deserialize database\n"
#endif
  "   -memtrace            trace all memory allocations and deallocations\n"
  "   -mmap N              default mmap size set to N\n"
#ifdef SQLITE_ENABLE_MULTIPLEX
  "   -multiplex           enable the multiplexor VFS\n"
#endif
11298
11299
11300
11301
11302
11303
11304
11305
11306
11307
11308
11309
11310
11311
11312
      zVfs = cmdline_option_value(argc, argv, ++i);
#ifdef SQLITE_HAVE_ZLIB
    }else if( strcmp(z,"-zip")==0 ){
      data.openMode = SHELL_OPEN_ZIPFILE;
#endif
    }else if( strcmp(z,"-append")==0 ){
      data.openMode = SHELL_OPEN_APPENDVFS;
#ifdef SQLITE_ENABLE_DESERIALIZE
    }else if( strcmp(z,"-deserialize")==0 ){
      data.openMode = SHELL_OPEN_DESERIALIZE;
    }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
      data.szMax = integerValue(argv[++i]);
#endif
    }else if( strcmp(z,"-readonly")==0 ){
      data.openMode = SHELL_OPEN_READONLY;







|







11298
11299
11300
11301
11302
11303
11304
11305
11306
11307
11308
11309
11310
11311
11312
      zVfs = cmdline_option_value(argc, argv, ++i);
#ifdef SQLITE_HAVE_ZLIB
    }else if( strcmp(z,"-zip")==0 ){
      data.openMode = SHELL_OPEN_ZIPFILE;
#endif
    }else if( strcmp(z,"-append")==0 ){
      data.openMode = SHELL_OPEN_APPENDVFS;
#ifndef SQLITE_OMIT_DESERIALIZE
    }else if( strcmp(z,"-deserialize")==0 ){
      data.openMode = SHELL_OPEN_DESERIALIZE;
    }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
      data.szMax = integerValue(argv[++i]);
#endif
    }else if( strcmp(z,"-readonly")==0 ){
      data.openMode = SHELL_OPEN_READONLY;
11417
11418
11419
11420
11421
11422
11423
11424
11425
11426
11427
11428
11429
11430
11431
      memcpy(data.colSeparator,",",2);
#ifdef SQLITE_HAVE_ZLIB
    }else if( strcmp(z,"-zip")==0 ){
      data.openMode = SHELL_OPEN_ZIPFILE;
#endif
    }else if( strcmp(z,"-append")==0 ){
      data.openMode = SHELL_OPEN_APPENDVFS;
#ifdef SQLITE_ENABLE_DESERIALIZE
    }else if( strcmp(z,"-deserialize")==0 ){
      data.openMode = SHELL_OPEN_DESERIALIZE;
    }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
      data.szMax = integerValue(argv[++i]);
#endif
    }else if( strcmp(z,"-readonly")==0 ){
      data.openMode = SHELL_OPEN_READONLY;







|







11417
11418
11419
11420
11421
11422
11423
11424
11425
11426
11427
11428
11429
11430
11431
      memcpy(data.colSeparator,",",2);
#ifdef SQLITE_HAVE_ZLIB
    }else if( strcmp(z,"-zip")==0 ){
      data.openMode = SHELL_OPEN_ZIPFILE;
#endif
    }else if( strcmp(z,"-append")==0 ){
      data.openMode = SHELL_OPEN_APPENDVFS;
#ifndef SQLITE_OMIT_DESERIALIZE
    }else if( strcmp(z,"-deserialize")==0 ){
      data.openMode = SHELL_OPEN_DESERIALIZE;
    }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
      data.szMax = integerValue(argv[++i]);
#endif
    }else if( strcmp(z,"-readonly")==0 ){
      data.openMode = SHELL_OPEN_READONLY;
Changes to src/sqlite.h.in.
1125
1126
1127
1128
1129
1130
1131

















1132
1133
1134
1135
1136
1137
1138
**
** <li>[[SQLITE_FCNTL_CKPT_DONE]]
** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint
** in wal mode after the client has finished copying pages from the wal
** file to the database file, but before the *-shm file is updated to
** record the fact that the pages have been checkpointed.
** </ul>

















*/
#define SQLITE_FCNTL_LOCKSTATE               1
#define SQLITE_FCNTL_GET_LOCKPROXYFILE       2
#define SQLITE_FCNTL_SET_LOCKPROXYFILE       3
#define SQLITE_FCNTL_LAST_ERRNO              4
#define SQLITE_FCNTL_SIZE_HINT               5
#define SQLITE_FCNTL_CHUNK_SIZE              6







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
**
** <li>[[SQLITE_FCNTL_CKPT_DONE]]
** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint
** in wal mode after the client has finished copying pages from the wal
** file to the database file, but before the *-shm file is updated to
** record the fact that the pages have been checkpointed.
** </ul>
**
** <li>[[SQLITE_FCNTL_EXTERNAL_READER]]
** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect
** whether or not there is a database client in another process with a wal-mode 
** transaction open on the database or not. It is only available on unix.The
** (void*) argument passed with this file-control should be a pointer to a
** value of type (int). The integer value is set to 1 if the database is a wal
** mode database and there exists at least one client in another process that
** currently has an SQL transaction open on the database. It is set to 0 if 
** the database is not a wal-mode db, or if there is no such connection in any
** other process. This opcode cannot be used to detect transactions opened
** by clients within the current process, only within other processes.
** </ul>
**
** <li>[[SQLITE_FCNTL_CKSM_FILE]]
** Used by the cksmvfs VFS module only.
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE               1
#define SQLITE_FCNTL_GET_LOCKPROXYFILE       2
#define SQLITE_FCNTL_SET_LOCKPROXYFILE       3
#define SQLITE_FCNTL_LAST_ERRNO              4
#define SQLITE_FCNTL_SIZE_HINT               5
#define SQLITE_FCNTL_CHUNK_SIZE              6
1164
1165
1166
1167
1168
1169
1170


1171
1172
1173
1174
1175
1176
1177
#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE  33
#define SQLITE_FCNTL_LOCK_TIMEOUT           34
#define SQLITE_FCNTL_DATA_VERSION           35
#define SQLITE_FCNTL_SIZE_LIMIT             36
#define SQLITE_FCNTL_CKPT_DONE              37
#define SQLITE_FCNTL_RESERVE_BYTES          38
#define SQLITE_FCNTL_CKPT_START             39



/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
#define SQLITE_SET_LOCKPROXYFILE      SQLITE_FCNTL_SET_LOCKPROXYFILE
#define SQLITE_LAST_ERRNO             SQLITE_FCNTL_LAST_ERRNO









>
>







1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE  33
#define SQLITE_FCNTL_LOCK_TIMEOUT           34
#define SQLITE_FCNTL_DATA_VERSION           35
#define SQLITE_FCNTL_SIZE_LIMIT             36
#define SQLITE_FCNTL_CKPT_DONE              37
#define SQLITE_FCNTL_RESERVE_BYTES          38
#define SQLITE_FCNTL_CKPT_START             39
#define SQLITE_FCNTL_EXTERNAL_READER        40
#define SQLITE_FCNTL_CKSM_FILE              41

/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
#define SQLITE_SET_LOCKPROXYFILE      SQLITE_FCNTL_SET_LOCKPROXYFILE
#define SQLITE_LAST_ERRNO             SQLITE_FCNTL_LAST_ERRNO


4176
4177
4178
4179
4180
4181
4182









4183
4184
4185
4186
4187
4188
4189
** 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.









*/
int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);

/*
** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement
** METHOD: sqlite3_stmt
**







>
>
>
>
>
>
>
>
>







4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
** 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.
*/
int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);

/*
** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement
** METHOD: sqlite3_stmt
**
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
** that parameter must be the byte offset
** where the NUL terminator would occur assuming the string were NUL
** terminated.  If any NUL characters occurs at byte offsets less than 
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs.  The result of expressions involving strings
** with embedded NULs is undefined.
**
** ^The fifth argument to the BLOB and string binding interfaces
** is a destructor used to dispose of the BLOB or

** string after SQLite has finished with it.  ^The destructor is called
** to dispose of the BLOB or string even if the call to the bind API fails,
** except the destructor is not called if the third parameter is a NULL
** pointer or the fourth parameter is negative.
** ^If the fifth argument is
** the special value [SQLITE_STATIC], then SQLite assumes that the
** information is in static, unmanaged space and does not need to be freed.



** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
** SQLite makes its own private copy of the data immediately, before
** the sqlite3_bind_*() routine returns.


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







|
|
>
|
|
|
|
<
|
|
>
>
>
|
<
|
>
>







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
** that parameter must be the byte offset
** where the NUL terminator would occur assuming the string were NUL
** terminated.  If any NUL characters occurs at byte offsets less than 
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs.  The result of expressions involving strings
** with embedded NULs is undefined.
**
** ^The fifth argument to the BLOB and string binding interfaces controls
** or indicates the lifetime of the object referenced by the third parameter.
** ^These three options exist:
** ^(1) A destructor to dispose of the BLOB or string after SQLite has finished
** with it may be passed. ^It is called to dispose of the BLOB or string even
** if the call to the bind API fails, except the destructor is not called if
** the third parameter is a NULL pointer or the fourth parameter is negative.

** ^(2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
** the application remains responsible for disposing of the object. ^In this
** case, the object and the provided pointer to it must remain valid until
** either the prepared statement is finalized or the same SQL parameter is
** bound to something else, whichever occurs sooner.
** ^(3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the

** object is to be copied prior to the return from sqlite3_bind_*(). ^The
** object and pointer to it must remain valid until then. ^SQLite will then
** manage the lifetime of its private copy.
**
** ^The sixth argument to sqlite3_bind_text64() must be one of
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
** to specify the encoding of the text in the third parameter.  If
** the sixth argument to sqlite3_bind_text64() is not one of the
** allowed values shown above, or if the text encoding is different
** from the encoding specified by the sixth parameter, then the behavior
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
**
** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate
** callback was invoked as a result of a direct insert, update, or delete
** operation; or 1 for inserts, updates, or deletes invoked by top-level 
** triggers; or 2 for changes resulting from triggers called by top-level
** triggers; and so forth.
**









** See also:  [sqlite3_update_hook()]
*/
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
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 **);

#endif

/*
** CAPI3REF: Low-level system error code
** METHOD: sqlite3
**
** ^Attempt to return the underlying operating system error code or error







>
>
>
>
>
>
>
>
>




















>







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
**
** ^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
9786
9787
9788
9789
9790
9791
9792
9793
9794
9795
9796
9797
9798
9799
9800
9801
** 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.
*/
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 */
);







|
|







9828
9829
9830
9831
9832
9833
9834
9835
9836
9837
9838
9839
9840
9841
9842
9843
** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy
** of the database exists.
**
** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
** allocation error occurs.
**
** This interface is omitted if SQLite is compiled with the
** [SQLITE_OMIT_DESERIALIZE] option.
*/
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 */
);
9838
9839
9840
9841
9842
9843
9844
9845
9846
9847
9848
9849
9850
9851
9852
9853
** database is currently in a read transaction or is involved in a backup
** operation.
**
** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the 
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
** [sqlite3_free()] is invoked on argument P prior to returning.
**
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_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[] */







|
|







9880
9881
9882
9883
9884
9885
9886
9887
9888
9889
9890
9891
9892
9893
9894
9895
** database is currently in a read transaction or is involved in a backup
** operation.
**
** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the 
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
** [sqlite3_free()] is invoked on argument P prior to returning.
**
** This interface is omitted if SQLite is compiled with the
** [SQLITE_OMIT_DESERIALIZE] option.
*/
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/sqliteInt.h.
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
  struct sqlite3InitInfo {      /* Information used during initialization */
    Pgno newTnum;               /* Rootpage of table being initialized */
    u8 iDb;                     /* Which db file is being initialized */
    u8 busy;                    /* TRUE if currently initializing */
    unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
    unsigned imposterTable : 1; /* Building an imposter table */
    unsigned reopenMemdb : 1;   /* ATTACH is really a reopen using MemDB */
    unsigned bDropColumn : 1;   /* Doing schema check after DROP COLUMN */
    char **azInit;              /* "type", "name", and "tbl_name" columns */
                                /*   or if bDropColumn, then azInit[0] is the */
                                /*   name of the column being dropped */
  } init;
  int nVdbeActive;              /* Number of VDBEs currently running */
  int nVdbeRead;                /* Number of active VDBEs that read or write */
  int nVdbeWrite;               /* Number of active VDBEs that read and write */
  int nVdbeExec;                /* Number of nested calls to VdbeExec() */
  int nVDestroy;                /* Number of active OP_VDestroy operations */
  int nExtension;               /* Number of loaded extensions */







<

<
<







1537
1538
1539
1540
1541
1542
1543

1544


1545
1546
1547
1548
1549
1550
1551
  struct sqlite3InitInfo {      /* Information used during initialization */
    Pgno newTnum;               /* Rootpage of table being initialized */
    u8 iDb;                     /* Which db file is being initialized */
    u8 busy;                    /* TRUE if currently initializing */
    unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
    unsigned imposterTable : 1; /* Building an imposter table */
    unsigned reopenMemdb : 1;   /* ATTACH is really a reopen using MemDB */

    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 */
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
#define SQLITE_Stat4          0x00000800 /* Use STAT4 data */
   /* TH3 expects this value  ^^^^^^^^^^ to be 0x0000800. Don't change it */
#define SQLITE_PushDown       0x00001000 /* The push-down optimization */
#define SQLITE_SimplifyJoin   0x00002000 /* Convert LEFT JOIN to JOIN */
#define SQLITE_SkipScan       0x00004000 /* Skip-scans */
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
#define SQLITE_MinMaxOpt      0x00010000 /* The min/max optimization */
#define SQLITE_ExistsToIN     0x00020000 /* The EXISTS-to-IN optimization */
#define SQLITE_AllOpts        0xffffffff /* All optimizations */

/*
** Macros for testing whether or not optimizations are enabled or disabled.
*/
#define OptimizationDisabled(db, mask)  (((db)->dbOptFlags&(mask))!=0)
#define OptimizationEnabled(db, mask)   (((db)->dbOptFlags&(mask))==0)







<







1744
1745
1746
1747
1748
1749
1750

1751
1752
1753
1754
1755
1756
1757
#define SQLITE_Stat4          0x00000800 /* Use STAT4 data */
   /* TH3 expects this value  ^^^^^^^^^^ to be 0x0000800. Don't change it */
#define SQLITE_PushDown       0x00001000 /* The push-down optimization */
#define SQLITE_SimplifyJoin   0x00002000 /* Convert LEFT JOIN to JOIN */
#define SQLITE_SkipScan       0x00004000 /* Skip-scans */
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
#define SQLITE_MinMaxOpt      0x00010000 /* The min/max optimization */

#define SQLITE_AllOpts        0xffffffff /* All optimizations */

/*
** Macros for testing whether or not optimizations are enabled or disabled.
*/
#define OptimizationDisabled(db, mask)  (((db)->dbOptFlags&(mask))!=0)
#define OptimizationEnabled(db, mask)   (((db)->dbOptFlags&(mask))==0)
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
** 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.
**







<

<







2116
2117
2118
2119
2120
2121
2122

2123

2124
2125
2126
2127
2128
2129
2130
** changing the affinity.
**
** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL.
** It causes an assert() to fire if either operand to a comparison
** operator is NULL.  It is added to certain comparison operators to
** prove that the operands are always NOT NULL.
*/

#define SQLITE_JUMPIFNULL   0x10  /* jumps if either operand is NULL */

#define SQLITE_NULLEQ       0x80  /* NULL=NULL */
#define SQLITE_NOTNULL      0x90  /* Assert that operands are never NULL */

/*
** An object of this type is created for each virtual table present in
** the database schema.
**
2257
2258
2259
2260
2261
2262
2263

2264
2265
2266
2267
2268
2269
2270
                                     ** Index.aiRowLogEst[] values */
#define TF_NoVisibleRowid  0x0200    /* No user-visible "rowid" column */
#define TF_OOOHidden       0x0400    /* Out-of-Order hidden columns */
#define TF_HasNotNull      0x0800    /* Contains NOT NULL constraints */
#define TF_Shadow          0x1000    /* True for a shadow table */
#define TF_HasStat4        0x2000    /* STAT4 info available for this table */
#define TF_Ephemeral       0x4000    /* An ephemeral table */


/*
** Test to see whether or not a table is a virtual table.  This is
** done as a macro so that it will be optimized out when virtual
** table support is omitted from the build.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE







>







2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
                                     ** Index.aiRowLogEst[] values */
#define TF_NoVisibleRowid  0x0200    /* No user-visible "rowid" column */
#define TF_OOOHidden       0x0400    /* Out-of-Order hidden columns */
#define TF_HasNotNull      0x0800    /* Contains NOT NULL constraints */
#define TF_Shadow          0x1000    /* True for a shadow table */
#define TF_HasStat4        0x2000    /* STAT4 info available for this table */
#define TF_Ephemeral       0x4000    /* An ephemeral table */
#define TF_Eponymous       0x8000    /* An eponymous virtual table */

/*
** Test to see whether or not a table is a virtual table.  This is
** done as a macro so that it will be optimized out when virtual
** table support is omitted from the build.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
2622
2623
2624
2625
2626
2627
2628

2629
2630
2631
2632
2633
2634
2635
                          ** Additional columns are used only as parameters to
                          ** aggregate functions */
  struct AggInfo_func {   /* For each aggregate function */
    Expr *pFExpr;            /* Expression encoding the function */
    FuncDef *pFunc;          /* The aggregate function implementation */
    int iMem;                /* Memory location that acts as accumulator */
    int iDistinct;           /* Ephemeral table used to enforce DISTINCT */

  } *aFunc;
  int nFunc;              /* Number of entries in aFunc[] */
  u32 selId;              /* Select to which this AggInfo belongs */
};

/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.







>







2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
                          ** Additional columns are used only as parameters to
                          ** aggregate functions */
  struct AggInfo_func {   /* For each aggregate function */
    Expr *pFExpr;            /* Expression encoding the function */
    FuncDef *pFunc;          /* The aggregate function implementation */
    int iMem;                /* Memory location that acts as accumulator */
    int iDistinct;           /* Ephemeral table used to enforce DISTINCT */
    int iDistAddr;           /* Address of OP_OpenEphemeral */
  } *aFunc;
  int nFunc;              /* Number of entries in aFunc[] */
  u32 selId;              /* Select to which this AggInfo belongs */
};

/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
2894
2895
2896
2897
2898
2899
2900

2901
2902
2903
2904
2905
2906
2907
**                     of subqueries
**
**    ENAME_SPAN       Text of the original result set
**                     expression.
*/
struct ExprList {
  int nExpr;             /* Number of expressions on the list */

  struct ExprList_item { /* For each expression in the list */
    Expr *pExpr;            /* The parse tree for this expression */
    char *zEName;           /* Token associated with this expression */
    u8 sortFlags;           /* Mask of KEYINFO_ORDER_* flags */
    unsigned eEName :2;     /* Meaning of zEName */
    unsigned done :1;       /* A flag to indicate when processing is finished */
    unsigned reusable :1;   /* Constant expression is reusable */







>







2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
**                     of subqueries
**
**    ENAME_SPAN       Text of the original result set
**                     expression.
*/
struct ExprList {
  int nExpr;             /* Number of expressions on the list */
  int nAlloc;            /* Number of a[] slots allocated */
  struct ExprList_item { /* For each expression in the list */
    Expr *pExpr;            /* The parse tree for this expression */
    char *zEName;           /* Token associated with this expression */
    u8 sortFlags;           /* Mask of KEYINFO_ORDER_* flags */
    unsigned eEName :2;     /* Meaning of zEName */
    unsigned done :1;       /* A flag to indicate when processing is finished */
    unsigned reusable :1;   /* Constant expression is reusable */
2967
2968
2969
2970
2971
2972
2973

2974
2975
2976
2977
2978
2979
2980
    unsigned isIndexedBy :1;   /* True if there is an INDEXED BY clause */
    unsigned isTabFunc :1;     /* True if table-valued-function syntax */
    unsigned isCorrelated :1;  /* True if sub-query is correlated */
    unsigned viaCoroutine :1;  /* Implemented as a co-routine */
    unsigned isRecursive :1;   /* True for recursive reference in WITH */
    unsigned fromDDL :1;       /* Comes from sqlite_schema */
    unsigned isCte :1;         /* This is a CTE */

  } fg;
  int iCursor;      /* The VDBE cursor number used to access this table */
  Expr *pOn;        /* The ON clause of a join */
  IdList *pUsing;   /* The USING clause of a join */
  Bitmask colUsed;  /* Bit N (1<<N) set if column N of pTab is used */
  union {
    char *zIndexedBy;    /* Identifier from "INDEXED BY <zIndex>" clause */







>







2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
    unsigned isIndexedBy :1;   /* True if there is an INDEXED BY clause */
    unsigned isTabFunc :1;     /* True if table-valued-function syntax */
    unsigned isCorrelated :1;  /* True if sub-query is correlated */
    unsigned viaCoroutine :1;  /* Implemented as a co-routine */
    unsigned isRecursive :1;   /* True for recursive reference in WITH */
    unsigned fromDDL :1;       /* Comes from sqlite_schema */
    unsigned isCte :1;         /* This is a CTE */
    unsigned notCte :1;        /* This item may not match a CTE */
  } fg;
  int iCursor;      /* The VDBE cursor number used to access this table */
  Expr *pOn;        /* The ON clause of a join */
  IdList *pUsing;   /* The USING clause of a join */
  Bitmask colUsed;  /* Bit N (1<<N) set if column N of pTab is used */
  union {
    char *zIndexedBy;    /* Identifier from "INDEXED BY <zIndex>" clause */
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
#define WHERE_DUPLICATES_OK    0x0010 /* Ok to return a row more than once */
#define WHERE_OR_SUBCLAUSE     0x0020 /* Processing a sub-WHERE as part of
                                      ** the OR optimization  */
#define WHERE_GROUPBY          0x0040 /* pOrderBy is really a GROUP BY */
#define WHERE_DISTINCTBY       0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT    0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP      0x0200 /* Support sqlite3WhereIsSorted() */
                        /*     0x0400    not currently used */
#define WHERE_ORDERBY_LIMIT    0x0800 /* ORDERBY+LIMIT on the inner loop */
                        /*     0x1000    not currently used */
                        /*     0x2000    not currently used */
#define WHERE_USE_LIMIT        0x4000 /* Use the LIMIT in cost estimates */
                        /*     0x8000    not currently used */

/* Allowed return values from sqlite3WhereIsDistinct()







|







3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
#define WHERE_DUPLICATES_OK    0x0010 /* Ok to return a row more than once */
#define WHERE_OR_SUBCLAUSE     0x0020 /* Processing a sub-WHERE as part of
                                      ** the OR optimization  */
#define WHERE_GROUPBY          0x0040 /* pOrderBy is really a GROUP BY */
#define WHERE_DISTINCTBY       0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT    0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP      0x0200 /* Support sqlite3WhereIsSorted() */
#define WHERE_AGG_DISTINCT     0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
#define WHERE_ORDERBY_LIMIT    0x0800 /* ORDERBY+LIMIT on the inner loop */
                        /*     0x1000    not currently used */
                        /*     0x2000    not currently used */
#define WHERE_USE_LIMIT        0x4000 /* Use the LIMIT in cost estimates */
                        /*     0x8000    not currently used */

/* Allowed return values from sqlite3WhereIsDistinct()
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
    ExprList *pEList;    /* Optional list of result-set columns */
    AggInfo *pAggInfo;   /* Information about aggregates at this level */
    Upsert *pUpsert;     /* ON CONFLICT clause information from an upsert */
    int iBaseReg;        /* For TK_REGISTER when parsing RETURNING */
  } uNC;
  NameContext *pNext;  /* Next outer name context.  NULL for outermost */
  int nRef;            /* Number of names resolved by this context */
  int nErr;            /* Number of errors encountered while resolving names */
  int ncFlags;         /* Zero or more NC_* flags defined below */
  Select *pWinSelect;  /* SELECT statement for any window functions */
};

/*
** Allowed values for the NameContext, ncFlags field.
**







|







3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
    ExprList *pEList;    /* Optional list of result-set columns */
    AggInfo *pAggInfo;   /* Information about aggregates at this level */
    Upsert *pUpsert;     /* ON CONFLICT clause information from an upsert */
    int iBaseReg;        /* For TK_REGISTER when parsing RETURNING */
  } uNC;
  NameContext *pNext;  /* Next outer name context.  NULL for outermost */
  int nRef;            /* Number of names resolved by this context */
  int nNcErr;          /* Number of errors encountered while resolving names */
  int ncFlags;         /* Zero or more NC_* flags defined below */
  Select *pWinSelect;  /* SELECT statement for any window functions */
};

/*
** Allowed values for the NameContext, ncFlags field.
**
3117
3118
3119
3120
3121
3122
3123

3124
3125
3126
3127
3128
3129
3130
#define NC_MinMaxAgg 0x01000  /* min/max aggregates seen.  See note above */
#define NC_Complex   0x02000  /* True if a function or subquery seen */
#define NC_AllowWin  0x04000  /* Window functions are allowed here */
#define NC_HasWin    0x08000  /* One or more window functions seen */
#define NC_IsDDL     0x10000  /* Resolving names in a CREATE statement */
#define NC_InAggFunc 0x20000  /* True if analyzing arguments to an agg func */
#define NC_FromDDL   0x40000  /* SQL text comes from sqlite_schema */


/*
** An instance of the following object describes a single ON CONFLICT
** clause in an upsert.
**
** The pUpsertTarget field is only set if the ON CONFLICT clause includes
** conflict-target clause.  (In "ON CONFLICT(a,b)" the "(a,b)" is the







>







3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
#define NC_MinMaxAgg 0x01000  /* min/max aggregates seen.  See note above */
#define NC_Complex   0x02000  /* True if a function or subquery seen */
#define NC_AllowWin  0x04000  /* Window functions are allowed here */
#define NC_HasWin    0x08000  /* One or more window functions seen */
#define NC_IsDDL     0x10000  /* Resolving names in a CREATE statement */
#define NC_InAggFunc 0x20000  /* True if analyzing arguments to an agg func */
#define NC_FromDDL   0x40000  /* SQL text comes from sqlite_schema */
#define NC_NoSelect  0x80000  /* Do not descend into sub-selects */

/*
** An instance of the following object describes a single ON CONFLICT
** clause in an upsert.
**
** The pUpsertTarget field is only set if the ON CONFLICT clause includes
** conflict-target clause.  (In "ON CONFLICT(a,b)" the "(a,b)" is the
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
#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
#ifdef SQLITE_ENABLE_DESERIALIZE
  sqlite3_int64 mxMemdbSize;        /* Default max memdb size */
#endif
#ifndef SQLITE_UNTESTABLE
  int (*xTestCallback)(int);        /* Invoked by sqlite3FaultSim() */
#endif
  int bLocaltimeFault;              /* True to fail localtime() calls */
  int iOnceResetThreshold;          /* When to reset OP_Once counters */







|







3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
#ifdef SQLITE_VDBE_COVERAGE
  /* The following callback (if not NULL) is invoked on every VDBE branch
  ** operation.  Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE.
  */
  void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx);  /* Callback */
  void *pVdbeBranchArg;                                     /* 1st argument */
#endif
#ifndef SQLITE_OMIT_DESERIALIZE
  sqlite3_int64 mxMemdbSize;        /* Default max memdb size */
#endif
#ifndef SQLITE_UNTESTABLE
  int (*xTestCallback)(int);        /* Invoked by sqlite3FaultSim() */
#endif
  int bLocaltimeFault;              /* True to fail localtime() calls */
  int iOnceResetThreshold;          /* When to reset OP_Once counters */
3901
3902
3903
3904
3905
3906
3907

3908
3909
3910
3911






3912
3913
3914
3915
3916
3917
3918
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*);


#ifdef SQLITE_DEBUG
void sqlite3SelectWalkAssert2(Walker*, Select*);
#endif







/*
** Return code from the parse-tree walking primitives and their
** callbacks.
*/
#define WRC_Continue    0   /* Continue down into children */
#define WRC_Prune       1   /* Omit children but continue walking siblings */







>




>
>
>
>
>
>







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
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 */
3939
3940
3941
3942
3943
3944
3945

3946
3947
3948
3949
3950
3951
3952

/*
** An instance of the With object represents a WITH clause containing
** one or more CTEs (common table expressions).
*/
struct With {
  int nCte;               /* Number of CTEs in the WITH clause */

  With *pOuter;           /* Containing WITH clause, or NULL */
  Cte a[1];               /* For each CTE in the WITH clause.... */
};

/*
** The Cte object is not guaranteed to persist for the entire duration
** of code generation.  (The query flattener or other parser tree







>







3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959

/*
** An instance of the With object represents a WITH clause containing
** one or more CTEs (common table expressions).
*/
struct With {
  int nCte;               /* Number of CTEs in the WITH clause */
  int bView;              /* Belongs to the outermost Select of a view */
  With *pOuter;           /* Containing WITH clause, or NULL */
  Cte a[1];               /* For each CTE in the WITH clause.... */
};

/*
** The Cte object is not guaranteed to persist for the entire duration
** of code generation.  (The query flattener or other parser tree
4309
4310
4311
4312
4313
4314
4315

4316
4317
4318
4319
4320
4321
4322
void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*);
Expr *sqlite3ExprSimplifiedAndOr(Expr*);
Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*);
void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
void sqlite3ExprDelete(sqlite3*, Expr*);

void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
void sqlite3ExprListSetSortOrder(ExprList*,int,int);
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
void sqlite3ExprListDelete(sqlite3*, ExprList*);







>







4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*);
Expr *sqlite3ExprSimplifiedAndOr(Expr*);
Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*);
void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
void sqlite3ExprDelete(sqlite3*, Expr*);
void sqlite3ExprDeferredDelete(Parse*, Expr*);
void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
void sqlite3ExprListSetSortOrder(ExprList*,int,int);
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
void sqlite3ExprListDelete(sqlite3*, ExprList*);
4330
4331
4332
4333
4334
4335
4336

4337
4338
4339
4340
4341
4342
4343
Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
#endif
void sqlite3ResetAllSchemasOfConnection(sqlite3*);
void sqlite3ResetOneSchema(sqlite3*,int);
void sqlite3CollapseDatabaseArray(sqlite3*);
void sqlite3CommitInternalChanges(sqlite3*);
void sqlite3DeleteColumnNames(sqlite3*,Table*);

int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char);
Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
void sqlite3OpenSchemaTable(Parse *, int);
Index *sqlite3PrimaryKeyIndex(Table*);
i16 sqlite3TableColumnToIndex(Index*, i16);
#ifdef SQLITE_OMIT_GENERATED_COLUMNS







>







4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
#endif
void sqlite3ResetAllSchemasOfConnection(sqlite3*);
void sqlite3ResetOneSchema(sqlite3*,int);
void sqlite3CollapseDatabaseArray(sqlite3*);
void sqlite3CommitInternalChanges(sqlite3*);
void sqlite3DeleteColumnNames(sqlite3*,Table*);
void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect);
int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char);
Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
void sqlite3OpenSchemaTable(Parse *, int);
Index *sqlite3PrimaryKeyIndex(Table*);
i16 sqlite3TableColumnToIndex(Index*, i16);
#ifdef SQLITE_OMIT_GENERATED_COLUMNS
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
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
int sqlite3MemdbInit(void);
#endif

const char *sqlite3ErrStr(int);
int sqlite3ReadSchema(Parse *pParse);
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
int sqlite3IsBinary(const CollSeq*);







|







4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
u8 sqlite3HexToInt(int h);
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);

#if defined(SQLITE_NEED_ERR_NAME)
const char *sqlite3ErrName(int);
#endif

#ifndef SQLITE_OMIT_DESERIALIZE
int sqlite3MemdbInit(void);
#endif

const char *sqlite3ErrStr(int);
int sqlite3ReadSchema(Parse *pParse);
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
int sqlite3IsBinary(const CollSeq*);
4759
4760
4761
4762
4763
4764
4765



4766
4767
4768
4769
4770
4771
4772
#endif
int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
extern const unsigned char sqlite3OpcodeProperty[];
extern const char sqlite3StrBINARY[];
extern const unsigned char sqlite3UpperToLower[];



extern const unsigned char sqlite3CtypeMap[];
extern SQLITE_WSD struct Sqlite3Config sqlite3Config;
extern FuncDefHash sqlite3BuiltinFunctions;
#ifndef SQLITE_OMIT_WSD
extern int sqlite3PendingByte;
#endif
#endif /* SQLITE_AMALGAMATION */







>
>
>







4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
#endif
int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
extern const unsigned char sqlite3OpcodeProperty[];
extern const char sqlite3StrBINARY[];
extern const unsigned char sqlite3UpperToLower[];
extern const unsigned char *sqlite3aLTb;
extern const unsigned char *sqlite3aEQb;
extern const unsigned char *sqlite3aGTb;
extern const unsigned char sqlite3CtypeMap[];
extern SQLITE_WSD struct Sqlite3Config sqlite3Config;
extern FuncDefHash sqlite3BuiltinFunctions;
#ifndef SQLITE_OMIT_WSD
extern int sqlite3PendingByte;
#endif
#endif /* SQLITE_AMALGAMATION */
Changes to src/tclsqlite.c.
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610

  /*
  **     $db deserialize ?-maxsize N? ?-readonly BOOL? ?DATABASE? VALUE
  **
  ** Reopen DATABASE (default "main") using the content in $VALUE
  */
  case DB_DESERIALIZE: {
#ifndef SQLITE_ENABLE_DESERIALIZE
    Tcl_AppendResult(interp, "MEMDB not available in this build",
                     (char*)0);
    rc = TCL_ERROR;
#else
    const char *zSchema = 0;
    Tcl_Obj *pValue = 0;
    unsigned char *pBA;







|







2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610

  /*
  **     $db deserialize ?-maxsize N? ?-readonly BOOL? ?DATABASE? VALUE
  **
  ** Reopen DATABASE (default "main") using the content in $VALUE
  */
  case DB_DESERIALIZE: {
#ifdef SQLITE_OMIT_DESERIALIZE
    Tcl_AppendResult(interp, "MEMDB not available in this build",
                     (char*)0);
    rc = TCL_ERROR;
#else
    const char *zSchema = 0;
    Tcl_Obj *pValue = 0;
    unsigned char *pBA;
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177

  /*
  **     $db serialize ?DATABASE?
  **
  ** Return a serialization of a database.  
  */
  case DB_SERIALIZE: {
#ifndef SQLITE_ENABLE_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;







|







3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177

  /*
  **     $db serialize ?DATABASE?
  **
  ** Return a serialization of a database.  
  */
  case DB_SERIALIZE: {
#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;
Changes to src/test1.c.
3821
3822
3823
3824
3825
3826
3827

3828
3829
3830

3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841





3842




3843

3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_stmt *pStmt;
  int idx;

  int bytes;
  char *value;
  int rc;


  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);
  if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;










  rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);

  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
    return TCL_ERROR;
  }

  return TCL_OK;
}

/*







>



>









|

>
>
>
>
>
|
>
>
>
>

>


|







3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_stmt *pStmt;
  int idx;
  int trueLength = 0;
  int bytes;
  char *value;
  int rc;
  char *toFree = 0;

  if( objc!=5 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"",
        Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
    return TCL_ERROR;
  }

  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
  value = (char*)Tcl_GetByteArrayFromObj(objv[3], &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), (void*)0);
    return TCL_ERROR;
  }

  return TCL_OK;
}

/*
3865
3866
3867
3868
3869
3870
3871

3872

3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889





3890




3891

3892
3893
3894
3895
3896
3897
3898
  Tcl_Obj *CONST objv[]
){
#ifndef SQLITE_OMIT_UTF16
  sqlite3_stmt *pStmt;
  int idx;
  int bytes;
  char *value;

  int rc;


  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);
  if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;










  rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);

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







>

>















|

>
>
>
>
>
|
>
>
>
>

>







3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
  Tcl_Obj *CONST objv[]
){
#ifndef SQLITE_OMIT_UTF16
  sqlite3_stmt *pStmt;
  int idx;
  int bytes;
  char *value;
  char *toFree = 0;
  int rc;
  int trueLength = 0;

  void (*xDel)(void*) = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
  Tcl_Obj *oStmt    = objv[objc-4];
  Tcl_Obj *oN       = objv[objc-3];
  Tcl_Obj *oString  = objv[objc-2];
  Tcl_Obj *oBytes   = objv[objc-1];

  if( objc!=5 && objc!=6){
    Tcl_AppendResult(interp, "wrong # args: should be \"",
        Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
    return TCL_ERROR;
  }

  if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR;
  value = (char*)Tcl_GetByteArrayFromObj(oString, &trueLength);
  if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;
  if( bytes<0 && xDel==SQLITE_TRANSIENT ){
    toFree = malloc( trueLength + 3 );
    if( toFree==0 ){
      Tcl_AppendResult(interp, "out of memory", (void*)0);
      return TCL_ERROR;
    }
    memcpy(toFree, value, trueLength);
    memset(toFree+trueLength, 0, 3);
    value = toFree;
  }
  rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
  free(toFree);
  if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
  if( rc!=SQLITE_OK ){
    Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
    return TCL_ERROR;
  }

#endif /* SQLITE_OMIT_UTF16 */
6486
6487
6488
6489
6490
6491
6492




































6493
6494
6495
6496
6497
6498
6499
  }
  sqlite3_file_control(db, zDbName, SQLITE_FCNTL_TEMPFILENAME, (void*)&zTName);
  Tcl_AppendResult(interp, zTName, (char*)0);
  sqlite3_free(zTName);
  return TCL_OK;  
}






































/*
** tclcmd:   sqlite3_vfs_list
**
**   Return a tcl list containing the names of all registered vfs's.
*/
static int SQLITE_TCLAPI vfs_list(







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
  }
  sqlite3_file_control(db, zDbName, SQLITE_FCNTL_TEMPFILENAME, (void*)&zTName);
  Tcl_AppendResult(interp, zTName, (char*)0);
  sqlite3_free(zTName);
  return TCL_OK;  
}

/*
** tclcmd:   file_control_external_reader DB ?AUXDB?
**
** Return a string that is a temporary filename
*/
static int SQLITE_TCLAPI file_control_external_reader(
  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int objc,              /* Number of arguments */
  Tcl_Obj *CONST objv[]  /* Command arguments */
){
  sqlite3 *db;
  const char *zName = "main";
  int iRes = 0;
  int rc = SQLITE_OK;

  if( objc!=2 && objc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"",
        Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
    return TCL_ERROR;
  }
  if( objc==3 ){
    zName = Tcl_GetString(objv[2]);
  }
  rc = sqlite3_file_control(db, zName, SQLITE_FCNTL_EXTERNAL_READER, &iRes);
  if( rc!=SQLITE_OK ){
    Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
    return TCL_ERROR;
  }
  Tcl_SetObjResult(interp, Tcl_NewIntObj(iRes));
  return TCL_OK;
}


/*
** tclcmd:   sqlite3_vfs_list
**
**   Return a tcl list containing the names of all registered vfs's.
*/
static int SQLITE_TCLAPI vfs_list(
8424
8425
8426
8427
8428
8429
8430

8431
8432
8433
8434
8435
8436
8437
     { "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   },

     { "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     },







>







8484
8485
8486
8487
8488
8489
8490
8491
8492
8493
8494
8495
8496
8497
8498
     { "file_control_win32_set_handle", file_control_win32_set_handle, 0  },
#endif
     { "file_control_persist_wal",    file_control_persist_wal,     0   },
     { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
     { "file_control_vfsname",        file_control_vfsname,         0   },
     { "file_control_reservebytes",   file_control_reservebytes,    0   },
     { "file_control_tempfilename",   file_control_tempfilename,    0   },
     { "file_control_external_reader",   file_control_external_reader,    0   },
     { "sqlite3_vfs_list",           vfs_list,     0   },
     { "sqlite3_create_function_v2", test_create_function_v2, 0 },

     /* Functions from os.h */
#ifndef SQLITE_OMIT_UTF16
     { "add_test_collate",        test_collate, 0            },
     { "add_test_collate_needed", test_collate_needed, 0     },
Changes to src/test8.c.
385
386
387
388
389
390
391

392
393
394
395
396
397
398
  sqlite3_free(p);
  return 0;
}

typedef struct EchoModule EchoModule;
struct EchoModule {
  Tcl_Interp *interp;

};

/*
** 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.
*/







>







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



  sqlite3_free(p);
}

/*
** Register the echo virtual table module.
*/
static int SQLITE_TCLAPI register_echo_module(







>
>
>







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

  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;

    rc = sqlite3_create_module_v2(db, "echo_v2", 
        &echoModuleV2, (void*)pMod, moduleDestroy
    );
  }

  Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
  return TCL_OK;







>








>







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







67
68
69
70
71
72
73
#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








#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








>
>
>
>
>
>
>







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

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







|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

#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

#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);
221
222
223
224
225
226
227






228
229
230
231
232
233
234
#endif

#ifdef SQLITE_ENABLE_ATOMIC_WRITE
  Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "0", TCL_GLOBAL_ONLY);
#endif







#ifdef SQLITE_ENABLE_JSON1
  Tcl_SetVar2(interp, "sqlite_options", "json1", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "json1", "0", TCL_GLOBAL_ONLY);
#endif








>
>
>
>
>
>







228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#endif

#ifdef SQLITE_ENABLE_ATOMIC_WRITE
  Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "atomicwrite", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_ENABLE_GEOPOLY
  Tcl_SetVar2(interp, "sqlite_options", "geopoly", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "geopoly", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_ENABLE_JSON1
  Tcl_SetVar2(interp, "sqlite_options", "json1", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "json1", "0", TCL_GLOBAL_ONLY);
#endif

Changes to src/tokenize.c.
52
53
54
55
56
57
58

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#define CC_COMMA     23    /* ',' */
#define CC_AND       24    /* '&' */
#define CC_TILDA     25    /* '~' */
#define CC_DOT       26    /* '.' */
#define CC_ID        27    /* unicode characters usable in IDs */
#define CC_ILLEGAL   28    /* Illegal character */
#define CC_NUL       29    /* 0x00 */


static const unsigned char aiClass[] = {
#ifdef SQLITE_ASCII
/*         x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xa  xb  xc  xd  xe  xf */
/* 0x */   29, 28, 28, 28, 28, 28, 28, 28, 28,  7,  7, 28,  7,  7, 28, 28,
/* 1x */   28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 2x */    7, 15,  8,  5,  4, 22, 24,  8, 17, 18, 21, 20, 23, 11, 26, 16,
/* 3x */    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  5, 19, 12, 14, 13,  6,
/* 4x */    5,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
/* 5x */    1,  1,  1,  1,  1,  1,  1,  1,  0,  2,  2,  9, 28, 28, 28,  2,
/* 6x */    8,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
/* 7x */    1,  1,  1,  1,  1,  1,  1,  1,  0,  2,  2, 28, 10, 28, 25, 28,
/* 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
#endif
#ifdef SQLITE_EBCDIC
/*         x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xa  xb  xc  xd  xe  xf */
/* 0x */   29, 28, 28, 28, 28,  7, 28, 28, 28, 28, 28, 28,  7,  7, 28, 28,
/* 1x */   28, 28, 28, 28, 28,  7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 2x */   28, 28, 28, 28, 28,  7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 3x */   28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,







>












|
|
|
|
|
|
|
|







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#define CC_COMMA     23    /* ',' */
#define CC_AND       24    /* '&' */
#define CC_TILDA     25    /* '~' */
#define CC_DOT       26    /* '.' */
#define CC_ID        27    /* unicode characters usable in IDs */
#define CC_ILLEGAL   28    /* Illegal character */
#define CC_NUL       29    /* 0x00 */
#define CC_BOM       30    /* First byte of UTF8 BOM:  0xEF 0xBB 0xBF */

static const unsigned char aiClass[] = {
#ifdef SQLITE_ASCII
/*         x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xa  xb  xc  xd  xe  xf */
/* 0x */   29, 28, 28, 28, 28, 28, 28, 28, 28,  7,  7, 28,  7,  7, 28, 28,
/* 1x */   28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 2x */    7, 15,  8,  5,  4, 22, 24,  8, 17, 18, 21, 20, 23, 11, 26, 16,
/* 3x */    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  5, 19, 12, 14, 13,  6,
/* 4x */    5,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
/* 5x */    1,  1,  1,  1,  1,  1,  1,  1,  0,  2,  2,  9, 28, 28, 28,  2,
/* 6x */    8,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
/* 7x */    1,  1,  1,  1,  1,  1,  1,  1,  0,  2,  2, 28, 10, 28, 25, 28,
/* 8x */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* 9x */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Ax */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Bx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Cx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Dx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
/* Ex */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 30,
/* Fx */   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27
#endif
#ifdef SQLITE_EBCDIC
/*         x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xa  xb  xc  xd  xe  xf */
/* 0x */   29, 28, 28, 28, 28,  7, 28, 28, 28, 28, 28, 28,  7,  7, 28, 28,
/* 1x */   28, 28, 28, 28, 28,  7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 2x */   28, 28, 28, 28, 28,  7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 3x */   28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
528
529
530
531
532
533
534








535
536
537
538
539
540
541
#endif
      /* If it is not a BLOB literal, then it must be an ID, since no
      ** SQL keywords start with the letter 'x'.  Fall through */
      /* no break */ deliberate_fall_through
    }
    case CC_KYWD:
    case CC_ID: {








      i = 1;
      break;
    }
    case CC_NUL: {
      *tokenType = TK_ILLEGAL;
      return 0;
    }







>
>
>
>
>
>
>
>







529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
#endif
      /* If it is not a BLOB literal, then it must be an ID, since no
      ** SQL keywords start with the letter 'x'.  Fall through */
      /* no break */ deliberate_fall_through
    }
    case CC_KYWD:
    case CC_ID: {
      i = 1;
      break;
    }
    case CC_BOM: {
      if( z[1]==0xbb && z[2]==0xbf ){
        *tokenType = TK_SPACE;
        return 3;
      }
      i = 1;
      break;
    }
    case CC_NUL: {
      *tokenType = TK_ILLEGAL;
      return 0;
    }
Changes to src/treeview.c.
130
131
132
133
134
135
136

137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
  int i;
  for(i=0; i<pSrc->nSrc; i++){
    const SrcItem *pItem = &pSrc->a[i];
    StrAccum x;
    char zLine[100];
    sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);

    sqlite3_str_appendf(&x, "{%d:*}", 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);
    }
    if( pItem->pTab ){
      sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
           pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
    }
    if( pItem->zAlias ){
      sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
    }
    if( pItem->fg.jointype & JT_LEFT ){
      sqlite3_str_appendf(&x, " LEFT-JOIN");
    }
    if( pItem->fg.fromDDL ){
      sqlite3_str_appendf(&x, " DDL");
    }
    if( pItem->fg.isCte ){







>
|
<
<
<
<
<




<
<
<







130
131
132
133
134
135
136
137
138





139
140
141
142



143
144
145
146
147
148
149
void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
  int i;
  for(i=0; i<pSrc->nSrc; i++){
    const SrcItem *pItem = &pSrc->a[i];
    StrAccum x;
    char zLine[100];
    sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
    x.printfFlags |= SQLITE_PRINTF_INTERNAL;
    sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);





    if( pItem->pTab ){
      sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
           pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
    }



    if( pItem->fg.jointype & JT_LEFT ){
      sqlite3_str_appendf(&x, " LEFT-JOIN");
    }
    if( pItem->fg.fromDDL ){
      sqlite3_str_appendf(&x, " DDL");
    }
    if( pItem->fg.isCte ){
Changes to src/trigger.c.
47
48
49
50
51
52
53








54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74


75
76

77
78
79
80



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 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 *pTmpSchema;       /* Schema of the pTab table */
  Trigger *pList;           /* List of triggers to return */
  HashElem *p;              /* Loop variable for TEMP triggers */









  if( pParse->disableTriggers ){
    return 0;
  }
  pTmpSchema = pParse->db->aDb[1].pSchema;
  p = sqliteHashFirst(&pTmpSchema->trigHash);
  if( p==0 ){
    return pTab->pTrigger;
  }
  pList = pTab->pTrigger;
  if( pTmpSchema!=pTab->pSchema ){
    sqlite3 *db = pParse->db;
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
    char *zSchema = 0;
    if( IsSharedSchema(db) ){
      zSchema = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
    }
#endif
    assert( sqlite3SchemaMutexHeld(db, 0, pTmpSchema) );
    while( p ){
      Trigger *pTrig = (Trigger *)sqliteHashData(p);


#ifdef SQLITE_ENABLE_SHARED_SCHEMA
      if( ( (zSchema==0 && pTrig->pTabSchema==pTab->pSchema)

         || (zSchema!=0 && 0==sqlite3StrICmp(pTrig->zTabSchema, zSchema)) 
          ) && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
      ){
#else 



      if( pTrig->pTabSchema==pTab->pSchema




       && 0==sqlite3StrICmp(pTrig->table, pTab->zName)

      ){
#endif
        pTrig->pNext = pList;
        pList = pTrig;
      }else if( pTrig->op==TK_RETURNING ){




        assert( pParse->bReturning );
        assert( &(pParse->u1.pReturning->retTrig) == pTrig );
        pTrig->table = pTab->zName;
        pTrig->pTabSchema = pTab->pSchema;
        pTrig->pNext = pList;
        pList = pTrig;
      }        
      p = sqliteHashNext(p);    
    }






  }




  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







>
>
>
>
>
>
>
>






<
<
<

<
<
<
<
<
<
<
<
<
|
|
>
>

|
>
|
<
<
|
>
>
>
|
>
>
>
>
|
>
|
<
|
|
|
>
>
>
>
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
|
>
>
>
>







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67



68









69
70
71
72
73
74
75
76


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

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
** 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 *pTmpSchema;       /* Schema of the pTab table */
  Trigger *pList;           /* List of triggers to return */
  HashElem *p;              /* Loop variable for TEMP triggers */

#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  char *zSchema = 0;
  sqlite3 *db = pParse->db;
  if( IsSharedSchema(db) ){
    zSchema = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
  }
#endif

  if( pParse->disableTriggers ){
    return 0;
  }
  pTmpSchema = pParse->db->aDb[1].pSchema;
  p = sqliteHashFirst(&pTmpSchema->trigHash);



  pList = pTab->pTrigger;









  while( p ){
    Trigger *pTrig = (Trigger *)sqliteHashData(p);

    int bSchemaMatch;
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
    if( zSchema ){
      /* Shared-schema */
      bSchemaMatch = (0==sqlite3StrICmp(pTrig->zTabSchema, zSchema));


    }else
#endif
    {
      /* Non-shared-schema */
      bSchemaMatch = (pTrig->pTabSchema==pTab->pSchema);
    }

    if( bSchemaMatch
     && pTrig->table
     && 0==sqlite3StrICmp(pTrig->table, pTab->zName)
     && pTrig->pTabSchema!=pTmpSchema
    ){

      pTrig->pNext = pList;
      pList = pTrig;
    }else if( pTrig->op==TK_RETURNING
#ifndef SQLITE_OMIT_VIRTUALTABLE
              && pParse->db->pVtabCtx==0
#endif 
    ){
      assert( pParse->bReturning );
      assert( &(pParse->u1.pReturning->retTrig) == pTrig );
      pTrig->table = pTab->zName;
      pTrig->pTabSchema = pTab->pSchema;
      pTrig->pNext = pList;
      pList = pTrig;
    }        
    p = sqliteHashNext(p);    
  }
#if 0
  if( pList ){
    Trigger *pX;
    printf("Triggers for %s:", pTab->zName);
    for(pX=pList; pX; pX=pX->pNext){
      printf(" %s", pX->zName);
    }
    printf("\n");
    fflush(stdout);
  }
#endif
  return pList;  
}

/*
** This is called by the parser when it sees a CREATE TRIGGER statement
** up to the point of the BEGIN before the trigger actions.  A Trigger
** structure is generated based on the information available and stored
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  }

  /* INSTEAD of triggers are only for views and views only support INSTEAD
  ** of triggers.
  */
  if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
    sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", 
        (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
    goto trigger_orphan_error;
  }
  if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
    sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
        " trigger on table: %S", pTableName, 0);
    goto trigger_orphan_error;
  }

#ifndef SQLITE_OMIT_AUTHORIZATION
  if( !IN_RENAME_OBJECT ){
    int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
    int code = SQLITE_CREATE_TRIGGER;







|




|







238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
  }

  /* INSTEAD of triggers are only for views and views only support INSTEAD
  ** of triggers.
  */
  if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
    sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S", 
        (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a);
    goto trigger_orphan_error;
  }
  if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
    sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
        " trigger on table: %S", pTableName->a);
    goto trigger_orphan_error;
  }

#ifndef SQLITE_OMIT_AUTHORIZATION
  if( !IN_RENAME_OBJECT ){
    int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
    int code = SQLITE_CREATE_TRIGGER;
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
    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);
    }else{
      sqlite3CodeVerifyNamedSchema(pParse, zDb);
    }
    pParse->checkSchema = 1;
    goto drop_trigger_cleanup;
  }
  sqlite3DropTriggerPtr(pParse, pTrigger);







|







649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
    if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue;
    assert( sqlite3SchemaMutexHeld(db, j, 0) );
    pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName);
    if( pTrigger ) break;
  }
  if( !pTrigger ){
    if( !noErr ){
      sqlite3ErrorMsg(pParse, "no such trigger: %S", pName->a);
    }else{
      sqlite3CodeVerifyNamedSchema(pParse, zDb);
    }
    pParse->checkSchema = 1;
    goto drop_trigger_cleanup;
  }
  sqlite3DropTriggerPtr(pParse, pTrigger);
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
      pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup);
    }
  }else{
    sqlite3DbFree(db, zName);
  }
  return pSrc;
}




















/* The input list pList is the list of result set terms from a RETURNING
** clause.  The table that we are returning from is pTab.
**
** This routine makes a copy of the pList, and at the same time expands
** any "*" wildcards to be the complete set of columns from pTab.
*/
static ExprList *sqlite3ExpandReturning(
  Parse *pParse,        /* Parsing context */
  ExprList *pList,      /* The arguments to RETURNING */
  Table *pTab           /* The table being updated */
){
  ExprList *pNew = 0;
  sqlite3 *db = pParse->db;
  int i;

  for(i=0; i<pList->nExpr; i++){
    Expr *pOldExpr = pList->a[i].pExpr;
    if( ALWAYS(pOldExpr!=0) && pOldExpr->op==TK_ASTERISK ){

      int jj;
      for(jj=0; jj<pTab->nCol; jj++){
        Expr *pNewExpr;
        if( IsHiddenColumn(pTab->aCol+jj) ) continue;
        pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zName);
        pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
        if( !db->mallocFailed ){







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


















|
>







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
      pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup);
    }
  }else{
    sqlite3DbFree(db, zName);
  }
  return pSrc;
}

/*
** Return true if the pExpr term from the RETURNING clause argument
** list is of the form "*".  Raise an error if the terms if of the
** form "table.*".
*/
static int isAsteriskTerm(
  Parse *pParse,      /* Parsing context */
  Expr *pTerm         /* A term in the RETURNING clause */
){
  assert( pTerm!=0 );
  if( pTerm->op==TK_ASTERISK ) return 1;
  if( pTerm->op!=TK_DOT ) return 0;
  assert( pTerm->pRight!=0 );
  assert( pTerm->pLeft!=0 );
  if( pTerm->pRight->op!=TK_ASTERISK ) return 0;
  sqlite3ErrorMsg(pParse, "RETURNING may not use \"TABLE.*\" wildcards");
  return 1;
}

/* The input list pList is the list of result set terms from a RETURNING
** clause.  The table that we are returning from is pTab.
**
** This routine makes a copy of the pList, and at the same time expands
** any "*" wildcards to be the complete set of columns from pTab.
*/
static ExprList *sqlite3ExpandReturning(
  Parse *pParse,        /* Parsing context */
  ExprList *pList,      /* The arguments to RETURNING */
  Table *pTab           /* The table being updated */
){
  ExprList *pNew = 0;
  sqlite3 *db = pParse->db;
  int i;

  for(i=0; i<pList->nExpr; i++){
    Expr *pOldExpr = pList->a[i].pExpr;
    if( NEVER(pOldExpr==0) ) continue;
    if( isAsteriskTerm(pParse, pOldExpr) ){
      int jj;
      for(jj=0; jj<pTab->nCol; jj++){
        Expr *pNewExpr;
        if( IsHiddenColumn(pTab->aCol+jj) ) continue;
        pNewExpr = sqlite3Expr(db, TK_ID, pTab->aCol[jj].zName);
        pNew = sqlite3ExprListAppend(pParse, pNew, pNewExpr);
        if( !db->mallocFailed ){
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
      if( !db->mallocFailed && ALWAYS(pList->a[i].zEName!=0) ){
        struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
        pItem->zEName = sqlite3DbStrDup(db, pList->a[i].zEName);
        pItem->eEName = pList->a[i].eEName;
      }
    }
  }
  if( !db->mallocFailed ){
    Vdbe *v = pParse->pVdbe;
    assert( v!=0 );
    sqlite3VdbeSetNumCols(v, pNew->nExpr);
    for(i=0; i<pNew->nExpr; i++){
      sqlite3VdbeSetColName(v, i, COLNAME_NAME, pNew->a[i].zEName,
                            SQLITE_TRANSIENT);
    }
  }
  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;

  ExprList *pNew;
  Returning *pReturning;



  assert( v!=0 );
  assert( pParse->bReturning );
  pReturning = pParse->u1.pReturning;
  assert( pTrigger == &(pReturning->retTrig) );











  pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab);
  if( pNew ){
    NameContext sNC;
    memset(&sNC, 0, sizeof(sNC));
    if( pReturning->nRetCol==0 ){
      pReturning->nRetCol = pNew->nExpr;
      pReturning->iRetCur = pParse->nTab++;
    }
    sNC.pParse = pParse;
    sNC.uNC.iBaseReg = regIn;
    sNC.ncFlags = NC_UBaseReg;
    pParse->eTriggerOp = pTrigger->op;
    pParse->pTriggerTab = pTab;
    if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK ){
      int i;
      int nCol = pNew->nExpr;
      int reg = pParse->nMem+1;
      pParse->nMem += nCol+2;
      pReturning->iRetReg = reg;
      for(i=0; i<nCol; i++){

        sqlite3ExprCodeFactorable(pParse, pNew->a[i].pExpr, 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(pParse->db, pNew);
    pParse->eTriggerOp = 0;
    pParse->pTriggerTab = 0;
  }
}










<
<
<
<
<
<
<
<
<















>


>
>





>
>
>
>
>
>
>
>
>
>
>




















>
|





|







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
      if( !db->mallocFailed && ALWAYS(pList->a[i].zEName!=0) ){
        struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
        pItem->zEName = sqlite3DbStrDup(db, pList->a[i].zEName);
        pItem->eEName = pList->a[i].eEName;
      }
    }
  }









  return pNew;
}

/*
** Generate code for the RETURNING trigger.  Unlike other triggers
** that invoke a subprogram in the bytecode, the code for RETURNING
** is generated in-line.
*/
static void codeReturningTrigger(
  Parse *pParse,       /* Parse context */
  Trigger *pTrigger,   /* The trigger step that defines the RETURNING */
  Table *pTab,         /* The table to code triggers from */
  int regIn            /* The first in an array of registers */
){
  Vdbe *v = pParse->pVdbe;
  sqlite3 *db = pParse->db;
  ExprList *pNew;
  Returning *pReturning;
  Select sSelect;
  SrcList sFrom;

  assert( v!=0 );
  assert( pParse->bReturning );
  pReturning = pParse->u1.pReturning;
  assert( pTrigger == &(pReturning->retTrig) );
  memset(&sSelect, 0, sizeof(sSelect));
  memset(&sFrom, 0, sizeof(sFrom));
  sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
  sSelect.pSrc = &sFrom;
  sFrom.nSrc = 1;
  sFrom.a[0].pTab = pTab;
  sqlite3SelectPrep(pParse, &sSelect, 0);
  if( db->mallocFailed==0 && pParse->nErr==0 ){
    sqlite3GenerateColumnNames(pParse, &sSelect);
  }
  sqlite3ExprListDelete(db, sSelect.pEList);
  pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab);
  if( pNew ){
    NameContext sNC;
    memset(&sNC, 0, sizeof(sNC));
    if( pReturning->nRetCol==0 ){
      pReturning->nRetCol = pNew->nExpr;
      pReturning->iRetCur = pParse->nTab++;
    }
    sNC.pParse = pParse;
    sNC.uNC.iBaseReg = regIn;
    sNC.ncFlags = NC_UBaseReg;
    pParse->eTriggerOp = pTrigger->op;
    pParse->pTriggerTab = pTab;
    if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK ){
      int i;
      int nCol = pNew->nExpr;
      int reg = pParse->nMem+1;
      pParse->nMem += nCol+2;
      pReturning->iRetReg = reg;
      for(i=0; i<nCol; i++){
        Expr *pCol = pNew->a[i].pExpr;
        sqlite3ExprCodeFactorable(pParse, pCol, reg+i);
      }
      sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, i, reg+i);
      sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1);
      sqlite3VdbeAddOp3(v, OP_Insert, pReturning->iRetCur, reg+i, reg+i+1);
    }
    sqlite3ExprListDelete(db, pNew);
    pParse->eTriggerOp = 0;
    pParse->pTriggerTab = 0;
  }
}



1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
  Expr *pWhen = 0;            /* Duplicate of trigger WHEN expression */
  Vdbe *v;                    /* Temporary VM */
  NameContext sNC;            /* Name context for sub-vdbe */
  SubProgram *pProgram = 0;   /* Sub-vdbe for trigger program */
  Parse *pSubParse;           /* Parse context for sub-vdbe */
  int iEndTrigger = 0;        /* Label to jump to if WHEN is false */

  assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger)
       || IsSharedSchema(pParse->db)
  );
  assert( pTop->pVdbe );

  /* Allocate the TriggerPrg and SubProgram objects. To ensure that they
  ** are freed if an error occurs, link them into the Parse.pTriggerPrg 
  ** list of the top-level Parse object sooner rather than later.  */
  pPrg = sqlite3DbMallocZero(db, sizeof(TriggerPrg));







|
|







1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
  Expr *pWhen = 0;            /* Duplicate of trigger WHEN expression */
  Vdbe *v;                    /* Temporary VM */
  NameContext sNC;            /* Name context for sub-vdbe */
  SubProgram *pProgram = 0;   /* Sub-vdbe for trigger program */
  Parse *pSubParse;           /* Parse context for sub-vdbe */
  int iEndTrigger = 0;        /* Label to jump to if WHEN is false */

  assert( pTrigger->zName==0 || IsSharedSchema(pParse->db)
      || pTab==tableOfTrigger(pTrigger)
  );
  assert( pTop->pVdbe );

  /* Allocate the TriggerPrg and SubProgram objects. To ensure that they
  ** are freed if an error occurs, link them into the Parse.pTriggerPrg 
  ** list of the top-level Parse object sooner rather than later.  */
  pPrg = sqlite3DbMallocZero(db, sizeof(TriggerPrg));
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1160
1161
#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( SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) 
       && db->mallocFailed==0 
      ){
        iEndTrigger = sqlite3VdbeMakeLabel(pSubParse);
        sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
      }
      sqlite3ExprDelete(db, pWhen);
    }








>
|
<







1190
1191
1192
1193
1194
1195
1196
1197
1198

1199
1200
1201
1202
1203
1204
1205
#endif

    /* If one was specified, code the WHEN clause. If it evaluates to false
    ** (or NULL) the sub-vdbe is immediately halted by jumping to the 
    ** OP_Halt inserted at the end of the program.  */
    if( pTrigger->pWhen ){
      pWhen = sqlite3ExprDup(db, pTrigger->pWhen, 0);
      if( db->mallocFailed==0
       && SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) 

      ){
        iEndTrigger = sqlite3VdbeMakeLabel(pSubParse);
        sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
      }
      sqlite3ExprDelete(db, pWhen);
    }

1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
  Trigger *pTrigger,   /* Trigger to code */
  Table *pTab,         /* The table trigger pTrigger is attached to */
  int orconf           /* ON CONFLICT algorithm. */
){
  Parse *pRoot = sqlite3ParseToplevel(pParse);
  TriggerPrg *pPrg;

  assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) 
       || IsSharedSchema(pParse->db)
  );

  /* It may be that this trigger has already been coded (or is in the
  ** process of being coded). If this is the case, then an entry with
  ** a matching TriggerPrg.pTrigger field will be present somewhere
  ** in the Parse.pTriggerPrg list. Search for such an entry.  */
  for(pPrg=pRoot->pTriggerPrg; 







|
|







1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
  Trigger *pTrigger,   /* Trigger to code */
  Table *pTab,         /* The table trigger pTrigger is attached to */
  int orconf           /* ON CONFLICT algorithm. */
){
  Parse *pRoot = sqlite3ParseToplevel(pParse);
  TriggerPrg *pPrg;

  assert( pTrigger->zName==0 || IsSharedSchema(pParse->db)
      || pTab==tableOfTrigger(pTrigger) 
  );

  /* It may be that this trigger has already been coded (or is in the
  ** process of being coded). If this is the case, then an entry with
  ** a matching TriggerPrg.pTrigger field will be present somewhere
  ** in the Parse.pTriggerPrg list. Search for such an entry.  */
  for(pPrg=pRoot->pTriggerPrg; 
Changes to src/update.c.
216
217
218
219
220
221
222

223
224
225
226
227
228
229
#endif

  pSrc = sqlite3SrcListDup(db, pTabList, 0);
  pWhere2 = sqlite3ExprDup(db, pWhere, 0);

  assert( pTabList->nSrc>1 );
  if( pSrc ){

    pSrc->a[0].iCursor = -1;
    pSrc->a[0].pTab->nTabRef--;
    pSrc->a[0].pTab = 0;
  }
  if( pPk ){
    for(i=0; i<pPk->nKeyCol; i++){
      Expr *pNew = exprRowColumn(pParse, pPk->aiColumn[i]);







>







216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
#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]);
245
246
247
248
249
250
251

252
253
254
255
256
257
258
259
    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
  }

  if( ALWAYS(pChanges) ){
    for(i=0; i<pChanges->nExpr; i++){
      pList = sqlite3ExprListAppend(pParse, pList, 
          sqlite3ExprDup(db, pChanges->a[i].pExpr, 0)
      );
    }
  }
  pSelect = sqlite3SelectNew(pParse, pList, 







>
|







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
    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, 
795
796
797
798
799
800
801

802




803
804
805
806
807
808
809
      if( addrOnce ){
        sqlite3VdbeJumpHereOrPopInst(v, addrOnce);
      }
    }
  
    /* Top of the update loop */
    if( eOnePass!=ONEPASS_OFF ){

      if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){




        assert( pPk );
        sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey);
        VdbeCoverage(v);
      }
      if( eOnePass!=ONEPASS_SINGLE ){
        labelContinue = sqlite3VdbeMakeLabel(pParse);
      }







>
|
>
>
>
>







797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
      if( addrOnce ){
        sqlite3VdbeJumpHereOrPopInst(v, addrOnce);
      }
    }
  
    /* Top of the update loop */
    if( eOnePass!=ONEPASS_OFF ){
      if( aiCurOnePass[0]!=iDataCur
       && aiCurOnePass[1]!=iDataCur
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
       && !isView
#endif
      ){
        assert( pPk );
        sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey);
        VdbeCoverage(v);
      }
      if( eOnePass!=ONEPASS_SINGLE ){
        labelContinue = sqlite3VdbeMakeLabel(pParse);
      }
Changes to src/vdbe.c.
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
      (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);

  assert( iCur>=0 && iCur<p->nCursor );
  if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
    sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
    p->apCsr[iCur] = 0;
  }

  if( SQLITE_OK==sqlite3VdbeMemClearAndResize(pMem, nByte) ){


















    p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
    memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
    pCx->eCurType = eCurType;
    pCx->iDb = iDb;
    pCx->nField = nField;
    pCx->aOffset = &pCx->aType[nField];
    if( eCurType==CURTYPE_BTREE ){
      pCx->uc.pCursor = (BtCursor*)
          &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
      sqlite3BtreeCursorZero(pCx->uc.pCursor);
    }
  }
  return pCx;
}

/*
** The string in pRec is known to look like an integer and to have a
** floating point value of rValue.  Return true and set *piValue to the







>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
<







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
      (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);

  assert( iCur>=0 && iCur<p->nCursor );
  if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
    sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
    p->apCsr[iCur] = 0;
  }

  /* There used to be a call to sqlite3VdbeMemClearAndResize() to make sure
  ** the pMem used to hold space for the cursor has enough storage available
  ** in pMem->zMalloc.  But for the special case of the aMem[] entries used
  ** to hold cursors, it is faster to in-line the logic. */
  assert( pMem->flags==MEM_Undefined );
  assert( (pMem->flags & MEM_Dyn)==0 );
  assert( pMem->szMalloc==0 || pMem->z==pMem->zMalloc );
  if( pMem->szMalloc<nByte ){
    if( pMem->szMalloc>0 ){
      sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
    }
    pMem->z = pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, nByte);
    if( pMem->zMalloc==0 ){
      pMem->szMalloc = 0;
      return 0;
    }
    pMem->szMalloc = nByte;
  }

  p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
  memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
  pCx->eCurType = eCurType;
  pCx->iDb = iDb;
  pCx->nField = nField;
  pCx->aOffset = &pCx->aType[nField];
  if( eCurType==CURTYPE_BTREE ){
    pCx->uc.pCursor = (BtCursor*)
        &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
    sqlite3BtreeCursorZero(pCx->uc.pCursor);

  }
  return pCx;
}

/*
** The string in pRec is known to look like an integer and to have a
** floating point value of rValue.  Return true and set *piValue to the
429
430
431
432
433
434
435
436



437
438
439
440
441
442
443
** accordingly.
*/
static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
  int rc;
  sqlite3_int64 ix;
  assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 );
  assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
  ExpandBlob(pMem);



  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;







|
>
>
>







447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
** accordingly.
*/
static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
  int rc;
  sqlite3_int64 ix;
  assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 );
  assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
  if( ExpandBlob(pMem) ){
    pMem->u.i = 0;
    return MEM_Int;
  }
  rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
  if( rc<=0 ){
    if( rc==0 && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
      pMem->u.i = ix;
      return MEM_Int;
    }else{
      return MEM_Real;
566
567
568
569
570
571
572





573
574
575
576
577
578
579
  printf("R[%d] = ", iReg);
  memTracePrint(p);
  if( p->pScopyFrom ){
    printf(" <== R[%d]", (int)(p->pScopyFrom - &p[-iReg]));
  }
  printf("\n");
  sqlite3VdbeCheckMemInvariants(p);





}
#endif

#ifdef SQLITE_DEBUG
/*
** Show the values of all registers in the virtual machine.  Used for
** interactive debugging.







>
>
>
>
>







587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
  printf("R[%d] = ", iReg);
  memTracePrint(p);
  if( p->pScopyFrom ){
    printf(" <== R[%d]", (int)(p->pScopyFrom - &p[-iReg]));
  }
  printf("\n");
  sqlite3VdbeCheckMemInvariants(p);
}
/**/ void sqlite3PrintMem(Mem *pMem){
  memTracePrint(pMem);
  printf("\n");
  fflush(stdout);
}
#endif

#ifdef SQLITE_DEBUG
/*
** Show the values of all registers in the virtual machine.  Used for
** interactive debugging.
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
** 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+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );

  /* Invalidate all ephemeral cursor row caches */
  p->cacheCtr = (p->cacheCtr + 2)|1;

  /* Make sure the results of the current row are \000 terminated
  ** and have an assigned type.  The results are de-ephemeralized as







|







1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
** structure to provide access to the r(P1)..r(P1+P2-1) values as
** the result row.
*/
case OP_ResultRow: {
  Mem *pMem;
  int i;
  assert( p->nResColumn==pOp->p2 );
  assert( pOp->p1>0 || CORRUPT_DB );
  assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );

  /* Invalidate all ephemeral cursor row caches */
  p->cacheCtr = (p->cacheCtr + 2)|1;

  /* Make sure the results of the current row are \000 terminated
  ** and have an assigned type.  The results are de-ephemeralized as
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
}
#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
** 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







|
<







1937
1938
1939
1940
1941
1942
1943
1944

1945
1946
1947
1948
1949
1950
1951
}
#endif /* SQLITE_OMIT_CAST */

/* Opcode: Eq P1 P2 P3 P4 P5
** Synopsis: IF r[P3]==r[P1]
**
** Compare the values in register P1 and P3.  If reg(P3)==reg(P1) then
** jump to address P2. 

**
** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made 
** to coerce both inputs according to this affinity before the
** comparison is made. If the SQLITE_AFF_MASK is 0x00, then numeric
** affinity is used. Note that the affinity conversions are stored
** back into the input registers P1 and P3.  So this opcode can cause
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
**
** 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).
** 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
** 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 







|
|
<







<
<
<
<





|
<







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
**
** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
** true or false and is never NULL.  If both operands are NULL then the result
** of comparison is true.  If either operand is NULL then the result is false.
** If neither operand is NULL the result is the same as it would be if
** the SQLITE_NULLEQ flag were omitted from P5.
**
** This opcode saves the result of comparison for use by the new
** OP_Jump opcode.

*/
/* Opcode: Ne P1 P2 P3 P4 P5
** Synopsis: IF r[P3]!=r[P1]
**
** This works just like the Eq opcode except that the jump is taken if
** the operands in registers P1 and P3 are not equal.  See the Eq opcode for
** additional information.




*/
/* Opcode: Lt P1 P2 P3 P4 P5
** Synopsis: IF r[P3]<r[P1]
**
** Compare the values in register P1 and P3.  If reg(P3)<reg(P1) then
** jump to address P2.

**
** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or
** reg(P3) is NULL then the take the jump.  If the SQLITE_JUMPIFNULL 
** bit is clear then fall through if either operand is NULL.
**
** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made 
1981
1982
1983
1984
1985
1986
1987



1988
1989
1990
1991
1992
1993
1994
** used to determine the results of the comparison.  If both values
** are text, then the appropriate collating function specified in
** P4 is  used to do the comparison.  If P4 is not specified then
** memcmp() is used to compare text string.  If both values are
** numeric, then a numeric comparison is used. If the two values
** are of different types, then numbers are considered less than
** strings and strings are considered less than blobs.



*/
/* Opcode: Le P1 P2 P3 P4 P5
** Synopsis: IF r[P3]<=r[P1]
**
** This works just like the Lt opcode except that the jump is taken if
** the content of register P3 is less than or equal to the content of
** register P1.  See the Lt opcode for additional information.







>
>
>







2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
** 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.
2018
2019
2020
2021
2022
2023
2024

























2025
2026
2027
2028
2029
2030
2031
  u16 flags1;         /* Copy of initial value of pIn1->flags */
  u16 flags3;         /* Copy of initial value of pIn3->flags */

  pIn1 = &aMem[pOp->p1];
  pIn3 = &aMem[pOp->p3];
  flags1 = pIn1->flags;
  flags3 = pIn3->flags;

























  if( (flags1 | flags3)&MEM_Null ){
    /* One or both operands are NULL */
    if( pOp->p5 & SQLITE_NULLEQ ){
      /* If SQLITE_NULLEQ is set (which will only happen if the operator is
      ** OP_Eq or OP_Ne) then take the jump or not depending on whether
      ** or not both operands are null.
      */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
  u16 flags1;         /* Copy of initial value of pIn1->flags */
  u16 flags3;         /* Copy of initial value of pIn3->flags */

  pIn1 = &aMem[pOp->p1];
  pIn3 = &aMem[pOp->p3];
  flags1 = pIn1->flags;
  flags3 = pIn3->flags;
  if( (flags1 & flags3 & MEM_Int)!=0 ){
    assert( (pOp->p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_TEXT || CORRUPT_DB );
    /* Common case of comparison of two integers */
    if( pIn3->u.i > pIn1->u.i ){
      iCompare = +1;
      if( sqlite3aGTb[pOp->opcode] ){
        VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
        goto jump_to_p2;
      }
    }else if( pIn3->u.i < pIn1->u.i ){
      iCompare = -1;
      if( sqlite3aLTb[pOp->opcode] ){
        VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
        goto jump_to_p2;
      }
    }else{
      iCompare = 0;
      if( sqlite3aEQb[pOp->opcode] ){
        VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
        goto jump_to_p2;
      }
    }
    VdbeBranchTaken(0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
    break;
  }
  if( (flags1 | flags3)&MEM_Null ){
    /* One or both operands are NULL */
    if( pOp->p5 & SQLITE_NULLEQ ){
      /* If SQLITE_NULLEQ is set (which will only happen if the operator is
      ** OP_Eq or OP_Ne) then take the jump or not depending on whether
      ** or not both operands are null.
      */
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
        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;
        }
      }
      break;
    }
  }else{
    /* Neither operand is NULL.  Do a comparison. */

    affinity = pOp->p5 & SQLITE_AFF_MASK;
    if( affinity>=SQLITE_AFF_NUMERIC ){
      if( (flags1 | flags3)&MEM_Str ){
        if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
          applyNumericAffinity(pIn1,0);
          testcase( flags3==pIn3->flags );
          flags3 = pIn3->flags;
        }
        if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
          applyNumericAffinity(pIn3,0);
        }
      }
      /* 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|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) );







<
<
|
<
<
<
<
|
|
|
<




|
>












<
<
<
<
<
<
<
<







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
        res = ((flags3 & MEM_Null) ? -1 : +1);  /* Operands are not equal */
      }
    }else{
      /* SQLITE_NULLEQ is clear and at least one operand is NULL,
      ** then the result is always NULL.
      ** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
      */


      iCompare = 1;    /* Operands are not equal */




      VdbeBranchTaken(2,3);
      if( pOp->p5 & SQLITE_JUMPIFNULL ){
        goto jump_to_p2;

      }
      break;
    }
  }else{
    /* Neither operand is NULL and we couldn't do the special high-speed
    ** integer comparison case.  So do a general-case comparison. */
    affinity = pOp->p5 & SQLITE_AFF_MASK;
    if( affinity>=SQLITE_AFF_NUMERIC ){
      if( (flags1 | flags3)&MEM_Str ){
        if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
          applyNumericAffinity(pIn1,0);
          testcase( flags3==pIn3->flags );
          flags3 = pIn3->flags;
        }
        if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
          applyNumericAffinity(pIn3,0);
        }
      }








    }else if( affinity==SQLITE_AFF_TEXT ){
      if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
        testcase( pIn1->flags & MEM_Int );
        testcase( pIn1->flags & MEM_Real );
        testcase( pIn1->flags & MEM_IntReal );
        sqlite3VdbeMemStringify(pIn1, encoding, 1);
        testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
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
        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 */
    static const unsigned char aLTb[] = { 1,  0,  0,  1,  1,  0 };
    res2 = aLTb[pOp->opcode - OP_Ne];
  }else if( res==0 ){
    static const unsigned char aEQb[] = { 0,  1,  0,  1,  0,  1 };
    res2 = aEQb[pOp->opcode - OP_Ne];
  }else{
    static const unsigned char aGTb[] = { 1,  0,  1,  0,  0,  1 };
    res2 = aGTb[pOp->opcode - OP_Ne];
  }


  /* Undo any changes made by applyAffinity() to the input registers. */
  assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
  pIn3->flags = flags3;
  assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
  pIn1->flags = flags1;

  if( pOp->p5 & SQLITE_STOREP2 ){
    pOut = &aMem[pOp->p2];
    iCompare = res;
    if( (pOp->p5 & SQLITE_KEEPNULL)!=0 ){
      /* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1
      ** and prevents OP_Ne from overwriting NULL with 0.  This flag
      ** is only used in contexts where either:
      **   (1) op==OP_Eq && (r[P2]==NULL || r[P2]==0)
      **   (2) op==OP_Ne && (r[P2]==NULL || r[P2]==1)
      ** Therefore it is not necessary to check the content of r[P2] for
      ** NULL. */
      assert( pOp->opcode==OP_Ne || pOp->opcode==OP_Eq );
      assert( res2==0 || res2==1 );
      testcase( res2==0 && pOp->opcode==OP_Eq );
      testcase( res2==1 && pOp->opcode==OP_Eq );
      testcase( res2==0 && pOp->opcode==OP_Ne );
      testcase( res2==1 && pOp->opcode==OP_Ne );
      if( (pOp->opcode==OP_Eq)==res2 ) break;
    }
    memAboutToChange(p, pOut);
    MemSetTypeFlag(pOut, MEM_Int);
    pOut->u.i = res2;
    REGISTER_TRACE(pOp->p2, pOut);
  }else{
    VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
    if( res2 ){
      goto jump_to_p2;
    }
  }
  break;
}

/* Opcode: ElseNotEq * P2 * * *
**
** This opcode must follow an OP_Lt or OP_Gt comparison operator.  There
** can be zero or more OP_ReleaseReg opcodes intervening, but no other
** opcodes are allowed to occur between this instruction and the previous
** OP_Lt or OP_Gt.  Furthermore, the prior OP_Lt or OP_Gt must have the
** SQLITE_STOREP2 bit set in the P5 field.
**
** If result of an OP_Eq comparison on the same two operands as the
** prior OP_Lt or OP_Gt would have been NULL or false (0), then then
** jump to P2.  If the result of an OP_Eq comparison on the two previous
** operands would have been true (1), then fall through.
*/
case OP_ElseNotEq: {       /* same as TK_ESCAPE, jump */

#ifdef SQLITE_DEBUG
  /* Verify the preconditions of this opcode - that it follows an OP_Lt or
  ** OP_Gt with the SQLITE_STOREP2 flag set, with zero or more intervening
  ** OP_ReleaseReg opcodes */
  int iAddr;
  for(iAddr = (int)(pOp - aOp) - 1; ALWAYS(iAddr>=0); iAddr--){
    if( aOp[iAddr].opcode==OP_ReleaseReg ) continue;
    assert( aOp[iAddr].opcode==OP_Lt || aOp[iAddr].opcode==OP_Gt );
    assert( aOp[iAddr].p5 & SQLITE_STOREP2 );
    break;
  }
#endif /* SQLITE_DEBUG */
  VdbeBranchTaken(iCompare!=0, 2);
  if( iCompare!=0 ) goto jump_to_p2;
  break;
}


/* Opcode: Permutation * * * P4 *
**
** Set the permutation used by the OP_Compare operator in the next







|








|
<
|

<
|

<
|

>







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
<



|




|
<


|
|
|

|



<
|




<



|
|







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
        testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
        flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
      }
    }
    assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
    res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
  }

  /* At this point, res is negative, zero, or positive if reg[P1] is
  ** less than, equal to, or greater than reg[P3], respectively.  Compute
  ** the answer to this operator in res2, depending on what the comparison
  ** operator actually is.  The next block of code depends on the fact
  ** that the 6 comparison operators are consecutive integers in this
  ** order:  NE, EQ, GT, LE, LT, GE */
  assert( OP_Eq==OP_Ne+1 ); assert( OP_Gt==OP_Ne+2 ); assert( OP_Le==OP_Ne+3 );
  assert( OP_Lt==OP_Ne+4 ); assert( OP_Ge==OP_Ne+5 );
  if( res<0 ){

    res2 = sqlite3aLTb[pOp->opcode];
  }else if( res==0 ){

    res2 = sqlite3aEQb[pOp->opcode];
  }else{

    res2 = sqlite3aGTb[pOp->opcode];
  }
  iCompare = res;

  /* Undo any changes made by applyAffinity() to the input registers. */
  assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
  pIn3->flags = flags3;
  assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
  pIn1->flags = flags1;

























  VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
  if( res2 ){
    goto jump_to_p2;
  }

  break;
}

/* Opcode: ElseEq * P2 * * *
**
** This opcode must follow an OP_Lt or OP_Gt comparison operator.  There
** can be zero or more OP_ReleaseReg opcodes intervening, but no other
** opcodes are allowed to occur between this instruction and the previous
** OP_Lt or OP_Gt. 

**
** If result of an OP_Eq comparison on the same two operands as the
** prior OP_Lt or OP_Gt would have been true, then jump to P2.
** If the result of an OP_Eq comparison on the two previous
** operands would have been false or NULL, then fall through.
*/
case OP_ElseEq: {       /* same as TK_ESCAPE, jump */

#ifdef SQLITE_DEBUG
  /* Verify the preconditions of this opcode - that it follows an OP_Lt or

  ** OP_Gt with zero or more intervening OP_ReleaseReg opcodes */
  int iAddr;
  for(iAddr = (int)(pOp - aOp) - 1; ALWAYS(iAddr>=0); iAddr--){
    if( aOp[iAddr].opcode==OP_ReleaseReg ) continue;
    assert( aOp[iAddr].opcode==OP_Lt || aOp[iAddr].opcode==OP_Gt );

    break;
  }
#endif /* SQLITE_DEBUG */
  VdbeBranchTaken(iCompare==0, 2);
  if( iCompare==0 ) goto jump_to_p2;
  break;
}


/* Opcode: Permutation * * * P4 *
**
** Set the permutation used by the OP_Compare operator in the next
2494
2495
2496
2497
2498
2499
2500


















2501
2502
2503
2504
2505
2506
2507
  pIn1 = &aMem[pOp->p1];
  VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2);
  if( (pIn1->flags & MEM_Null)!=0 ){
    goto jump_to_p2;
  }
  break;
}



















/* Opcode: NotNull P1 P2 * * *
** Synopsis: if r[P1]!=NULL goto P2
**
** Jump to P2 if the value in register P1 is not NULL.  
*/
case OP_NotNull: {            /* same as TK_NOTNULL, jump, in1 */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
  pIn1 = &aMem[pOp->p1];
  VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2);
  if( (pIn1->flags & MEM_Null)!=0 ){
    goto jump_to_p2;
  }
  break;
}

/* Opcode: ZeroOrNull P1 P2 P3 * *
** Synopsis: r[P2] = 0 OR NULL
**
** If all both registers P1 and P3 are NOT NULL, then store a zero in
** register P2.  If either registers P1 or P3 are NULL then put
** a NULL in register P2.
*/
case OP_ZeroOrNull: {            /* in1, in2, out2, in3 */
  if( (aMem[pOp->p1].flags & MEM_Null)!=0
   || (aMem[pOp->p3].flags & MEM_Null)!=0
  ){
    sqlite3VdbeMemSetNull(aMem + pOp->p2);
  }else{
    sqlite3VdbeMemSetInt64(aMem + pOp->p2, 0);
  }
  break;
}

/* Opcode: NotNull P1 P2 * * *
** Synopsis: if r[P1]!=NULL goto P2
**
** Jump to P2 if the value in register P1 is not NULL.  
*/
case OP_NotNull: {            /* same as TK_NOTNULL, jump, in1 */
4551
4552
4553
4554
4555
4556
4557





4558
4559





4560
4561
4562
4563
4564
4565
4566
case OP_SeekHit: {
  VdbeCursor *pC;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pOp->p3>=pOp->p2 );
  if( pC->seekHit<pOp->p2 ){





    pC->seekHit = pOp->p2;
  }else if( pC->seekHit>pOp->p3 ){





    pC->seekHit = pOp->p3;
  }
  break;
}

/* Opcode: IfNotOpen P1 P2 * * *
** Synopsis: if( !csr[P1] ) goto P2







>
>
>
>
>


>
>
>
>
>







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
case OP_SeekHit: {
  VdbeCursor *pC;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pOp->p3>=pOp->p2 );
  if( pC->seekHit<pOp->p2 ){
#ifdef SQLITE_DEBUG
    if( db->flags&SQLITE_VdbeTrace ){
      printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p2);
    }        
#endif
    pC->seekHit = pOp->p2;
  }else if( pC->seekHit>pOp->p3 ){
#ifdef SQLITE_DEBUG
    if( db->flags&SQLITE_VdbeTrace ){
      printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p3);
    }        
#endif
    pC->seekHit = pOp->p3;
  }
  break;
}

/* Opcode: IfNotOpen P1 P2 * * *
** Synopsis: if( !csr[P1] ) goto P2
4667
4668
4669
4670
4671
4672
4673





4674
4675
4676
4677
4678
4679
4680
** See also: NotFound, Found, NotExists
*/
case OP_IfNoHope: {     /* jump, in3 */
  VdbeCursor *pC;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );





  if( pC->seekHit>=pOp->p4.i ) break;
  /* Fall through into OP_NotFound */
  /* no break */ deliberate_fall_through
}
case OP_NoConflict:     /* jump, in3 */
case OP_NotFound:       /* jump, in3 */
case OP_Found: {        /* jump, in3 */







>
>
>
>
>







4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
** See also: NotFound, Found, NotExists
*/
case OP_IfNoHope: {     /* jump, in3 */
  VdbeCursor *pC;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
#ifdef SQLITE_DEBUG
  if( db->flags&SQLITE_VdbeTrace ){
    printf("seekHit is %d\n", pC->seekHit);
  }        
#endif
  if( pC->seekHit>=pOp->p4.i ) break;
  /* Fall through into OP_NotFound */
  /* no break */ deliberate_fall_through
}
case OP_NoConflict:     /* jump, in3 */
case OP_NotFound:       /* jump, in3 */
case OP_Found: {        /* jump, in3 */
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
    zDb = 0;  /* Not needed.  Silence a compiler warning. */
  }

#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  /* Invoke the pre-update hook, if any */
  if( pTab ){
    if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){
      sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey,pOp->p2);
    }
    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;







|







5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
    zDb = 0;  /* Not needed.  Silence a compiler warning. */
  }

#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
  /* Invoke the pre-update hook, if any */
  if( pTab ){
    if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){
      sqlite3VdbePreUpdateHook(p,pC,SQLITE_INSERT,zDb,pTab,x.nKey,pOp->p2,-1);
    }
    if( db->xUpdateCallback==0 || pTab->aCol==0 ){
      /* Prevent post-update hook from running in cases when it should not */
      pTab = 0;
    }
  }
  if( pOp->p5 & OPFLAG_ISNOOP ) break;
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
    assert( !(opflags & OPFLAG_ISUPDATE) 
         || HasRowid(pTab)==0 
         || (aMem[pOp->p3].flags & MEM_Int) 
    );
    sqlite3VdbePreUpdateHook(p, pC,
        (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, 
        zDb, pTab, pC->movetoTarget,
        pOp->p3
    );
  }
  if( opflags & OPFLAG_ISNOOP ) break;
#endif
 
  /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ 
  assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 );







|







5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
    assert( !(opflags & OPFLAG_ISUPDATE) 
         || HasRowid(pTab)==0 
         || (aMem[pOp->p3].flags & MEM_Int) 
    );
    sqlite3VdbePreUpdateHook(p, pC,
        (opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE, 
        zDb, pTab, pC->movetoTarget,
        pOp->p3, -1
    );
  }
  if( opflags & OPFLAG_ISNOOP ) break;
#endif
 
  /* Only flags that can be set are SAVEPOISTION and AUXDELETE */ 
  assert( (pOp->p5 & ~(OPFLAG_SAVEPOSITION|OPFLAG_AUXDELETE))==0 );
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
  for(iDb=0; iDb<db->nDb; iDb++){
    assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
  }
#endif

  iDb = pOp->p1;
  assert( iDb>=0 && iDb<db->nDb );
  assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );

#ifndef SQLITE_OMIT_ALTERTABLE
  if( pOp->p4.z==0 ){
    sqlite3SchemaClear(db->aDb[iDb].pSchema);
    db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
    rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5);
    db->mDbFlags |= DBFLAG_SchemaChange;







|







6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
  for(iDb=0; iDb<db->nDb; iDb++){
    assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
  }
#endif

  iDb = pOp->p1;
  assert( iDb>=0 && iDb<db->nDb );
  assert( DbHasProperty(db, iDb, DB_SchemaLoaded) || db->mallocFailed );

#ifndef SQLITE_OMIT_ALTERTABLE
  if( pOp->p4.z==0 ){
    sqlite3SchemaClear(db->aDb[iDb].pSchema);
    db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
    rc = sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5);
    db->mDbFlags |= DBFLAG_SchemaChange;
7207
7208
7209
7210
7211
7212
7213

7214
7215
7216
7217
7218
7219
7220
  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  assert( p->readOnly==0 );

  pBt = db->aDb[pOp->p1].pBt;
  pPager = sqlite3BtreePager(pBt);
  eOld = sqlite3PagerGetJournalMode(pPager);
  if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld;

  if( !sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld;

#ifndef SQLITE_OMIT_WAL
  zFilename = sqlite3PagerFilename(pPager, 1);

  /* Do not allow a transition to journal_mode=WAL for a database
  ** in temporary storage or if the VFS does not support shared memory 







>







7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
  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 
Changes to src/vdbeInt.h.
468
469
470
471
472
473
474

475
476
477
478
479
480
481
  VdbeCursor *pCsr;               /* Cursor to read old values from */
  int op;                         /* One of SQLITE_INSERT, UPDATE, DELETE */
  u8 *aRecord;                    /* old.* database record */
  KeyInfo keyinfo;
  UnpackedRecord *pUnpacked;      /* Unpacked version of aRecord[] */
  UnpackedRecord *pNewUnpacked;   /* Unpacked version of new.* record */
  int iNewReg;                    /* Register for new.* values */

  i64 iKey1;                      /* First key value passed to hook */
  i64 iKey2;                      /* Second key value passed to hook */
  Mem *aNew;                      /* Array of new.* values */
  Table *pTab;                    /* Schema object being upated */          
  Index *pPk;                     /* PK index if pTab is WITHOUT ROWID */
};








>







468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
  VdbeCursor *pCsr;               /* Cursor to read old values from */
  int op;                         /* One of SQLITE_INSERT, UPDATE, DELETE */
  u8 *aRecord;                    /* old.* database record */
  KeyInfo keyinfo;
  UnpackedRecord *pUnpacked;      /* Unpacked version of aRecord[] */
  UnpackedRecord *pNewUnpacked;   /* Unpacked version of new.* record */
  int iNewReg;                    /* Register for new.* values */
  int iBlobWrite;                 /* Value returned by preupdate_blobwrite() */
  i64 iKey1;                      /* First key value passed to hook */
  i64 iKey2;                      /* Second key value passed to hook */
  Mem *aNew;                      /* Array of new.* values */
  Table *pTab;                    /* Schema object being upated */          
  Index *pPk;                     /* PK index if pTab is WITHOUT ROWID */
};

556
557
558
559
560
561
562
563

564
565
566
567
568
569
570
#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);

#endif
int sqlite3VdbeTransferError(Vdbe *p);

int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);







|
>







557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
#ifdef SQLITE_DEBUG
int sqlite3VdbeFrameIsValid(VdbeFrame*);
#endif
void sqlite3VdbeFrameMemDel(void*);      /* Destructor on Mem */
void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */
int sqlite3VdbeFrameRestore(VdbeFrame *);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
void sqlite3VdbePreUpdateHook(
    Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int,int);
#endif
int sqlite3VdbeTransferError(Vdbe *p);

int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
Changes to src/vdbeapi.c.
1900
1901
1902
1903
1904
1905
1906











1907
1908
1909
1910
1911
1912
1913
** 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 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){







>
>
>
>
>
>
>
>
>
>
>







1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
** or SET DEFAULT action is considered a trigger.
*/
int sqlite3_preupdate_depth(sqlite3 *db){
  PreUpdate *p = db->pPreUpdate;
  return (p ? p->v->nFrame : 0);
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */

#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
** This function is designed to be called from within a pre-update callback
** only. 
*/
int sqlite3_preupdate_blobwrite(sqlite3 *db){
  PreUpdate *p = db->pPreUpdate;
  return (p ? p->iBlobWrite : -1);
}
#endif

#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
** This function is called from within a pre-update callback to retrieve
** a field of the row currently being updated or inserted.
*/
int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
Changes to src/vdbeaux.c.
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
  zOpName = sqlite3OpcodeName(pOp->opcode);
  nOpName = sqlite3Strlen30(zOpName);
  if( zOpName[nOpName+1] ){
    int seenCom = 0;
    char c;
    zSynopsis = zOpName += nOpName + 1;
    if( strncmp(zSynopsis,"IF ",3)==0 ){
      if( pOp->p5 & SQLITE_STOREP2 ){
        sqlite3_snprintf(sizeof(zAlt), zAlt, "r[P2] = (%s)", zSynopsis+3);
      }else{
        sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3);
      }
      zSynopsis = zAlt;
    }
    for(ii=0; (c = zSynopsis[ii])!=0; ii++){
      if( c=='P' ){
        c = zSynopsis[++ii];
        if( c=='4' ){
          sqlite3_str_appendall(&x, zP4);







<
<
<
|
<







1485
1486
1487
1488
1489
1490
1491



1492

1493
1494
1495
1496
1497
1498
1499
  zOpName = sqlite3OpcodeName(pOp->opcode);
  nOpName = sqlite3Strlen30(zOpName);
  if( zOpName[nOpName+1] ){
    int seenCom = 0;
    char c;
    zSynopsis = zOpName += nOpName + 1;
    if( strncmp(zSynopsis,"IF ",3)==0 ){



      sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3);

      zSynopsis = zAlt;
    }
    for(ii=0; (c = zSynopsis[ii])!=0; ii++){
      if( c=='P' ){
        c = zSynopsis[++ii];
        if( c=='4' ){
          sqlite3_str_appendall(&x, zP4);
5191
5192
5193
5194
5195
5196
5197
5198

5199
5200
5201
5202
5203
5204
5205
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 */

){
  sqlite3 *db = v->db;
  i64 iKey2;
  PreUpdate preupdate;
  const char *zTbl = pTab->zName;
  static const u8 fakeSortOrder = 0;








|
>







5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
void sqlite3VdbePreUpdateHook(
  Vdbe *v,                        /* Vdbe pre-update hook is invoked by */
  VdbeCursor *pCsr,               /* Cursor to grab old.* values from */
  int op,                         /* SQLITE_INSERT, UPDATE or DELETE */
  const char *zDb,                /* Database name */
  Table *pTab,                    /* Modified table */
  i64 iKey1,                      /* Initial key value */
  int iReg,                       /* Register for new.* record */
  int iBlobWrite
){
  sqlite3 *db = v->db;
  i64 iKey2;
  PreUpdate preupdate;
  const char *zTbl = pTab->zName;
  static const u8 fakeSortOrder = 0;

5227
5228
5229
5230
5231
5232
5233

5234
5235
5236
5237
5238
5239
5240
  preupdate.keyinfo.db = db;
  preupdate.keyinfo.enc = ENC(db);
  preupdate.keyinfo.nKeyField = pTab->nCol;
  preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder;
  preupdate.iKey1 = iKey1;
  preupdate.iKey2 = iKey2;
  preupdate.pTab = pTab;


  db->pPreUpdate = &preupdate;
  db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
  db->pPreUpdate = 0;
  sqlite3DbFree(db, preupdate.aRecord);
  vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked);
  vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked);







>







5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
  preupdate.keyinfo.db = db;
  preupdate.keyinfo.enc = ENC(db);
  preupdate.keyinfo.nKeyField = pTab->nCol;
  preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder;
  preupdate.iKey1 = iKey1;
  preupdate.iKey2 = iKey2;
  preupdate.pTab = pTab;
  preupdate.iBlobWrite = iBlobWrite;

  db->pPreUpdate = &preupdate;
  db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
  db->pPreUpdate = 0;
  sqlite3DbFree(db, preupdate.aRecord);
  vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked);
  vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked);
Changes to src/vdbeblob.c.
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
      ** slightly more efficient). Since you cannot write to a PK column
      ** using the incremental-blob API, this works. For the sessions module
      ** anyhow.
      */
      sqlite3_int64 iKey;
      iKey = sqlite3BtreeIntegerKey(p->pCsr);
      sqlite3VdbePreUpdateHook(
          v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1
      );
    }
#endif

    rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
    sqlite3BtreeLeaveCursor(p->pCsr);
    if( rc==SQLITE_ABORT ){







|







422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
      ** slightly more efficient). Since you cannot write to a PK column
      ** using the incremental-blob API, this works. For the sessions module
      ** anyhow.
      */
      sqlite3_int64 iKey;
      iKey = sqlite3BtreeIntegerKey(p->pCsr);
      sqlite3VdbePreUpdateHook(
          v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol
      );
    }
#endif

    rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
    sqlite3BtreeLeaveCursor(p->pCsr);
    if( rc==SQLITE_ABORT ){
493
494
495
496
497
498
499

500
501
502
503
504
505
506
  if( p->pStmt==0 ){
    /* If there is no statement handle, then the blob-handle has
    ** already been invalidated. Return SQLITE_ABORT in this case.
    */
    rc = SQLITE_ABORT;
  }else{
    char *zErr;

    rc = blobSeekToRow(p, iRow, &zErr);
    if( rc!=SQLITE_OK ){
      sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
      sqlite3DbFree(db, zErr);
    }
    assert( rc!=SQLITE_SCHEMA );
  }







>







493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
  if( p->pStmt==0 ){
    /* If there is no statement handle, then the blob-handle has
    ** already been invalidated. Return SQLITE_ABORT in this case.
    */
    rc = SQLITE_ABORT;
  }else{
    char *zErr;
    ((Vdbe*)p->pStmt)->rc = SQLITE_OK;
    rc = blobSeekToRow(p, iRow, &zErr);
    if( rc!=SQLITE_OK ){
      sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
      sqlite3DbFree(db, zErr);
    }
    assert( rc!=SQLITE_SCHEMA );
  }
Changes to src/vdbemem.c.
71
72
73
74
75
76
77


78
79
80
81
82
83
84
85
  }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->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







>
>
|







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  }else{
    /* The MEM_Cleared bit is only allowed on NULLs */
    assert( (p->flags & MEM_Cleared)==0 );
  }

  /* The szMalloc field holds the correct memory allocation size */
  assert( p->szMalloc==0
       || (p->flags==MEM_Undefined 
           && p->szMalloc<=sqlite3DbMallocSize(p->db,p->zMalloc))
       || p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc));

  /* If p holds a string or blob, the Mem.z must point to exactly
  ** one of the following:
  **
  **   (1) Memory in Mem.zMalloc and managed by the Mem object
  **   (2) Memory to be freed using Mem.xDel
  **   (3) An ephemeral string or blob
235
236
237
238
239
240
241


242
243
244
245
246
247
248
249

  /* 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->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
  if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
    if( pMem->db ){
      pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
    }else{
      pMem->zMalloc = sqlite3Realloc(pMem->z, n);
      if( pMem->zMalloc==0 ) sqlite3_free(pMem->z);
      pMem->z = pMem->zMalloc;







>
>
|







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253

  /* If the bPreserve flag is set to true, then the memory cell must already
  ** contain a valid string or blob value.  */
  assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
  testcase( bPreserve && pMem->z==0 );

  assert( pMem->szMalloc==0
       || (pMem->flags==MEM_Undefined 
           && pMem->szMalloc<=sqlite3DbMallocSize(pMem->db,pMem->zMalloc))
       || pMem->szMalloc==sqlite3DbMallocSize(pMem->db,pMem->zMalloc));
  if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
    if( pMem->db ){
      pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
    }else{
      pMem->zMalloc = sqlite3Realloc(pMem->z, n);
      if( pMem->zMalloc==0 ) sqlite3_free(pMem->z);
      pMem->z = pMem->zMalloc;
Changes to src/vtab.c.
1255
1256
1257
1258
1259
1260
1261

1262
1263
1264
1265
1266
1267
1268
    return 0;
  }
  pMod->pEpoTab = pTab;
  pTab->nTabRef = 1;
  pTab->pSchema = db->aDb[0].pSchema;
  assert( pTab->nModuleArg==0 );
  pTab->iPKey = -1;

  addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
  addModuleArgument(pParse, pTab, 0);
  addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
  rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr);
  if( rc ){
    sqlite3ErrorMsg(pParse, "%s", zErr);
    sqlite3DbFree(db, zErr);







>







1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
    return 0;
  }
  pMod->pEpoTab = pTab;
  pTab->nTabRef = 1;
  pTab->pSchema = db->aDb[0].pSchema;
  assert( pTab->nModuleArg==0 );
  pTab->iPKey = -1;
  pTab->tabFlags |= TF_Eponymous;
  addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
  addModuleArgument(pParse, pTab, 0);
  addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
  rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr);
  if( rc ){
    sqlite3ErrorMsg(pParse, "%s", zErr);
    sqlite3DbFree(db, zErr);
Changes to src/wal.c.
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
** actually needed.
*/
static void walCleanupHash(Wal *pWal){
  WalHashLoc sLoc;                /* Hash table location */
  int iLimit = 0;                 /* Zero values greater than this */
  int nByte;                      /* Number of bytes to zero in aPgno[] */
  int i;                          /* Used to iterate through aHash[] */
  int rc;                         /* Return code form walHashGet() */

  assert( pWal->writeLock );
  testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 );
  testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE );
  testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE+1 );

  if( pWal->hdr.mxFrame==0 ) return;

  /* Obtain pointers to the hash-table and page-number array containing 
  ** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed
  ** that the page said hash-table and array reside on is already mapped.(1)
  */
  assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) );
  assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] );
  rc = walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
  if( NEVER(rc) ) return; /* Defense-in-depth, in case (1) above is wrong */

  /* Zero all hash-table entries that correspond to frame numbers greater
  ** than pWal->hdr.mxFrame.
  */
  iLimit = pWal->hdr.mxFrame - sLoc.iZero;
  assert( iLimit>0 );
  for(i=0; i<HASHTABLE_NSLOT; i++){







<














|
|







995
996
997
998
999
1000
1001

1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
** actually needed.
*/
static void walCleanupHash(Wal *pWal){
  WalHashLoc sLoc;                /* Hash table location */
  int iLimit = 0;                 /* Zero values greater than this */
  int nByte;                      /* Number of bytes to zero in aPgno[] */
  int i;                          /* Used to iterate through aHash[] */


  assert( pWal->writeLock );
  testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 );
  testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE );
  testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE+1 );

  if( pWal->hdr.mxFrame==0 ) return;

  /* Obtain pointers to the hash-table and page-number array containing 
  ** the entry that corresponds to frame pWal->hdr.mxFrame. It is guaranteed
  ** that the page said hash-table and array reside on is already mapped.(1)
  */
  assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) );
  assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] );
  i = walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
  if( NEVER(i) ) return; /* Defense-in-depth, in case (1) above is wrong */

  /* Zero all hash-table entries that correspond to frame numbers greater
  ** than pWal->hdr.mxFrame.
  */
  iLimit = pWal->hdr.mxFrame - sLoc.iZero;
  assert( iLimit>0 );
  for(i=0; i<HASHTABLE_NSLOT; i++){
Changes to src/walker.c.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
    int rc;
    rc = sqlite3WalkExprList(pWalker, pWin->pOrderBy);
    if( rc ) return WRC_Abort;
    rc = sqlite3WalkExprList(pWalker, pWin->pPartition);
    if( rc ) return WRC_Abort;
    rc = sqlite3WalkExpr(pWalker, pWin->pFilter);
    if( rc ) return WRC_Abort;

    /* The next two are purely for calls to sqlite3RenameExprUnmap()
    ** within sqlite3WindowOffsetExpr().  Because of constraints imposed
    ** by sqlite3WindowOffsetExpr(), they can never fail.  The results do
    ** not matter anyhow. */
    rc = sqlite3WalkExpr(pWalker, pWin->pStart);
    if( NEVER(rc) ) return WRC_Abort;
    rc = sqlite3WalkExpr(pWalker, pWin->pEnd);
    if( NEVER(rc) ) return WRC_Abort;
    if( bOneOnly ) break;
  }
  return WRC_Continue;
}
#endif

/*







<
<
<
<
<

|

|







28
29
30
31
32
33
34





35
36
37
38
39
40
41
42
43
44
45
    int rc;
    rc = sqlite3WalkExprList(pWalker, pWin->pOrderBy);
    if( rc ) return WRC_Abort;
    rc = sqlite3WalkExprList(pWalker, pWin->pPartition);
    if( rc ) return WRC_Abort;
    rc = sqlite3WalkExpr(pWalker, pWin->pFilter);
    if( rc ) return WRC_Abort;





    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

/*
112
113
114
115
116
117
118










119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

135

136




137
138
139
140
141
142
143
  if( p ){
    for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
      if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort;
    }
  }
  return WRC_Continue;
}











/*
** Walk all expressions associated with SELECT statement p.  Do
** not invoke the SELECT callback on p, but do (of course) invoke
** any expr callbacks and SELECT callbacks that come from subqueries.
** Return WRC_Abort or WRC_Continue.
*/
int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
  if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
  if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
  if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
  if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
  if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
  if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
#if !defined(SQLITE_OMIT_WINDOWFUNC) && !defined(SQLITE_OMIT_ALTERTABLE)
  {

    Parse *pParse = pWalker->pParse;

    if( pParse && IN_RENAME_OBJECT ){




      /* The following may return WRC_Abort if there are unresolvable
      ** symbols (e.g. a table that does not exist) in a window definition. */
      int rc = walkWindowList(pWalker, p->pWinDefn, 0);
      return rc;
    }
  }
#endif







>
>
>
>
>
>
>
>
>
>














|
<
>
|
>
|
>
>
>
>







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
  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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
*/
int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
  SrcList *pSrc;
  int i;
  SrcItem *pItem;

  pSrc = p->pSrc;
  if( 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







|












|







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
*/
int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
  SrcList *pSrc;
  int i;
  SrcItem *pItem;

  pSrc = p->pSrc;
  if( ALWAYS(pSrc) ){
    for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
      if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
        return WRC_Abort;
      }
      if( pItem->fg.isTabFunc
       && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg)
      ){
        return WRC_Abort;
      }
    }
  }
  return WRC_Continue;
}

/*
** Call sqlite3WalkExpr() for every expression in Select statement p.
** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
** on the compound select chain, p->pPrior. 
**
** If it is not NULL, the xSelectCallback() callback is invoked before
Changes to src/where.c.
257
258
259
260
261
262
263
264


265
266
267
268
269
270
271

/*
** If the right-hand branch of the expression is a TK_COLUMN, then return
** a pointer to the right-hand branch.  Otherwise, return NULL.
*/
static Expr *whereRightSubexprIsColumn(Expr *p){
  p = sqlite3ExprSkipCollateAndLikely(p->pRight);
  if( ALWAYS(p!=0) && p->op==TK_COLUMN ) return p;


  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.







|
>
>







257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273

/*
** If the right-hand branch of the expression is a TK_COLUMN, then return
** a pointer to the right-hand branch.  Otherwise, return NULL.
*/
static Expr *whereRightSubexprIsColumn(Expr *p){
  p = sqlite3ExprSkipCollateAndLikely(p->pRight);
  if( ALWAYS(p!=0) && p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
    return p;
  }
  return 0;
}

/*
** Advance to the next WhereTerm that matches according to the criteria
** established when the pScan object was initialized by whereScanInit().
** Return NULL if there are no more matching WhereTerms.
332
333
334
335
336
337
338












339
340
341
342
343
344
345
             && pX->iColumn==pScan->aiColumn[0]
            ){
              testcase( pTerm->eOperator & WO_IS );
              continue;
            }
            pScan->pWC = pWC;
            pScan->k = k+1;












            return pTerm;
          }
        }
      }
      pWC = pWC->pOuter;
      k = 0;
    }while( pWC!=0 );







>
>
>
>
>
>
>
>
>
>
>
>







334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
             && pX->iColumn==pScan->aiColumn[0]
            ){
              testcase( pTerm->eOperator & WO_IS );
              continue;
            }
            pScan->pWC = pWC;
            pScan->k = k+1;
#ifdef WHERETRACE_ENABLED
            if( sqlite3WhereTrace & 0x20000 ){
              int ii;
              sqlite3DebugPrintf("SCAN-TERM %p: nEquiv=%d",
                 pTerm, pScan->nEquiv);
              for(ii=0; ii<pScan->nEquiv; ii++){
                sqlite3DebugPrintf(" {%d:%d}",
                   pScan->aiCur[ii], pScan->aiColumn[ii]);
              }
              sqlite3DebugPrintf("\n");
            }
#endif
            return pTerm;
          }
        }
      }
      pWC = pWC->pOuter;
      k = 0;
    }while( pWC!=0 );
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
){
  int i;
  const char *zColl = pIdx->azColl[iCol];

  for(i=0; i<pList->nExpr; i++){
    Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr);
    if( ALWAYS(p!=0)
     && p->op==TK_COLUMN
     && p->iColumn==pIdx->aiColumn[iCol]
     && p->iTable==iBase
    ){
      CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr);
      if( 0==sqlite3StrICmp(pColl->zName, zColl) ){
        return i;
      }







|







502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
){
  int i;
  const char *zColl = pIdx->azColl[iCol];

  for(i=0; i<pList->nExpr; i++){
    Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr);
    if( ALWAYS(p!=0)
     && (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN)
     && p->iColumn==pIdx->aiColumn[iCol]
     && p->iTable==iBase
    ){
      CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr);
      if( 0==sqlite3StrICmp(pColl->zName, zColl) ){
        return i;
      }
553
554
555
556
557
558
559

560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577

578
579
580
581
582
583
584
  /* If any of the expressions is an IPK column on table iBase, then return 
  ** true. Note: The (p->iTable==iBase) part of this test may be false if the
  ** current SELECT is a correlated sub-query.
  */
  for(i=0; i<pDistinct->nExpr; i++){
    Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
    if( NEVER(p==0) ) continue;

    if( p->op==TK_COLUMN && p->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;

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







>
|

















>







567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
  /* If any of the expressions is an IPK column on table iBase, then return 
  ** true. Note: The (p->iTable==iBase) part of this test may be false if the
  ** current SELECT is a correlated sub-query.
  */
  for(i=0; i<pDistinct->nExpr; i++){
    Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
    if( NEVER(p==0) ) continue;
    if( p->op!=TK_COLUMN && p->op!=TK_AGG_COLUMN ) continue;
    if( p->iTable==iBase && p->iColumn<0 ) return 1;
  }

  /* Loop through all indices on the table, checking each to see if it makes
  ** the DISTINCT qualifier redundant. It does so if:
  **
  **   1. The index is itself UNIQUE, and
  **
  **   2. All of the columns in the index are either part of the pDistinct
  **      list, or else the WHERE clause contains a term of the form "col=X",
  **      where X is a constant value. The collation sequences of the
  **      comparison and select-list expressions must match those of the index.
  **
  **   3. All of those index columns for which the WHERE clause does not
  **      contain a "col=X" term are subject to a NOT NULL constraint.
  */
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    if( !IsUniqueIndex(pIdx) ) continue;
    if( pIdx->pPartIdxWhere ) continue;
    for(i=0; i<pIdx->nKeyCol; i++){
      if( 0==sqlite3WhereFindTerm(pWC, iBase, i, ~(Bitmask)0, WO_EQ, pIdx) ){
        if( findIndexCol(pParse, pDistinct, iBase, pIdx, i)<0 ) break;
        if( indexColumnNotNull(pIdx, i)==0 ) break;
      }
    }
    if( i==pIdx->nKeyCol ){
625
626
627
628
629
630
631
632
633
634
635


636
637
638
639

640
641
642
643
644
645
646
    if( pOp->p1!=iTabCur ) continue;
    if( pOp->opcode==OP_Column ){
      pOp->opcode = OP_Copy;
      pOp->p1 = pOp->p2 + iRegister;
      pOp->p2 = pOp->p3;
      pOp->p3 = 0;
    }else if( pOp->opcode==OP_Rowid ){
      if( iAutoidxCur ){
        pOp->opcode = OP_Sequence;
        pOp->p1 = iAutoidxCur;
      }else{


        pOp->opcode = OP_Null;
        pOp->p1 = 0;
        pOp->p3 = 0;
      }

    }
  }
}

/*
** Two routines for printing the content of an sqlite3_index_info
** structure.  Used for testing and debugging only.  If neither







<
|
|
<
>
>

<


>







641
642
643
644
645
646
647

648
649

650
651
652

653
654
655
656
657
658
659
660
661
662
    if( pOp->p1!=iTabCur ) continue;
    if( pOp->opcode==OP_Column ){
      pOp->opcode = OP_Copy;
      pOp->p1 = pOp->p2 + iRegister;
      pOp->p2 = pOp->p3;
      pOp->p3 = 0;
    }else if( pOp->opcode==OP_Rowid ){

      pOp->opcode = OP_Sequence;
      pOp->p1 = iAutoidxCur;

#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
      if( iAutoidxCur==0 ){
        pOp->opcode = OP_Null;

        pOp->p3 = 0;
      }
#endif
    }
  }
}

/*
** Two routines for printing the content of an sqlite3_index_info
** structure.  Used for testing and debugging only.  If neither
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
          goto end_auto_index_create;
        }
        pLoop->aLTerm[nKeyCol++] = pTerm;
        idxCols |= cMask;
      }
    }
  }
  assert( nKeyCol>0 );
  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







|







813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
          goto end_auto_index_create;
        }
        pLoop->aLTerm[nKeyCol++] = pTerm;
        idxCols |= cMask;
      }
    }
  }
  assert( nKeyCol>0 || pParse->db->mallocFailed );
  pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol;
  pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED
                     | WHERE_AUTO_INDEX;

  /* Count the number of additional columns needed to create a
  ** covering index.  A "covering index" is an index that contains all
  ** columns that are needed by the query.  With a covering index, the
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948

/*
** Transfer content from the second pLoop into the first.
*/
static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
  whereLoopClearUnion(db, pTo);
  if( whereLoopResize(db, pTo, pFrom->nLTerm) ){
    memset(&pTo->u, 0, sizeof(pTo->u));
    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 ){







|







1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964

/*
** Transfer content from the second pLoop into the first.
*/
static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
  whereLoopClearUnion(db, pTo);
  if( whereLoopResize(db, pTo, pFrom->nLTerm) ){
    memset(pTo, 0, WHERE_LOOP_XFER_SZ);
    return SQLITE_NOMEM_BKPT;
  }
  memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ);
  memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0]));
  if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){
    pFrom->u.vtab.needFree = 0;
  }else if( (pFrom->wsFlags & WHERE_AUTO_INDEX)!=0 ){
1976
1977
1978
1979
1980
1981
1982











1983
1984
1985
1986
1987
1988
1989
    WhereLoop *p = pWInfo->pLoops;
    pWInfo->pLoops = p->pNextLoop;
    whereLoopDelete(db, p);
  }
  assert( pWInfo->pExprMods==0 );
  sqlite3DbFreeNN(db, pWInfo);
}












/*
** Return TRUE if all of the following are true:
**
**   (1)  X has the same or lower cost that Y
**   (2)  X uses fewer WHERE clause terms than Y
**   (3)  Every WHERE clause term used by X is also used by Y







>
>
>
>
>
>
>
>
>
>
>







1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
    WhereLoop *p = pWInfo->pLoops;
    pWInfo->pLoops = p->pNextLoop;
    whereLoopDelete(db, p);
  }
  assert( pWInfo->pExprMods==0 );
  sqlite3DbFreeNN(db, pWInfo);
}

/* Undo all Expr node modifications
*/
static void whereUndoExprMods(WhereInfo *pWInfo){
  while( pWInfo->pExprMods ){
    WhereExprMod *p = pWInfo->pExprMods;
    pWInfo->pExprMods = p->pNext;
    memcpy(p->pExpr, &p->orig, sizeof(p->orig));
    sqlite3DbFree(pWInfo->pParse->db, p);
  }
}

/*
** Return TRUE if all of the following are true:
**
**   (1)  X has the same or lower cost that Y
**   (2)  X uses fewer WHERE clause terms than Y
**   (3)  Every WHERE clause term used by X is also used by Y
2482
2483
2484
2485
2486
2487
2488


2489
2490
2491
2492
2493
2494
2495
  }else{
    assert( pNew->u.btree.nBtm==0 );
    opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
  }
  if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);

  assert( pNew->u.btree.nEq<pProbe->nColumn );



  saved_nEq = pNew->u.btree.nEq;
  saved_nBtm = pNew->u.btree.nBtm;
  saved_nTop = pNew->u.btree.nTop;
  saved_nSkip = pNew->nSkip;
  saved_nLTerm = pNew->nLTerm;
  saved_wsFlags = pNew->wsFlags;







>
>







2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
  }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;
2615
2616
2617
2618
2619
2620
2621

2622
2623
2624
2625
2626
2627
2628
         || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ) 
        ){
          pNew->wsFlags |= WHERE_ONEROW;
        }else{
          pNew->wsFlags |= WHERE_UNQ_WANTED;
        }
      }

    }else if( eOp & WO_ISNULL ){
      pNew->wsFlags |= WHERE_COLUMN_NULL;
    }else if( eOp & (WO_GT|WO_GE) ){
      testcase( eOp & WO_GT );
      testcase( eOp & WO_GE );
      pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
      pNew->u.btree.nBtm = whereRangeVectorLen(







>







2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
         || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ) 
        ){
          pNew->wsFlags |= WHERE_ONEROW;
        }else{
          pNew->wsFlags |= WHERE_UNQ_WANTED;
        }
      }
      if( scan.iEquiv>1 ) pNew->wsFlags |= WHERE_TRANSCONS;
    }else if( eOp & WO_ISNULL ){
      pNew->wsFlags |= WHERE_COLUMN_NULL;
    }else if( eOp & (WO_GT|WO_GE) ){
      testcase( eOp & WO_GT );
      testcase( eOp & WO_GE );
      pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
      pNew->u.btree.nBtm = whereRangeVectorLen(
2758
2759
2760
2761
2762
2763
2764


2765
2766
2767
2768
2769
2770
2771
      pNew->nOut = saved_nOut;
    }else{
      pNew->nOut = nOutUnadjusted;
    }

    if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
     && pNew->u.btree.nEq<pProbe->nColumn


    ){
      whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
    }
    pNew->nOut = saved_nOut;
#ifdef SQLITE_ENABLE_STAT4
    pBuilder->nRecValid = nRecValid;
#endif







>
>







2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
      pNew->nOut = saved_nOut;
    }else{
      pNew->nOut = nOutUnadjusted;
    }

    if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
     && pNew->u.btree.nEq<pProbe->nColumn
     && (pNew->u.btree.nEq<pProbe->nKeyCol ||
           pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY)
    ){
      whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
    }
    pNew->nOut = saved_nOut;
#ifdef SQLITE_ENABLE_STAT4
    pBuilder->nRecValid = nRecValid;
#endif
3589
3590
3591
3592
3593
3594
3595
3596


3597
3598
3599
3600
3601
3602
3603
#endif
        {
          rc = whereLoopAddBtree(&sSubBuild, mPrereq);
        }
        if( rc==SQLITE_OK ){
          rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
        }
        assert( rc==SQLITE_OK || rc==SQLITE_DONE || sCur.n==0 );


        testcase( rc==SQLITE_DONE );
        if( sCur.n==0 ){
          sSum.n = 0;
          break;
        }else if( once ){
          whereOrMove(&sSum, &sCur);
          once = 0;







|
>
>







3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
#endif
        {
          rc = whereLoopAddBtree(&sSubBuild, mPrereq);
        }
        if( rc==SQLITE_OK ){
          rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
        }
        assert( rc==SQLITE_OK || rc==SQLITE_DONE || sCur.n==0
                || rc==SQLITE_NOMEM );
        testcase( rc==SQLITE_NOMEM && sCur.n>0 );
        testcase( rc==SQLITE_DONE );
        if( sCur.n==0 ){
          sSum.n = 0;
          break;
        }else if( once ){
          whereOrMove(&sSum, &sCur);
          once = 0;
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
    ** clause of the form X IS NULL or X=? that reference only outer
    ** loops.
    */
    for(i=0; i<nOrderBy; i++){
      if( MASKBIT(i) & obSat ) continue;
      pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
      if( NEVER(pOBExpr==0) ) continue;
      if( pOBExpr->op!=TK_COLUMN ) continue;
      if( pOBExpr->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







|







3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
    ** clause of the form X IS NULL or X=? that reference only outer
    ** loops.
    */
    for(i=0; i<nOrderBy; i++){
      if( MASKBIT(i) & obSat ) continue;
      pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
      if( NEVER(pOBExpr==0) ) continue;
      if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue;
      if( pOBExpr->iTable!=iCur ) continue;
      pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
                       ~ready, eqOpMask, 0);
      if( pTerm==0 ) continue;
      if( pTerm->eOperator==WO_IN ){
        /* IN terms are only valid for sorting in the ORDER BY LIMIT 
        ** optimization, and then only if they are actually used
3858
3859
3860
3861
3862
3863
3864




3865
3866
3867
3868
3869
3870
3871
        return 0;
      }else{
        nKeyCol = pIndex->nKeyCol;
        nColumn = pIndex->nColumn;
        assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
        assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
                          || !HasRowid(pIndex->pTable));




        isOrderDistinct = IsUniqueIndex(pIndex)
                          && (pLoop->wsFlags & WHERE_SKIPSCAN)==0;
      }

      /* Loop through all columns of the index and deal with the ones
      ** that are not constrained by == or IN.
      */







>
>
>
>







3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
        return 0;
      }else{
        nKeyCol = pIndex->nKeyCol;
        nColumn = pIndex->nColumn;
        assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
        assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
                          || !HasRowid(pIndex->pTable));
        /* All relevant terms of the index must also be non-NULL in order
        ** for isOrderDistinct to be true.  So the isOrderDistint value
        ** computed here might be a false positive.  Corrections will be
        ** made at tag-20210426-1 below */
        isOrderDistinct = IsUniqueIndex(pIndex)
                          && (pLoop->wsFlags & WHERE_SKIPSCAN)==0;
      }

      /* Loop through all columns of the index and deal with the ones
      ** that are not constrained by == or IN.
      */
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940




3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
          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
        */
        if( isOrderDistinct
         && iColumn>=0
         && j>=pLoop->u.btree.nEq
         && pIndex->pTable->aCol[iColumn].notNull==0
        ){
          isOrderDistinct = 0;
        }





        /* Find the ORDER BY term that corresponds to the j-th column
        ** of the index and mark that ORDER BY term off 
        */
        isMatch = 0;
        for(i=0; bOnce && i<nOrderBy; i++){
          if( MASKBIT(i) & obSat ) continue;
          pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
          testcase( wctrlFlags & WHERE_GROUPBY );
          testcase( wctrlFlags & WHERE_DISTINCTBY );
          if( NEVER(pOBExpr==0) ) continue;
          if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
          if( iColumn>=XN_ROWID ){
            if( pOBExpr->op!=TK_COLUMN ) continue;
            if( pOBExpr->iTable!=iCur ) continue;
            if( pOBExpr->iColumn!=iColumn ) continue;
          }else{
            Expr *pIdxExpr = pIndex->aColExpr->a[j].pExpr;
            if( sqlite3ExprCompareSkip(pOBExpr, pIdxExpr, iCur) ){
              continue;
            }







|

|
|
|
|
|
|
|
>
>
>
>













|







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
          if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID;
        }else{
          iColumn = XN_ROWID;
          revIdx = 0;
        }

        /* An unconstrained column that might be NULL means that this
        ** WhereLoop is not well-ordered.  tag-20210426-1
        */
        if( isOrderDistinct ){
          if( iColumn>=0
           && j>=pLoop->u.btree.nEq
           && pIndex->pTable->aCol[iColumn].notNull==0
          ){
            isOrderDistinct = 0;
          }
          if( iColumn==XN_EXPR ){
            isOrderDistinct = 0;
          }
        } 

        /* Find the ORDER BY term that corresponds to the j-th column
        ** of the index and mark that ORDER BY term off 
        */
        isMatch = 0;
        for(i=0; bOnce && i<nOrderBy; i++){
          if( MASKBIT(i) & obSat ) continue;
          pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
          testcase( wctrlFlags & WHERE_GROUPBY );
          testcase( wctrlFlags & WHERE_DISTINCTBY );
          if( NEVER(pOBExpr==0) ) continue;
          if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
          if( iColumn>=XN_ROWID ){
            if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue;
            if( pOBExpr->iTable!=iCur ) continue;
            if( pOBExpr->iColumn!=iColumn ) continue;
          }else{
            Expr *pIdxExpr = pIndex->aColExpr->a[j].pExpr;
            if( sqlite3ExprCompareSkip(pOBExpr, pIdxExpr, iCur) ){
              continue;
            }
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
  ** rows, so fudge it downwards a bit.
  */
  if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 && pWInfo->iLimit<nRow ){
    nRow = pWInfo->iLimit;
  }else if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT) ){
    /* TUNING: In the sort for a DISTINCT operator, assume that the DISTINCT
    ** reduces the number of output rows by a factor of 2 */
    if( nRow>10 ) nRow -= 10;  assert( 10==sqlite3LogEst(2) );
  }
  rSortCost += estLog(nRow);
  return rSortCost;
}

/*
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine







|







4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
  ** rows, so fudge it downwards a bit.
  */
  if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 && pWInfo->iLimit<nRow ){
    nRow = pWInfo->iLimit;
  }else if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT) ){
    /* TUNING: In the sort for a DISTINCT operator, assume that the DISTINCT
    ** reduces the number of output rows by a factor of 2 */
    if( nRow>10 ){ nRow -= 10;  assert( 10==sqlite3LogEst(2) ); }
  }
  rSortCost += estLog(nRow);
  return rSortCost;
}

/*
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
5048
5049
5050
5051
5052
5053
5054
5055

5056
5057
5058
5059
5060
5061
5062
  **
  **     SELECT DISTINCT v1, v3 FROM t1 
  **       LEFT JOIN t2
  **       LEFT JOIN t3 ON (t1.ipk=t3.ipk)
  */
  notReady = ~(Bitmask)0;
  if( pWInfo->nLevel>=2
   && pResultSet!=0               /* guarantees condition (1) above */

   && OptimizationEnabled(db, SQLITE_OmitNoopJoin)
  ){
    int i;
    Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet);
    if( sWLB.pOrderBy ){
      tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy);
    }







|
>







5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
  **
  **     SELECT DISTINCT v1, v3 FROM t1 
  **       LEFT JOIN t2
  **       LEFT JOIN t3 ON (t1.ipk=t3.ipk)
  */
  notReady = ~(Bitmask)0;
  if( pWInfo->nLevel>=2
   && pResultSet!=0                         /* these two combine to guarantee */
   && 0==(wctrlFlags & WHERE_AGG_DISTINCT)  /* condition (1) above */
   && OptimizationEnabled(db, SQLITE_OmitNoopJoin)
  ){
    int i;
    Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet);
    if( sWLB.pOrderBy ){
      tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy);
    }
5307
5308
5309
5310
5311
5312
5313


5314
5315
5316
5317
5318
5319
5320
  VdbeModuleComment((v, "Begin WHERE-core"));
  pWInfo->iEndWhere = sqlite3VdbeCurrentAddr(v);
  return pWInfo;

  /* Jump here if malloc fails */
whereBeginError:
  if( pWInfo ){


    pParse->nQueryLoop = pWInfo->savedNQueryLoop;
    whereInfoFree(db, pWInfo);
  }
  return 0;
}

/*







>
>







5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
  VdbeModuleComment((v, "Begin WHERE-core"));
  pWInfo->iEndWhere = sqlite3VdbeCurrentAddr(v);
  return pWInfo;

  /* Jump here if malloc fails */
whereBeginError:
  if( pWInfo ){
    testcase( pWInfo->pExprMods!=0 );
    whereUndoExprMods(pWInfo);
    pParse->nQueryLoop = pWInfo->savedNQueryLoop;
    whereInfoFree(db, pWInfo);
  }
  return 0;
}

/*
5403
5404
5405
5406
5407
5408
5409


5410
5411
5412
5413
5414
5415
5416
      sqlite3VdbeResolveLabel(v, pLevel->addrCont);
    }
    if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
      struct InLoop *pIn;
      int j;
      sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
      for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){


        sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
        if( pIn->eEndLoopOp!=OP_Noop ){
          if( pIn->nPrefix ){
            int bEarlyOut = 
                (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
                 && (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0;
            if( pLevel->iLeftJoin ){







>
>







5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
      sqlite3VdbeResolveLabel(v, pLevel->addrCont);
    }
    if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
      struct InLoop *pIn;
      int j;
      sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
      for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
        assert( sqlite3VdbeGetOp(v, pIn->addrInTop+1)->opcode==OP_IsNull
                 || pParse->db->mallocFailed );
        sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
        if( pIn->eEndLoopOp!=OP_Noop ){
          if( pIn->nPrefix ){
            int bEarlyOut = 
                (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
                 && (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0;
            if( pLevel->iLeftJoin ){
5427
5428
5429
5430
5431
5432
5433





5434
5435
5436
5437
5438
5439
5440
              VdbeCoverage(v);
            }
            if( bEarlyOut ){
              sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
                  sqlite3VdbeCurrentAddr(v)+2,
                  pIn->iBase, pIn->nPrefix);
              VdbeCoverage(v);





            }
          }
          sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
          VdbeCoverage(v);
          VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev);
          VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next);
        }







>
>
>
>
>







5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
              VdbeCoverage(v);
            }
            if( bEarlyOut ){
              sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
                  sqlite3VdbeCurrentAddr(v)+2,
                  pIn->iBase, pIn->nPrefix);
              VdbeCoverage(v);
              /* Retarget the OP_IsNull against the left operand of IN so 
              ** it jumps past the OP_IfNoHope.  This is because the
              ** OP_IsNull also bypasses the OP_Affinity opcode that is
              ** required by OP_IfNoHope. */
              sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
            }
          }
          sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
          VdbeCoverage(v);
          VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Prev);
          VdbeCoverageIf(v, pIn->eEndLoopOp==OP_Next);
        }
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
      pOp = sqlite3VdbeGetOp(v, k - 1);
      assert( pOp->opcode!=OP_Column || pOp->p1!=pLevel->iTabCur );
      assert( pOp->opcode!=OP_Rowid  || pOp->p1!=pLevel->iTabCur );
      assert( pOp->opcode!=OP_IfNullRow || pOp->p1!=pLevel->iTabCur );
#endif
      pOp = sqlite3VdbeGetOp(v, k);
      pLastOp = pOp + (last - k);
      assert( pOp<pLastOp || (pParse->nErr>0 && pOp==pLastOp) );
      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







|







5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
      pOp = sqlite3VdbeGetOp(v, k - 1);
      assert( pOp->opcode!=OP_Column || pOp->p1!=pLevel->iTabCur );
      assert( pOp->opcode!=OP_Rowid  || pOp->p1!=pLevel->iTabCur );
      assert( pOp->opcode!=OP_IfNullRow || pOp->p1!=pLevel->iTabCur );
#endif
      pOp = sqlite3VdbeGetOp(v, k);
      pLastOp = pOp + (last - k);
      assert( pOp<=pLastOp );
      do{
        if( pOp->p1!=pLevel->iTabCur ){
          /* no-op */
        }else if( pOp->opcode==OP_Column
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
         || pOp->opcode==OP_Offset
#endif
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622

5623
5624
5625
5626
      }while( (++pOp)<pLastOp );
#ifdef SQLITE_DEBUG
      if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n");
#endif
    }
  }

  /* Undo all Expr node modifications */
  while( pWInfo->pExprMods ){
    WhereExprMod *p = pWInfo->pExprMods;
    pWInfo->pExprMods = p->pNext;
    memcpy(p->pExpr, &p->orig, sizeof(p->orig));
    sqlite3DbFree(db, p);
  }

  /* Final cleanup
  */

  pParse->nQueryLoop = pWInfo->savedNQueryLoop;
  whereInfoFree(db, pWInfo);
  return;
}







<
<
<
<
<
<
<
<


>




5658
5659
5660
5661
5662
5663
5664








5665
5666
5667
5668
5669
5670
5671
      }while( (++pOp)<pLastOp );
#ifdef SQLITE_DEBUG
      if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n");
#endif
    }
  }









  /* Final cleanup
  */
  if( pWInfo->pExprMods ) whereUndoExprMods(pWInfo);
  pParse->nQueryLoop = pWInfo->savedNQueryLoop;
  whereInfoFree(db, pWInfo);
  return;
}
Changes to src/whereInt.h.
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
*/
struct WhereScan {
  WhereClause *pOrigWC;      /* Original, innermost WhereClause */
  WhereClause *pWC;          /* WhereClause currently being scanned */
  const char *zCollName;     /* Required collating sequence, if not NULL */
  Expr *pIdxExpr;            /* Search for this index expression */
  char idxaff;               /* Must match this affinity, if zCollName!=NULL */
  unsigned char nEquiv;      /* Number of entries in aEquiv[] */
  unsigned char iEquiv;      /* Next unused slot in aEquiv[] */
  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 */
};

/*







|
|







289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
*/
struct WhereScan {
  WhereClause *pOrigWC;      /* Original, innermost WhereClause */
  WhereClause *pWC;          /* WhereClause currently being scanned */
  const char *zCollName;     /* Required collating sequence, if not NULL */
  Expr *pIdxExpr;            /* Search for this index expression */
  char idxaff;               /* Must match this affinity, if zCollName!=NULL */
  unsigned char nEquiv;      /* Number of entries in aiCur[] and aiColumn[] */
  unsigned char iEquiv;      /* Next unused slot in aiCur[] and aiColumn[] */
  u32 opMask;                /* Acceptable operators */
  int k;                     /* Resume scanning at this->pWC->a[this->k] */
  int aiCur[11];             /* Cursors in the equivalence class */
  i16 aiColumn[11];          /* Corresponding column number in the eq-class */
};

/*
599
600
601
602
603
604
605

606
607
#define WHERE_AUTO_INDEX   0x00004000  /* Uses an ephemeral index */
#define WHERE_SKIPSCAN     0x00008000  /* Uses the skip-scan algorithm */
#define WHERE_UNQ_WANTED   0x00010000  /* WHERE_ONEROW would have been helpful*/
#define WHERE_PARTIALIDX   0x00020000  /* The automatic index is partial */
#define WHERE_IN_EARLYOUT  0x00040000  /* Perhaps quit IN loops early */
#define WHERE_BIGNULL_SORT 0x00080000  /* Column nEq of index is BIGNULL */
#define WHERE_IN_SEEKSCAN  0x00100000  /* Seek-scan optimization for IN */


#endif /* !defined(SQLITE_WHEREINT_H) */







>


599
600
601
602
603
604
605
606
607
608
#define WHERE_AUTO_INDEX   0x00004000  /* Uses an ephemeral index */
#define WHERE_SKIPSCAN     0x00008000  /* Uses the skip-scan algorithm */
#define WHERE_UNQ_WANTED   0x00010000  /* WHERE_ONEROW would have been helpful*/
#define WHERE_PARTIALIDX   0x00020000  /* The automatic index is partial */
#define WHERE_IN_EARLYOUT  0x00040000  /* Perhaps quit IN loops early */
#define WHERE_BIGNULL_SORT 0x00080000  /* Column nEq of index is BIGNULL */
#define WHERE_IN_SEEKSCAN  0x00100000  /* Seek-scan optimization for IN */
#define WHERE_TRANSCONS    0x00200000  /* Uses a transitive constraint */

#endif /* !defined(SQLITE_WHEREINT_H) */
Changes to src/wherecode.c.
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
    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);
    }

    if( pItem->zAlias ){
      sqlite3_str_appendf(&str, " AS %s", pItem->zAlias);
    }
    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) );







<
<
<
<
<
<
|
<
|
<







144
145
146
147
148
149
150






151

152

153
154
155
156
157
158
159
    if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_OR_SUBCLAUSE) ) return 0;

    isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
            || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
            || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));

    sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);






    str.printfFlags = SQLITE_PRINTF_INTERNAL;

    sqlite3_str_appendf(&str, "%s %S", isSearch ? "SEARCH" : "SCAN", pItem);

    if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
      const char *zFmt = 0;
      Index *pIdx;

      assert( pLoop->u.btree.pIndex!=0 );
      pIdx = pLoop->u.btree.pIndex;
      assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) );
301
302
303
304
305
306
307






308
309
310
311
312
313
314
      && (pLevel->notReady & pTerm->prereqAll)==0
  ){
    if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){
      pTerm->wtFlags |= TERM_LIKECOND;
    }else{
      pTerm->wtFlags |= TERM_CODED;
    }






    if( pTerm->iParent<0 ) break;
    pTerm = &pTerm->pWC->a[pTerm->iParent];
    assert( pTerm!=0 );
    pTerm->nChild--;
    if( pTerm->nChild!=0 ) break;
    nLoop++;
  }







>
>
>
>
>
>







293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
      && (pLevel->notReady & pTerm->prereqAll)==0
  ){
    if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){
      pTerm->wtFlags |= TERM_LIKECOND;
    }else{
      pTerm->wtFlags |= TERM_CODED;
    }
#ifdef WHERETRACE_ENABLED
    if( sqlite3WhereTrace & 0x20000 ){
      sqlite3DebugPrintf("DISABLE-");
      sqlite3WhereTermPrint(pTerm, (int)(pTerm - (pTerm->pWC->a)));
    }
#endif
    if( pTerm->iParent<0 ) break;
    pTerm = &pTerm->pWC->a[pTerm->iParent];
    assert( pTerm!=0 );
    pTerm->nChild--;
    if( pTerm->nChild!=0 ) break;
    nLoop++;
  }
618
619
620
621
622
623
624













625


626
627
628
629
630
631
632
      }
    }else{
      pLevel->u.in.nIn = 0;
    }
    sqlite3DbFree(pParse->db, aiMap);
#endif
  }













  disableTerm(pLevel, pTerm);


  return iReg;
}

/*
** Generate code that will evaluate all == and IN constraints for an
** index scan.
**







>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>







616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
      }
    }else{
      pLevel->u.in.nIn = 0;
    }
    sqlite3DbFree(pParse->db, aiMap);
#endif
  }

  /* As an optimization, try to disable the WHERE clause term that is
  ** driving the index as it will always be true.  The correct answer is
  ** obtained regardless, but we might get the answer with fewer CPU cycles
  ** by omitting the term.
  **
  ** But do not disable the term unless we are certain that the term is
  ** not a transitive constraint.  For an example of where that does not
  ** work, see https://sqlite.org/forum/forumpost/eb8613976a (2021-05-04)
  */
  if( (pLevel->pWLoop->wsFlags & WHERE_TRANSCONS)==0
   || (pTerm->eOperator & WO_EQUIV)==0
  ){
    disableTerm(pLevel, pTerm);
  }

  return iReg;
}

/*
** Generate code that will evaluate all == and IN constraints for an
** index scan.
**
704
705
706
707
708
709
710

711
712
713
714
715
716
717
  pParse->nMem += nReg;

  zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx));
  assert( zAff!=0 || pParse->db->mallocFailed );

  if( nSkip ){
    int iIdxCur = pLevel->iIdxCur;

    sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur);
    VdbeCoverageIf(v, bRev==0);
    VdbeCoverageIf(v, bRev!=0);
    VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
    j = sqlite3VdbeAddOp0(v, OP_Goto);
    pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
                            iIdxCur, 0, regBase, nSkip);







>







717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
  pParse->nMem += nReg;

  zAff = sqlite3DbStrDup(pParse->db,sqlite3IndexAffinityStr(pParse->db,pIdx));
  assert( zAff!=0 || pParse->db->mallocFailed );

  if( nSkip ){
    int iIdxCur = pLevel->iIdxCur;
    sqlite3VdbeAddOp3(v, OP_Null, 0, regBase, regBase+nSkip-1);
    sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur);
    VdbeCoverageIf(v, bRev==0);
    VdbeCoverageIf(v, bRev!=0);
    VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
    j = sqlite3VdbeAddOp0(v, OP_Goto);
    pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
                            iIdxCur, 0, regBase, nSkip);
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
      }
    }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( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){
          zAff[j] = SQLITE_AFF_BLOB;
        }
        if( sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j]) ){
          zAff[j] = SQLITE_AFF_BLOB;
        }
      }







|







769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
      }
    }else if( (pTerm->eOperator & WO_ISNULL)==0 ){
      Expr *pRight = pTerm->pExpr->pRight;
      if( (pTerm->wtFlags & TERM_IS)==0 && sqlite3ExprCanBeNull(pRight) ){
        sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
        VdbeCoverage(v);
      }
      if( 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;
        }
      }
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
      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))
     || (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







|
<
<







1745
1746
1747
1748
1749
1750
1751
1752


1753
1754
1755
1756
1757
1758
1759
      pLevel->addrBignull = sqlite3VdbeMakeLabel(pParse);
    }

    /* If we are doing a reverse order scan on an ascending index, or
    ** a forward order scan on a descending index, interchange the 
    ** start and end terms (pRangeStart and pRangeEnd).
    */
    if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC)) ){


      SWAP(WhereTerm *, pRangeEnd, pRangeStart);
      SWAP(u8, bSeekPastNull, bStopAtNull);
      SWAP(u8, nBtm, nTop);
    }

    if( iLevel>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 ){
      /* In case OP_SeekScan is used, ensure that the index cursor does not
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
        pExpr = sqlite3ExprDup(db, pExpr, 0);
        pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr);
      }
      if( pAndExpr ){
        /* The extra 0x10000 bit on the opcode is masked off and does not
        ** become part of the new Expr.op.  However, it does make the
        ** op==TK_AND comparison inside of sqlite3PExpr() false, and this
        ** prevents sqlite3PExpr() from implementing AND short-circuit 
        ** optimization, which we do not want here. */
        pAndExpr = sqlite3PExpr(pParse, TK_AND|0x10000, 0, pAndExpr);
      }
    }

    /* Run a separate WHERE clause for each term of the OR clause.  After
    ** eliminating duplicates from other WHERE clauses, the action for each
    ** sub-WHERE clause is to to invoke the main loop body as a subroutine.
    */
    ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR"));
    for(ii=0; ii<pOrWc->nTerm; ii++){
      WhereTerm *pOrTerm = &pOrWc->a[ii];
      if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
        WhereInfo *pSubWInfo;           /* Info for single OR-term scan */
        Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */

        int jmp1 = 0;                   /* Address of jump operation */
        testcase( (pTabItem[0].fg.jointype & JT_LEFT)!=0
               && !ExprHasProperty(pOrExpr, EP_FromJoin)
        ); /* See TH3 vtab25.400 and ticket 614b25314c766238 */





        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"));







|















>




>
>
>
>
>







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
        pExpr = sqlite3ExprDup(db, pExpr, 0);
        pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr);
      }
      if( pAndExpr ){
        /* The extra 0x10000 bit on the opcode is masked off and does not
        ** become part of the new Expr.op.  However, it does make the
        ** op==TK_AND comparison inside of sqlite3PExpr() false, and this
        ** prevents sqlite3PExpr() from applying the AND short-circuit 
        ** optimization, which we do not want here. */
        pAndExpr = sqlite3PExpr(pParse, TK_AND|0x10000, 0, pAndExpr);
      }
    }

    /* Run a separate WHERE clause for each term of the OR clause.  After
    ** eliminating duplicates from other WHERE clauses, the action for each
    ** sub-WHERE clause is to to invoke the main loop body as a subroutine.
    */
    ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR"));
    for(ii=0; ii<pOrWc->nTerm; ii++){
      WhereTerm *pOrTerm = &pOrWc->a[ii];
      if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
        WhereInfo *pSubWInfo;           /* Info for single OR-term scan */
        Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
        Expr *pDelete;                  /* Local copy of OR clause term */
        int jmp1 = 0;                   /* Address of jump operation */
        testcase( (pTabItem[0].fg.jointype & JT_LEFT)!=0
               && !ExprHasProperty(pOrExpr, EP_FromJoin)
        ); /* See TH3 vtab25.400 and ticket 614b25314c766238 */
        pDelete = pOrExpr = sqlite3ExprDup(db, pOrExpr, 0);
        if( db->mallocFailed ){
          sqlite3ExprDelete(db, pDelete);
          continue;
        }
        if( pAndExpr ){
          pAndExpr->pLeft = pOrExpr;
          pOrExpr = pAndExpr;
        }
        /* Loop through table entries that match term pOrTerm. */
        ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1));
        WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
2288
2289
2290
2291
2292
2293
2294

2295
2296
2297
2298
2299
2300
2301
            pWInfo->bDeferredSeek = 1;
          }

          /* Finish the loop through table entries that match term pOrTerm. */
          sqlite3WhereEnd(pSubWInfo);
          ExplainQueryPlanPop(pParse);
        }

      }
    }
    ExplainQueryPlanPop(pParse);
    pLevel->u.pCovidx = pCov;
    if( pCov ) pLevel->iIdxCur = iCovCur;
    if( pAndExpr ){
      pAndExpr->pLeft = 0;







>







2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
            pWInfo->bDeferredSeek = 1;
          }

          /* Finish the loop through table entries that match term pOrTerm. */
          sqlite3WhereEnd(pSubWInfo);
          ExplainQueryPlanPop(pParse);
        }
        sqlite3ExprDelete(db, pDelete);
      }
    }
    ExplainQueryPlanPop(pParse);
    pLevel->u.pCovidx = pCov;
    if( pCov ) pLevel->iIdxCur = iCovCur;
    if( pAndExpr ){
      pAndExpr->pLeft = 0;
2452
2453
2454
2455
2456
2457
2458

2459
2460
2461
2462
2463
2464
2465
    testcase( pAlt->eOperator & WO_EQ );
    testcase( pAlt->eOperator & WO_IS );
    testcase( pAlt->eOperator & WO_IN );
    VdbeModuleComment((v, "begin transitive constraint"));
    sEAlt = *pAlt->pExpr;
    sEAlt.pLeft = pE->pLeft;
    sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);

  }

  /* For a LEFT OUTER JOIN, generate code that will record the fact that
  ** at least one row of the right table has matched the left table.  
  */
  if( pLevel->iLeftJoin ){
    pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);







>







2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
    testcase( pAlt->eOperator & WO_EQ );
    testcase( pAlt->eOperator & WO_IS );
    testcase( pAlt->eOperator & WO_IN );
    VdbeModuleComment((v, "begin transitive constraint"));
    sEAlt = *pAlt->pExpr;
    sEAlt.pLeft = pE->pLeft;
    sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);
    pAlt->wtFlags |= TERM_CODED;
  }

  /* For a LEFT OUTER JOIN, generate code that will record the fact that
  ** at least one row of the right table has matched the left table.  
  */
  if( pLevel->iLeftJoin ){
    pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
Changes to src/whereexpr.c.
507
508
509
510
511
512
513

514
515
516
517
518
519
520
){
  u16 eOp = pOne->eOperator | pTwo->eOperator;
  sqlite3 *db;           /* Database connection (for malloc) */
  Expr *pNew;            /* New virtual expression */
  int op;                /* Operator for the combined expression */
  int idxNew;            /* Index in pWC of the next virtual term */


  if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
  if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
  if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
   && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
  assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
  assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
  if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;







>







507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
){
  u16 eOp = pOne->eOperator | pTwo->eOperator;
  sqlite3 *db;           /* Database connection (for malloc) */
  Expr *pNew;            /* New virtual expression */
  int op;                /* Operator for the combined expression */
  int idxNew;            /* Index in pWC of the next virtual term */

  if( (pOne->wtFlags | pTwo->wtFlags) & TERM_VNULL ) return;
  if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
  if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
  if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
   && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
  assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
  assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
  if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
        int idxNew;
        transferJoinMarkings(pNew, pExpr);
        assert( !ExprHasProperty(pNew, EP_xIsSelect) );
        pNew->x.pList = pList;
        idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
        testcase( idxNew==0 );
        exprAnalyze(pSrc, pWC, idxNew);
        /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where used again */
        markTermAsChild(pWC, idxNew, idxTerm);
      }else{
        sqlite3ExprListDelete(db, pList);
      }
    }
  }
}







|







868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
        int idxNew;
        transferJoinMarkings(pNew, pExpr);
        assert( !ExprHasProperty(pNew, EP_xIsSelect) );
        pNew->x.pList = pList;
        idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
        testcase( idxNew==0 );
        exprAnalyze(pSrc, pWC, idxNew);
        /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where reused */
        markTermAsChild(pWC, idxNew, idxTerm);
      }else{
        sqlite3ExprListDelete(db, pList);
      }
    }
  }
}
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
  ** inequality constraint (>, <, >= or <=), perform the processing 
  ** on the first element of the vector.  */
  assert( TK_GT+1==TK_LE && TK_GT+2==TK_LT && TK_GT+3==TK_GE );
  assert( TK_IS<TK_GE && TK_ISNULL<TK_GE && TK_IN<TK_GE );
  assert( op<=TK_GE );
  if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){
    pExpr = pExpr->x.pList->a[0].pExpr;

  }

  if( pExpr->op==TK_COLUMN ){
    aiCurCol[0] = pExpr->iTable;
    aiCurCol[1] = pExpr->iColumn;
    return 1;
  }
  if( mPrereq==0 ) return 0;                 /* No table references */
  if( (mPrereq&(mPrereq-1))!=0 ) return 0;   /* Refs more than one table */
  return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr);
}

/*
** Expression callback for exprUsesSrclist().
*/
static int exprUsesSrclistCb(Walker *p, Expr *pExpr){
  if( pExpr->op==TK_COLUMN ){
    SrcList *pSrc = p->u.pSrcList;
    int iCsr = pExpr->iTable;
    int ii;
    for(ii=0; ii<pSrc->nSrc; ii++){
      if( pSrc->a[ii].iCursor==iCsr ){
        return p->eCode ? WRC_Abort : WRC_Continue;
      }
    }
    return p->eCode ? WRC_Continue : WRC_Abort;
  }
  return WRC_Continue;
}

/*
** Select callback for exprUsesSrclist().
*/
static int exprUsesSrclistSelectCb(Walker *NotUsed1, Select *NotUsed2){
  UNUSED_PARAMETER(NotUsed1);
  UNUSED_PARAMETER(NotUsed2);
  return WRC_Abort;
}

/*
** This function always returns true if expression pExpr contains
** a sub-select.
**
** If there is no sub-select in pExpr, then return true if pExpr
** contains a TK_COLUMN node for a table that is (bUses==1)
** or is not (bUses==0) in pSrc.
**
** Said another way:
**
**   bUses      Return     Meaning
**   --------   ------     ------------------------------------------------
**
**   bUses==1   true       pExpr contains either a sub-select or a
**                         TK_COLUMN referencing pSrc.
**
**   bUses==1   false      pExpr contains no sub-selects and all TK_COLUMN
**                         nodes reference tables not found in pSrc
**
**   bUses==0   true       pExpr contains either a sub-select or a TK_COLUMN
**                         that references a table not in pSrc.
**
**   bUses==0   false      pExpr contains no sub-selects and all TK_COLUMN
**                         nodes reference pSrc
*/
static int exprUsesSrclist(SrcList *pSrc, Expr *pExpr, int bUses){
  Walker sWalker;
  memset(&sWalker, 0, sizeof(Walker));
  sWalker.eCode = bUses;
  sWalker.u.pSrcList = pSrc;
  sWalker.xExprCallback = exprUsesSrclistCb;
  sWalker.xSelectCallback = exprUsesSrclistSelectCb;
  return (sqlite3WalkExpr(&sWalker, pExpr)==WRC_Abort);
}

/*
** Context object used by exprExistsToInIter() as it iterates through an
** expression tree.
*/
struct ExistsToInCtx {
  SrcList *pSrc;    /* The tables in an EXISTS(SELECT ... FROM <here> ...) */
  Expr *pInLhs;     /* OUT:  Use this as the LHS of the IN operator */
  Expr *pEq;        /* OUT:  The == term that include pInLhs */
  Expr **ppAnd;     /* OUT:  The AND operator that includes pEq as a child */
  Expr **ppParent;  /* The AND operator currently being examined */
};

/*
** Iterate through all AND connected nodes in the expression tree
** headed by (*ppExpr), populating the structure passed as the first
** argument with the values required by exprAnalyzeExistsFindEq().
**
** This function returns non-zero if the expression tree does not meet
** the two conditions described by the header comment for
** exprAnalyzeExistsFindEq(), or zero if it does.
*/
static int exprExistsToInIter(struct ExistsToInCtx *p, Expr **ppExpr){
  Expr *pExpr = *ppExpr;
  switch( pExpr->op ){
    case TK_AND:
      p->ppParent = ppExpr;
      if( exprExistsToInIter(p, &pExpr->pLeft) ) return 1;
      p->ppParent = ppExpr;
      if( exprExistsToInIter(p, &pExpr->pRight) ) return 1;
      break;
    case TK_EQ: {
      int bLeft = exprUsesSrclist(p->pSrc, pExpr->pLeft, 0);
      int bRight = exprUsesSrclist(p->pSrc, pExpr->pRight, 0);
      if( bLeft || bRight ){
        if( (bLeft && bRight) || p->pInLhs ) return 1;
        p->pInLhs = bLeft ? pExpr->pLeft : pExpr->pRight;
        if( exprUsesSrclist(p->pSrc, p->pInLhs, 1) ) return 1;
        p->pEq = pExpr;
        p->ppAnd = p->ppParent;
      }
      break;
    }
    default:
      if( exprUsesSrclist(p->pSrc, pExpr, 0) ){
        return 1;
      }
      break;
  }

  return 0;
}

/*
** This function is used by exprAnalyzeExists() when creating virtual IN(...)
** terms equivalent to user-supplied EXIST(...) clauses. It splits the WHERE
** clause of the Select object passed as the first argument into one or more
** expressions joined by AND operators, and then tests if the following are
** true:
**
**   1. Exactly one of the AND separated terms refers to the outer
**      query, and it is an == (TK_EQ) expression.
**
**   2. Only one side of the == expression refers to the outer query, and 
**      it does not refer to any columns from the inner query.
**
** If both these conditions are true, then a pointer to the side of the ==
** expression that refers to the outer query is returned. The caller will
** use this expression as the LHS of the IN(...) virtual term. Or, if one
** or both of the above conditions are not true, NULL is returned.
**
** If non-NULL is returned and ppEq is non-NULL, *ppEq is set to point
** to the == expression node before returning. If pppAnd is non-NULL and
** the == node is not the root of the WHERE clause, then *pppAnd is set
** to point to the pointer to the AND node that is the parent of the ==
** node within the WHERE expression tree.
*/
static Expr *exprAnalyzeExistsFindEq(
  Select *pSel,                   /* The SELECT of the EXISTS */
  Expr **ppEq,                    /* OUT: == node from WHERE clause */
  Expr ***pppAnd                  /* OUT: Pointer to parent of ==, if any */
){
  struct ExistsToInCtx ctx;
  memset(&ctx, 0, sizeof(ctx));
  ctx.pSrc = pSel->pSrc;
  if( exprExistsToInIter(&ctx, &pSel->pWhere) ){
    return 0;
  }
  if( ppEq ) *ppEq = ctx.pEq;
  if( pppAnd ) *pppAnd = ctx.ppAnd;
  return ctx.pInLhs;
}

/*
** Term idxTerm of the WHERE clause passed as the second argument is an
** EXISTS expression with a correlated SELECT statement on the RHS.
** This function analyzes the SELECT statement, and if possible adds an
** equivalent "? IN(SELECT...)" virtual term to the WHERE clause. 
**
** For an EXISTS term such as the following:
**
**     EXISTS (SELECT ... FROM <srclist> WHERE <e1> = <e2> AND <e3>)
**
** The virtual IN() term added is:
**
**     <e1> IN (SELECT <e2> FROM <srclist> WHERE <e3>)
**
** The virtual term is only added if the following conditions are met:
**
**     1. The sub-select must not be an aggregate or use window functions,
**
**     2. The sub-select must not be a compound SELECT,
**
**     3. Expression <e1> must refer to at least one column from the outer
**        query, and must not refer to any column from the inner query 
**        (i.e. from <srclist>).
**
**     4. <e2> and <e3> must not refer to any values from the outer query.
**        In other words, once <e1> has been removed, the inner query
**        must not be correlated.
**
*/
static void exprAnalyzeExists(
  SrcList *pSrc,            /* the FROM clause */
  WhereClause *pWC,         /* the WHERE clause */
  int idxTerm               /* Index of the term to be analyzed */
){
  Parse *pParse = pWC->pWInfo->pParse;
  WhereTerm *pTerm = &pWC->a[idxTerm];
  Expr *pExpr = pTerm->pExpr;
  Select *pSel = pExpr->x.pSelect;
  Expr *pDup = 0;
  Expr *pEq = 0;
  Expr *pRet = 0;
  Expr *pInLhs = 0;
  Expr **ppAnd = 0;
  int idxNew;
  sqlite3 *db = pParse->db;

  assert( pExpr->op==TK_EXISTS );
  assert( (pExpr->flags & EP_VarSelect) && (pExpr->flags & EP_xIsSelect) );

  if( pSel->selFlags & SF_Aggregate ) return;
#ifndef SQLITE_OMIT_WINDOWFUNC
  if( pSel->pWin ) return;
#endif
  if( pSel->pPrior ) return;
  if( pSel->pWhere==0 ) return;
  if( 0==exprAnalyzeExistsFindEq(pSel, 0, 0) ) return;

  pDup = sqlite3ExprDup(db, pExpr, 0);
  if( db->mallocFailed ){
    sqlite3ExprDelete(db, pDup);
    return;
  }
  pSel = pDup->x.pSelect;
  sqlite3ExprListDelete(db, pSel->pEList);
  pSel->pEList = 0;

  pInLhs = exprAnalyzeExistsFindEq(pSel, &pEq, &ppAnd);
  assert( pInLhs && pEq );
  assert( pEq==pSel->pWhere || ppAnd );
  if( pInLhs==pEq->pLeft ){
    pRet = pEq->pRight;
  }else{
    CollSeq *p = sqlite3ExprCompareCollSeq(pParse, pEq);
    pInLhs = sqlite3ExprAddCollateString(pParse, pInLhs, p?p->zName:"BINARY");
    pRet = pEq->pLeft;
  }

  assert( pDup->pLeft==0 );
  pDup->op = TK_IN;
  pDup->pLeft = pInLhs;
  pDup->flags &= ~EP_VarSelect;
  if( pRet->op==TK_VECTOR ){
    pSel->pEList = pRet->x.pList;
    pRet->x.pList = 0;
    sqlite3ExprDelete(db, pRet);
  }else{
    pSel->pEList = sqlite3ExprListAppend(pParse, 0, pRet);
  }
  pEq->pLeft = 0;
  pEq->pRight = 0;
  if( ppAnd ){
    Expr *pAnd = *ppAnd;
    Expr *pOther = (pAnd->pLeft==pEq) ? pAnd->pRight : pAnd->pLeft;
    pAnd->pLeft = pAnd->pRight = 0;
    sqlite3ExprDelete(db, pAnd);
    *ppAnd = pOther;
  }else{
    assert( pSel->pWhere==pEq );
    pSel->pWhere = 0;
  }
  sqlite3ExprDelete(db, pEq);

#ifdef WHERETRACE_ENABLED  /* 0x20 */
  if( sqlite3WhereTrace & 0x20 ){
    sqlite3DebugPrintf("Convert EXISTS:\n");
    sqlite3TreeViewExpr(0, pExpr, 0);
    sqlite3DebugPrintf("into IN:\n");
    sqlite3TreeViewExpr(0, pDup, 0);
  }
#endif
  idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
  exprAnalyze(pSrc, pWC, idxNew);
  markTermAsChild(pWC, idxNew, idxTerm);
  pWC->a[idxTerm].wtFlags |= TERM_COPIED;
}

/*
** The input to this routine is an WhereTerm structure with only the
** "pExpr" field filled in.  The job of this routine is to analyze the
** subexpression and populate all the other fields of the WhereTerm
** structure.
**







>












<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
  ** inequality constraint (>, <, >= or <=), perform the processing 
  ** on the first element of the vector.  */
  assert( TK_GT+1==TK_LE && TK_GT+2==TK_LT && TK_GT+3==TK_GE );
  assert( TK_IS<TK_GE && TK_ISNULL<TK_GE && TK_IN<TK_GE );
  assert( op<=TK_GE );
  if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){
    pExpr = pExpr->x.pList->a[0].pExpr;

  }

  if( pExpr->op==TK_COLUMN ){
    aiCurCol[0] = pExpr->iTable;
    aiCurCol[1] = pExpr->iColumn;
    return 1;
  }
  if( mPrereq==0 ) return 0;                 /* No table references */
  if( (mPrereq&(mPrereq-1))!=0 ) return 0;   /* Refs more than one table */
  return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr);
}















































































































































































































































































/*
** The input to this routine is an WhereTerm structure with only the
** "pExpr" field filled in.  The job of this routine is to analyze the
** subexpression and populate all the other fields of the WhereTerm
** structure.
**
1371
1372
1373
1374
1375
1376
1377

1378
1379
1380
1381
1382
1383
1384
      pTerm->leftCursor = aiCurCol[0];
      pTerm->u.x.leftColumn = aiCurCol[1];
      pTerm->eOperator = operatorMask(op) & opMask;
    }
    if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
    if( pRight 
     && exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op)

    ){
      WhereTerm *pNew;
      Expr *pDup;
      u16 eExtraOp = 0;        /* Extra bits for pNew->eOperator */
      assert( pTerm->u.x.iField==0 );
      if( pTerm->leftCursor>=0 ){
        int idxNew;







>







1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
      pTerm->leftCursor = aiCurCol[0];
      pTerm->u.x.leftColumn = aiCurCol[1];
      pTerm->eOperator = operatorMask(op) & opMask;
    }
    if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
    if( pRight 
     && exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op)
     && !ExprHasProperty(pRight, EP_FixedCol)
    ){
      WhereTerm *pNew;
      Expr *pDup;
      u16 eExtraOp = 0;        /* Extra bits for pNew->eOperator */
      assert( pTerm->u.x.iField==0 );
      if( pTerm->leftCursor>=0 ){
        int idxNew;
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
  */
  else if( pExpr->op==TK_OR ){
    assert( pWC->op==TK_AND );
    exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
    pTerm = &pWC->a[idxTerm];
  }
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */

  else if( pExpr->op==TK_EXISTS ){
    /* Perhaps treat an EXISTS operator as an IN operator */
    if( (pExpr->flags & EP_VarSelect)!=0
     && OptimizationEnabled(db, SQLITE_ExistsToIN)
    ){
      exprAnalyzeExists(pSrc, pWC, idxTerm);
    }
  }

  /* The form "x IS NOT NULL" can sometimes be evaluated more efficiently
  ** as "x>NULL" if x is not an INTEGER PRIMARY KEY.  So construct a
  ** virtual term of that form.
  **
  ** The virtual term must be tagged with TERM_VNULL.
  */
  else if( pExpr->op==TK_NOTNULL ){







<
<
<
<
<
<
<
<
<
<







1197
1198
1199
1200
1201
1202
1203










1204
1205
1206
1207
1208
1209
1210
  */
  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 ){
Changes to src/window.c.
784
785
786
787
788
789
790

791
792
793
794
795
796
797
        }
      }
      /* no break */ deliberate_fall_through

    case TK_AGG_FUNCTION:
    case TK_COLUMN: {
      int iCol = -1;

      if( p->pSub ){
        int i;
        for(i=0; i<p->pSub->nExpr; i++){
          if( 0==sqlite3ExprCompare(0, p->pSub->a[i].pExpr, pExpr, -1) ){
            iCol = i;
            break;
          }







>







784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
        }
      }
      /* no break */ deliberate_fall_through

    case TK_AGG_FUNCTION:
    case TK_COLUMN: {
      int iCol = -1;
      if( pParse->db->mallocFailed ) return WRC_Abort;
      if( p->pSub ){
        int i;
        for(i=0; i<p->pSub->nExpr; i++){
          if( 0==sqlite3ExprCompare(0, p->pSub->a[i].pExpr, pExpr, -1) ){
            iCol = i;
            break;
          }
893
894
895
896
897
898
899

900
901




902
903
904
905
906
907
908
909
  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++){

      Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
      assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );




      if( bIntToNull && pDup ){
        int iDummy;
        Expr *pSub;
        for(pSub=pDup; ExprHasProperty(pSub, EP_Skip); pSub=pSub->pLeft){
          assert( pSub );
        }
        if( sqlite3ExprIsInteger(pSub, &iDummy) ){
          pSub->op = TK_NULL;







>
|

>
>
>
>
|







894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
  ExprList *pAppend,      /* List of values to append. Might be NULL */
  int bIntToNull
){
  if( pAppend ){
    int i;
    int nInit = pList ? pList->nExpr : 0;
    for(i=0; i<pAppend->nExpr; i++){
      sqlite3 *db = pParse->db;
      Expr *pDup = sqlite3ExprDup(db, pAppend->a[i].pExpr, 0);
      assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
      if( db->mallocFailed ){
        sqlite3ExprDelete(db, pDup);
        break;
      }
      if( bIntToNull ){
        int iDummy;
        Expr *pSub;
        for(pSub=pDup; ExprHasProperty(pSub, EP_Skip); pSub=pSub->pLeft){
          assert( pSub );
        }
        if( sqlite3ExprIsInteger(pSub, &iDummy) ){
          pSub->op = TK_NULL;
930
931
932
933
934
935
936








937
938
939
940
941
942
943
  if( pExpr->op==TK_AGG_FUNCTION
   && pExpr->op2>=pWalker->walkerDepth
  ){
    pExpr->op2++;
  }
  return WRC_Continue;
}









/*
** If the SELECT statement passed as the second argument does not invoke
** any SQL window functions, this function is a no-op. Otherwise, it 
** rewrites the SELECT statement so that window function xStep functions
** are invoked in the correct order as described under "SELECT REWRITING"
** at the top of this file.







>
>
>
>
>
>
>
>







936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
  if( pExpr->op==TK_AGG_FUNCTION
   && pExpr->op2>=pWalker->walkerDepth
  ){
    pExpr->op2++;
  }
  return WRC_Continue;
}

static int disallowAggregatesInOrderByCb(Walker *pWalker, Expr *pExpr){
  if( pExpr->op==TK_AGG_FUNCTION && pExpr->pAggInfo==0 ){
    sqlite3ErrorMsg(pWalker->pParse,
         "misuse of aggregate: %s()", pExpr->u.zToken);
  }
  return WRC_Continue;
}

/*
** If the SELECT statement passed as the second argument does not invoke
** any SQL window functions, this function is a no-op. Otherwise, it 
** rewrites the SELECT statement so that window function xStep functions
** are invoked in the correct order as described under "SELECT REWRITING"
** at the top of this file.
964
965
966
967
968
969
970





971
972
973
974
975
976
977

    pTab = sqlite3DbMallocZero(db, sizeof(Table));
    if( pTab==0 ){
      return sqlite3ErrorToParser(db, SQLITE_NOMEM);
    }
    sqlite3AggInfoPersistWalkerInit(&w, pParse);
    sqlite3WalkSelect(&w, p);






    p->pSrc = 0;
    p->pWhere = 0;
    p->pGroupBy = 0;
    p->pHaving = 0;
    p->selFlags &= ~SF_Aggregate;
    p->selFlags |= SF_WinRewrite;







>
>
>
>
>







978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996

    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;
1465
1466
1467
1468
1469
1470
1471

1472
1473
1474
1475
1476
1477
1478
    VdbeCoverage(v);
    assert( eCond==0 || eCond==1 || eCond==2 );
    VdbeCoverageIf(v, eCond==0);
    VdbeCoverageIf(v, eCond==1);
    VdbeCoverageIf(v, eCond==2);
  }
  sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg);

  VdbeCoverageNeverNullIf(v, eCond==0); /* NULL case captured by */
  VdbeCoverageNeverNullIf(v, eCond==1); /*   the OP_MustBeInt */
  VdbeCoverageNeverNullIf(v, eCond==2);
  VdbeCoverageNeverNullIf(v, eCond==3); /* NULL case caught by */
  VdbeCoverageNeverNullIf(v, eCond==4); /*   the OP_Ge */
  sqlite3MayAbort(pParse);
  sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort);







>







1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
    VdbeCoverage(v);
    assert( eCond==0 || eCond==1 || eCond==2 );
    VdbeCoverageIf(v, eCond==0);
    VdbeCoverageIf(v, eCond==1);
    VdbeCoverageIf(v, eCond==2);
  }
  sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlite3VdbeCurrentAddr(v)+2, reg);
  sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC);
  VdbeCoverageNeverNullIf(v, eCond==0); /* NULL case captured by */
  VdbeCoverageNeverNullIf(v, eCond==1); /*   the OP_MustBeInt */
  VdbeCoverageNeverNullIf(v, eCond==2);
  VdbeCoverageNeverNullIf(v, eCond==3); /* NULL case caught by */
  VdbeCoverageNeverNullIf(v, eCond==4); /*   the OP_Ge */
  sqlite3MayAbort(pParse);
  sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_ERROR, OE_Abort);
1559
1560
1561
1562
1563
1564
1565

1566
1567
1568
1569
1570
1571
1572
  Parse *pParse;             /* Parse context */
  Window *pMWin;             /* First in list of functions being processed */
  Vdbe *pVdbe;               /* VDBE object */
  int addrGosub;             /* OP_Gosub to this address to return one row */
  int regGosub;              /* Register used with OP_Gosub(addrGosub) */
  int regArg;                /* First in array of accumulator registers */
  int eDelete;               /* See above */


  WindowCsrAndReg start;
  WindowCsrAndReg current;
  WindowCsrAndReg end;
};

/*







>







1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
  Parse *pParse;             /* Parse context */
  Window *pMWin;             /* First in list of functions being processed */
  Vdbe *pVdbe;               /* VDBE object */
  int addrGosub;             /* OP_Gosub to this address to return one row */
  int regGosub;              /* Register used with OP_Gosub(addrGosub) */
  int regArg;                /* First in array of accumulator registers */
  int eDelete;               /* See above */
  int regRowid;

  WindowCsrAndReg start;
  WindowCsrAndReg current;
  WindowCsrAndReg end;
};

/*
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
        sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
        addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
        VdbeCoverage(v);
        sqlite3ReleaseTempReg(pParse, regTmp);
      }
      
      if( pWin->bExprArgs ){
        int iStart = sqlite3VdbeCurrentAddr(v);
        VdbeOp *pOp, *pEnd;

        nArg = pWin->pOwner->x.pList->nExpr;
        regArg = sqlite3GetTempRange(pParse, nArg);
        sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);

        pEnd = sqlite3VdbeGetOp(v, -1);
        for(pOp=sqlite3VdbeGetOp(v, iStart); pOp<=pEnd; pOp++){
          if( pOp->opcode==OP_Column && pOp->p1==pWin->iEphCsr ){
            pOp->p1 = csr;
          }
        }
      }
      if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
        CollSeq *pColl;







|
|





|
|







1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
        sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
        addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
        VdbeCoverage(v);
        sqlite3ReleaseTempReg(pParse, regTmp);
      }
      
      if( pWin->bExprArgs ){
        int iOp = sqlite3VdbeCurrentAddr(v);
        int iEnd;

        nArg = pWin->pOwner->x.pList->nExpr;
        regArg = sqlite3GetTempRange(pParse, nArg);
        sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);

        for(iEnd=sqlite3VdbeCurrentAddr(v); iOp<iEnd; iOp++){
          VdbeOp *pOp = sqlite3VdbeGetOp(v, iOp);
          if( pOp->opcode==OP_Column && pOp->p1==pWin->iEphCsr ){
            pOp->p1 = csr;
          }
        }
      }
      if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
        CollSeq *pColl;
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
** subtracted. And the comparison operator is inverted to - ">=" becomes "<=",
** ">" becomes "<", and so on. So, with DESC sort order, if the argument op
** is OP_Ge, the generated code is equivalent to:
**
**   if( csr1.peerVal - regVal <= csr2.peerVal ) goto lbl;
**
** A special type of arithmetic is used such that if csr1.peerVal is not
** a numeric type (real or integer), then the result of the addition addition
** or subtraction is a a copy of csr1.peerVal.
*/
static void windowCodeRangeTest(
  WindowCodeArg *p, 
  int op,                         /* OP_Ge, OP_Gt, or OP_Le */
  int csr1,                       /* Cursor number for cursor 1 */
  int regVal,                     /* Register containing non-negative number */
  int csr2,                       /* Cursor number for cursor 2 */
  int lbl                         /* Jump destination if condition is true */
){
  Parse *pParse = p->pParse;
  Vdbe *v = sqlite3GetVdbe(pParse);
  ExprList *pOrderBy = p->pMWin->pOrderBy;  /* ORDER BY clause for window */
  int reg1 = sqlite3GetTempReg(pParse);     /* Reg. for csr1.peerVal+regVal */
  int reg2 = sqlite3GetTempReg(pParse);     /* Reg. for csr2.peerVal */
  int regString = ++pParse->nMem;           /* Reg. for constant value '' */
  int arith = OP_Add;                       /* OP_Add or OP_Subtract */
  int addrGe;                               /* Jump destination */

  CollSeq *pColl;





  assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
  assert( pOrderBy && pOrderBy->nExpr==1 );
  if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_DESC ){
    switch( op ){
      case OP_Ge: op = OP_Le; break;
      case OP_Gt: op = OP_Lt; break;
      default: assert( op==OP_Le ); op = OP_Ge; break;
    }
    arith = OP_Subtract;
  }

  /* Read the peer-value from each cursor into a register */
  windowReadPeerValues(p, csr1, reg1);
  windowReadPeerValues(p, csr2, reg2);

  VdbeModuleComment((v, "CodeRangeTest: if( R%d %s R%d %s R%d ) goto lbl",
      reg1, (arith==OP_Add ? "+" : "-"), regVal,
      ((op==OP_Ge) ? ">=" : (op==OP_Le) ? "<=" : (op==OP_Gt) ? ">" : "<"), reg2
  ));

  /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
  ** This block adds (or subtracts for DESC) the numeric value in regVal
  ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
  ** then leave reg1 as it is. In pseudo-code, this is implemented as:
  **
  **   if( reg1>='' ) goto addrGe;
  **   reg1 = reg1 +/- regVal
  **   addrGe:
  **
  ** Since all strings and blobs are greater-than-or-equal-to an empty string,
  ** the add/subtract is skipped for these, as required. If reg1 is a NULL,
  ** then the arithmetic is performed, but since adding or subtracting from
  ** NULL is always NULL anyway, this case is handled as required too.  */
  sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
  addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
  VdbeCoverage(v);
  sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
  sqlite3VdbeJumpHere(v, addrGe);

  /* If the BIGNULL flag is set for the ORDER BY, then it is required to 
  ** consider NULL values to be larger than all other values, instead of 
  ** the usual smaller. The VDBE opcodes OP_Ge and so on do not handle this
  ** (and adding that capability causes a performance regression), so
  ** instead if the BIGNULL flag is set then cases where either reg1 or
  ** reg2 are NULL are handled separately in the following block. The code
  ** generated is equivalent to:







|


















>

>
>
>
>












<
<
<
<





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
** subtracted. And the comparison operator is inverted to - ">=" becomes "<=",
** ">" becomes "<", and so on. So, with DESC sort order, if the argument op
** is OP_Ge, the generated code is equivalent to:
**
**   if( csr1.peerVal - regVal <= csr2.peerVal ) goto lbl;
**
** A special type of arithmetic is used such that if csr1.peerVal is not
** a numeric type (real or integer), then the result of the addition
** or subtraction is a a copy of csr1.peerVal.
*/
static void windowCodeRangeTest(
  WindowCodeArg *p, 
  int op,                         /* OP_Ge, OP_Gt, or OP_Le */
  int csr1,                       /* Cursor number for cursor 1 */
  int regVal,                     /* Register containing non-negative number */
  int csr2,                       /* Cursor number for cursor 2 */
  int lbl                         /* Jump destination if condition is true */
){
  Parse *pParse = p->pParse;
  Vdbe *v = sqlite3GetVdbe(pParse);
  ExprList *pOrderBy = p->pMWin->pOrderBy;  /* ORDER BY clause for window */
  int reg1 = sqlite3GetTempReg(pParse);     /* Reg. for csr1.peerVal+regVal */
  int reg2 = sqlite3GetTempReg(pParse);     /* Reg. for csr2.peerVal */
  int regString = ++pParse->nMem;           /* Reg. for constant value '' */
  int arith = OP_Add;                       /* OP_Add or OP_Subtract */
  int addrGe;                               /* Jump destination */
  int addrDone = sqlite3VdbeMakeLabel(pParse);   /* Address past OP_Ge */
  CollSeq *pColl;

  /* Read the peer-value from each cursor into a register */
  windowReadPeerValues(p, csr1, reg1);
  windowReadPeerValues(p, csr2, reg2);

  assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
  assert( pOrderBy && pOrderBy->nExpr==1 );
  if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_DESC ){
    switch( op ){
      case OP_Ge: op = OP_Le; break;
      case OP_Gt: op = OP_Lt; break;
      default: assert( op==OP_Le ); op = OP_Ge; break;
    }
    arith = OP_Subtract;
  }





  VdbeModuleComment((v, "CodeRangeTest: if( R%d %s R%d %s R%d ) goto lbl",
      reg1, (arith==OP_Add ? "+" : "-"), regVal,
      ((op==OP_Ge) ? ">=" : (op==OP_Le) ? "<=" : (op==OP_Gt) ? ">" : "<"), reg2
  ));




















  /* If the BIGNULL flag is set for the ORDER BY, then it is required to 
  ** consider NULL values to be larger than all other values, instead of 
  ** the usual smaller. The VDBE opcodes OP_Ge and so on do not handle this
  ** (and adding that capability causes a performance regression), so
  ** instead if the BIGNULL flag is set then cases where either reg1 or
  ** reg2 are NULL are handled separately in the following block. The code
  ** generated is equivalent to:
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
        break;
      case OP_Le: 
        sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); 
        VdbeCoverage(v); 
        break;
      default: assert( op==OP_Lt ); /* no-op */ break;
    }
    sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);

    /* This block runs if reg1 is not NULL, but reg2 is. */
    sqlite3VdbeJumpHere(v, addr);
    sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); VdbeCoverage(v);
    if( op==OP_Gt || op==OP_Ge ){
      sqlite3VdbeChangeP2(v, -1, sqlite3VdbeCurrentAddr(v)+1);
    }
  }























  /* Compare registers reg2 and reg1, taking the jump if required. Note that
  ** control skips over this test if the BIGNULL flag is set and either
  ** reg1 or reg2 contain a NULL value.  */
  sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
  pColl = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[0].pExpr);
  sqlite3VdbeAppendP4(v, (void*)pColl, P4_COLLSEQ);
  sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);


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







|





|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








>







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
        break;
      case OP_Le: 
        sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); 
        VdbeCoverage(v); 
        break;
      default: assert( op==OP_Lt ); /* no-op */ break;
    }
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone);

    /* This block runs if reg1 is not NULL, but reg2 is. */
    sqlite3VdbeJumpHere(v, addr);
    sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); VdbeCoverage(v);
    if( op==OP_Gt || op==OP_Ge ){
      sqlite3VdbeChangeP2(v, -1, addrDone);
    }
  }

  /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
  ** This block adds (or subtracts for DESC) the numeric value in regVal
  ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
  ** then leave reg1 as it is. In pseudo-code, this is implemented as:
  **
  **   if( reg1>='' ) goto addrGe;
  **   reg1 = reg1 +/- regVal
  **   addrGe:
  **
  ** Since all strings and blobs are greater-than-or-equal-to an empty string,
  ** the add/subtract is skipped for these, as required. If reg1 is a NULL,
  ** then the arithmetic is performed, but since adding or subtracting from
  ** NULL is always NULL anyway, this case is handled as required too.  */
  sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
  addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
  VdbeCoverage(v);
  if( (op==OP_Ge && arith==OP_Add) || (op==OP_Le && arith==OP_Subtract) ){
    sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
  }
  sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
  sqlite3VdbeJumpHere(v, addrGe);

  /* Compare registers reg2 and reg1, taking the jump if required. Note that
  ** control skips over this test if the BIGNULL flag is set and either
  ** reg1 or reg2 contain a NULL value.  */
  sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
  pColl = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[0].pExpr);
  sqlite3VdbeAppendP4(v, (void*)pColl, P4_COLLSEQ);
  sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
  sqlite3VdbeResolveLabel(v, addrDone);

  assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le );
  testcase(op==OP_Ge); VdbeCoverageIf(v, op==OP_Ge);
  testcase(op==OP_Lt); VdbeCoverageIf(v, op==OP_Lt);
  testcase(op==OP_Le); VdbeCoverageIf(v, op==OP_Le);
  testcase(op==OP_Gt); VdbeCoverageIf(v, op==OP_Gt);
  sqlite3ReleaseTempReg(pParse, reg1);
2230
2231
2232
2233
2234
2235
2236
2237


2238
2239
2240
2241
2242

2243
2244
2245
2246





2247
2248
2249
2250
2251
2252
2253
    windowAggFinal(p, 0);
  }
  addrContinue = sqlite3VdbeCurrentAddr(v);

  /* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING) or
  ** (RANGE BETWEEN b PRECEDING AND a PRECEDING) frame, ensure the 
  ** start cursor does not advance past the end cursor within the 
  ** temporary table. It otherwise might, if (a>b).  */


  if( pMWin->eStart==pMWin->eEnd && regCountdown
   && pMWin->eFrmType==TK_RANGE && op==WINDOW_AGGINVERSE
  ){
    int regRowid1 = sqlite3GetTempReg(pParse);
    int regRowid2 = sqlite3GetTempReg(pParse);

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





    sqlite3ReleaseTempReg(pParse, regRowid1);
    sqlite3ReleaseTempReg(pParse, regRowid2);
    assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING );
  }

  switch( op ){
    case WINDOW_RETURN_ROW:







|
>
>

|



>
|
|
|
|
>
>
>
>
>







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
    windowAggFinal(p, 0);
  }
  addrContinue = sqlite3VdbeCurrentAddr(v);

  /* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING) or
  ** (RANGE BETWEEN b PRECEDING AND a PRECEDING) frame, ensure the 
  ** start cursor does not advance past the end cursor within the 
  ** temporary table. It otherwise might, if (a>b). Also ensure that,
  ** if the input cursor is still finding new rows, that the end
  ** cursor does not go past it to EOF. */
  if( pMWin->eStart==pMWin->eEnd && regCountdown
   && pMWin->eFrmType==TK_RANGE
  ){
    int regRowid1 = sqlite3GetTempReg(pParse);
    int regRowid2 = sqlite3GetTempReg(pParse);
    if( op==WINDOW_AGGINVERSE ){
      sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1);
      sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2);
      sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1);
      VdbeCoverage(v);
    }else if( p->regRowid ){
      sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid1);
      sqlite3VdbeAddOp3(v, OP_Ge, p->regRowid, lblDone, regRowid1);
      VdbeCoverageNeverNull(v);
    }
    sqlite3ReleaseTempReg(pParse, regRowid1);
    sqlite3ReleaseTempReg(pParse, regRowid2);
    assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING );
  }

  switch( op ){
    case WINDOW_RETURN_ROW:
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
  int iInput;                               /* To iterate through sub cols */
  int addrNe;                     /* Address of OP_Ne */
  int addrGosubFlush = 0;         /* Address of OP_Gosub to flush: */
  int addrInteger = 0;            /* Address of OP_Integer */
  int addrEmpty;                  /* Address of OP_Rewind in flush: */
  int regNew;                     /* Array of registers holding new input row */
  int regRecord;                  /* regNew array in record form */
  int regRowid;                   /* Rowid for regRecord in eph table */
  int regNewPeer = 0;             /* Peer values for new row (part of regNew) */
  int regPeer = 0;                /* Peer values for current row */
  int regFlushPart = 0;           /* Register for "Gosub flush_partition" */
  WindowCodeArg s;                /* Context object for sub-routines */
  int lblWhereEnd;                /* Label just before sqlite3WhereEnd() code */
  int regStart = 0;               /* Value of <expr> PRECEDING */
  int regEnd = 0;                 /* Value of <expr> FOLLOWING */







<







2770
2771
2772
2773
2774
2775
2776

2777
2778
2779
2780
2781
2782
2783
  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 */
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822

  /* Allocate registers for the array of values from the sub-query, the
  ** samve values in record form, and the rowid used to insert said record
  ** into the ephemeral table.  */
  regNew = pParse->nMem+1;
  pParse->nMem += nInput;
  regRecord = ++pParse->nMem;
  regRowid = ++pParse->nMem;

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







|







2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855

  /* Allocate registers for the array of values from the sub-query, the
  ** samve values in record form, and the rowid used to insert said record
  ** into the ephemeral table.  */
  regNew = pParse->nMem+1;
  pParse->nMem += nInput;
  regRecord = ++pParse->nMem;
  s.regRowid = ++pParse->nMem;

  /* If the window frame contains an "<expr> PRECEDING" or "<expr> FOLLOWING"
  ** clause, allocate registers to store the results of evaluating each
  ** <expr>.  */
  if( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING ){
    regStart = ++pParse->nMem;
  }
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
    VdbeCoverageEqNe(v);
    addrGosubFlush = sqlite3VdbeAddOp1(v, OP_Gosub, regFlushPart);
    VdbeComment((v, "call flush_partition"));
    sqlite3VdbeAddOp3(v, OP_Copy, regNewPart, pMWin->regPart, nPart-1);
  }

  /* Insert the new row into the ephemeral table */
  sqlite3VdbeAddOp2(v, OP_NewRowid, csrWrite, regRowid);
  sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, regRowid);
  addrNe = sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, regRowid);
  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);







|
|
|







2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
    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);
2984
2985
2986
2987
2988
2989
2990

2991
2992
2993
2994
2995
2996
2997

  /* Fall through */
  if( pMWin->pPartition ){
    addrInteger = sqlite3VdbeAddOp2(v, OP_Integer, 0, regFlushPart);
    sqlite3VdbeJumpHere(v, addrGosubFlush);
  }


  addrEmpty = sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite);
  VdbeCoverage(v);
  if( pMWin->eEnd==TK_PRECEDING ){
    int bRPS = (pMWin->eStart==TK_PRECEDING && pMWin->eFrmType==TK_RANGE);
    windowCodeOp(&s, WINDOW_AGGSTEP, regEnd, 0);
    if( bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
    windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0);







>







3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031

  /* Fall through */
  if( pMWin->pPartition ){
    addrInteger = sqlite3VdbeAddOp2(v, OP_Integer, 0, regFlushPart);
    sqlite3VdbeJumpHere(v, addrGosubFlush);
  }

  s.regRowid = 0;
  addrEmpty = sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite);
  VdbeCoverage(v);
  if( pMWin->eEnd==TK_PRECEDING ){
    int bRPS = (pMWin->eStart==TK_PRECEDING && pMWin->eFrmType==TK_RANGE);
    windowCodeOp(&s, WINDOW_AGGSTEP, regEnd, 0);
    if( bRPS ) windowCodeOp(&s, WINDOW_AGGINVERSE, regStart, 0);
    windowCodeOp(&s, WINDOW_RETURN_ROW, 0, 0);
Changes to test/alter4.test.
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
        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;
    }
  } {b 1 2 a 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;
    }
  } {b 1 2 a 1 2 b 3 4 a 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);







|

|




|

|







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 ORDER BY trig, a, b;
    }
  } {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 ORDER BY trig, a, b;
    }
  } {a 1 2 a 3 4 b 1 2 b 3 4}
}

# Ticket #1183 - Make sure adding columns to large tables does not cause
# memory corruption (as was the case before this bug was fixed).
do_test alter4-8.1 {
  execsql {
    CREATE TEMP TABLE t4(c1);
Changes to test/alterauth2.test.
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

103
104
105
106
107
108
109
110
111
112

113
114
115

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_test {} {}} 
  {SQLITE_READ sqlite_master name main {}} 
  {SQLITE_READ sqlite_master sql main {}} 
  {SQLITE_READ sqlite_master tbl_name main {}} 
  {SQLITE_READ sqlite_master type main {}} 
  {SQLITE_READ sqlite_temp_master name temp {}} 
  {SQLITE_READ sqlite_temp_master sql temp {}} 
  {SQLITE_READ sqlite_temp_master type temp {}} 
  {SQLITE_SELECT {} {} {} {}} 
  {SQLITE_UPDATE sqlite_master sql main {}} 
  {SQLITE_UPDATE sqlite_temp_master sql temp {}}
}

do_auth_test 1.3 {
  ALTER TABLE t2 DROP COLUMN c;
} {
  {SQLITE_FUNCTION {} like {} {}} 
  {SQLITE_FUNCTION {} sqlite_drop_column {} {}}

  {SQLITE_FUNCTION {} sqlite_rename_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 {}}

}

finish_test







>


















>










>



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

do_auth_test 1.2 {
  ALTER TABLE t2 RENAME a TO aaa;
} {
  {SQLITE_ALTER_TABLE main t2 {} {}} 
  {SQLITE_FUNCTION {} like {} {}} 
  {SQLITE_FUNCTION {} sqlite_rename_column {} {}} 
  {SQLITE_FUNCTION {} sqlite_rename_quotefix {} {}} 
  {SQLITE_FUNCTION {} sqlite_rename_test {} {}} 
  {SQLITE_READ sqlite_master name main {}} 
  {SQLITE_READ sqlite_master sql main {}} 
  {SQLITE_READ sqlite_master tbl_name main {}} 
  {SQLITE_READ sqlite_master type main {}} 
  {SQLITE_READ sqlite_temp_master name temp {}} 
  {SQLITE_READ sqlite_temp_master sql temp {}} 
  {SQLITE_READ sqlite_temp_master type temp {}} 
  {SQLITE_SELECT {} {} {} {}} 
  {SQLITE_UPDATE sqlite_master sql main {}} 
  {SQLITE_UPDATE sqlite_temp_master sql temp {}}
}

do_auth_test 1.3 {
  ALTER TABLE t2 DROP COLUMN c;
} {
  {SQLITE_FUNCTION {} like {} {}} 
  {SQLITE_FUNCTION {} sqlite_drop_column {} {}}
  {SQLITE_FUNCTION {} sqlite_rename_quotefix {} {}} 
  {SQLITE_FUNCTION {} sqlite_rename_test {} {}} 
  {SQLITE_READ sqlite_master name main {}} 
  {SQLITE_READ sqlite_master sql main {}} 
  {SQLITE_READ sqlite_master tbl_name main {}} 
  {SQLITE_READ sqlite_master type main {}} 
  {SQLITE_READ sqlite_temp_master name temp {}} 
  {SQLITE_READ sqlite_temp_master sql temp {}} 
  {SQLITE_READ sqlite_temp_master type temp {}} 
  {SQLITE_SELECT {} {} {} {}} 
  {SQLITE_UPDATE sqlite_master sql main {}}
  {SQLITE_UPDATE sqlite_temp_master sql temp {}}
}

finish_test
Changes to test/altercol.test.
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577

do_execsql_test 13.1.6 {
  UPDATE sqlite_master SET sql = '' WHERE name='x1i';
} {}

do_catchsql_test 13.1.7 {
  ALTER TABLE x1 RENAME COLUMN t TO ttt;
} {1 {database disk image is malformed}}

do_execsql_test 13.1.8 {
  DELETE FROM sqlite_master WHERE name = 'x1i';
}

do_execsql_test 13.2.0 {
  CREATE TABLE data(x UNIQUE, y, z);







|







563
564
565
566
567
568
569
570
571
572
573
574
575
576
577

do_execsql_test 13.1.6 {
  UPDATE sqlite_master SET sql = '' WHERE name='x1i';
} {}

do_catchsql_test 13.1.7 {
  ALTER TABLE x1 RENAME COLUMN t TO ttt;
} {1 {error in index x1i: }}

do_execsql_test 13.1.8 {
  DELETE FROM sqlite_master WHERE name = 'x1i';
}

do_execsql_test 13.2.0 {
  CREATE TABLE data(x UNIQUE, y, z);
830
831
832
833
834
835
836
837

838























839
  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))}
}


























finish_test








>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
  CREATE TABLE t2(c, othername, extra AS (c + 1));
  ALTER TABLE t1 RENAME a to othername;
  SELECT sql FROM sqlite_schema;
} {
  {CREATE TABLE t1(othername, b)}
  {CREATE TABLE t2(c, othername, extra AS (c + 1))}
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 22.0 {
  CREATE TABLE t1(a, b);
  CREATE INDEX x1 on t1("c"=b);
  INSERT INTO t1 VALUES('a', 'a');
  INSERT INTO t1 VALUES('b', 'b');
  INSERT INTO t1 VALUES('c', 'c');
  ALTER TABLE t1 RENAME COLUMN a TO "c";
  PRAGMA integrity_check;
} {ok}

reset_db
do_execsql_test 23.0 {
  CREATE TABLE t1('a'"b",c);
  CREATE INDEX i1 ON t1('a');
  INSERT INTO t1 VALUES(1,2), (3,4);
  ALTER TABLE t1 RENAME COLUMN a TO x;
  PRAGMA integrity_check;
  SELECT sql FROM sqlite_schema WHERE name='t1';

} {ok {CREATE TABLE t1("x" "b",c)}}


finish_test
Changes to test/alterdropcol.test.
271
272
273
274
275
276
277




























































278
279
  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}}





























































finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
  CREATE TABLE t2(x,y,z);
  PRAGMA writable_schema=ON;
  UPDATE sqlite_schema SET sql='CREATE VIEW t2(x,y,z) AS SELECT b,a,c FROM t1'
   WHERE name='t2';
  PRAGMA writable_schema=OFF;
  ALTER TABLE t2 DROP COLUMN z;
} {1 {database disk image is malformed}}

# 2021-04-06 dbsqlfuzz crash-331c5c29bb76257b198f1318eef3288f9624c8ce
reset_db
do_execsql_test 7.0 {
  CREATE TABLE t1(a, b, c, PRIMARY KEY(a COLLATE nocase, a)) WITHOUT ROWID;
  INSERT INTO t1 VALUES(1, 2, 3);
  INSERT INTO t1 VALUES(4, 5, 6);
}
do_execsql_test 7.1 {
  ALTER TABLE t1 DROP COLUMN c;                
}
do_execsql_test 7.2 {
  SELECT sql FROM sqlite_schema;
} {{CREATE TABLE t1(a, b, PRIMARY KEY(a COLLATE nocase, a)) WITHOUT ROWID}}
do_execsql_test 7.3 {
  SELECT * FROM t1;
} {1 2 4 5}

reset_db
do_execsql_test 8.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  PRAGMA writable_schema = 1;
  UPDATE sqlite_schema 
  SET sql = 'CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b)'
}
db close
sqlite3 db test.db
do_execsql_test 8.1 {
  ALTER TABLE t1 DROP COLUMN b;                
}
do_execsql_test 8.2 {
  SELECT sql FROM sqlite_schema;
} {{CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT)}}

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

foreach {tn wo} {
  1 {}
  2 {WITHOUT ROWID}
} {
  reset_db
  do_execsql_test 9.$tn.0 "
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c) $wo;
  "
  do_execsql_test 9.$tn.1 {
    WITH s(i) AS (
        SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000
    )
    INSERT INTO t1(a, b, c) SELECT i, 123, 456 FROM s;
  }
  do_execsql_test 9.$tn.2 {
    ALTER TABLE t1 DROP COLUMN b;
  }

  do_execsql_test 9.$tn.3 {
    SELECT count(*), c FROM t1 GROUP BY c;
  } {50000 456}
}



finish_test
Changes to test/altermalloc3.test.
18
19
20
21
22
23
24








25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 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, d, PRIMARY KEY(d, b)) WITHOUT ROWID;
  INSERT INTO t1 VALUES(1, 2, 3, 4);
}
faultsim_save_and_close

do_faultsim_test 1 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { ALTER TABLE t1 DROP COLUMN c }
} -test {
  faultsim_test_result {0 {}}
}


finish_test








>
>
>
>
>
>
>
>















<
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE x1(
      one, two, three, PRIMARY KEY(one), 
      CHECK (three!="xyz"), CHECK (two!="one")
  ) WITHOUT ROWID;
  CREATE INDEX x1i ON x1(one+"two"+"four") WHERE "five";
  CREATE TEMP TRIGGER AFTER INSERT ON x1 BEGIN
    UPDATE x1 SET two=new.three || "new" WHERE one=new.one||"";
  END;
  CREATE TABLE t1(a, b, c, d, PRIMARY KEY(d, b)) WITHOUT ROWID;
  INSERT INTO t1 VALUES(1, 2, 3, 4);
}
faultsim_save_and_close

do_faultsim_test 1 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { ALTER TABLE t1 DROP COLUMN c }
} -test {
  faultsim_test_result {0 {}}
}


finish_test

Added test/alterqf.test.






























































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# 2021 March 16
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. This
# script focuses on testing internal function sqlite_rename_quotefix().
#


set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix alterqf

sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db

do_execsql_test 1.0 {
  CREATE TABLE t1(a, b, c);
}

foreach {tn before after} {
  1 {CREATE VIEW v1 AS SELECT "a", "b", "notacolumn!", "c" FROM t1}
    {CREATE VIEW v1 AS SELECT "a", "b", 'notacolumn!', "c" FROM t1}

  2 {CREATE VIEW v1 AS SELECT "a", "b", "not'a'column!", "c" FROM t1}
    {CREATE VIEW v1 AS SELECT "a", "b", 'not''a''column!', "c" FROM t1}

  3 {CREATE VIEW v1 AS SELECT "a", "b", "not""a""column!", "c" FROM t1}
    {CREATE VIEW v1 AS SELECT "a", "b", 'not"a"column!', "c" FROM t1}

  4 {CREATE VIEW v1 AS SELECT "val", count("b") FROM t1 GROUP BY "abc"}
    {CREATE VIEW v1 AS SELECT 'val', count("b") FROM t1 GROUP BY 'abc'}

  5 {CREATE TABLE xyz(a CHECK (a!="str"), b AS (a||"str"))}
    {CREATE TABLE xyz(a CHECK (a!='str'), b AS (a||'str'))}

  6 {CREATE INDEX i1 ON t1(a || "str", "b", "val")}
    {CREATE INDEX i1 ON t1(a || 'str', "b", 'val')}

  7 {CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN SELECT "abcd"; END}
    {CREATE TRIGGER tr AFTER INSERT ON t1 BEGIN SELECT 'abcd'; END}

  8 {CREATE VIEW v1 AS SELECT "string"'alias' FROM t1}
    {CREATE VIEW v1 AS SELECT 'string' 'alias' FROM t1}

  9 {CREATE INDEX i1 ON t1(a) WHERE "b"="bb"}
    {CREATE INDEX i1 ON t1(a) WHERE "b"='bb'}

 10 {CREATE TABLE t2(abc, xyz CHECK (xyz != "123"))} 
    {CREATE TABLE t2(abc, xyz CHECK (xyz != '123'))} 

 11 {
    CREATE TRIGGER ott AFTER UPDATE ON t1 BEGIN 
      SELECT max("str", new."a") FROM t1 
          WHERE group_concat("b", ",") OVER (ORDER BY c||"str");
      UPDATE t1 SET c= b + "str";
      DELETE FROM t1 WHERE EXISTS (
        SELECT 1 FROM t1 AS o WHERE o."a" = "o.a" AND t1.b IN("t1.b")
      );
    END;
 } {
    CREATE TRIGGER ott AFTER UPDATE ON t1 BEGIN 
      SELECT max('str', new."a") FROM t1 
          WHERE group_concat("b", ',') OVER (ORDER BY c||'str');
      UPDATE t1 SET c= b + 'str';
      DELETE FROM t1 WHERE EXISTS (
        SELECT 1 FROM t1 AS o WHERE o."a" = 'o.a' AND t1.b IN('t1.b')
      );
    END;
 }

} {
  do_execsql_test 1.$tn {
    SELECT sqlite_rename_quotefix('main', $before)
  } [list $after]
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE x1(
      one, two, three, PRIMARY KEY(one), 
      CHECK (three!="xyz"), CHECK (two!="one")
  ) WITHOUT ROWID;
  CREATE INDEX x1i ON x1(one+"two"+"four") WHERE "five";
  CREATE TEMP TRIGGER AFTER INSERT ON x1 BEGIN
    UPDATE x1 SET two=new.three || "new" WHERE one=new.one||"";
  END;
}

do_execsql_test 2.1 {
  ALTER TABLE x1 RENAME two TO 'four';
  SELECT sql FROM sqlite_schema;
  SELECT sql FROM sqlite_temp_schema;
} {{CREATE TABLE x1(
      one, "four", three, PRIMARY KEY(one), 
      CHECK (three!='xyz'), CHECK ("four"!="one")
  ) WITHOUT ROWID}
  {CREATE INDEX x1i ON x1(one+"four"+'four') WHERE 'five'}
  {CREATE TRIGGER AFTER INSERT ON x1 BEGIN
    UPDATE x1 SET "four"=new.three || 'new' WHERE one=new.one||'';
  END}
}


finish_test
Changes to test/altertab.test.
732
733
734
735
736
737
738

739





740




741



















































  END;
  CREATE VIEW v1 AS SELECT * FROM nosuchtable;
}
do_catchsql_test 24.2.1 {
  ALTER TABLE t1 RENAME TO t2;
} {1 {error in trigger AFTER: no such table: main.nosuchtable}}








finish_test































































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


breakpoint
do_execsql_test 27.2 {
  alter table t_sa rename column c_muyat to c_dg;
}





finish_test
Changes to test/analyze3.test.
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

# 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<?)}
do_eqp_test analyze3-1.1.3 {
  SELECT sum(y) FROM t1 WHERE x>0 AND x<1100 
} {SCAN TABLE 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<?)}
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<?)}
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}
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<?)}
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}

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]







|


|









|




|




|




|




|







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

# The first of the following two SELECT statements visits 99 rows. So
# it is better to use the index. But the second visits every row in 
# the table (1000 in total) so it is better to do a full-table scan.
#
do_eqp_test analyze3-1.1.2 {
  SELECT sum(y) FROM t1 WHERE x>200 AND x<300
} {SEARCH 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 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 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 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 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 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 t1}

do_test analyze3-1.1.4 {
  sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
} {199 0 14850}
do_test analyze3-1.1.5 {
  set l [string range "200" 0 end]
  set u [string range "300" 0 end]
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
} {}
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<?)}
do_eqp_test analyze3-1.2.3 {
  SELECT sum(y) FROM t2 WHERE x>0 AND x<99
} {SCAN TABLE 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]







|


|







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

do_test analyze3-1.2.4 {
  sf_execsql { SELECT sum(y) FROM t2 WHERE x>12 AND x<20 }
} {161 0 4760}
do_test analyze3-1.2.5 {
  set l [string range "12" 0 end]
  set u [string range "20" 0 end]
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
} {}
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<?)}
do_eqp_test analyze3-1.3.3 {
  SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
} {SCAN TABLE 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]







|


|







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

do_test analyze3-1.3.4 {
  sf_execsql { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 }
} {199 0 14850}
do_test analyze3-1.3.5 {
  set l [string range "200" 0 end]
  set u [string range "300" 0 end]
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
    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<?)}
do_eqp_test analyze3-2.3 {
  SELECT count(a) FROM t1 WHERE b LIKE '%a'
} {SCAN TABLE 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







|


|







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 t1 USING INDEX i1 (b>? AND b<?)}
do_eqp_test analyze3-2.3 {
  SELECT count(a) FROM t1 WHERE b LIKE '%a'
} {SCAN t1}

# Return the first argument if like_match_blobs is true (the default)
# or the second argument if not
#
proc ilmb {a b} {
  ifcapable like_match_blobs {return $a}
  return $b
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
  }
  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=?)}

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=?)}

#-----------------------------------------------------------------------------
# 2015-04-20.
# Memory leak in sqlite3Stat4ProbeFree().  (Discovered while fuzzing.)
#
do_execsql_test analyze-7.1 {
  DROP TABLE IF EXISTS t1;







|



|







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 t1 USING INDEX i2 (c=?)}

do_eqp_test analyze3-6-2 {
  SELECT * FROM t1 WHERE a = 5 AND b > 'w' AND c = 13;
} {SEARCH t1 USING INDEX i2 (c=?)}

#-----------------------------------------------------------------------------
# 2015-04-20.
# Memory leak in sqlite3Stat4ProbeFree().  (Discovered while fuzzing.)
#
do_execsql_test analyze-7.1 {
  DROP TABLE IF EXISTS t1;
Changes to test/analyze4.test.
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
    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=?)*/}

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







|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
    INSERT INTO t1 SELECT a+32, b FROM t1;
    INSERT INTO t1 SELECT a+64, b FROM t1;
    ANALYZE;
  }

  # Should choose the t1a index since it is more specific than t1b.
  db eval {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=5 AND b IS NULL}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}

# Verify that the t1b index shows that it does not narrow down the
# search any at all.
#
do_test analyze4-1.1 {
  db eval {
    SELECT idx, stat FROM sqlite_stat1 WHERE tbl='t1' ORDER BY idx;
Changes to test/analyze6.test.
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# 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=?)*/}

# 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=?)
}


# 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=?)*/}
do_test analyze6-2.2 {
  eqp {SELECT * FROM t201 WHERE y=5}
} {/*SEARCH TABLE 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=?)*/}
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=?)*/}
do_test analyze6-2.5 {
  eqp {SELECT * FROM t201 WHERE y=5}
} {/*SEARCH TABLE 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=?)*/}
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=?)*/}
do_test analyze6-2.8 {
  eqp {SELECT * FROM t201 WHERE y=5}
} {/*SEARCH TABLE 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=?)*/}

finish_test







|








|
|














|


|


|






|


|


|









|


|


|


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# 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 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 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 t201 USING INDEX t201z (z=?)*/}
do_test analyze6-2.2 {
  eqp {SELECT * FROM t201 WHERE y=5}
} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
do_test analyze6-2.3 {
  eqp {SELECT * FROM t201 WHERE x=5}
} {/*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 t201 USING INDEX t201z (z=?)*/}
do_test analyze6-2.5 {
  eqp {SELECT * FROM t201 WHERE y=5}
} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
do_test analyze6-2.6 {
  eqp {SELECT * FROM t201 WHERE x=5}
} {/*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 t201 USING INDEX t201z (z=?)*/}
do_test analyze6-2.8 {
  eqp {SELECT * FROM t201 WHERE y=5}
} {/*SEARCH t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
do_test analyze6-2.9 {
  eqp {SELECT * FROM t201 WHERE x=5}
} {/*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
    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=?)*/}
do_test analyze7-1.1 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
} {/*SEARCH TABLE 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=?)*/}

# 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=?)*/}
do_test analyze7-2.1 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
} {/*SEARCH TABLE 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=?)*/}

# 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=?)*/}

# 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=?)*/}
do_test analyze7-3.1 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
} {/*SEARCH TABLE 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 {
  # 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=?)*/}
} 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=?)*/}
}
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=?)*/}

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=?)*/}
  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=?)*/}
}
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=?)*/}

finish_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
    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 t1 USING INDEX t1a (a=?)*/}
do_test analyze7-1.1 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test analyze7-1.2 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
} {/*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 t1 USING INDEX t1a (a=?)*/}
do_test analyze7-2.1 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test analyze7-2.2 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
} {/*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 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 t1 USING INDEX t1a (a=?)*/}
do_test analyze7-3.1 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test analyze7-3.2.1 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=?;}
} {/*SEARCH t1 USING INDEX t1cd (c=?)*/}
ifcapable stat4 {
  # If ENABLE_STAT4 is defined, SQLite comes up with a different estimated
  # row count for (c=2) than it does for (c=?).
  do_test analyze7-3.2.2 {
    execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
  } {/*SEARCH 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 t1 USING INDEX t1cd (c=?)*/}
}
do_test analyze7-3.3 {
  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}

ifcapable {!stat4} {
  do_test analyze7-3.4 {
    execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND b=123}
  } {/*SEARCH t1 USING INDEX t1b (b=?)*/}
  do_test analyze7-3.5 {
    execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123}
  } {/*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 t1 USING INDEX t1cd (c=? AND d=?)*/}

finish_test
Changes to test/analyze8.test.
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# 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=?)*/}
do_test 1.2 {
  eqp {SELECT * FROM t1 WHERE a=99 AND b=55}
} {/*SEARCH TABLE 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=?)*/}
do_test 1.4 {
  eqp {SELECT * FROM t1 WHERE a=100 AND b=56}
} {/*SEARCH TABLE 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=?)*/}
do_test 1.6 {
  eqp {SELECT * FROM t1 WHERE a=101 AND b=56}
} {/*SEARCH TABLE 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<?)*/}

# 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<?)*/}
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<?)*/}
do_test 3.3 {
  eqp {SELECT * FROM t1 WHERE a=100 AND c BETWEEN 0 AND 100000}
} {/*SEARCH TABLE 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<?)*/}

finish_test







|


|


|


|


|


|


|



















|



|


|



|


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# 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 t1 USING INDEX t1b (b=?)*/}
do_test 1.2 {
  eqp {SELECT * FROM t1 WHERE a=99 AND b=55}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 1.3 {
  eqp {SELECT * FROM t1 WHERE a=101 AND b=55}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 1.4 {
  eqp {SELECT * FROM t1 WHERE a=100 AND b=56}
} {/*SEARCH t1 USING INDEX t1b (b=?)*/}
do_test 1.5 {
  eqp {SELECT * FROM t1 WHERE a=99 AND b=56}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 1.6 {
  eqp {SELECT * FROM t1 WHERE a=101 AND b=56}
} {/*SEARCH t1 USING INDEX t1a (a=?)*/}
do_test 2.1 {
  eqp {SELECT * FROM t1 WHERE a=100 AND b BETWEEN 50 AND 54}
} {/*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 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 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 t1 USING INDEX t1a (a=?)*/}
do_test 3.4 {
  eqp {SELECT * FROM t1
       WHERE a=100 AND c BETWEEN 800000 AND 900000}
} {/*SEARCH t1 USING INDEX t1c (c>? AND c<?)*/}

finish_test
Changes to test/analyze9.test.
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
    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/}
do_eqp_test 13.2.2 {
  SELECT * FROM t1 WHERE a='abc' AND rowid<'15' AND b<12
} {/SEARCH TABLE 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/}
do_eqp_test 13.3.2 {
  SELECT * FROM t1 WHERE a='abc' AND rowid<'100' AND b<12
} {/SEARCH TABLE 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







|


|


|


|







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 t1 USING INDEX i1/}
do_eqp_test 13.2.2 {
  SELECT * FROM t1 WHERE a='abc' AND rowid<'15' AND b<12
} {/SEARCH t1 USING INDEX i1/}
do_eqp_test 13.3.1 {
  SELECT * FROM t1 WHERE a='abc' AND rowid<100 AND b<12
} {/SEARCH t1 USING INDEX i2/}
do_eqp_test 13.3.2 {
  SELECT * FROM t1 WHERE a='abc' AND rowid<'100' AND b<12
} {/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
    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/}
do_eqp_test 13.2.2 {
  SELECT * FROM t1 WHERE a='ott' AND b<'10' AND c=1
} {/SEARCH TABLE 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} {







|


|







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 t1 USING INDEX i1/}
do_eqp_test 13.2.2 {
  SELECT * FROM t1 WHERE a='ott' AND b<'10' AND c=1
} {/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

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<?)}
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<?)}

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 







|



|







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 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 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
    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<?)}
  do_eqp_test 25.2.2 { SELECT * FROM t6 WHERE a<20 AND b<? } \
    {SEARCH TABLE 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<?)}
  
  # 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<?)}

  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<?)}
}

#-------------------------------------------------------------------------
# Check that a problem in they way stat4 data is used has been 
# resolved (see below).
#
reset_db







|

|




|






|



|







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 t6 USING INDEX bb (b<?)}
  do_eqp_test 25.2.2 { SELECT * FROM t6 WHERE a<20 AND b<? } \
    {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 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 t6 USING INDEX aa (a<?)}

  do_eqp_test 25.4.2 { 
    SELECT * FROM t6 WHERE a < 20 AND (b BETWEEN ? AND 60)
  } {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
# 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=?)}


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







|







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 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
    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>?)}


finish_test







|



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 t1 USING INDEX i1 (x=? AND y>?)}


finish_test
Changes to test/analyzeC.test.
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
} {/.* 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.*/}
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.







|







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 t1 USING INDEX t1a.*/}
do_execsql_test 1.3x {
  EXPLAIN QUERY PLAN
  SELECT c FROM t1 ORDER BY a;
} {~/.*B-TREE FOR ORDER BY.*/}

# Now mark the t1a index as "unordered".  Range queries and ORDER BY no
# longer use the index, but equality queries do.
Changes to test/analyzeD.test.
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
} {}

# 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=?)}

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=?)}

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=?)}

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=?)}

finish_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
} {}

# 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 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 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 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 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
  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/}
do_execsql_test analyzeE-1.2 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000;
} {/SEARCH TABLE 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/}
do_execsql_test analyzeE-1.4 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 1 AND 500
} {/SEARCH TABLE 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/}
do_execsql_test analyzeE-1.6 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<500
} {/SEARCH TABLE 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/}
do_execsql_test analyzeE-1.8 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1900
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.9 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1100
} {/SCAN TABLE t1/}
do_execsql_test analyzeE-1.10 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1100
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.11 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1900
} {/SCAN TABLE 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/}
do_execsql_test analyzeE-2.2 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000;
} {/SEARCH TABLE 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/}
do_execsql_test analyzeE-2.4 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 1 AND 500
} {/SEARCH TABLE 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/}
do_execsql_test analyzeE-2.6 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<500
} {/SEARCH TABLE 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/}
do_execsql_test analyzeE-2.8 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1900
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.9 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1100
} {/SCAN TABLE t1/}
do_execsql_test analyzeE-2.10 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1100
} {/SEARCH TABLE t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.11 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1900
} {/SCAN TABLE 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/}
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/}
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/}
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/}
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/}
do_execsql_test analyzeE-3.6 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<500 AND c=123
} {/SEARCH TABLE 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/}
do_execsql_test analyzeE-3.8 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1900 AND c=123
} {/SEARCH TABLE 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/}
do_execsql_test analyzeE-3.10 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1100 AND c=123
} {/SEARCH TABLE 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/}

# 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/}
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/}
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/}
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/}
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/}
do_execsql_test analyzeE-4.6 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<500 AND c=123
} {/SEARCH TABLE 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/}
do_execsql_test analyzeE-4.8 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1900 AND c=123
} {/SEARCH TABLE 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/}
do_execsql_test analyzeE-4.10 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1100 AND c=123
} {/SEARCH TABLE 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/}

finish_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
  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 t1/}
do_execsql_test analyzeE-1.2 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000;
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.3 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750;
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.4 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 1 AND 500
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.5 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.6 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<500
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.7 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>2500
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.8 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1900
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.9 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1100
} {/SCAN t1/}
do_execsql_test analyzeE-1.10 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1100
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-1.11 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1900
} {/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 t1/}
do_execsql_test analyzeE-2.2 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000;
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.3 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 1700 AND 1750;
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.4 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 1 AND 500
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.5 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 3000 AND 3000000
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.6 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<500
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.7 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>2500
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.8 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1900
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.9 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1100
} {/SCAN t1/}
do_execsql_test analyzeE-2.10 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1100
} {/SEARCH t1 USING INDEX t1a/}
do_execsql_test analyzeE-2.11 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1900
} {/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 t1/}
do_execsql_test analyzeE-3.2 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000 AND c=123;
} {/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 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 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 t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.6 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<500 AND c=123
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.7 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>2500 AND c=123
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.8 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1900 AND c=123
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.9 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1100 AND c=123
} {/SCAN t1/}
do_execsql_test analyzeE-3.10 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1100 AND c=123
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-3.11 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1900 AND c=123
} {/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 t1/}
do_execsql_test analyzeE-4.2 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a BETWEEN 2900 AND 3000 AND c=123;
} {/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 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 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 t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.6 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<500 AND c=123
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.7 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>2500 AND c=123
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.8 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1900 AND c=123
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.9 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a>1100 AND c=123
} {/SCAN t1/}
do_execsql_test analyzeE-4.10 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1100 AND c=123
} {/SEARCH t1 USING INDEX t1ca/}
do_execsql_test analyzeE-4.11 {
  EXPLAIN QUERY PLAN
  SELECT * FROM t1 WHERE a<1900 AND c=123
} {/SCAN t1/}

finish_test
Changes to test/analyzeF.test.
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"
  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)







|







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 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
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"
  do_eqp_test 3.$tn "SELECT * FROM t1 WHERE $where" $res
}


execsql { DELETE FROM t1 }

proc throw_error {err} { error $err }







|







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 t1 USING INDEX $idx"
  do_eqp_test 3.$tn "SELECT * FROM t1 WHERE $where" $res
}


execsql { DELETE FROM t1 }

proc throw_error {err} { error $err }
Changes to test/analyzeG.test.
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

ifcapable !stat4 {
  finish_test
  return
}
set testprefix analyzeG

proc do_scan_order_test {tn sql expect} {
  uplevel [list do_test $tn [subst -nocommands {
    set res ""
    db eval "explain query plan $sql" {
      lappend res [set detail]
    }
    set res
  }] [list {*}$expect]]
}

#-------------------------------------------------------------------------
# Test cases 1.* seek to verify that even if an index is not used, its
# stat4 data may be used by the planner to estimate the number of
# rows that match an unindexed constraint on the same column.
#
do_execsql_test 1.0 {
  PRAGMA automatic_index = 0;







<
<
<
<
<
<
<
<
<
<







16
17
18
19
20
21
22










23
24
25
26
27
28
29

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;
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

65

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

79

80
81
82
83

84

85
86
87
88
}

# Join tables t1 and t2. Both contain 100 rows. (a=44) matches 2 rows
# in "t1", (b=44) matches 95 rows in table "t2". But the planner doesn't
# know this, so it has no preference as to which order the tables are
# scanned in. In practice this means that tables are scanned in the order
# they are specified in in the FROM clause.
do_scan_order_test 1.1.1 {
  SELECT * FROM t1, t2 WHERE a=44 AND b=44;
} {
  {SCAN TABLE t1} {SCAN TABLE t2}
}
do_scan_order_test 1.1.2 {
  SELECT * FROM t2, t1 WHERE a=44 AND b=44 
} {

  {SCAN TABLE t2} {SCAN TABLE t1} 

}

do_execsql_test 1.2 {
  CREATE INDEX t2b ON t2(b);
  ANALYZE;
}

# Now, with the ANALYZE data, the planner knows that (b=44) matches a 
# large number of rows. So it elects to scan table "t1" first, regardless
# of the order in which the tables are specified in the FROM clause.
do_scan_order_test 1.3.1 {
  SELECT * FROM t1, t2 WHERE a=44 AND b=44;
} {

  {SCAN TABLE t1} {SCAN TABLE t2}

}
do_scan_order_test 1.3.2 {
  SELECT * FROM t2, t1 WHERE a=44 AND b=44 
} {

  {SCAN TABLE t1} {SCAN TABLE t2} 

}


finish_test







|


|

|


>
|
>










|


>
|
>

|


>
|
>




40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
}

# Join tables t1 and t2. Both contain 100 rows. (a=44) matches 2 rows
# in "t1", (b=44) matches 95 rows in table "t2". But the planner doesn't
# know this, so it has no preference as to which order the tables are
# scanned in. In practice this means that tables are scanned in the order
# they are specified in in the FROM clause.
do_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/attach4.test.
131
132
133
134
135
136
137
138
}

do_execsql_test 2.2 {
  DROP TRIGGER tr1;
}

finish_test








<
131
132
133
134
135
136
137

}

do_execsql_test 2.2 {
  DROP TRIGGER tr1;
}

finish_test

Changes to test/autoindex1.test.
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  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 xxxxxx
     `--SCAN TABLE 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 xxxxxx
     `--SEARCH TABLE 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 xxxxxx
     `--SCAN TABLE 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.







|

|






|

|







|

|







179
180
181
182
183
184
185
186
187
188
189
190
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 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 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 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
           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 xxxxxx
  |     `--SEARCH TABLE flock_owner AS later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date<?)
  |--SCAN TABLE sheep AS x USING INDEX sheep_reg_flock_index
  `--SEARCH SUBQUERY xxxxxx AS y USING AUTOMATIC COVERING INDEX (sheep_no=?)
}


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







|
|
|

|
|
|










|







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 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=?)
}


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

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







|







|







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 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 data .*SEARCH raw_contacts/}

# Another test case from an important user of SQLite.  The key feature of
# this test is that the "aggindex" subquery should make use of an
# automatic index.  If it does, the query is fast.  If it does not, the
# query is deathly slow.  It worked OK in 3.7.17 but started going slow
# with version 3.8.0.  The problem was fixed for 3.8.7 by reducing the
# cost estimate for automatic indexes on views and subqueries.
Changes to test/autoindex3.test.
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

  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=?)
#
# 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=?)
}


finish_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

  DROP TABLE IF EXISTS sqlite_stat4;
  ANALYZE sqlite_master;
}

# At one point, SQLite was using the inferior plan:
#
#   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 v USING INDEX ve (e>?)
  `--SEARCH u USING AUTOMATIC COVERING INDEX (b=?)
}


finish_test
Changes to test/autoindex5.test.
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  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=?)}

#-------------------------------------------------------------------------
# Test that ticket [8a2adec1] has been fixed.
#
do_execsql_test 2.1 {
  CREATE TABLE one(o);
  INSERT INTO one DEFAULT VALUES;

  CREATE TABLE t1(x, z);
  INSERT INTO t1 VALUES('aaa', 4.0);
  INSERT INTO t1 VALUES('aaa', 4.0);
  CREATE VIEW vvv AS
    SELECT * FROM t1
    UNION ALL
    SELECT 0, 0 WHERE 0;

  SELECT (
      SELECT sum(z) FROM vvv WHERE x='aaa'
  ) FROM one;
} {8.0}
do_execsql_test 2.2 {
  DROP TABLE t1;
  CREATE TABLE t1(aaa);
  INSERT INTO t1(aaa) VALUES(9);
  SELECT (
    SELECT aaa FROM t1 GROUP BY (
      SELECT bbb FROM (
        SELECT ccc AS bbb FROM (
           SELECT 1 ccc
        ) WHERE rowid IS NOT 1
      ) WHERE bbb = 1
    )
  );
} {9}

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







|




















|












|







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  WHERE
     sp.rowid = st.package
     AND st.bug_name = bugs.name
     AND ( st.bug_name LIKE 'CVE-%' OR st.bug_name LIKE 'TEMP-%' )
     AND ( sp.release = 'sid' OR sp.release = 'stretch' OR sp.release = 'jessie'
            OR sp.release = 'wheezy' OR sp.release = 'squeeze' )
  ORDER BY sp.name, st.bug_name, sp.release, sp.subrelease;
} {SEARCH debian_cve USING AUTOMATIC COVERING INDEX (bug_name=?)}

#-------------------------------------------------------------------------
# Test that ticket [8a2adec1] has been fixed.
#
do_execsql_test 2.1 {
  CREATE TABLE one(o);
  INSERT INTO one DEFAULT VALUES;

  CREATE TABLE t1(x, z);
  INSERT INTO t1 VALUES('aaa', 4.0);
  INSERT INTO t1 VALUES('aaa', 4.0);
  CREATE VIEW vvv AS
    SELECT * FROM t1
    UNION ALL
    SELECT 0, 0 WHERE 0;

  SELECT (
      SELECT sum(z) FROM vvv WHERE x='aaa'
  ) FROM one;
} {8.0}
do_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
    )
  );
} {1 {no such column: rowid}}

# Ticket https://www.sqlite.org/src/info/787fa716be3a7f65
# Segfault due to multiple uses of the same subquery where the
# subquery is implemented via coroutine.
#
ifcapable windowfunc {
sqlite3 db :memory:
Changes to test/bestindex1.test.
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

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

do_eqp_test 1.2 {
  SELECT * FROM x1 WHERE a IN ('abc', 'def');
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}

#-------------------------------------------------------------------------
#
reset_db
register_tcl_module db

# Parameter $mode may be one of:







|



|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE x1 USING tcl(vtab_command);
} {}

do_eqp_test 1.1 {
  SELECT * FROM x1 WHERE a = 'abc'
} {SCAN x1 VIRTUAL TABLE INDEX 555:eq!}

do_eqp_test 1.2 {
  SELECT * FROM x1 WHERE a IN ('abc', 'def');
} {SCAN x1 VIRTUAL TABLE INDEX 555:eq!}

#-------------------------------------------------------------------------
#
reset_db
register_tcl_module db

# Parameter $mode may be one of:
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

  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%'
    `--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%'
    `--USE TEMP B-TREE FOR ORDER BY
  }
  set plan(use2) {
    QUERY PLAN
    |--SCAN TABLE 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)]
}







|




|




|







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

  do_execsql_test 2.2.$mode.5 {
    SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid
  } {1 4} 

  set plan(use) {
    QUERY PLAN
    |--SCAN t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
    `--USE TEMP B-TREE FOR ORDER BY
  }
  set plan(omit) {
    QUERY PLAN
    |--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 t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x
    `--USE TEMP B-TREE FOR ORDER BY
  }

  do_eqp_test 2.2.$mode.6 { 
    SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid
  } [string map {"\n  " "\n"} $plan($mode)]
}
Changes to test/bestindex2.test.
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  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=?)}

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=?)}

do_eqp_test 1.3 {
  SELECT * FROM t1 WHERE a='abc' AND a='def'
} {SCAN TABLE 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=?)
}

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=?)
}

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=?)
}

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=?)
}

finish_test







|



|



|





|
|






|
|
|






|
|
|










|
|
|
|



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  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 t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}

do_eqp_test 1.2 {
  SELECT * FROM t1 WHERE a='abc' AND b='def'
} {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 t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}

do_eqp_test 1.4 {
  SELECT * FROM t1,t2 WHERE c=a
} {
  QUERY PLAN
  |--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 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 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 x1
  |--SCAN t1 VIRTUAL TABLE INDEX 0:
  |--SCAN t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
  `--SCAN t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
}

finish_test
Changes to test/bestindex3.test.
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

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

do_eqp_test 1.2 {
  SELECT * FROM t1 WHERE a = 'abc';
} {SCAN TABLE 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 ?
     `--INDEX 2
        `--SCAN TABLE 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 ?
     `--INDEX 2
        `--SCAN TABLE 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');







|



|







|

|








|

|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

do_execsql_test 1.0 {
  CREATE VIRTUAL TABLE t1 USING tcl("vtab_cmd 0");
}

do_eqp_test 1.1 {
  SELECT * FROM t1 WHERE a LIKE 'abc';
} {SCAN t1 VIRTUAL TABLE INDEX 0:a LIKE ?}

do_eqp_test 1.2 {
  SELECT * FROM t1 WHERE a = 'abc';
} {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 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 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');
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

  do_eqp_test 2.2 {
    SELECT * FROM t2 WHERE x LIKE 'abc%' OR y = 'def'
  } [string map {"\n  " \n} {
    QUERY PLAN
    `--MULTI-INDEX OR
       |--INDEX 1
       |  `--SEARCH TABLE t2 USING INDEX t2x (x>? AND x<?)
       `--INDEX 2
          `--SEARCH TABLE t2 USING INDEX t2y (y=?)
  }]
}

#-------------------------------------------------------------------------
# Test that any PRIMARY KEY within a sqlite3_decl_vtab() CREATE TABLE 
# statement is currently ignored.
#







|

|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

  do_eqp_test 2.2 {
    SELECT * FROM t2 WHERE x LIKE 'abc%' OR y = 'def'
  } [string map {"\n  " \n} {
    QUERY PLAN
    `--MULTI-INDEX OR
       |--INDEX 1
       |  `--SEARCH 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.
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
  CREATE TABLE t1 (x INT PRIMARY KEY);
} {}

do_eqp_test 2.1 {
  SELECT * FROM t1, x1 WHERE x1.d=t1.x;
} {
  QUERY PLAN
  |--SCAN TABLE x1 VIRTUAL TABLE INDEX 0:
  `--SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (x=?)
}

do_eqp_test 2.2 {
  SELECT * FROM t1, x1(t1.x)
} {
  QUERY PLAN
  |--SCAN TABLE t1
  `--SCAN TABLE x1 VIRTUAL TABLE INDEX 555:
}


finish_test







|
|






|
|




155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
  CREATE TABLE t1 (x INT PRIMARY KEY);
} {}

do_eqp_test 2.1 {
  SELECT * FROM t1, x1 WHERE x1.d=t1.x;
} {
  QUERY PLAN
  |--SCAN 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 t1
  `--SCAN x1 VIRTUAL TABLE INDEX 555:
}


finish_test
Changes to test/bestindex7.test.
72
73
74
75
76
77
78
79
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








<
72
73
74
75
76
77
78

do_execsql_test 1.9 { select * from vt1 WHERE a=1 OR a=0} {0}
do_execsql_test 1.10 { select * from vt1 WHERE a IN (2) } {}
do_execsql_test 1.10 { select * from vt1 WHERE a IN (0,1,2,3) } {0}
do_execsql_test 1.11 { select * from vt1 WHERE a IN (0, NULL) } {0}
do_execsql_test 1.12 { select * from vt1 WHERE a IN (NULL) } {}

finish_test

Changes to test/between.test.
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
  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]} {
      lappend data $tab $idx
    } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} {
      lappend data $tab *
    }
  }
  return $data   
}

do_test between-1.1.1 {







|
|

|







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 {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
        $x all ss as tab idx]} {
      lappend data $tab $idx
    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+)\y} $x all ss as tab]} {
      lappend data $tab *
    }
  }
  return $data   
}

do_test between-1.1.1 {
Changes to test/bigmmap.test.
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
    
    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 xxxxxx
         `--SEARCH TABLE t$t AS i USING INTEGER PRIMARY KEY (rowid=?)
    "]
  }
}

finish_test







|

|





90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
    
    do_eqp_test 2.$i.$t.3 "
      SELECT * FROM t$t AS o WHERE 
        NOT EXISTS( SELECT * FROM t$t AS i WHERE a=o.a AND +b=o.b AND +c=o.c )
      ORDER BY b, c;
    " [string map {"\n    " "\n"} "
      QUERY PLAN
      |--SCAN 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/busy2.test.
164
165
166
167
168
169
170
171
    set ::busy_called 0
    list [catch { sql1 { SELECT * FROM t1 } } msg] $::busy_called
  } {1 1}

}

finish_test








<
164
165
166
167
168
169
170

    set ::busy_called 0
    list [catch { sql1 { SELECT * FROM t1 } } msg] $::busy_called
  } {1 1}

}

finish_test

Changes to test/columncount.test.
50
51
52
53
54
55
56
57
do_ccsql_test 1.5 { ALTER TABLE t3 ADD COLUMN d } {0}

do_ccsql_test 1.6 { DROP TABLE t3 } {0}



finish_test








<
50
51
52
53
54
55
56

do_ccsql_test 1.5 { ALTER TABLE t3 ADD COLUMN d } {0}

do_ccsql_test 1.6 { DROP TABLE t3 } {0}



finish_test

Changes to test/corrupt4.test.
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
#
#***********************************************************************
# 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


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







<



>







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


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




































































finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
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/corruptL.test.
1333
1334
1335
1336
1337
1338
1339
























































































1340
1341
  } {1 {database disk image is malformed}}
  
  do_test 17.3 {
    close $fd
  } {}
}


























































































finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
  } {1 {database disk image is malformed}}
  
  do_test 17.3 {
    close $fd
  } {}
}

#-------------------------------------------------------------------------
reset_db
do_test 18.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 12288 pagesize 4096 filename crash-40d5739835cbdb.db
| page 1 offset 0
|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.
|     16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 00   .....@  ........
|     96: 00 00 00 00 0d 00 00 00 02 0f 4e 00 0f a2 0f 4e   ..........N....N
|   3904: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 52 02   ..............R.
|   3920: 07 17 11 11 01 81 0f 74 61 62 6c 65 74 32 74 32   .......tablet2t2
|   3936: 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 32   .CREATE TABLE t2
|   3952: 28 61 20 49 4e 54 2c 20 62 20 49 4e 54 45 47 45   (a INT, b INTEGE
|   3968: 52 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 61   R, PRIMARY KEY(a
|   3984: 2c 62 29 29 20 57 49 54 48 4f 55 54 20 52 4f 57   ,b)) WITHOUT ROW
|   4000: 49 44 5c 01 07 16 11 11 01 81 23 74 61 62 6c 65   ID........#table
|   4016: 74 31 74 31 02 43 52 45 41 54 45 20 54 41 42 4c   t1t1.CREATE TABL
|   4032: 45 20 74 31 28 61 20 49 4e 54 20 50 52 49 4d 41   E t1(a INT PRIMA
|   4048: 52 59 20 4b 45 59 2c 20 62 20 54 45 58 54 2c 20   RY KEY, b TEXT, 
|   4064: 63 20 54 45 58 54 2c 20 64 20 49 4e 54 45 47 45   c TEXT, d INTEGE
|   4080: 52 29 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44   R) WITHOUT ROWID
| page 2 offset 4096
|      0: 0a 00 00 00 06 0f a7 00 0f f4 0f e5 0f d5 0f c5   ................
|     16: 0f b6 0f 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   4000: 00 00 00 00 00 00 00 0f 05 01 15 13 01 06 65 7f   ..............e.
|   4016: 25 6e 73 69 78 06 0e 05 01 13 15 03 b5 6f 64 64   %nsix........odd
|   4032: 66 69 76 65 05 0f 05 01 15 15 01 04 65 76 65 61   five........evea
|   4048: e6 6f 75 82 04 0f 05 01 13 17 01 03 6f 64 64 74   .ou.........oddt
|   4064: 68 72 61 15 03 0e 05 01 15 12 01 02 64 76 64 6e   hra.........dvdn
|   4080: 74 77 6f 02 00 00 00 00 00 00 00 00 00 00 00 00   two.............
| page 3 offset 8192
|   2816: 00 00 00 00 00 00 00 00 00 00 00 06 03 02 01 00   ................
|   2832: c8 07 06 03 02 01 00 c7 11 06 03 02 01 02 a6 52   ...............R
|   2848: 06 d5 02 01 10 c5 1b 06 03 02 00 ef c4 53 06 03   .............S..
|   2864: 02 01 00 c3 22 06 04 02 01 00 c2 26 06 03 02 01   ...........&....
|   2880: 00 c2 1e 02 b3 02 01 00 c0 3a 06 03 3c 01 00 bf   .........:..<...
|   2896: 2c 06 03 02 01 00 be 27 00 83 02 01 01 bd 15 06   ,......'........
|   2912: 03 02 01 00 bc 21 06 03 02 01 00 bb 54 16 13 02   .....!......T...
|   2928: 01 09 9a 0a 06 03 02 01 00 b9 53 06 03 02 01 00   ..........S.....
|   2944: b8 52 06 13 02 01 00 b7 1e 06 03 02 01 00 b6 34   .R.............4
|   2960: 06 13 02 01 00 b5 3a 05 f3 12 01 00 b4 45 05 03   ......:......E..
|   2976: 02 00 00 b4 6f 06 03 02 01 00 b2 03 06 03 02 01   ....o...........
|   2992: 00 b1 63 06 03 02 01 00 b0 24 06 03 02 01 00 9f   ..c......$......
|   3008: ac 06 03 02 01 00 a2 2f 07 03 02 01 01 ad 21 06   ......./......!.
|   3024: 03 02 01 fb cd 5b 06 c0 01 f1 00 ab 23 06 03 02   .....[......#...
|   3040: 01 00 aa 5b 06 03 02 01 00 a3 ce 06 02 03 01 00   ...[............
|   3056: a8 0e 06 03 02 01 00 a7 0c 06 02 f1 01 00 a6 0d   ................
|   3072: 06 03 02 01 00 95 25 06 03 02 01 00 a4 17 06 03   ......%.........
|   3088: 02 01 00 a3 09 06 03 02 01 00 a2 51 06 03 02 02   ...........Q....
|   3104: 00 a1 40 06 01 e2 00 00 a0 4b 06 13 02 00 00 9e   ..@......K......
|   3120: 5d 06 03 02 01 10 9e 81 06 03 02 01 00 9d 42 06   ].............B.
|   3136: 03 69 01 00 9c 48 06 03 02 01 00 9b 48 06 03 01   .i...H......H...
|   3152: 01 00 9a 09 06 03 02 01 00 99 2f 06 03 02 01 00   ........../.....
|   3168: 98 3a 06 03 02 01 00 97 24 06 03 02 01 00 96 4a   .:......$......J
|   3184: 06 03 02 11 00 f9 50 02 93 02 01 00 94 2f 06 03   ......P....../..
|   3200: 02 11 04 93 1a 06 03 01 04 e0 92 1a 06 03 02 01   ................
|   3216: 00 91 27 06 03 02 01 00 90 23 06 03 02 01 00 8f   ..'......#......
|   3232: 3b 06 03 02 01 00 8e 46 06 16 02 01 00 8d 1d 07   ;......F........
|   3248: 23 12 01 00 8c 5a 06 03 02 01 00 8a 39 06 03 02   #....Z......9...
|   3264: 00 ff 84 b5 06 03 02 01 00 89 07 06 03 02 11 00   ................
|   3280: 88 02 06 03 02 01 00 87 19 06 03 02 01 00 86 4d   ...............M
|   3296: 06 13 12 00 00 85 4b 06 03 02 01 00 84 37 06 13   ......K......7..
|   3312: 02 01 00 83 2c 06 03 02 01 00 81 60 06 13 02 11   ....,......`....
|   3328: 00 81 3b 06 03 02 01 0a b0 5a 06 03 01 01 7f 22   ..;......Z......
|   3344: 05 03 01 01 7e 21 05 03 01 01 7d 0b 15 03 01 02   ....~!..........
|   3360: 7b 08 05 03 06 91 7b 22 05 03 01 01 7a 58 05 03   ............zX..
|   3376: 01 01 7a 4f 05 03 01 01 78 49 05 03 01 01 77 16   ..zO....xI....w.
|   3392: 05 03 01 01 76 5f 05 03 01 01 75 0f 05 03 01 01   ....v_....u.....
|   3408: 74 2f 05 03 01 01 3f 1f 05 03 01 02 72 14 05 03   t/....?.....r...
|   3424: 00 f1 71 08 05 03 01 01 70 0c 05 03 01 47 7f 29   ..q.....p....G.)
|   3440: 05 03 01 01 6e 57 05 03 01 01 6d 33 05 13 00 f1   ....nW....m3....
|   3456: 6c 0b 05 03 01 01 6b 49 05 03 01 01 69 05 05 03   l.....kI....i...
|   3472: 01 02 ed 23 00 00 01 00 00 00 00 00 00 00 00 00   ...#............
| end crash-40d5739835cbdb.db
}]} {}

ifcapable json1 {
do_catchsql_test 18.1 {
  SELECT 
    json_group_array(c) OVER win4 
  FROM t1
    WINDOW win4 AS (
        ORDER BY a COLLATE nocase RANGE BETWEEN 1.0 PRECEDING AND CURRENT ROW
    )
} {1 {JSON cannot hold BLOB values}}
} ;# ifcapable json1

finish_test
Changes to test/corruptN.test.
97
98
99
100
101
102
103




















































































































104
105
106
|    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}}






















































































































finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
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
|    448: ff ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00   ................
| end sql024239.txt.db
}]} {}

do_catchsql_test 1.1 {
  VACUUM;
} {1 {database disk image is malformed}}

# 2021-04-05 dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618
do_test 2.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
| size 16384 pagesize 4096 filename c-b92b.txt.db
| page 1 offset 0
|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.
|     16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 04   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 04   ................
|     48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00   ................
|     96: 00 00 00 00 0d 0f f8 00 04 0f 12 00 0f 91 0f d3   ................
|    112: 0f 67 0f 12 00 00 00 00 00 00 00 00 00 00 00 00   .g..............
|   3856: 00 00 53 04 07 1b 13 11 08 81 0d 74 72 69 67 67   ..S........trigg
|   3872: 65 72 74 72 30 74 31 43 52 45 41 54 45 20 54 52   ertr0t1CREATE TR
|   3888: 49 47 47 45 52 20 74 72 30 20 44 45 4c 45 54 45   IGGER tr0 DELETE
|   3904: 20 4f 4e 20 74 31 20 42 45 47 49 4e 0a 20 20 55    ON t1 BEGIN.  U
|   3920: 50 44 41 54 45 20 74 31 20 53 45 54 20 62 20 3d   PDATE t1 SET b =
|   3936: 20 61 3b 0a 45 4e 44 28 03 06 17 11 11 01 3d 69    a;.END(......=i
|   3952: 6e 64 65 78 69 30 74 31 04 43 52 45 41 54 45 20   ndexi0t1.CREATE 
|   3968: 49 4e 44 45 58 20 69 30 20 4f 4e 20 74 31 28 62   INDEX i0 ON t1(b
|   3984: 29 40 01 06 17 11 11 01 6d 74 61 62 6c 65 74 31   )@......mtablet1
|   4000: 74 31 02 43 52 45 41 54 45 20 54 41 42 4c 45 20   t1.CREATE TABLE 
|   4016: 74 31 28 61 20 55 4e 49 51 55 45 20 4f 4e 20 43   t1(a UNIQUE ON C
|   4032: 4f 4e 46 4c 49 43 54 20 52 45 50 4c 41 43 45 2c   ONFLICT REPLACE,
|   4048: 20 62 29 23 02 06 17 37 11 01 00 69 6e 64 65 78    b)#...7...index
|   4064: 73 71 6c 69 74 65 5f 61 75 74 6f 69 6e 64 65 78   sqlite_autoindex
|   4080: 5f 74 31 5f 31 74 31 03 00 00 00 08 00 00 00 00   _t1_1t1.........
| page 2 offset 4096
|      0: 0d 00 00 00 02 0f 00 00 00 00 00 00 00 00 00 00   ................
|   4080: 00 00 05 02 03 01 01 09 0d 05 01 03 01 01 04 0c   ................
| page 3 offset 8192
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 03 01 01 09 02 04 03 01 09 04   ................
| page 4 offset 12288
|      0: 0a 00 00 00 02 0f f5 00 0f fb 0f f5 00 00 00 00   ................
|   4080: 00 00 00 00 00 05 03 01 01 0d 02 04 03 00 00 00   ................
| end c-b92b.txt.db
}]} {}

prng_seed 0 db
do_catchsql_test 2.1 {
SELECT count(*) FROM sqlite_schema;
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
INSERT INTO t1(a) SELECT randomblob(null) FROM c;
} {1 {database disk image is malformed}}

reset_db
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);
  } {1 {database disk image is malformed}}

}

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

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';
  }

  db close
  sqlite3 db test.db

  do_execsql_test 5.1 {
    PRAGMA writable_schema = 1;
    SELECT * FROM t1
  }
}; # ifcapable json1&&vtab


finish_test
Changes to test/cost.test.
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
  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=?)
}


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}

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=?)
  |  |--INDEX 2
  |  |  `--SEARCH TABLE t5 USING INDEX t5c (c=?)
  |  `--INDEX 3
  |     `--SEARCH TABLE 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=?)}

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<?)}


#-------------------------------------------------------------------------
#
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
  `--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<?)
  `--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<?)
  |  `--INDEX 2
  |     `--SEARCH TABLE t3 USING INDEX t3i2 (c=?)
  `--USE TEMP B-TREE FOR ORDER BY
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 7.1 {







|
|












|



















|

|

|



















|



|














|







|

















|

|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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 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 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 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 t1 USING INDEX i1 (a=?)}

do_eqp_test 4.3 {
  SELECT * FROM t1 WHERE likelihood(a=?, 0.016) AND b BETWEEN ? AND ?;
} {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 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 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 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 {
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  SELECT a FROM t1
     WHERE (b>=950 AND b<=1010) OR (b IS NULL AND c NOT NULL)
  ORDER BY a
} {
  QUERY PLAN
  |--MULTI-INDEX OR
  |  |--INDEX 1
  |  |  `--SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)
  |  `--INDEX 2
  |     `--SEARCH TABLE 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}

do_eqp_test 7.4 {
  SELECT rowid FROM t1 WHERE (+b IS NULL AND c NOT NULL) OR c IS NULL
} {SCAN TABLE t1}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 8.1 {
  CREATE TABLE composer(
    cid INTEGER PRIMARY KEY,







|

|








|



|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  SELECT a FROM t1
     WHERE (b>=950 AND b<=1010) OR (b IS NULL AND c NOT NULL)
  ORDER BY a
} {
  QUERY PLAN
  |--MULTI-INDEX OR
  |  |--INDEX 1
  |  |  `--SEARCH 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 t1}

do_eqp_test 7.4 {
  SELECT rowid FROM t1 WHERE (+b IS NULL AND c NOT NULL) OR c IS NULL
} {SCAN t1}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 8.1 {
  CREATE TABLE composer(
    cid INTEGER PRIMARY KEY,
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  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=?)
  `--USE TEMP B-TREE FOR DISTINCT
}

#-------------------------------------------------------------------------
#
do_execsql_test 9.1 {
  CREATE TABLE t1(







|
|
|







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 track
  |--SEARCH album USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH composer USING INTEGER PRIMARY KEY (rowid=?)
  `--USE TEMP B-TREE FOR DISTINCT
}

#-------------------------------------------------------------------------
#
do_execsql_test 9.1 {
  CREATE TABLE t1(
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
      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=?)}

  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=?)}

  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=?)}

  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=?)}
}

finish_test







|



|



|



|



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 t6 USING INDEX t6i2 (c=?)}

  do_eqp_test 10.4 {
    SELECT rowid FROM t6 WHERE a=0 AND b='xyz' AND c=0
  } {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 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 t6 USING INDEX t6i1 (a=? AND b=?)}
}

finish_test
Changes to test/count.test.
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
  UPDATE sqlite_stat1 SET stat='1000000 10' WHERE idx='t1b';
  ANALYZE sqlite_master;
}
do_eqp_test count-7.2 {
  SELECT count(1) FROM t1;
} {
  QUERY PLAN
  `--SCAN TABLE t1 USING COVERING INDEX t1b
}
do_eqp_test count-7.3 {
  SELECT count(1) FROM t1 NOT INDEXED
} {
  QUERY PLAN
  `--SCAN TABLE t1
}
do_eqp_test count-7.3 {
  SELECT count(*) FROM t1;
} {
  QUERY PLAN
  `--SCAN TABLE t1 USING COVERING INDEX t1b
}
do_eqp_test count-7.4 {
  SELECT count(*) FROM t1 NOT INDEXED
} {
  QUERY PLAN
  `--SCAN TABLE t1
}


finish_test







|





|





|





|




208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
  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
}


finish_test
Changes to test/coveridxscan.test.
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}

do_eqp_test 5.1.2 {
  SELECT * FROM t2 ORDER BY c1, c2;
} {SCAN TABLE t2 USING COVERING INDEX i2}


finish_test







|



|



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 t1 USING COVERING INDEX i1}

do_eqp_test 5.1.2 {
  SELECT * FROM t2 ORDER BY c1, c2;
} {SCAN t2 USING COVERING INDEX i2}


finish_test
Changes to test/dbfuzz2.c.
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
**
** 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 \
**       -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>







|
<







27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
**
** 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 -DTHREADSAFE=0 \

**       -DSQLITE_ENABLE_DBSTAT_VTAB dbfuzz2.c sqlite3.c -ldl
**     ./a.out dir
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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
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 }
  }
  db eval "EXPLAIN $sql2" {
    if {$opcode != "Noop"} { 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} {







|


|

<







26
27
28
29
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
proc is_distinct_noop {sql} {
  set sql1 $sql
  set sql2 [string map {DISTINCT ""} $sql]

  set program1 [list]
  set program2 [list]
  db eval "EXPLAIN $sql1" {
    if {$opcode != "Noop" && $opcode != "Explain"} { lappend program1 $opcode }
  }
  db eval "EXPLAIN $sql2" {
    if {$opcode != "Noop" && $opcode != "Explain"} { lappend program2 $opcode }
  }

  return [expr {$program1==$program2}]
}

proc do_distinct_noop_test {tn sql} {
  uplevel [list do_test $tn [list is_distinct_noop $sql] 1]
}
proc do_distinct_not_noop_test {tn sql} {
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

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







<







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


  24  0   "SELECT DISTINCT rowid/2 FROM t1"
  25  1   "SELECT DISTINCT rowid/2, rowid FROM t1"
  26.1  0   "SELECT DISTINCT rowid/2, b FROM t1 WHERE c = ?"
  26.2  1   "SELECT DISTINCT rowid/2, b FROM t4 WHERE c = ?"
} {
  if {$noop} {
289
290
291
292
293
294
295
296









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










finish_test








>
>
>
>
>
>
>
>
>

287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
  WITH t2(b) AS (
    SELECT DISTINCT y FROM t5 ORDER BY y
  )
  SELECT * FROM 
    t4 CROSS JOIN t3 CROSS JOIN t1 
  WHERE (t1.a=t3.a) AND (SELECT count(*) FROM t2 AS y WHERE t4.x!='abc')=t1.a
} {2 2 2}

# 2021-04-06 forum post https://sqlite.org/forum/forumpost/66954e9ece
reset_db
do_execsql_test 8.0 {
  CREATE TABLE person ( pid INT) ;
  CREATE UNIQUE INDEX idx ON person ( pid ) WHERE pid == 1;
  INSERT INTO person VALUES (1), (10), (10);
  SELECT DISTINCT pid FROM person where pid = 10;
} {10}

finish_test
Changes to test/distinctagg.test.
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 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


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
  }
} {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;







>















|







12
13
14
15
16
17
18
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
  }
} {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

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


























































































































































finish_test









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
  }
} {1 {DISTINCT aggregates must have exactly one argument}}
do_test distinctagg-2.2 {
  catchsql {
    SELECT group_concat(distinct a,b) FROM t1;
  }
} {1 {DISTINCT aggregates must have exactly one argument}}

#--------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(a, b, c);
  CREATE TABLE t2(d, e, f);

  INSERT INTO t1 VALUES (1, 1, 1);
  INSERT INTO t1 VALUES (2, 2, 2);
  INSERT INTO t1 VALUES (3, 3, 3);
  INSERT INTO t1 VALUES (4, 1, 4);
  INSERT INTO t1 VALUES (5, 2, 1);
  INSERT INTO t1 VALUES (5, 3, 2);
  INSERT INTO t1 VALUES (4, 1, 3);
  INSERT INTO t1 VALUES (3, 2, 4);
  INSERT INTO t1 VALUES (2, 3, 1);
  INSERT INTO t1 VALUES (1, 1, 2);

  INSERT INTO t2 VALUES('a', 'a', 'a');
  INSERT INTO t2 VALUES('b', 'b', 'b');
  INSERT INTO t2 VALUES('c', 'c', 'c');

  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t1bc ON t1(b, c);
}

foreach {tn use_eph sql res} {
  1  0  "SELECT count(DISTINCT a) FROM t1"                5
  2  0  "SELECT count(DISTINCT b) FROM t1"                3
  3  1  "SELECT count(DISTINCT c) FROM t1"                4
  4  0  "SELECT count(DISTINCT c) FROM t1 WHERE b=3"      3
  5  0  "SELECT count(DISTINCT rowid) FROM t1"           10
  6  0  "SELECT count(DISTINCT a) FROM t1, t2"            5
  7  0  "SELECT count(DISTINCT a) FROM t2, t1"            5
  8  1  "SELECT count(DISTINCT a+b) FROM t1, t2, t2, t2"  6
  9  0  "SELECT count(DISTINCT c) FROM t1 WHERE c=2"      1
 10  1  "SELECT count(DISTINCT t1.rowid) FROM t1, t2"    10
} {
  do_test 3.$tn.1 {
    set prg [db eval "EXPLAIN $sql"]
    set idx [lsearch $prg OpenEphemeral]
    expr {$idx>=0}
  } $use_eph

  do_execsql_test 3.$tn.2 $sql $res
}

do_execsql_test 3.10 {
  SELECT a, count(DISTINCT b) FROM t1 GROUP BY a;
} {
  1 1  2 2  3 2  4 1  5 2
}

#--------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(a, b, c);
  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t1bc ON t1(b, c);

  INSERT INTO t1 VALUES(1, 'A', 1);
  INSERT INTO t1 VALUES(1, 'A', 1);
  INSERT INTO t1 VALUES(2, 'A', 2);
  INSERT INTO t1 VALUES(2, 'A', 2);
  INSERT INTO t1 VALUES(1, 'B', 1);
  INSERT INTO t1 VALUES(2, 'B', 2);
  INSERT INTO t1 VALUES(3, 'B', 3);
  INSERT INTO t1 VALUES(NULL, 'B', NULL);
  INSERT INTO t1 VALUES(NULL, 'C', NULL);
  INSERT INTO t1 VALUES('d', 'D', 'd');

  CREATE TABLE t2(d, e, f);
  CREATE INDEX t2def ON t2(d, e, f);

  INSERT INTO t2 VALUES(1, 1, 'a');
  INSERT INTO t2 VALUES(1, 1, 'a');
  INSERT INTO t2 VALUES(1, 2, 'a');
  INSERT INTO t2 VALUES(1, 2, 'a');
  INSERT INTO t2 VALUES(1, 2, 'b');
  INSERT INTO t2 VALUES(1, 3, 'b');
  INSERT INTO t2 VALUES(1, 3, 'a');
  INSERT INTO t2 VALUES(1, 3, 'b');
  INSERT INTO t2 VALUES(2, 3, 'x');
  INSERT INTO t2 VALUES(2, 3, 'y');
  INSERT INTO t2 VALUES(2, 3, 'z');

  CREATE TABLE t3(x, y, z);
  INSERT INTO t3 VALUES(1,1,1);
  INSERT INTO t3 VALUES(2,2,2);
}

foreach {tn use_eph sql res} {
  1 0  "SELECT count(DISTINCT c) FROM t1 GROUP BY b"   {2 3 0 1}
  2 1  "SELECT count(DISTINCT a) FROM t1 GROUP BY b"   {2 3 0 1}
  3 1  "SELECT count(DISTINCT a) FROM t1 GROUP BY b+c" {0 1 1 1 1}

  4 0  "SELECT count(DISTINCT f) FROM t2 GROUP BY d, e" {1 2 2 3}
  5 1  "SELECT count(DISTINCT f) FROM t2 GROUP BY d" {2 3}
  6 0  "SELECT count(DISTINCT f) FROM t2 WHERE d IS 1 GROUP BY e" {1 2 2}
} {
  do_test 4.$tn.1 {
    set prg [db eval "EXPLAIN $sql"]
    set idx [lsearch $prg OpenEphemeral]
    expr {$idx>=0}
  } $use_eph

  do_execsql_test 4.$tn.2 $sql $res
}


set t3root [db one {SELECT rootpage FROM sqlite_schema WHERE name='t3'}]
foreach {tn use_t3 sql res} {
  1 1 "SELECT count(*) FROM t3"   2
  2 0 "SELECT count(*) FROM t1"   10
  2 1 "SELECT count(DISTINCT a) FROM t1, t3" 4
  3 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3" 4
  4 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3 WHERE t3.x=1" 4
  5 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3 WHERE t3.x=0" 0
  6 1 "SELECT count(DISTINCT a) FROM t1 LEFT JOIN t3 ON (t3.x=0)"  4
  7 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3" 2
  8 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3 WHERE t3.x=1" 1
  9 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3 WHERE t3.x=0" 0
 10 1 "SELECT count(DISTINCT x) FROM t1 LEFT JOIN t3 ON (t3.x=0)"  0

} {
  do_test 5.$tn.1 {
    set bUse 0
    db eval "EXPLAIN $sql" a {
      if {$a(opcode)=="OpenRead" && $a(p2)==$t3root} {set bUse 1}
    }
    set bUse
  } $use_t3

  do_execsql_test 5.$tn.2 $sql $res
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 6.0 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c, d);
  INSERT INTO t1 VALUES(123,456);
  INSERT INTO t2 VALUES(123,456);
}
do_execsql_test 6.1 {
  SELECT count(DISTINCT c) FROM t1 LEFT JOIN t2;
} {1}

do_execsql_test 7.0 {
  CREATE TABLE v1 ( v2 UNIQUE, v3 AS( TYPEOF ( NULL ) ) UNIQUE ); 
  SELECT COUNT ( DISTINCT TRUE ) FROM v1 GROUP BY likelihood ( v3 , 0.100000 );
}


finish_test

Changes to test/e_createtable.test.
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
#
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=?)*/}

  2    "EXPLAIN QUERY PLAN SELECT * FROM t2 ORDER BY b, c"
       {/*SCAN TABLE 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>?)*/}
}

# 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 







|


|


|







1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
#
do_execsql_test 4.10.0 {
  CREATE TABLE t1(a, b PRIMARY KEY);
  CREATE TABLE t2(a, b, c, UNIQUE(b, c));
}
do_createtable_tests 4.10 {
  1    "EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b = 5" 
       {/*SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (b=?)*/}

  2    "EXPLAIN QUERY PLAN SELECT * FROM t2 ORDER BY b, c"
       {/*SCAN t2 USING INDEX sqlite_autoindex_t2_1*/}

  3    "EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE b=10 AND c>10"
       {/*SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (b=? AND c>?)*/}
}

# EVIDENCE-OF: R-45493-35653 A CHECK constraint may be attached to a
# column definition or specified as a table constraint. In practice it
# makes no difference.
#
#   All the tests that deal with CHECK constraints below (4.11.* and 
Changes to test/e_fkey.test.
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
  }
} {}
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}
}
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}
}
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);







|
|





|
|







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 artist} 
  {SCAN track}
}
do_detail_test e_fkey-25.3 {
  PRAGMA foreign_keys = ON;
  EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1;
} {
  {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
} {}
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=?)}
}
do_detail_test e_fkey-27.4 {
  EXPLAIN QUERY PLAN DELETE FROM artist
} {
  {SCAN TABLE artist} 
  {SEARCH TABLE track USING COVERING INDEX trackindex (trackartist=?)}
}

###########################################################################
### SECTION 4.1: Composite Foreign Key Constraints
###########################################################################

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







|
|
|




|
|







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 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 artist} 
  {SEARCH track USING COVERING INDEX trackindex (trackartist=?)}
}

###########################################################################
### SECTION 4.1: Composite Foreign Key Constraints
###########################################################################

#-------------------------------------------------------------------------
Changes to test/eqp.test.
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101




















102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617

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=?)
  |  `--INDEX 2
  |     `--SEARCH TABLE t1 USING INDEX i2 (b=?)
  `--SCAN TABLE 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
  `--MULTI-INDEX OR
     |--INDEX 1
     |  `--SEARCH TABLE t1 USING INDEX i1 (a=?)
     `--INDEX 2
        `--SEARCH TABLE 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
}
do_eqp_test 1.4 {
  SELECT a FROM t1 ORDER BY +a
} {
  QUERY PLAN
  |--SCAN TABLE 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=?)
}
do_eqp_test 1.6 {
  SELECT DISTINCT count(*) FROM t3 GROUP BY a;
} {
  QUERY PLAN
  |--SCAN TABLE t3
  |--USE TEMP B-TREE FOR GROUP BY
  `--USE TEMP B-TREE FOR DISTINCT
}

do_eqp_test 1.7 {
  SELECT * FROM t3 JOIN (SELECT 1)
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  `--SCAN CONSTANT ROW
  |--SCAN SUBQUERY xxxxxx
  `--SCAN TABLE t3
}




















do_eqp_test 1.8 {
  SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2)
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  `--COMPOUND QUERY
  |     |--LEFT-MOST SUBQUERY
  |     |  `--SCAN CONSTANT ROW
  |     `--UNION USING TEMP B-TREE
  |        `--SCAN CONSTANT ROW
  |--SCAN SUBQUERY xxxxxx
  `--SCAN TABLE t3
}
do_eqp_test 1.9 {
  SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17)
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  `--COMPOUND QUERY
  |     |--LEFT-MOST SUBQUERY
  |     |  `--SCAN CONSTANT ROW
  |     `--EXCEPT USING TEMP B-TREE
  |        `--SCAN TABLE t3
  |--SCAN SUBQUERY xxxxxx
  `--SCAN TABLE t3
}
do_eqp_test 1.10 {
  SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17)
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  `--COMPOUND QUERY
  |     |--LEFT-MOST SUBQUERY
  |     |  `--SCAN CONSTANT ROW
  |     `--INTERSECT USING TEMP B-TREE
  |        `--SCAN TABLE t3
  |--SCAN SUBQUERY xxxxxx
  `--SCAN TABLE t3
}

do_eqp_test 1.11 {
  SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17)
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  `--COMPOUND QUERY
  |     |--LEFT-MOST SUBQUERY
  |     |  `--SCAN CONSTANT ROW
  |     `--UNION ALL
  |        `--SCAN TABLE t3
  |--SCAN SUBQUERY xxxxxx
  `--SCAN TABLE 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
  |--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
  |--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
  `--USE TEMP B-TREE FOR DISTINCT
}
det 2.2.4 "SELECT DISTINCT * FROM t1, t2" {
  QUERY PLAN
  |--SCAN TABLE t1
  |--SCAN TABLE 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
  |--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
}

det 2.3.1 "SELECT max(x) FROM t2" {
  QUERY PLAN
  `--SEARCH TABLE t2 USING COVERING INDEX t2i1
}
det 2.3.2 "SELECT min(x) FROM t2" {
  QUERY PLAN
  `--SEARCH TABLE 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
}

det 2.4.1 "SELECT * FROM t1 WHERE rowid=?" {
  QUERY PLAN
  `--SEARCH TABLE 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 xxxxxx
     `--SCAN TABLE t1 AS sub
}
do_eqp_test 3.1.2 {
  SELECT * FROM t1 WHERE (SELECT x FROM t1 AS sub);
} {
  QUERY PLAN
  |--SCAN TABLE t1
  `--SCALAR SUBQUERY xxxxxx
     `--SCAN TABLE t1 AS 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 xxxxxx
     |--SCAN TABLE t1 AS 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 xxxxxx
     `--SCAN TABLE 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
  |  `--USE TEMP B-TREE FOR ORDER BY
  |--SCAN SUBQUERY xxxxxx
  `--USE TEMP B-TREE FOR ORDER BY
}
det 3.2.2 {
  SELECT * FROM 
    (SELECT * FROM t1 ORDER BY x LIMIT 10) AS x1,
    (SELECT * FROM t2 ORDER BY x LIMIT 10) AS x2
  ORDER BY x2.y LIMIT 5
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  |--SCAN TABLE t1
  |  `--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
  `--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 xxxxxx
     `--SCAN TABLE 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 xxxxxx
     `--SCAN TABLE 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 xxxxxx
     `--SCAN TABLE 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
     `--UNION ALL
        `--SCAN TABLE 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
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--SCAN TABLE 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
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--SCAN TABLE 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
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--SCAN TABLE 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
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--SCAN TABLE 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
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        `--SCAN TABLE 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
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--SCAN TABLE 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
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--SCAN TABLE 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
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--SCAN TABLE 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
     `--UNION USING TEMP B-TREE
        `--SCAN TABLE 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
     |--UNION USING TEMP B-TREE
     |  `--SCAN TABLE t2 USING COVERING INDEX t2i1
     `--UNION USING TEMP B-TREE
        `--SCAN TABLE 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
     |     |  `--USE TEMP B-TREE FOR ORDER BY
     |     `--RIGHT
     |        `--SCAN TABLE t2 USING COVERING INDEX t2i1
     `--RIGHT
        |--SCAN TABLE 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
#
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}
}

# 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
#
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=?)}
}

# 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=?)
#
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=?)}
}

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

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

# 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=?)
#
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=?)}
}

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

# 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|EXECUTE SCALAR SUBQUERY 1
# 1|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
# 0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 2
# 2|0|0|SEARCH TABLE 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 {EXECUTE SCALAR SUBQUERY 1}
  1 0 0 {SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)}
  0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2}
  2 0 0 {SEARCH TABLE 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
# 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}
  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
#
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}
}

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







|

|
|





|


|

|





|





|






|





|




|



|


|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|






|


|


|




|
|
|


|


|




|
|
|



|


|




|
|
|















|






|





|




|
|




|
|





|
|




|



|



|




|











|

|





|

|





|

|






|

|






|
|











|
|

|
|
|
|







|

|





|

|





|

|











|

|







|


|








|


|








|


|








|


|









|


|







|


|








|


|








|


|









|

|








|

|

|









|


|

|












|



|




|



|




|



|




|
|



|
|




|
|


|
|




|
|



|
|




|



|





|



|




|

|

|




|

|

|




|






|






|
|


|
|




|
|



|
|





|
|



|
|







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
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 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 t2
  `--MULTI-INDEX OR
     |--INDEX 1
     |  `--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 t1 USING COVERING INDEX i1
}
do_eqp_test 1.4 {
  SELECT a FROM t1 ORDER BY +a
} {
  QUERY PLAN
  |--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 t1 USING COVERING INDEX i1 (a=?)
}
do_eqp_test 1.6 {
  SELECT DISTINCT count(*) FROM t3 GROUP BY a;
} {
  QUERY PLAN
  |--SCAN t3
  |--USE TEMP B-TREE FOR GROUP BY
  `--USE TEMP B-TREE FOR DISTINCT
}

do_eqp_test 1.7.1 {
  SELECT * FROM t3 JOIN (SELECT 1)
} {
  QUERY PLAN
  |--MATERIALIZE SUBQUERY xxxxxx
  |  `--SCAN CONSTANT ROW
  |--SCAN SUBQUERY xxxxxx
  `--SCAN t3
}
do_eqp_test 1.7.2 {
  SELECT * FROM t3 JOIN (SELECT 1) AS v1
} {
  QUERY PLAN
  |--MATERIALIZE v1
  |  `--SCAN CONSTANT ROW
  |--SCAN v1
  `--SCAN t3
}
do_eqp_test 1.7.3 {
  SELECT * FROM t3 AS xx JOIN (SELECT 1) AS yy
} {
  QUERY PLAN
  |--MATERIALIZE yy
  |  `--SCAN CONSTANT ROW
  |--SCAN yy
  `--SCAN xx
}


do_eqp_test 1.8 {
  SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2)
} {
  QUERY PLAN
  |--MATERIALIZE SUBQUERY xxxxxx
  |  `--COMPOUND QUERY
  |     |--LEFT-MOST SUBQUERY
  |     |  `--SCAN CONSTANT ROW
  |     `--UNION USING TEMP B-TREE
  |        `--SCAN CONSTANT ROW
  |--SCAN SUBQUERY xxxxxx
  `--SCAN t3
}
do_eqp_test 1.9 {
  SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17) AS abc
} {
  QUERY PLAN
  |--MATERIALIZE abc
  |  `--COMPOUND QUERY
  |     |--LEFT-MOST SUBQUERY
  |     |  `--SCAN CONSTANT ROW
  |     `--EXCEPT USING TEMP B-TREE
  |        `--SCAN t3
  |--SCAN abc
  `--SCAN t3
}
do_eqp_test 1.10 {
  SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17) AS abc
} {
  QUERY PLAN
  |--MATERIALIZE abc
  |  `--COMPOUND QUERY
  |     |--LEFT-MOST SUBQUERY
  |     |  `--SCAN CONSTANT ROW
  |     `--INTERSECT USING TEMP B-TREE
  |        `--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) abc
} {
  QUERY PLAN
  |--MATERIALIZE abc
  |  `--COMPOUND QUERY
  |     |--LEFT-MOST SUBQUERY
  |     |  `--SCAN CONSTANT ROW
  |     `--UNION ALL
  |        `--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 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 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 t1
  `--USE TEMP B-TREE FOR DISTINCT
}
det 2.2.4 "SELECT DISTINCT * FROM t1, t2" {
  QUERY PLAN
  |--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 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 t2 USING COVERING INDEX t2i1
  `--SCAN t1
}

det 2.3.1 "SELECT max(x) FROM t2" {
  QUERY PLAN
  `--SEARCH t2 USING COVERING INDEX t2i1
}
det 2.3.2 "SELECT min(x) FROM t2" {
  QUERY PLAN
  `--SEARCH t2 USING COVERING INDEX t2i1
}
det 2.3.3 "SELECT min(x), max(x) FROM t2" {
  QUERY PLAN
  `--SCAN t2 USING COVERING INDEX t2i1
}

det 2.4.1 "SELECT * FROM t1 WHERE rowid=?" {
  QUERY PLAN
  `--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 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 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 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 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 SUBQUERY xxxxxx
  |  |--SCAN t1
  |  `--USE TEMP B-TREE FOR ORDER BY
  |--SCAN SUBQUERY xxxxxx
  `--USE TEMP B-TREE FOR ORDER BY
}
det 3.2.2 {
  SELECT * FROM 
    (SELECT * FROM t1 ORDER BY x LIMIT 10) AS x1,
    (SELECT * FROM t2 ORDER BY x LIMIT 10) AS x2
  ORDER BY x2.y LIMIT 5
} {
  QUERY PLAN
  |--MATERIALIZE x1
  |  |--SCAN t1
  |  `--USE TEMP B-TREE FOR ORDER BY
  |--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 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 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 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 t1
     `--UNION ALL
        `--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 t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--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 t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--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 t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--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 t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--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 t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        `--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 t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--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 t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--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 t1
     |  `--USE TEMP B-TREE FOR ORDER BY
     `--RIGHT
        |--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 t1
     `--UNION USING TEMP B-TREE
        `--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 t1
     |--UNION USING TEMP B-TREE
     |  `--SCAN t2 USING COVERING INDEX t2i1
     `--UNION USING TEMP B-TREE
        `--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 t1
     |     |  `--USE TEMP B-TREE FOR ORDER BY
     |     `--RIGHT
     |        `--SCAN t2 USING COVERING INDEX t2i1
     `--RIGHT
        |--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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 t2
# 0|0|0|EXECUTE SCALAR SUBQUERY 1
# 1|0|0|SEARCH t1 USING COVERING INDEX i2 (a=?)
# 0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 2
# 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 t2 USING COVERING INDEX i4}
  0 0 0 {EXECUTE SCALAR SUBQUERY 1}
  1 0 0 {SEARCH t1 USING COVERING INDEX i2 (a=?)}
  0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2}
  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 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 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 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 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 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 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 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 t1 USING COVERING INDEX i1}
  2 0 0 {SCAN t2}
  2 0 0 {USE TEMP B-TREE FOR ORDER BY}
  0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
}

if {![nonzero_reserved_bytes]} {
  #-------------------------------------------------------------------------
  # The following tests - eqp-6.* - test that the example C code on 
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
      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
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
}

det 7.2 "SELECT count(*) FROM t2" {
  QUERY PLAN
  `--SCAN TABLE 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
}

det 7.5 "SELECT count(*) FROM t2" {
  QUERY PLAN
  `--SCAN TABLE 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
}

det 8.1.2 "SELECT * FROM t2 WHERE rowid=?" {
  QUERY PLAN
  `--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
}

det 8.1.3 "SELECT count(*) FROM t2" {
  QUERY PLAN
  `--SCAN TABLE t2
}

det 8.2.1 "SELECT * FROM t1" {
  QUERY PLAN
  `--SCAN TABLE t1
}

det 8.2.2 "SELECT * FROM t1 WHERE b=?" {
  QUERY PLAN
  `--SEARCH TABLE 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=?)
}

det 8.2.4 "SELECT count(*) FROM t1" {
  QUERY PLAN
  `--SCAN TABLE 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 {







|
|




















|




|


















|




|















|




|




|




|




|




|




|







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

det 7.2 "SELECT count(*) FROM t2" {
  QUERY PLAN
  `--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 t1
}

det 7.5 "SELECT count(*) FROM t2" {
  QUERY PLAN
  `--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 t2
}

det 8.1.2 "SELECT * FROM t2 WHERE rowid=?" {
  QUERY PLAN
  `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}

det 8.1.3 "SELECT count(*) FROM t2" {
  QUERY PLAN
  `--SCAN t2
}

det 8.2.1 "SELECT * FROM t1" {
  QUERY PLAN
  `--SCAN t1
}

det 8.2.2 "SELECT * FROM t1 WHERE b=?" {
  QUERY PLAN
  `--SEARCH t1 USING PRIMARY KEY (b=?)
}

det 8.2.3 "SELECT * FROM t1 WHERE b=? AND c=?" {
  QUERY PLAN
  `--SEARCH t1 USING PRIMARY KEY (b=? AND c=?)
}

det 8.2.4 "SELECT count(*) FROM t1" {
  QUERY PLAN
  `--SCAN t1
}

# 2018-08-16:  While working on Fossil I discovered that EXPLAIN QUERY PLAN
# did not describe IN operators implemented using a ROWID lookup.  These
# test cases ensure that problem as been fixed.
#
do_execsql_test 9.0 {
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
    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
  |  |--USING ROWID SEARCH ON TABLE private FOR IN-OPERATOR
  |  |--CORRELATED SCALAR SUBQUERY xxxxxx
  |  |  |--SEARCH TABLE 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=?)
  `--USE TEMP B-TREE FOR ORDER BY
}

finish_test







|
|


|


|
|
|




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 thread
  |  |--SCAN x USING INDEX forumthread
  |  |--USING ROWID SEARCH ON TABLE private FOR IN-OPERATOR
  |  |--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 thread
  |--SEARCH blob USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH event USING INTEGER PRIMARY KEY (rowid=?)
  `--USE TEMP B-TREE FOR ORDER BY
}

finish_test
Deleted test/exists2.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# 2021 January 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing cases where EXISTS expressions are
# transformed to IN() expressions by where.c
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix exists2

do_execsql_test 1.0 {
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
  INSERT INTO t1 VALUES(1, 'one');
  INSERT INTO t1 VALUES(2, 'two');
  INSERT INTO t1 VALUES(3, 'three');
  INSERT INTO t1 VALUES(4, 'four');
  INSERT INTO t1 VALUES(5, 'five');
  INSERT INTO t1 VALUES(6, 'six');
  INSERT INTO t1 VALUES(7, 'seven');

  CREATE TABLE t2(c INTEGER, d INTEGER);
  INSERT INTO t2 VALUES(1, 1);
  INSERT INTO t2 VALUES(3, 2);
  INSERT INTO t2 VALUES(5, 3);
  INSERT INTO t2 VALUES(7, 4);
}

proc do_execsql_eqp_test {tn sql eqp res} {
  uplevel [list do_eqp_test $tn.1 $sql [string trim $eqp]]
  uplevel [list do_execsql_test $tn.2 $sql $res]
}

do_execsql_eqp_test 1.1 {
  SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t1.a=t2.c);
} {
  USING INTEGER PRIMARY KEY
} {
  1 one 3 three 5 five 7 seven
}

do_execsql_eqp_test 1.2 {
  SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c=t1.a);
} {
  SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
  1 one 3 three 5 five 7 seven
}

do_execsql_eqp_test 1.3 {
  SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c+1=t1.a);
} {
  SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
  2 two 4 four 6 six
}

do_execsql_eqp_test 1.4 {
  SELECT t1.* FROM t1 WHERE EXISTS(SELECT * FROM t2 WHERE t2.c+1=t1.a+1);
} {
  SCAN TABLE t1
} {
  1 one 3 three 5 five 7 seven
}

do_execsql_eqp_test 1.5 {
  SELECT t1.* FROM t1 WHERE EXISTS(
    SELECT * FROM t2 WHERE t1.a=t2.c AND d IN (1, 2, 3)
  );
} {
  SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
  1 one 3 three 5 five
}

do_execsql_eqp_test 1.6 {
  SELECT t1.* FROM t1 WHERE EXISTS(
    SELECT * FROM t2 WHERE d IN (1, 2, 3)AND t1.a=t2.c 
  );
} {
  SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
  1 one 3 three 5 five
}

do_execsql_eqp_test 1.7 {
  SELECT t1.* FROM t1 WHERE EXISTS(
    SELECT * FROM t2 WHERE d IN (1, 2, 3)AND t1.a=t2.c 
  );
} {
  SEARCH TABLE t1 USING INTEGER PRIMARY KEY
} {
  1 one 3 three 5 five
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t3(a TEXT PRIMARY KEY, b TEXT, x INT) WITHOUT ROWID;
  CREATE TABLE t4(c TEXT COLLATE nocase, y INT);

  INSERT INTO t3 VALUES('one', 'i', 1);
  INSERT INTO t3 VALUES('two', 'ii', 2);
  INSERT INTO t3 VALUES('three', 'iii', 3);
  INSERT INTO t3 VALUES('four', 'iv', 4);
  INSERT INTO t3 VALUES('five', 'v', 5);

  INSERT INTO t4 VALUES('FIVE',5), ('four',4), ('TWO',2), ('one',1);
}

do_execsql_test 2.1 { SELECT a FROM t3, t4 WHERE a=c } {four one}
do_execsql_test 2.2 { SELECT a FROM t3, t4 WHERE c=a } {five four one two}

do_execsql_eqp_test 2.3 {
  SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE a=c)
} {
  SEARCH TABLE t3 USING PRIMARY KEY
} {
  four one
}

do_execsql_eqp_test 2.4 {
  SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE c=a)
} {
  SCAN TABLE t3
} {
  five four one two
}

do_execsql_test 2.5 {
  CREATE INDEX t3anc ON t3(a COLLATE nocase, x);
}

do_execsql_eqp_test 2.6 {
  SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE c=a)
} {
  SEARCH TABLE t3 USING COVERING INDEX t3anc
} {
  five four one two
}
do_execsql_test 2.6a {
  SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE (c,y)=(a,x))
} {five four one two}

do_execsql_eqp_test 2.7 {
  SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE a=c)
} {
  SEARCH TABLE t3 USING PRIMARY KEY
} {
  four one
}
do_execsql_test 2.7a {
  SELECT a FROM t3 WHERE EXISTS (SELECT 1 FROM t4 WHERE (a,x)=(c,y))
} {
  four one
}

# EXISTS clauses using vector expressions in the WHERE clause.
#
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t1(a,b);
  INSERT INTO t1(a,b) VALUES(1,111),(2,222),(8,888);
  CREATE TABLE t2(x INTEGER PRIMARY KEY, y);
  INSERT INTO t2(x,y) VALUES(2,222),(3,333),(7,333);
  SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (x,y)=(a,b));
} {222}
do_execsql_test 3.1 {
  SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (a,b)=(x,y));
} {222}
do_execsql_test 3.2 {
  SELECT y FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE (x,b)=(a,y));
} {222}





finish_test
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
























































































































































































































































































































































































Deleted test/existsfault.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# 2021 January 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing cases where EXISTS expressions are
# transformed to IN() expressions by where.c
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix existsfault

do_execsql_test 1 {
  CREATE TABLE t1(a PRIMARY KEY, b);
  INSERT INTO t1 VALUES(1, 'one');
  INSERT INTO t1 VALUES(2, 'two');
  INSERT INTO t1 VALUES(3, 'three');
  INSERT INTO t1 VALUES(4, 'four');
  INSERT INTO t1 VALUES(5, 'five');
  INSERT INTO t1 VALUES(6, 'six');
  INSERT INTO t1 VALUES(7, 'seven');

  CREATE TABLE t2(c INTEGER, d INTEGER);
  INSERT INTO t2 VALUES(1, 1);
  INSERT INTO t2 VALUES(3, 2);
  INSERT INTO t2 VALUES(5, 3);
  INSERT INTO t2 VALUES(7, 4);
}
faultsim_save_and_close

do_faultsim_test 1 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    SELECT t1.* FROM t1 WHERE EXISTS(
        SELECT * FROM t2 WHERE t2.c=t1.a AND d IN (1, 2, 3)
    )
  }
} -test {
  faultsim_test_result {0 {1 one 3 three 5 five}}
}


finish_test

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








































































































Added test/exprfault.test.






































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 2021 April 17
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix exprfault

do_execsql_test 1.0 {
  CREATE TABLE t1(a);                 
  CREATE TABLE t2(d);                 
}
faultsim_save_and_close

do_faultsim_test 1.1 -faults oom* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    SELECT a = ( SELECT d FROM (SELECT d FROM t2) ) FROM t1 
  }
} -test {
  faultsim_test_result {0 {}}
}


finish_test
Added test/external_reader.test.




















































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# 2021 April 2
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set testprefix external_reader

ifcapable !wal {
  finish_test 
  return 
}
if {$::tcl_platform(platform)!="unix"} {
  finish_test 
  return
}

do_multiclient_test tn {

  set bExternal 1
  if {[info commands db3]!=""} { set bExternal 0 }

  do_test 1.$tn.0 {
    sql1 {
      PRAGMA journal_mode = wal;
      CREATE TABLE t1(a, b);
      INSERT INTO t1 VALUES(1, 2);
    }
  } {wal}

  do_test 1.$tn.1 {
    sql2 { SELECT * FROM t1 }
  } {1 2}

  do_test 1.$tn.2 {
    code1 {
      file_control_external_reader db
    } 
  } {0}

  do_test 1.$tn.3 {
    sql2 { 
      BEGIN;
        SELECT * FROM t1;
    }
  } {1 2}

  do_test 1.$tn.4 {
    code1 {
      file_control_external_reader db
    } 
  } $bExternal

  do_test 1.$tn.5 {
    sql2 { COMMIT }
  } {}

  do_test 1.$tn.6 {
    code1 { file_control_external_reader db } 
  } 0

}


finish_test
Changes to test/fts3aux1.test.
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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:*/}
do_execsql_test 2.1.1.2 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term='braid'
} {/*SCAN TABLE 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' }







|


|







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 terms VIRTUAL TABLE INDEX 1:*/}
do_execsql_test 2.1.1.2 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term='braid'
} {/*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

# 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:*/}
do_execsql_test 2.2.1.2 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term>'brain'
} {/*SCAN TABLE 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:*/}
do_execsql_test 2.2.1.4 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term<'brain'
} {/*SCAN TABLE 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:*/}
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:*/}

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 {







|


|



|


|



|


|







150
151
152
153
154
155
156
157
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 terms VIRTUAL TABLE INDEX 2:*/}
do_execsql_test 2.2.1.2 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term>'brain'
} {/*SCAN terms VIRTUAL TABLE INDEX 0:*/}

do_execsql_test 2.2.1.3 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term<'brain'
} {/*SCAN terms VIRTUAL TABLE INDEX 4:*/}
do_execsql_test 2.2.1.4 {
  EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term<'brain'
} {/*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 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 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
  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:}
  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
}








|







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 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
  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:
} {
  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:
} {
  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=?)
} {
  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=?)
} {
  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







|
|








|
|








|
|








|
|







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 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 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 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 terms VIRTUAL TABLE INDEX 0:
  `--SEARCH x3 USING COVERING INDEX i1 (y=?)
} {
  a k l
}

#-------------------------------------------------------------------------
# The following tests check that fts4aux can handle an fts table with an
# odd name (one that requires quoting for use in SQL statements). And that
Changes to test/fts3corrupt4.test.
6380
6381
6382
6383
6384
6385
6386











































































































































































































6387
6388
6389
| 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}}













































































































































































































finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
| end sql038051.txt.db
}]} {}

do_catchsql_test 48.1 {
  INSERT INTO x1(x1) VALUES('nodesize=24'),('merge=3,4');
  INSERT INTO x1(x1) VALUES( 'merge=3,4' ),('merge=3,4');
} {1 {database disk image is malformed}}

#-------------------------------------------------------------------------
#
reset_db
do_test 49.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-58821b8eae6883.db
| page 1 offset 0
|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.
|     16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 07   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04   ................
|     96: 00 00 00 00 0d 0e ef 00 07 0d 4d 00 0f bd 0f 5f   ..........M...._
|    112: 0e f7 0e 06 0e bc 0d a4 0d 4d 00 00 00 00 00 00   .........M......
|   3392: 00 00 00 00 00 00 00 00 00 00 00 00 00 55 07 07   .............U..
|   3408: 17 1b 1b 01 81 01 74 61 62 6c 65 74 31 5f 73 74   ......tablet1_st
|   3424: 61 74 74 31 5f 73 74 61 74 07 43 52 45 41 54 45   att1_stat.CREATE
|   3440: 20 54 41 42 4c 45 20 27 74 31 5f 73 74 61 74 27    TABLE 't1_stat'
|   3456: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   (id INTEGER PRIM
|   3472: 41 52 59 20 4b 45 59 2c 20 76 61 6c 75 65 20 42   ARY KEY, value B
|   3488: 4c 4f 42 29 60 06 07 17 21 21 01 81 0b 74 61 62   LOB)`...!!...tab
|   3504: 6c 65 74 31 5f 64 6f 63 73 69 7a 65 74 31 5f 64   let1_docsizet1_d
|   3520: 6f 63 73 69 7a 65 06 43 52 45 41 54 45 20 54 41   ocsize.CREATE TA
|   3536: 42 4c 45 20 27 74 31 5f 64 6f 63 73 69 7a 65 27   BLE 't1_docsize'
|   3552: 28 64 6f 63 69 64 20 49 4e 54 45 47 45 52 20 50   (docid INTEGER P
|   3568: 52 49 4d 41 52 59 20 4b 45 59 2c 20 73 69 7a 65   RIMARY KEY, size
|   3584: 20 42 4c 4f 42 29 81 33 04 07 17 1f 1f 01 82 35    BLOB).3.......5
|   3600: 74 61 62 6c 65 74 31 5f 73 65 67 64 69 72 74 31   tablet1_segdirt1
|   3616: 5f 73 65 67 64 69 72 04 43 52 45 41 54 45 20 54   _segdir.CREATE T
|   3632: 41 42 4c 45 20 27 74 31 5f 73 65 67 64 69 72 27   ABLE 't1_segdir'
|   3648: 28 6c 65 76 65 6c 20 49 4e 54 45 47 45 52 2c 69   (level INTEGER,i
|   3664: 64 78 20 49 4e 54 45 47 45 52 2c 73 74 61 72 74   dx INTEGER,start
|   3680: 5f 62 6c 6f 63 6b 20 49 4e 54 45 47 45 52 2c 6c   _block INTEGER,l
|   3696: 65 61 76 65 73 5f 65 6e 64 5f 62 6c 6f 63 6b 20   eaves_end_block 
|   3712: 49 4e 54 45 47 45 52 2c 65 6e 64 5f 62 6c 6f 63   INTEGER,end_bloc
|   3728: 6b 20 49 4e 54 45 47 45 52 2c 72 6f 6f 74 20 42   k INTEGER,root B
|   3744: 4c 4f 42 2c 50 52 49 4d 41 52 59 20 4b 45 59 28   LOB,PRIMARY KEY(
|   3760: 6c 65 76 65 6c 2c 20 69 64 78 29 29 31 05 06 17   level, idx))1...
|   3776: 45 1f 01 00 69 6e 64 65 78 73 71 6c 69 74 65 5f   E...indexsqlite_
|   3792: 61 75 74 6f 69 6e 64 65 78 5f 74 31 5f 73 65 67   autoindex_t1_seg
|   3808: 64 69 72 5f 31 74 31 5f 73 65 67 64 69 72 05 00   dir_1t1_segdir..
|   3824: 00 00 08 00 00 00 00 66 03 07 17 23 23 01 81 13   .......f...##...
|   3840: 74 61 62 6c 65 74 31 5f 73 65 67 6d 65 6e 74 73   tablet1_segments
|   3856: 74 31 5f 73 65 67 6d 65 6e 74 73 03 43 52 45 41   t1_segments.CREA
|   3872: 54 45 20 54 41 42 4c 45 20 27 74 31 5f 73 65 67   TE TABLE 't1_seg
|   3888: 6d 65 6e 74 73 27 28 62 6c 6f 63 6b 69 64 20 49   ments'(blockid I
|   3904: 4e 54 45 47 45 52 20 f9 52 49 4d 41 52 59 20 4b   NTEGER .RIMARY K
|   3920: 45 59 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 5c   EY, block BLOB).
|   3936: 02 07 17 21 21 01 81 03 74 61 62 6c 65 74 31 5f   ...!!...tablet1_
|   3952: 63 6f 6e 74 65 6e 74 74 31 5f 63 6f 6e 74 65 6e   contentt1_conten
|   3968: 74 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 27   t.CREATE TABLE '
|   3984: 74 31 5f 63 6f 6e 74 65 6e 74 27 28 64 6f 63 69   t1_content'(doci
|   4000: 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52   d INTEGER PRIMAR
|   4016: 59 20 4b 45 59 2c 20 27 63 30 61 27 29 41 01 06   Y KEY, 'c0a')A..
|   4032: 17 11 11 08 71 74 61 62 6c 65 74 31 74 31 43 52   ....qtablet1t1CR
|   4048: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42   EATE VIRTUAL TAB
|   4064: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 34   LE t1 USING fts4
|   4080: 28 61 2c 70 72 65 66 69 78 3d 27 32 2c 32 27 29   (a,prefix='2,2')
| page 2 offset 4096
|      0: 0d 00 00 00 08 0e 1f 00 0f c4 0f 7c 0f 34 0f 07   ...........|.4..
|     16: 0e c3 0e 97 0e 00 00 00 00 00 00 00 00 00 00 00   ................
|   3600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42   ...............B
|   3616: 08 04 00 81 09 73 75 6e 74 20 69 6e 20 63 75 6c   .....sunt in cul
|   3632: 70 61 20 71 75 69 20 6f 66 66 69 63 69 61 20 64   pa qui officia d
|   3648: 65 73 65 72 75 6e 74 20 6d 6f 6c 6c 69 74 20 61   eserunt mollit a
|   3664: 6e 69 6d 20 69 64 20 65 73 74 20 6c 61 62 6f 72   nim id est labor
|   3680: 75 6d 2e 32 07 03 00 6b 45 78 63 65 70 74 65 75   um.2...kExcepteu
|   3696: 72 20 73 69 6e 74 20 6f 63 63 61 65 63 61 74 20   r sint occaecat 
|   3712: 63 75 70 69 64 61 74 61 74 20 6e 6f 6e 20 70 72   cupidatat non pr
|   3728: 6f 69 64 65 6e 74 2c 2a 06 03 00 5b 63 69 6c 6c   oident,*...[cill
|   3744: 75 6d 20 64 6f 6c 6f 72 65 20 65 75 20 66 75 67   um dolore eu fug
|   3760: 69 61 74 20 6e 75 6c 6c 61 20 70 61 72 69 61 74   iat nulla pariat
|   3776: 75 72 2e 42 05 04 00 81 09 44 75 69 73 20 61 75   ur.B.....Duis au
|   3792: 74 65 20 69 72 75 72 65 20 64 6f 6c 6f 72 20 69   te irure dolor i
|   3808: 6e 20 72 65 70 72 65 68 65 6e 64 65 72 69 74 20   n reprehenderit 
|   3824: 69 6e 20 76 6f 6c 75 70 74 61 74 65 20 76 65 6c   in voluptate vel
|   3840: 69 74 20 65 73 73 65 2b 04 03 00 5d 6e 69 73 69   it esse+...]nisi
|   3856: 20 75 74 20 61 6c 69 71 75 69 70 20 65 78 20 65    ut aliquip ex e
|   3872: 61 20 63 6f 6d 6d 6f 64 6f 20 63 6f 6e 73 65 71   a commodo conseq
|   3888: 75 61 74 2e 46 03 04 00 81 11 55 74 20 65 6e 69   uat.F.....Ut eni
|   3904: 6d 20 61 64 20 6d 69 6e 69 6d 20 76 65 6e 69 61   m ad minim venia
|   3920: 6d 2c 20 71 75 69 73 20 6e 6f 73 74 72 75 64 20   m, quis nostrud 
|   3936: 65 78 65 72 63 69 74 61 74 69 6f 6e 20 75 6c 6c   exercitation ull
|   3952: 61 6d 63 6f 20 6c 61 62 6f 72 69 73 46 02 04 00   amco laborisF...
|   3968: 81 11 73 65 64 20 64 6f 20 65 69 75 73 6d 6f 64   ..sed do eiusmod
|   3984: 20 74 65 6d 70 6f 72 20 69 6e 63 69 64 69 64 75    tempor incididu
|   4000: 6e 74 20 75 74 20 6c 61 62 6f 72 65 20 65 74 20   nt ut labore et 
|   4016: 64 6f 6c 6f 72 65 20 6d 61 67 6e 61 20 61 6c 69   dolore magna ali
|   4032: 71 75 61 2e 3a 01 03 00 7b 4c 6f 72 65 6d 20 69   qua.:....Lorem i
|   4048: 70 73 75 6d 20 64 6f 6c 6f 72 20 73 69 74 20 61   psum dolor sit a
|   4064: 6d 65 74 2c 20 63 6f 6e 73 65 63 74 65 74 75 72   met, consectetur
|   4080: 20 61 64 69 70 69 73 63 69 6e 67 20 65 00 01 00    adipiscing e...
| page 4 offset 12288
|      0: 0d 00 00 00 03 0a a6 00 0d 57 0c 4a 0a a6 00 00   .........W.J....
|   2720: 00 00 00 00 00 00 83 21 03 08 02 08 08 08 17 86   .......!........
|   2736: 30 08 00 30 20 34 30 32 00 02 61 64 06 01 08 00   0..0 402..ad....
|   2752: 02 04 00 01 01 6c 06 02 0c 00 02 04 00 01 01 6d   .....l.........m
|   2768: 03 01 06 00 01 01 6e 03 08 09 00 01 01 75 03 05   ......n......u..
|   2784: 03 00 00 02 63 69 03 06 02 00 01 01 6f 07 01 07   ....ci......o...
|   2800: 00 03 07 03 00 01 01 75 06 07 05 00 01 04 00 00   .......u........
|   2816: 02 64 65 03 08 07 00 01 01 6f 0d 01 04 00 01 03   .de......o......
|   2832: 09 00 03 05 00 01 03 00 01 01 75 03 05 02 00 00   ..........u.....
|   2848: 02 65 61 03 04 06 00 01 01 69 03 02 04 00 01 01   .ea......i......
|   2864: 6c 03 01 09 00 01 01 6e 03 03 03 00 01 01 73 06   l......n......s.
|   2880: 05 0b 00 03 0b 00 01 01 74 03 02 09 00 01 01 75   ........t......u
|   2896: 03 06 04 00 01 01 78 09 03 09 00 01 05 00 03 02   ......x.........
|   2912: 00 00 02 66 75 03 06 05 00 00 02 69 64 03 08 0a   ...fu......id...
|   2928: 00 01 01 6e 0a 02 06 00 03 06 04 00 03 03 00 01   ...n............
|   2944: 01 70 03 01 03 00 01 01 72 03 05 04 00 00 02 6c   .p......r......l
|   2960: 61 09 02 08 00 01 0b 00 05 0c 00 01 01 6f 03 01   a............o..
|   2976: 02 00 00 02 6d 61 03 02 0b 00 01 01 69 03 03 05   ....ma......i...
|   2992: 00 01 01 6f 03 08 08 00 00 02 6e 69 03 04 02 00   ...o......ni....
|   3008: 01 01 6f 06 03 08 00 04 06 00 01 01 75 03 06 06   ..o.........u...
|   3024: 00 00 02 6f 63 03 07 04 00 01 01 66 03 08 06 00   ...oc......f....
|   3040: 00 02 70 61 03 06 07 00 01 01 72 03 07 07 00 00   ..pa......r.....
|   3056: 02 71 75 06 03 07 00 05 05 00 00 02 72 65 03 05   .qu.........re..
|   3072: 07 00 00 02 73 65 03 02 02 00 01 01 69 06 01 05   ....se......i...
|   3088: 00 06 03 00 01 01 75 03 08 02 00 00 02 74 65 03   ......u......te.
|   3104: 02 05 00 00 02 75 6c 03 03 0a 00 01 01 74 09 02   .....ul......t..
|   3120: 07 00 01 02 00 01 03 00 00 02 76 65 06 03 06 00   ..........ve....
|   3136: 02 0a 00 01 01 6f 03 05 09 00 82 0a 02 08 02 08   .....o..........
|   3152: 08 08 17 84 02 04 00 30 20 32 35 31 00 01 61 13   .......0 251..a.
|   3168: 01 06 04 00 01 0c 00 01 04 00 01 04 00 01 03 00   ................
|   3184: 03 09 00 00 01 63 10 01 07 00 03 07 03 00 02 02   .....c..........
|   3200: 00 01 05 00 01 04 00 00 01 64 11 01 04 00 01 03   .........d......
|   3216: 09 00 03 02 05 00 01 03 00 02 07 00 00 01 65 1b   ..............e.
|   3232: 01 09 00 01 04 07 00 01 03 08 00 01 05 03 00 01   ................
|   3248: 0b 00 01 04 00 01 02 00 01 0b 00 00 01 66 03 06   .............f..
|   3264: 05 00 00 01 69 0f 01 03 00 01 06 00 03 04 04 04   ....i...........
|   3280: 00 03 03 09 00 00 01 6c 0c 01 02 00 01 08 00 01   .......l........
|   3296: 0b 00 05 0c 00 00 01 6d 09 02 0b 00 01 05 00 05   .......m........
|   3312: 08 00 00 01 6e 0c 03 08 00 01 02 00 02 06 00 01   ....n...........
|   3328: 06 00 00 01 6f 06 07 04 00 01 06 00 00 01 70 06   ....o.........p.
|   3344: 06 07 00 01 07 00 00 01 71 06 03 07 00 05 05 00   ........q.......
|   3360: 00 01 72 03 05 07 00 00 01 73 0c 01 05 00 01 02   ..r......s......
|   3376: 00 05 03 00 01 02 00 00 01 74 03 02 05 00 00 01   .........t......
|   3392: 75 0a 02 07 00 01 02 0a 00 01 03 00 00 01 76 07   u.............v.
|   3408: 03 06 00 02 09 03 00 85 26 01 08 08 08 08 08 17   ........&.......
|   3424: 8a 3e 30 20 36 36 35 00 02 61 65 03 03 04 00 02   .>0 665..ae.....
|   3440: 08 69 70 69 73 63 69 6e 67 03 01 08 00 01 05 6c   .ipiscing......l
|   3456: 69 71 75 61 03 02 0c 00 05 02 69 70 03 04 04 00   iqua......ip....
|   3472: 01 03 6d 65 74 03 01 06 00 01 03 6e 69 6d 03 08   ..met......nim..
|   3488: 09 00 01 03 75 74 65 03 05 03 00 00 06 63 69 6c   ....ute......cil
|   3504: 6c 75 6d 03 06 02 00 01 06 6f 6d 6d 6f 64 6f 03   lum......ommodo.
|   3520: 04 07 00 02 09 6e 73 65 63 74 65 74 b5 72 03 01   .....nsectet.r..
|   3536: 07 00 05 04 71 75 61 74 03 04 08 00 01 04 75 6c   ....quat......ul
|   3552: 70 61 03 08 04 00 02 07 70 69 64 61 74 61 74 03   pa......pidatat.
|   3568: 07 05 00 00 08 64 65 73 65 72 75 6e 74 03 08 07   .....deserunt...
|   3584: 00 01 01 6f 03 02 03 00 02 03 6c 6f 72 06 01 04   ...o......lor...
|   3600: 00 04 05 00 05 01 65 06 02 0a 00 04 03 00 01 03   ......e.........
|   3616: 75 69 73 03 05 02 00 00 02 65 61 03 04 06 00 01   uis......ea.....
|   3632: 06 69 75 73 6d 6f 64 03 02 04 00 01 03 6c 69 74   .iusmod......lit
|   3648: 03 01 09 00 01 03 6e 69 6d 03 03 03 00 01 03 73   ......nim......s
|   3664: 73 65 03 05 0b 00 02 01 74 03 08 0b 00 01 01 74   se......t......t
|   3680: 03 02 09 00 01 01 75 03 06 04 00 01 01 78 03 04   ......u......x..
|   3696: 05 00 02 07 63 65 70 74 65 75 72 03 07 02 00 02   ....cepteur.....
|   3712: 0a 65 72 63 69 74 61 74 69 6f 6e 03 03 09 00 00   .ercitation.....
|   3728: 06 66 75 67 69 61 74 03 06 05 00 00 02 69 64 03   .fugiat......id.
|   3744: 08 0a 00 01 01 6e 07 05 06 04 00 03 03 00 02 08   .....n..........
|   3760: 63 69 64 69 64 75 6e 74 03 02 06 00 01 04 70 73   cididunt......ps
|   3776: 75 6d 03 01 03 00 01 04 72 75 72 65 03 05 04 00   um......rure....
|   3792: 00 06 6c 61 62 6f 72 65 03 02 08 00 05 02 69 73   ..labore......is
|   3808: 03 03 0b 00 05 02 75 6d 03 08 0c 00 01 04 6f 72   ......um......or
|   3824: 65 6d 03 01 02 00 00 05 6d 61 67 6e 61 03 02 0b   em......magna...
|   3840: 00 01 04 69 6e 69 6d 03 03 05 00 01 05 6f 6c 6c   ...inim......oll
|   3856: 69 74 03 08 08 00 00 04 6e 69 73 69 03 04 02 00   it......nisi....
|   3872: 01 02 6f 6e 03 07 06 00 02 05 73 74 72 75 64 03   ..on......strud.
|   3888: 03 08 00 01 04 75 6c 6c 61 03 06 06 00 00 08 6f   .....ulla......o
|   3904: 63 63 61 65 63 61 74 03 07 04 00 01 06 66 66 69   ccaecat......ffi
|   3920: 63 69 61 03 08 06 00 00 08 70 61 72 69 61 74 75   cia......pariatu
|   3936: 72 03 06 07 00 01 07 72 6f 69 64 65 6e 74 03 07   r......roident..
|   3952: 07 00 00 03 71 75 69 03 08 05 00 03 01 73 03 03   ....qui......s..
|   3968: 07 00 00 0d 72 65 70 72 65 68 65 6e 64 65 72 69   ....reprehenderi
|   3984: 74 03 05 07 00 00 03 73 65 64 03 02 02 00 01 03   t......sed......
|   4000: 69 6e 74 03 07 03 00 02 01 74 03 01 05 00 01 03   int......t......
|   4016: 75 6e 74 03 08 02 00 00 06 74 65 6d 70 6f 72 03   unt......tempor.
|   4032: 02 05 00 00 07 75 6c 6c 61 6d 63 6f 03 03 0a 00   .....ullamco....
|   4048: 01 01 74 09 02 07 00 01 02 00 01 03 00 00 05 76   ..t............v
|   4064: 65 6c 69 74 03 05 0a 00 02 04 6e 69 61 6d 03 03   elit......niam..
|   4080: 06 00 01 08 6f 6c 75 70 74 61 74 65 03 05 09 00   ....oluptate....
| page 5 offset 16384
|      0: 0a 00 00 00 03 0f eb 00 0f fb 0f f3 0f eb 00 00   ................
|   4064: 00 00 00 00 00 00 00 00 00 00 00 07 04 02 08 01   ................
|   4080: 08 00 03 07 04 02 08 01 04 00 02 04 04 08 08 09   ................
| page 6 offset 20480
|      0: 0d 00 00 00 08 0f d0 00 0f fa 0f f4 0f ee 0f e8   ................
|     16: 0f e2 0f dc 0f d6 0f d0 00 00 00 00 00 00 00 00   ................
|   4048: 04 08 03 00 0e 0b 04 07 03 00 0e 06 04 06 03 00   ................
|   4064: 0e 06 04 05 03 00 0e 0a 04 04 03 00 0e 07 04 03   ................
|   4080: 03 00 0e 0a 04 02 03 00 0e 0b 04 01 03 00 0e 08   ................
| page 7 offset 24576
|      0: 0d 00 00 00 01 0f f7 00 0f f7 00 00 00 00 01 00   ................
|   4080: 00 00 00 00 00 00 00 07 00 03 00 14 08 45 b5 03   .............E..
| end crash-58821b8eae6883.db
}]} {}

do_catchsql_test 49.1 {
  SAVEPOINT one;
  DELETE FROM t1 WHERE t1 MATCH 'c*';
  SELECT matchinfo(t1,'pcx') IS NULL FROM t1 WHERE t1 MATCH 'f*e*';
} {0 0}



finish_test
Changes to test/fts3corrupt6.test.
60
61
62
63
64
65
66
67
68
}
do_execsql_test 2.1 {
  SELECT count(*) FROM t0 WHERE t0 MATCH '(1 NEAR 1) AND (aaaa OR 1)';
} 1

set sqlite_fts3_enable_parentheses $saved_sqlite_fts3_enable_parentheses
finish_test









<
<
60
61
62
63
64
65
66


}
do_execsql_test 2.1 {
  SELECT count(*) FROM t0 WHERE t0 MATCH '(1 NEAR 1) AND (aaaa OR 1)';
} 1

set sqlite_fts3_enable_parentheses $saved_sqlite_fts3_enable_parentheses
finish_test


Changes to test/fts3join.test.
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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=?)
}

finish_test







|
|
|
|



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 rr
  |  `--SCAN ft4 VIRTUAL TABLE INDEX 3:
  |--SCAN t4
  `--SEARCH rr USING AUTOMATIC COVERING INDEX (docid=?)
}

finish_test
Changes to test/fts3query.test.
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
    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:
}
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:
}
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=?)
}
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=?)
}


# Test that calling matchinfo() with the wrong number of arguments, or with
# an invalid argument returns an error.
#
do_execsql_test 5.1 {







|
|





|
|





|
|





|
|







115
116
117
118
119
120
121
122
123
124
125
126
127
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 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 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 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 t1 USING COVERING INDEX i1
  `--SEARCH bt USING INTEGER PRIMARY KEY (rowid=?)
}


# Test that calling matchinfo() with the wrong number of arguments, or with
# an invalid argument returns an error.
#
do_execsql_test 5.1 {
Changes to test/fts3snippet2.test.
53
54
55
56
57
58
59
60
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








<
53
54
55
56
57
58
59

do_execsql_test 2.2 {
  SELECT snippet(t0)  FROM t0 WHERE t0 MATCH 
  '(def AND (one NEAR abc)) OR one'
} {<b>one</b>}

set sqlite_fts3_enable_parentheses 0
finish_test

Changes to test/fts4upfrom.test.
133
134
135
136
137
138
139
140
    12 b apple blueberry
    13 c banana clementine
    14 d cherry dewberry
  }
}

finish_test








<
133
134
135
136
137
138
139

    12 b apple blueberry
    13 c banana clementine
    14 d cherry dewberry
  }
}

finish_test

Changes to test/fuzzcheck.c.
932
933
934
935
936
937
938




939

940
941
942
943
944
945
946
  }

  /* Block debug pragmas and ATTACH/DETACH.  But wait until after
  ** deserialize to do this because deserialize depends on ATTACH */
  sqlite3_set_authorizer(cx.db, block_troublesome_sql, 0);

  /* Consistent PRNG seed */




  sqlite3_randomness(0,0);


  zSql = sqlite3_malloc( nSql + 1 );
  if( zSql==0 ){
    fprintf(stderr, "Out of memory!\n");
  }else{
    memcpy(zSql, aData+iSql, nSql);
    zSql[nSql] = 0;







>
>
>
>

>







932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
  }

  /* Block debug pragmas and ATTACH/DETACH.  But wait until after
  ** deserialize to do this because deserialize depends on ATTACH */
  sqlite3_set_authorizer(cx.db, block_troublesome_sql, 0);

  /* Consistent PRNG seed */
#ifdef SQLITE_TESTCTRL_PRNG_SEED
  sqlite3_table_column_metadata(cx.db, 0, "x", 0, 0, 0, 0, 0, 0);
  sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, 1, cx.db);
#else
  sqlite3_randomness(0,0);
#endif

  zSql = sqlite3_malloc( nSql + 1 );
  if( zSql==0 ){
    fprintf(stderr, "Out of memory!\n");
  }else{
    memcpy(zSql, aData+iSql, nSql);
    zSql[nSql] = 0;
976
977
978
979
980
981
982


983
984
985
986
987
988
989
    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;
}

/*
** END of the dbsqlfuzz code
***************************************************************************/








>
>







981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
    int nAlloc = 0;
    int nNotUsed = 0;
    sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &nAlloc, &nNotUsed, 0);
    fprintf(stderr,"Memory leak: %lld bytes in %d allocations\n",
            sqlite3_memory_used(), nAlloc);
    exit(1);
  }
  sqlite3_hard_heap_limit64(0);
  sqlite3_soft_heap_limit64(0);
  return 0;
}

/*
** END of the dbsqlfuzz code
***************************************************************************/

1424
1425
1426
1427
1428
1429
1430
1431
1432
1433

1434
1435
1436
1437
1438
1439
1440
"  --export-sql DIR     Write SQL to file(s) in DIR. Also works with --sqlid\n"
"  --help               Show this help text\n"
"  --info               Show information about SOURCE-DB w/o running tests\n"
"  --limit-depth N      Limit expression depth to N.  Default: 500\n"
"  --limit-heap N       Limit heap memory to N.  Default: 100M\n"
"  --limit-mem N        Limit memory used by test SQLite instance to N bytes\n"
"  --limit-vdbe         Panic if any test runs for more than 100,000 cycles\n"
"  --load-sql ARGS...   Load SQL scripts fron files into SOURCE-DB\n"
"  --load-db ARGS...    Load template databases from files into SOURCE_DB\n"
"  --load-dbsql ARGS..  Load dbsqlfuzz outputs into the xsql table\n"

"  -m TEXT              Add a description to the database\n"
"  --native-vfs         Use the native VFS for initially empty database files\n"
"  --native-malloc      Turn off MEMSYS3/5 and Lookaside\n"
"  --oss-fuzz           Enable OSS-FUZZ testing\n"
"  --prng-seed N        Seed value for the PRGN inside of SQLite\n"
"  -q|--quiet           Reduced output\n"
"  --rebuild            Rebuild and vacuum the database file\n"







|
|
|
>







1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
"  --export-sql DIR     Write SQL to file(s) in DIR. Also works with --sqlid\n"
"  --help               Show this help text\n"
"  --info               Show information about SOURCE-DB w/o running tests\n"
"  --limit-depth N      Limit expression depth to N.  Default: 500\n"
"  --limit-heap N       Limit heap memory to N.  Default: 100M\n"
"  --limit-mem N        Limit memory used by test SQLite instance to N bytes\n"
"  --limit-vdbe         Panic if any test runs for more than 100,000 cycles\n"
"  --load-sql   FILE..  Load SQL scripts fron files into SOURCE-DB\n"
"  --load-db    FILE..  Load template databases from files into SOURCE_DB\n"
"  --load-dbsql FILE..  Load dbsqlfuzz outputs into the xsql table\n"
"               ^^^^------ Use \"-\" for FILE to read filenames from stdin\n"
"  -m TEXT              Add a description to the database\n"
"  --native-vfs         Use the native VFS for initially empty database files\n"
"  --native-malloc      Turn off MEMSYS3/5 and Lookaside\n"
"  --oss-fuzz           Enable OSS-FUZZ testing\n"
"  --prng-seed N        Seed value for the PRGN inside of SQLite\n"
"  -q|--quiet           Reduced output\n"
"  --rebuild            Rebuild and vacuum the database file\n"
1767
1768
1769
1770
1771
1772
1773













1774

1775
1776
1777

1778
1779
1780
1781
1782
1783
1784
                              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++){













        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_finalize(pStmt);
      rc = sqlite3_exec(db, "COMMIT", 0, 0, 0);
      if( rc ) fatalError("cannot commit the transaction: %s",
                          sqlite3_errmsg(db));
      rebuild_database(db, dbSqlOnly);
      sqlite3_close(db);







>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
|
>







1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
                              isDbSqlFunc, 0, 0);
      rc = sqlite3_prepare_v2(db, zInsSql, -1, &pStmt, 0);
      if( rc ) fatalError("cannot prepare statement [%s]: %s",
                          zInsSql, sqlite3_errmsg(db));
      rc = sqlite3_exec(db, "BEGIN", 0, 0, 0);
      if( rc ) fatalError("cannot start a transaction");
      for(i=iFirstInsArg; i<argc; i++){
        if( strcmp(argv[i],"-")==0 ){
          /* A filename of "-" means read multiple filenames from stdin */
          char zLine[2000];
          while( rc==0 && fgets(zLine,sizeof(zLine),stdin)!=0 ){
            size_t kk = strlen(zLine);
            while( kk>0 && zLine[kk-1]<=' ' ) kk--;
            sqlite3_bind_text(pStmt, 1, zLine, kk, SQLITE_STATIC);
            if( verboseFlag ) printf("loading %.*s\n", (int)kk, zLine);
            sqlite3_step(pStmt);
            rc = sqlite3_reset(pStmt);
            if( rc ) fatalError("insert failed for %s", zLine);
          }
        }else{
          sqlite3_bind_text(pStmt, 1, argv[i], -1, SQLITE_STATIC);
          if( verboseFlag ) printf("loading %s\n", argv[i]);
          sqlite3_step(pStmt);
          rc = sqlite3_reset(pStmt);
          if( rc ) fatalError("insert failed for %s", argv[i]);
        }
      }
      sqlite3_finalize(pStmt);
      rc = sqlite3_exec(db, "COMMIT", 0, 0, 0);
      if( rc ) fatalError("cannot commit the transaction: %s",
                          sqlite3_errmsg(db));
      rebuild_database(db, dbSqlOnly);
      sqlite3_close(db);
2039
2040
2041
2042
2043
2044
2045

2046
2047
2048
2049
2050
2051
2052
2053
            iSrcDb = nSrcDb-1;
            goto sourcedb_cleanup;
          }
        }
      }
    }
    if( bSpinner ){

      printf("\n");
    }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:







>
|







2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
            iSrcDb = nSrcDb-1;
            goto sourcedb_cleanup;
          }
        }
      }
    }
    if( bSpinner ){
      int nTotal = g.nDb*g.nSql;
      printf("\r%s: %d/%d   \n", zDbName, nTotal, nTotal);
    }else if( !quietFlag && !verboseFlag ){
      printf(" 100%% - %d tests\n", g.nDb*g.nSql);
    }
  
    /* Clean up at the end of processing a single source database
    */
  sourcedb_cleanup:
Changes to test/fuzzdata8.db.

cannot compute difference between binary files

Changes to test/hook.test.
1011
1012
1013
1014
1015
1016
1017
1018
} {}

do_catchsql_test 12.6 {
  INSERT INTO t4 VALUES('def', 3);
} {1 {UNIQUE constraint failed: t4.a}}

finish_test








<
1011
1012
1013
1014
1015
1016
1017

} {}

do_catchsql_test 12.6 {
  INSERT INTO t4 VALUES('def', 3);
} {1 {UNIQUE constraint failed: t4.a}}

finish_test

Changes to test/in4.test.
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
  INSERT INTO t6b VALUES(4,44),(5,55),(6,66);

  SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c);
} {3 4 4 44}
do_execsql_test in4-6.1-eqp {
  EXPLAIN QUERY PLAN
  SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c);
} {~/SCAN TABLE t6a/}
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/}







|







326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
  INSERT INTO t6b VALUES(4,44),(5,55),(6,66);

  SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c);
} {3 4 4 44}
do_execsql_test in4-6.1-eqp {
  EXPLAIN QUERY PLAN
  SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c);
} {~/SCAN t6a/}
do_execsql_test in4-6.2 {
  SELECT * FROM t6a, t6b WHERE a=3 AND c IN (b);
} {3 4 4 44}
do_execsql_test in4-6.2-eqp {
  EXPLAIN QUERY PLAN
  SELECT * FROM t6a, t6b WHERE a=3 AND c IN (b);
} {~/SCAN/}
Changes to test/in6.test.
92
93
94
95
96
97
98



















99
100
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}




















finish_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
do_execsql_test in6-3.110 {
  CREATE TABLE v0(v1);
  CREATE TABLE v3(v5, v4);
  INSERT INTO v0 VALUES(0);
  CREATE INDEX v9 ON v3(v4, v4, v5);
  SELECT quote(v5) FROM v0 LEFT JOIN v3 ON v4 = NULL AND v5 IN(0);
} {NULL}

# 2021-04-29 forum https://sqlite.org/forum/forumpost/6a3ec138e9
# An early OP_IsNull bypass might skip over the OP_Affinity and
# cause the OP_IfNoHope to jump on a false-positive, resulting in
# incomplete output.
#
reset_db
do_execsql_test in6-3.120 {
  CREATE TABLE t1(a TEXT, b TEXT);
  INSERT INTO t1 VALUES(null,10),(0,10),(10,10);
  CREATE INDEX t1ab ON t1(a,b);
  SELECT quote(a), quote(b), '|' FROM t1 WHERE b in (SELECT a FROM t1) AND a=0;
} {'0' '10' |}
do_execsql_test in6-3.130 {
  CREATE TABLE t2(x TEXT);
  INSERT INTO t2(x) VALUES(NULL),(0),(10);
  SELECT quote(x), quote(a), quote(b), 'x'
    FROM t2 LEFT JOIN t1 ON a=x AND b in (null,0,10);
} {NULL NULL NULL x '0' '0' '10' x '10' '10' '10' x}

finish_test
Changes to test/incrvacuum.test.
828
829
830
831
832
833
834
835
























































836
    db eval { SELECT a FROM t3 } {
      if {$a==3} { db eval COMMIT }
      lappend res $a
    }
    set res
  } {1 2 3 4}
}
  
























































finish_test







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
    db eval { SELECT a FROM t3 } {
      if {$a==3} { db eval COMMIT }
      lappend res $a
    }
    set res
  } {1 2 3 4}
}

# 2021-04-05 dbsqlfuzz cced0668cfd4da4eb2382cb9dd26c17c64aaff76
#
# This is an incremental vacuum database that has one free page that
# needs to be filled.  After removing the last page from the end of
# the database file to fill the free page slot, the last page that
# is left is the tail of an overflow chain.
#
# But the size of the database file is shorter than the actual data
# so that after incremental vacuum runs, the file is actually too
# small to hold the last page of the overflow chain.
#
# At one point this caused an assertion fault in 
# sqlite3PagerTruncateImage().
#
do_test incrvacuum-17.0 {
  sqlite3 db {}
  database_may_be_corrupt
  db deserialize [decode_hexdb {
| size 20480 pagesize 4096 filename x2.db
| page 1 offset 0
|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.
|     16: 10 00 01 01 00 40 20 20 00 00 00 05 00 00 00 07   .....@  ........
|     32: 00 00 00 04 00 00 00 01 00 00 00 03 00 00 00 04   ................
|     48: 00 00 00 00 00 00 00 03 00 00 00 01 00 00 00 00   ................
|     64: 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00   ................
|     80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05   ................
|     96: 00 2e 53 60 0d 0f dc 00 01 0f b8 00 0f b8 0f b8   ..S`............
|   4016: 00 00 00 00 00 00 00 00 22 02 06 17 11 11 01 31   ...............1
|   4032: 74 61 62 6c 65 74 32 74 32 03 43 52 45 41 54 45   tablet2t2.CREATE
|   4048: 20 54 41 42 4c 45 20 74 32 28 79 29 00 00 00 24    TABLE t2(y)...$
|   4064: 11 11 01 31 74 61 62 6c 65 74 31 74 31 03 43 52   ...1tablet1t1.CR
|   4080: 45 41 54 45 20 54 41 42 4c 45 20 74 31 28 78 29   EATE TABLE t1(x)
| page 2 offset 4096
|      0: 01 00 00 00 00 02 00 00 00 00 03 00 00 00 03 04   ................
|     16: 00 00 00 05 03 00 00 00 03 00 00 00 00 00 00 00   ................
| page 3 offset 8192
|      0: 0d 00 00 00 02 05 47 00 08 dd 05 47 00 00 00 00   ......G....G....
|   1344: 00 00 00 00 00 00 00 a7 0b 02 03 ce 1c 00 00 00   ................
|   2256: 00 00 00 00 00 00 00 00 00 00 00 00 07 ce 14 01   ................
|   2272: 04 81 9c 2c 00 00 00 00 00 00 00 00 00 00 00 00   ...,............
|   4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05   ................
| page 4 offset 12288
|      0: 00 00 00 00 00 00 00 00 08 dd 05 47 00 00 00 00   ...........G....
|   1344: 00 00 00 00 00 00 00 a7 0b 02 03 ce 1c 00 00 00   ................
|   2256: 00 00 00 00 00 00 00 00 00 00 00 00 07 ce 14 01   ................
|   2272: 04 81 9c 2c 00 00 00 00 00 00 00 00 00 00 00 00   ...,............
|   4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 05   ................
| page 5 offset 16384
|      0: 00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00   ................
| end x2.db
}]} {}
do_catchsql_test incrvacuum-17.1 {
  PRAGMA writable_schema=ON;
  PRAGMA incremental_vacuum(10);
} {0 {}}

finish_test
Changes to test/index6.test.
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
  }
} {500}
do_test index6-2.2 {
  execsql {
    EXPLAIN QUERY PLAN
    SELECT * FROM t2 WHERE a=5;
  }
} {/.* TABLE 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 .*/}
} 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 .*/}
}
do_test index6-2.4 {
  execsql {
    EXPLAIN QUERY PLAN
    SELECT * FROM t2 WHERE a IS NULL;
  }
} {~/.*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 {







|







|






|






|







154
155
156
157
158
159
160
161
162
163
164
165
166
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;
  }
} {/(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;
    }
  } {/(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;
    }
  } {/(SEARCH|SCANE) t2 USING INDEX t2a1 /}
}
do_test index6-2.4 {
  execsql {
    EXPLAIN QUERY PLAN
    SELECT * FROM t2 WHERE a IS NULL;
  }
} {~/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
  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=?)
}

do_execsql_test index6-8.2 {
  SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a)
} {
  1 one value 1 
  2 two {} {} 







|
|







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 t8a
  `--SEARCH t8b USING INDEX i8c (y=?)
}

do_execsql_test index6-8.2 {
  SELECT * FROM t8a LEFT JOIN t8b ON (x = 'value' AND y = a)
} {
  1 one value 1 
  2 two {} {} 
Changes to test/index7.test.
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  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 /}
do_execsql_test index7-1.8 {
  DELETE FROM t1 WHERE c>=101;
  DROP INDEX IF EXISTS bad1;
} {}

do_test index7-1.10 {
  execsql {







|







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 t1 USING COVERING INDEX bad1 /}
do_execsql_test index7-1.8 {
  DELETE FROM t1 WHERE c>=101;
  DROP INDEX IF EXISTS bad1;
} {}

do_test index7-1.10 {
  execsql {
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
  }
} {800}
do_test index7-2.2 {
  execsql {
    EXPLAIN QUERY PLAN
    SELECT * FROM t2 WHERE a=5;
  }
} {/.* TABLE 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 .*/}
} 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 .*/}
}
do_test index7-2.4 {
  execsql {
    EXPLAIN QUERY PLAN
    SELECT * FROM t2 WHERE a IS NULL;
  }
} {~/.*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 {







|






|






|






|







198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
  }
} {800}
do_test index7-2.2 {
  execsql {
    EXPLAIN QUERY PLAN
    SELECT * FROM t2 WHERE a=5;
  }
} {/(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;
    }
  } {/(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;
    }
  } {/(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/}

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
  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=?)}

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







|







317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
  INSERT INTO t4 VALUES('def', 'xyz');
  SELECT * FROM v4 WHERE d='xyz' AND c='def'
} {
  def xyz
}
do_eqp_test index7-6.4 {
  SELECT * FROM v4 WHERE d='xyz' AND c='def'
} {SEARCH t4 USING INDEX i4 (c=?)}

do_catchsql_test index7-6.5 {
  CREATE INDEX t5a ON t5(a) WHERE a=#1;
} {1 {near "#1": syntax error}}

do_execsql_test index7-7.0 {
  CREATE TABLE t6(x, y);
345
346
347
348
349
350
351
352
353
354
355
reset_db
do_execsql_test index7-8.1 {
  CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
  CREATE INDEX t1y ON t1(y) WHERE y IS NOT NULL;
  INSERT INTO t1(x) VALUES(1),(2);
  ANALYZE;
  EXPLAIN QUERY PLAN SELECT 1 FROM t1 WHERE y=5;
} {/SEARCH TABLE t1 USING COVERING INDEX t1y/}


finish_test







|



345
346
347
348
349
350
351
352
353
354
355
reset_db
do_execsql_test index7-8.1 {
  CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
  CREATE INDEX t1y ON t1(y) WHERE y IS NOT NULL;
  INSERT INTO t1(x) VALUES(1),(2);
  ANALYZE;
  EXPLAIN QUERY PLAN SELECT 1 FROM t1 WHERE y=5;
} {/SEARCH 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

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

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







|







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 t1 USING INDEX t1abc/}

# If we change the index so that it no longer covers the WHERE clause,
# then we should (correctly) revert to using a table scan.
#
do_execsql_test 1.1 {
  DROP INDEX t1abc;
  CREATE INDEX t1abd ON t1(a,b,d);
Changes to test/indexedby.test.
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  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=?)}
do_eqp_test indexedby-1.3 {
  select * from t1 ; 
} {SCAN TABLE 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
}

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







|


|




|
|







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 t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-1.3 {
  select * from t1 ; 
} {SCAN t1}
do_eqp_test indexedby-1.4 {
  select * from t1, t2 WHERE c = 10; 
} {
  QUERY PLAN
  |--SEARCH t2 USING INDEX i3 (c=?)
  `--SCAN t1
}

# Parser tests. Test that an INDEXED BY or NOT INDEX clause can be 
# attached to a table in the FROM clause, but not to a sub-select or
# SQL view. Also test that specifying an index that does not exist or
# is attached to a different table is detected as an error.
#
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# 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/}
do_eqp_test indexedby-3.1.1 {
  SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'
} {SCAN TABLE t1}
do_eqp_test indexedby-3.1.2 {
  SELECT * FROM t1 NOT INDEXED WHERE rowid=1
} {/SEARCH TABLE 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=?)}
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=?)}
do_test indexedby-3.4 {
  catchsql { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' }
} {0 {}}
do_test indexedby-3.5 {
  catchsql { SELECT * FROM t1 INDEXED BY i2 ORDER BY a }
} {0 {}}
do_test indexedby-3.6 {
  catchsql { SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' }
} {0 {}}
do_test indexedby-3.7 {
  catchsql { SELECT * FROM t1 INDEXED BY i1 ORDER BY a }
} {0 {}}

do_eqp_test indexedby-3.8 {
  SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 ORDER BY e 
} {SCAN TABLE t3 USING INDEX sqlite_autoindex_t3_1}
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=?)}
do_test indexedby-3.10 {
  catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE f = 10 }
} {0 {}}
do_test indexedby-3.11 {
  catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_2 WHERE f = 10 }
} {1 {no such index: sqlite_autoindex_t3_2}}

# Tests for multiple table cases.
#
do_eqp_test indexedby-4.1 {
  SELECT * FROM t1, t2 WHERE a = c 
} {
  QUERY PLAN
  |--SCAN TABLE t1
  `--SEARCH TABLE t2 USING INDEX i3 (c=?)
}
do_eqp_test indexedby-4.2 {
  SELECT * FROM t1 INDEXED BY i1, t2 WHERE a = c 
} {
  QUERY PLAN
  |--SCAN TABLE t1 USING INDEX i1
  `--SEARCH TABLE t2 USING INDEX i3 (c=?)
}
do_test indexedby-4.3 {
  catchsql {
    SELECT * FROM t1 INDEXED BY i1, t2 INDEXED BY i3 WHERE a=c
  }
} {0 {}}
do_test indexedby-4.4 {
  catchsql {
    SELECT * FROM t2 INDEXED BY i3, t1 INDEXED BY i1 WHERE a=c
  }
} {0 {}}

# Test embedding an INDEXED BY in a CREATE VIEW statement. This block
# also tests that nothing bad happens if an index refered to by
# a CREATE VIEW statement is dropped and recreated.
#
do_execsql_test indexedby-5.1 {
  CREATE VIEW v2 AS SELECT * FROM t1 INDEXED BY i1 WHERE a > 5;
  EXPLAIN QUERY PLAN SELECT * FROM v2 
} {/*SEARCH TABLE t1 USING INDEX i1 (a>?)*/}
do_execsql_test indexedby-5.2 {
  EXPLAIN QUERY PLAN SELECT * FROM v2 WHERE b = 10 
} {/*SEARCH TABLE t1 USING INDEX i1 (a>?)*/}
do_test indexedby-5.3 {
  execsql { DROP INDEX i1 }
  catchsql { SELECT * FROM v2 }
} {1 {no such index: i1}}
do_test indexedby-5.4 {
  # Recreate index i1 in such a way as it cannot be used by the view query.
  execsql { CREATE INDEX i1 ON t1(b) }
  catchsql { SELECT * FROM v2 }
} {0 {}}
do_test indexedby-5.5 {
  # Drop and recreate index i1 again. This time, create it so that it can
  # be used by the query.
  execsql { DROP INDEX i1 ; CREATE INDEX i1 ON t1(a) }
  catchsql { SELECT * FROM v2 }
} {0 {}}

# Test that "NOT INDEXED" may use the rowid index, but not others.
# 
do_eqp_test indexedby-6.1 {
  SELECT * FROM t1 WHERE b = 10 ORDER BY rowid 
} {SEARCH TABLE t1 USING INDEX i2 (b=?)}
do_eqp_test indexedby-6.2 {
  SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid 
} {SCAN TABLE 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=?)}
do_eqp_test indexedby-7.2 {
  DELETE FROM t1 NOT INDEXED WHERE a = 5 
} {SCAN TABLE t1}
do_eqp_test indexedby-7.3 {
  DELETE FROM t1 INDEXED BY i1 WHERE a = 5 
} {SEARCH TABLE 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=?)}
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=?)}
do_test indexedby-7.6 {
  catchsql { DELETE FROM t1 INDEXED BY i2 WHERE a = 5}
} {0 {}}

# Test that "INDEXED BY" can be used in an UPDATE statement.
# 
do_eqp_test indexedby-8.1 {
  UPDATE t1 SET rowid=rowid+1 WHERE a = 5 
} {SEARCH TABLE t1 USING COVERING INDEX i1 (a=?)}
do_eqp_test indexedby-8.2 {
  UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5 
} {SCAN TABLE 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=?)}
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=?)}
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=?)}
do_test indexedby-8.6 {
  catchsql { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5}
} {0 {}}

# Test that bug #3560 is fixed.
#
do_test indexedby-9.1 {







|


|


|




|


|















|


|













|
|





|
|



















|


|




















|


|









|


|


|


|


|








|


|


|


|


|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# index shall be used when accessing the preceding table, including
# implied indices create by UNIQUE and PRIMARY KEY constraints. However,
# the rowid can still be used to look up entries even when "NOT INDEXED"
# is specified.
#
do_eqp_test indexedby-3.1 {
  SELECT * FROM t1 WHERE a = 'one' AND b = 'two'
} {/SEARCH t1 USING INDEX/}
do_eqp_test indexedby-3.1.1 {
  SELECT * FROM t1 NOT INDEXED WHERE a = 'one' AND b = 'two'
} {SCAN t1}
do_eqp_test indexedby-3.1.2 {
  SELECT * FROM t1 NOT INDEXED WHERE rowid=1
} {/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 t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-3.3 {
  SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' AND b = 'two'
} {SEARCH t1 USING INDEX i2 (b=?)}
do_test indexedby-3.4 {
  catchsql { SELECT * FROM t1 INDEXED BY i2 WHERE a = 'one' }
} {0 {}}
do_test indexedby-3.5 {
  catchsql { SELECT * FROM t1 INDEXED BY i2 ORDER BY a }
} {0 {}}
do_test indexedby-3.6 {
  catchsql { SELECT * FROM t1 INDEXED BY i1 WHERE a = 'one' }
} {0 {}}
do_test indexedby-3.7 {
  catchsql { SELECT * FROM t1 INDEXED BY i1 ORDER BY a }
} {0 {}}

do_eqp_test indexedby-3.8 {
  SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 ORDER BY e 
} {SCAN 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 t3 USING INDEX sqlite_autoindex_t3_1 (e=?)}
do_test indexedby-3.10 {
  catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_1 WHERE f = 10 }
} {0 {}}
do_test indexedby-3.11 {
  catchsql { SELECT * FROM t3 INDEXED BY sqlite_autoindex_t3_2 WHERE f = 10 }
} {1 {no such index: sqlite_autoindex_t3_2}}

# Tests for multiple table cases.
#
do_eqp_test indexedby-4.1 {
  SELECT * FROM t1, t2 WHERE a = c 
} {
  QUERY PLAN
  |--SCAN 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 t1 USING INDEX i1
  `--SEARCH t2 USING INDEX i3 (c=?)
}
do_test indexedby-4.3 {
  catchsql {
    SELECT * FROM t1 INDEXED BY i1, t2 INDEXED BY i3 WHERE a=c
  }
} {0 {}}
do_test indexedby-4.4 {
  catchsql {
    SELECT * FROM t2 INDEXED BY i3, t1 INDEXED BY i1 WHERE a=c
  }
} {0 {}}

# Test embedding an INDEXED BY in a CREATE VIEW statement. This block
# also tests that nothing bad happens if an index refered to by
# a CREATE VIEW statement is dropped and recreated.
#
do_execsql_test indexedby-5.1 {
  CREATE VIEW v2 AS SELECT * FROM t1 INDEXED BY i1 WHERE a > 5;
  EXPLAIN QUERY PLAN SELECT * FROM v2 
} {/*SEARCH t1 USING INDEX i1 (a>?)*/}
do_execsql_test indexedby-5.2 {
  EXPLAIN QUERY PLAN SELECT * FROM v2 WHERE b = 10 
} {/*SEARCH t1 USING INDEX i1 (a>?)*/}
do_test indexedby-5.3 {
  execsql { DROP INDEX i1 }
  catchsql { SELECT * FROM v2 }
} {1 {no such index: i1}}
do_test indexedby-5.4 {
  # Recreate index i1 in such a way as it cannot be used by the view query.
  execsql { CREATE INDEX i1 ON t1(b) }
  catchsql { SELECT * FROM v2 }
} {0 {}}
do_test indexedby-5.5 {
  # Drop and recreate index i1 again. This time, create it so that it can
  # be used by the query.
  execsql { DROP INDEX i1 ; CREATE INDEX i1 ON t1(a) }
  catchsql { SELECT * FROM v2 }
} {0 {}}

# Test that "NOT INDEXED" may use the rowid index, but not others.
# 
do_eqp_test indexedby-6.1 {
  SELECT * FROM t1 WHERE b = 10 ORDER BY rowid 
} {SEARCH t1 USING INDEX i2 (b=?)}
do_eqp_test indexedby-6.2 {
  SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid 
} {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 t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-7.2 {
  DELETE FROM t1 NOT INDEXED WHERE a = 5 
} {SCAN t1}
do_eqp_test indexedby-7.3 {
  DELETE FROM t1 INDEXED BY i1 WHERE a = 5 
} {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 t1 USING INDEX i1 (a=?)}
do_eqp_test indexedby-7.5 {
  DELETE FROM t1 INDEXED BY i2 WHERE a = 5 AND b = 10
} {SEARCH t1 USING INDEX i2 (b=?)}
do_test indexedby-7.6 {
  catchsql { DELETE FROM t1 INDEXED BY i2 WHERE a = 5}
} {0 {}}

# Test that "INDEXED BY" can be used in an UPDATE statement.
# 
do_eqp_test indexedby-8.1 {
  UPDATE t1 SET rowid=rowid+1 WHERE a = 5 
} {SEARCH t1 USING COVERING INDEX i1 (a=?)}
do_eqp_test indexedby-8.2 {
  UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5 
} {SCAN t1}
do_eqp_test indexedby-8.3 {
  UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 
} {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 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 t1 USING INDEX i2 (b=?)}
do_test indexedby-8.6 {
  catchsql { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5}
} {0 {}}

# Test that bug #3560 is fixed.
#
do_test indexedby-9.1 {
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
  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=?)}

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=?)}

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







|




















|







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 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 x2 USING COVERING INDEX x2i (a=? AND b=? AND rowid=?)}

#-------------------------------------------------------------------------
# Check INDEXED BY works (throws an exception) with partial indexes that 
# cannot be used.
do_execsql_test 12.1 {
  CREATE TABLE o1(x INTEGER PRIMARY KEY, y, z);
  CREATE INDEX p1 ON o1(z);
Changes to test/indexexpr1.test.
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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/}
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/}

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







|






|







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
do_execsql_test indexexpr1-170 {
  CREATE INDEX t1alen ON t1(length(a));
  SELECT length(a) FROM t1 ORDER BY length(a);
} {20 25 27 29 38 52}
do_execsql_test indexexpr1-170eqp {
  EXPLAIN QUERY PLAN
  SELECT length(a) FROM t1 ORDER BY length(a);
} {/SCAN 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 t1 USING INDEX t1alen/}

do_execsql_test indexexpr1-200 {
  DROP TABLE t1;
  CREATE TABLE t1(id ANY PRIMARY KEY, a,b,c) WITHOUT ROWID;
  INSERT INTO t1(id,a,b,c)
  VALUES(1,'In_the_beginning_was_the_Word',1,1),
        (2,'and_the_Word_was_with_God',1,2),
Changes to test/indexexpr2.test.
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  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
    `--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>=?)
    `--USE TEMP B-TREE FOR GROUP BY
  }]
}

do_execsql_test 3.4.0 {
  CREATE TABLE t4(a, b);
  INSERT INTO t4 VALUES('.ABC', 1);







|














|







89
90
91
92
93
94
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 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 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
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/}
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.
#







|







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 t4 USING INDEX i4/}
do_execsql_test 3.4.6 {
  SELECT * FROM t4 ORDER BY Substr(a,-2) COLLATE binary;
} {.ABC1 1 .ABC3 3 .abc2 2 .abc4 4}

# 2014-09-15:  Verify that UPDATEs of columns not referenced by a
# index on expression do not modify the index.
#
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
} {1 123   2 123   3 123abc  4 123.0}
do_execsql_test 6.1.2 {
  CREATE INDEX x1i ON x1( CAST(b AS INTEGER) );
  SELECT a, b FROM x1 WHERE CAST(b AS INTEGER) = 123;
} {1 123   2 123   3 123abc  4 123.0}
do_eqp_test 6.1.3 {
  SELECT a, b FROM x1 WHERE CAST(b AS INTEGER) = 123;
} {SEARCH TABLE x1 USING INDEX x1i (<expr>=?)}

do_execsql_test 6.2.1 {
  SELECT a, b FROM x1 WHERE CAST(b AS TEXT) = 123;
} {1 123   2 123}
do_execsql_test 6.2.2 {
  CREATE INDEX x1i2 ON x1( CAST(b AS TEXT) );
  SELECT a, b FROM x1 WHERE CAST(b AS TEXT) = 123;
} {1 123   2 123}
do_eqp_test 6.2.3 {
  SELECT a, b FROM x1 WHERE CAST(b AS TEXT) = 123;
} {SEARCH TABLE x1 USING INDEX x1i2 (<expr>=?)}

do_execsql_test 7.0 {
  CREATE TABLE IF NOT EXISTS t0(c0);
  INSERT INTO t0(c0) VALUES (-9223372036854775808);
  BEGIN;
}
do_catchsql_test 7.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
} {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 {
Changes to test/intpkey.test.
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 /}

# 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');







|







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 t1 /}

# Try to insert a non-integer value into the primary key field.  This
# should result in a data type mismatch.
#
do_test intpkey-1.13.1 {
  set r [catch {execsql {
    INSERT INTO t1 VALUES('x','y','z');
Changes to test/join2.test.
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  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=?)
}

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=?)
}

#-------------------------------------------------------------------------
# Test that tables other than the rightmost can be omitted from a
# LEFT JOIN query.
#
do_execsql_test 4.0 {







|
|






|
|







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  CREATE TABLE t3_2(v3, k3 PRIMARY KEY) WITHOUT ROWID;
}

do_eqp_test 3.1 {
  SELECT v2 FROM t1 LEFT JOIN t2 USING (k2) LEFT JOIN t3_1 USING (k3);
} {
  QUERY PLAN
  |--SCAN t1
  `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}

do_eqp_test 3.2 {
  SELECT v2 FROM t1 LEFT JOIN t2 USING (k2) LEFT JOIN t3_2 USING (k3);
} {
  QUERY PLAN
  |--SCAN t1
  `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)
}

#-------------------------------------------------------------------------
# Test that tables other than the rightmost can be omitted from a
# LEFT JOIN query.
#
do_execsql_test 4.0 {
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  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=?)
}
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=?)
}

do_execsql_test 4.2.0 {
  DROP TABLE c1;
  DROP TABLE c2;
  DROP TABLE c3;
  CREATE TABLE c1(k UNIQUE, v1);







|
|
|





|
|







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  SELECT v1, v3 FROM c1 LEFT JOIN c2 LEFT JOIN c3 ON (c3.k=v1+1);
} {2 v3 2 v3 1112 {} 1112 {}}

do_eqp_test 4.1.5 {
  SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v2);
} {
  QUERY PLAN
  |--SCAN c1
  |--SEARCH c2 USING INTEGER PRIMARY KEY (rowid=?)
  `--SEARCH c3 USING INTEGER PRIMARY KEY (rowid=?)
}
do_eqp_test 4.1.6 {
  SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v1+1);
} {
  QUERY PLAN
  |--SCAN c1
  `--SEARCH c3 USING INTEGER PRIMARY KEY (rowid=?)
}

do_execsql_test 4.2.0 {
  DROP TABLE c1;
  DROP TABLE c2;
  DROP TABLE c3;
  CREATE TABLE c1(k UNIQUE, v1);
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  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=?)
}
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=?)
}

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







|
|
|





|
|







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  SELECT v1, v3 FROM c1 LEFT JOIN c2 LEFT JOIN c3 ON (c3.k=v1+1);
} {2 v3 2 v3 1112 {} 1112 {}}

do_eqp_test 4.2.5 {
  SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v2);
} {
  QUERY PLAN
  |--SCAN c1
  |--SEARCH c2 USING INDEX sqlite_autoindex_c2_1 (k=?)
  `--SEARCH c3 USING INDEX sqlite_autoindex_c3_1 (k=?)
}
do_eqp_test 4.2.6 {
  SELECT v1, v3 FROM c1 LEFT JOIN c2 ON (c2.k=v1) LEFT JOIN c3 ON (c3.k=v1+1);
} {
  QUERY PLAN
  |--SCAN c1
  `--SEARCH c3 USING INDEX sqlite_autoindex_c3_1 (k=?)
}

# 2017-11-23 (Thanksgiving day)
# OSSFuzz found an assertion fault in the new LEFT JOIN eliminator code.
#
do_execsql_test 4.3.0 {
  DROP TABLE IF EXISTS t1;
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
  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}

do_eqp_test 5.2 {
  SELECT s1.a FROM s1 left join s3 using (a);
} {SCAN TABLE 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}

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







|



|








|







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
  CREATE TABLE s1 (a INTEGER PRIMARY KEY);
  CREATE TABLE s2 (a INTEGER PRIMARY KEY);
  CREATE TABLE s3 (a INTEGER);
  CREATE UNIQUE INDEX ndx on s3(a);
}
do_eqp_test 5.1 {
  SELECT s1.a FROM s1 left join s2 using (a);
} {SCAN s1}

do_eqp_test 5.2 {
  SELECT s1.a FROM s1 left join s3 using (a);
} {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 u2}

db close
sqlite3 db :memory:
do_execsql_test 7.0 {
  CREATE TABLE t1(a,b);  INSERT INTO t1 VALUES(1,2),(3,4),(5,6);
  CREATE TABLE t2(c,d);  INSERT INTO t2 VALUES(2,4),(3,6);
  CREATE TABLE t3(x);    INSERT INTO t3 VALUES(9);
Changes to test/join5.test.
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

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
  `--MULTI-INDEX OR
     |--INDEX 1
     |  `--SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)
     `--INDEX 2
        `--SEARCH TABLE t2 USING INDEX t2xy (x=? AND y=?)
}

do_execsql_test 7.3 {
  CREATE TABLE t3(x);

  CREATE TABLE t4(x, y, z);
  CREATE INDEX t4xy ON t4(x, y);
  CREATE INDEX t4xz ON t4(x, z);

  WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000)
  INSERT INTO t4 SELECT i/10, i, i FROM s;

  ANALYZE;
}

do_eqp_test 7.4 {
  SELECT * FROM t3 LEFT JOIN t4 ON (t4.x = t3.x) WHERE (t4.y = ? OR t4.z = ?);
} {
  QUERY PLAN
  |--SCAN TABLE t3
  `--SEARCH TABLE t4 USING INDEX t4xz (x=?)
} 

reset_db
do_execsql_test 8.0 {
  CREATE TABLE t0 (c0, c1, PRIMARY KEY (c0, c1));
  CREATE TABLE t1 (c0);








|


|

|



















|
|







273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

do_eqp_test 7.2 {
  SELECT * FROM t1 LEFT JOIN t2 ON (
    t2.x = t1.x AND (t2.y=? OR (t2.y=? AND t2.z IS NOT NULL))
  );
} {
  QUERY PLAN
  |--SCAN t1
  `--MULTI-INDEX OR
     |--INDEX 1
     |  `--SEARCH t2 USING INDEX t2xy (x=? AND y=?)
     `--INDEX 2
        `--SEARCH t2 USING INDEX t2xy (x=? AND y=?)
}

do_execsql_test 7.3 {
  CREATE TABLE t3(x);

  CREATE TABLE t4(x, y, z);
  CREATE INDEX t4xy ON t4(x, y);
  CREATE INDEX t4xz ON t4(x, z);

  WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000)
  INSERT INTO t4 SELECT i/10, i, i FROM s;

  ANALYZE;
}

do_eqp_test 7.4 {
  SELECT * FROM t3 LEFT JOIN t4 ON (t4.x = t3.x) WHERE (t4.y = ? OR t4.z = ?);
} {
  QUERY PLAN
  |--SCAN t3
  `--SEARCH t4 USING INDEX t4xz (x=?)
} 

reset_db
do_execsql_test 8.0 {
  CREATE TABLE t0 (c0, c1, PRIMARY KEY (c0, c1));
  CREATE TABLE t1 (c0);

Changes to test/like.test.
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  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]} {
      lappend data {} $idx
    } elseif {[regexp { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
        $x all as tab idx]} {
      lappend data $tab $idx
    } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} {
      lappend data $tab *
    }
  }
  return $data   
}

# Perform tests on the like optimization.







|
|

|
|

|







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 {(SCAN|SEARCH) (\w+ AS )?(\w+) USING COVERING INDEX (\w+)\y} \
        $x all ss as tab idx]} {
      lappend data {} $idx
    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
        $x all ss as tab idx]} {
      lappend data $tab $idx
    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+)\y} $x all ss as tab]} {
      lappend data $tab *
    }
  }
  return $data   
}

# Perform tests on the like optimization.
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
    }]
  } {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
    } {1}
  }
  do_test like-9.5.1 {
    set res [sqlite3_exec_hex db {
       SELECT x FROM t2 WHERE x LIKE '%fe%25'
    }]
  } {0 {}}







|







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 t2} $res
    } {1}
  }
  do_test like-9.5.1 {
    set res [sqlite3_exec_hex db {
       SELECT x FROM t2 WHERE x LIKE '%fe%25'
    }]
  } {0 {}}
1032
1033
1034
1035
1036
1037
1038

1039
1040
1041
1042
1043
1044
1045
1046

1047
1048
1049
1050
1051
1052
1053
1054
1055
# 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]

  puts -nonewline " ($x ms - want less than 1000) "
  expr {$x<1000}
} {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]

    puts -nonewline " ($x ms - want less than 1000) "
    expr {$x<1000}
  } {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.
#







>
|
|






>
|
|







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 $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 $tlimit) "
  expr {$x<$tlimit}
  } {1}
}

ifcapable !icu {
# As of 2017-07-27 (3.21.0) the LIKE optimization works with ESCAPE as
# long as the ESCAPE is a single-byte literal.
#
Changes to test/like3.test.
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  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
}
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<?)
}
}
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
}
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
}

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
}
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<?)
}

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







|









|









|








|











|








|







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  INSERT INTO t5a(x) VALUES('/abc'),(123),(-234);
  SELECT x FROM t5a WHERE x LIKE '/%';
} {/abc}
do_eqp_test like3-5.101 {
  SELECT x FROM t5a WHERE x LIKE '/%';
} {
  QUERY PLAN
  `--SCAN 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 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 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 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 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 t5b USING COVERING INDEX sqlite_autoindex_t5b_1 (x>? AND x<?)
}

# 2019-05-01
# another case of the above reported on the mailing list by Manuel Rigger.
#
do_execsql_test like3-5.300 {
  CREATE TABLE t5c (c0 REAL);
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(path TEXT COLLATE nocase PRIMARY KEY,a,b,c) WITHOUT ROWID;
}
do_eqp_test like3-6.110 {
  SELECT * FROM t1 WHERE path LIKE 'a%';
} {
  QUERY PLAN
  `--SEARCH TABLE t1 USING PRIMARY KEY (path>? AND path<?)
}
do_eqp_test like3-6.120 {
  SELECT * FROM t1 WHERE path LIKE 'a%' ESCAPE 'x';
} {
  QUERY PLAN
  `--SEARCH TABLE t1 USING PRIMARY KEY (path>? AND path<?)
}
do_execsql_test like3-6.200 {
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(path TEXT,x,y,z);
  CREATE INDEX t2path ON t2(path COLLATE nocase);
  CREATE INDEX t2path2 ON t2(path);
}
do_eqp_test like3-6.210 {
  SELECT * FROM t2 WHERE path LIKE 'a%';
} {
  QUERY PLAN
  `--SEARCH TABLE t2 USING INDEX t2path (path>? AND path<?)
}
do_eqp_test like3-6.220 {
  SELECT * FROM t2 WHERE path LIKE 'a%' ESCAPE '\';
} {
  QUERY PLAN
  `--SEARCH TABLE t2 USING INDEX t2path (path>? AND path<?)
}
db eval {PRAGMA case_sensitive_like=ON}
do_eqp_test like3-6.230 {
  SELECT * FROM t2 WHERE path LIKE 'a%';
} {
  QUERY PLAN
  `--SEARCH TABLE t2 USING INDEX t2path2 (path>? AND path<?)
}
do_eqp_test like3-6.240 {
  SELECT * FROM t2 WHERE path LIKE 'a%' ESCAPE '\';
} {
  QUERY PLAN
  `--SEARCH TABLE t2 USING INDEX t2path2 (path>? AND path<?)
}
}

finish_test







|





|











|





|






|





|




230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(path TEXT COLLATE nocase PRIMARY KEY,a,b,c) WITHOUT ROWID;
}
do_eqp_test like3-6.110 {
  SELECT * FROM t1 WHERE path LIKE 'a%';
} {
  QUERY PLAN
  `--SEARCH 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/mallocK.test.
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<?)
    `--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' }







|







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 t3 USING INDEX i3 (ANY(a) AND b>? AND b<?)
    `--USE TEMP B-TREE FOR DISTINCT
  }]
}

do_faultsim_test 6 -faults oom* -body {
  db cache flush
  db eval { SELECT DISTINCT c FROM t3 WHERE b BETWEEN '.xx..' AND '.xxxx' }
Changes to test/memdb1.test.
153
154
155
156
157
158
159










160
161
162
163
164
165
166
} {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!}











# Deserialize something that is not a database.
#
db close
sqlite3 db
do_test 500 {
  set rc [catch {db deserialize not-a-database} msg]







>
>
>
>
>
>
>
>
>
>







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
} {ok}
do_execsql_test 410 {
  CREATE TABLE t4(a,b);
  INSERT INTO t4 VALUES('hello','world!');
  PRAGMA integrity_check;
  SELECT * FROM t4;
} {ok hello world!}
do_execsql_test 420 {
  PRAGMA journal_mode=TRUNCATE;
  PRAGMA journal_mode=OFF;
  PRAGMA journal_mode=DELETE;
  PRAGMA journal_mode=WAL;
  PRAGMA journal_mode=PERSIST;
  PRAGMA journal_mode=MEMORY;
  PRAGMA journal_mode=OFF;
  PRAGMA journal_mode=DELETE;
} {truncate off delete delete persist memory off delete}

# Deserialize something that is not a database.
#
db close
sqlite3 db
do_test 500 {
  set rc [catch {db deserialize not-a-database} msg]
Changes to test/minmax.test.
290
291
292
293
294
295
296





297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  }
} {34 1234}

# Ticket #658:  Test the min()/max() optimization when the FROM clause
# is a subquery.
#
ifcapable {compound && subquery} {





  do_test minmax-9.1 {
    execsql {
      SELECT max(rowid) FROM (
        SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5
      )
    }
  } {{}}
  do_test minmax-9.2 {
    execsql {
      SELECT max(rowid) FROM (
        SELECT max(rowid) 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.







>
>
>
>
>


|
|


|


|
|







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(yy) FROM (
        SELECT max(rowid) AS yy FROM t4 UNION SELECT max(rowid) FROM t5
      )
    }
  } {3}
  do_test minmax-9.2 {
    execsql {
      SELECT max(yy) FROM (
        SELECT max(rowid) AS yy FROM t4 EXCEPT SELECT max(rowid) FROM t5
      )
    }
  } {{}}
} ;# ifcapable compound&&subquery

# If there is a NULL in an aggregate max() or min(), ignore it.  An
# aggregate min() or max() will only return NULL if all values are NULL.
Changes to test/minmax2.test.
279
280
281
282
283
284
285





286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
  }
} {34 1234}

# Ticket #658:  Test the min()/max() optimization when the FROM clause
# is a subquery.
#
ifcapable {compound && subquery} {





  do_test minmax2-9.1 {
    execsql {
      SELECT max(rowid) FROM (
        SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5
      )
    }
  } {{}}
  do_test minmax2-9.2 {
    execsql {
      SELECT max(rowid) FROM (
        SELECT max(rowid) 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.







>
>
>
>
>


|
|


|


|
|







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(yy) FROM (
        SELECT max(rowid) AS yy FROM t4 UNION SELECT max(rowid) FROM t5
      )
    }
  } {3}
  do_test minmax2-9.2 {
    execsql {
      SELECT max(yy) FROM (
        SELECT max(rowid) AS yy FROM t4 EXCEPT SELECT max(rowid) FROM t5
      )
    }
  } {{}}
} ;# ifcapable compound&&subquery

# If there is a NULL in an aggregate max() or min(), ignore it.  An
# aggregate min() or max() will only return NULL if all values are NULL.
Changes to test/misc2.test.
50
51
52
53
54
55
56
57
58
59




60
61
62
63
64
65
66
67
68



69
70
71
72
73
74
75
76
    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 {
    execsql {
      SELECT rowid, * FROM (SELECT * FROM t1, t2);




    }
  } {{} 1 2 3 7 8 9}
}
ifcapable view {
  do_test misc2-2.3 {
    execsql {
      CREATE VIEW v1 AS SELECT * FROM t1, t2;
      SELECT rowid, * FROM v1;
    }



  } {{} 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)







|
<
|
>
>
>
>
|
<
|

|
<
|
|
<
>
>
>
|







50
51
52
53
54
55
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_catchsql_test misc2-2.2 {

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


ifcapable view {
  do_catchsql_test misc2-2.3 {

    CREATE VIEW v1 AS SELECT * FROM t1, t2;
    SELECT rowid, * FROM v1;

  } {1 {no such column: rowid}}
  do_catchsql_test misc2-2.3b {
    SELECT 'rowid', * FROM v1;
  } {0 {rowid 1 2 3 7 8 9}}
} ;# ifcapable view

# Ticket #2002 and #1952.
ifcapable subquery {
  do_test misc2-2.4 {
    execsql2 {
      SELECT * FROM (SELECT a, b AS 'a', c AS 'a', 4 AS 'a' FROM t1)
Changes to test/misc7.test.
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
  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=?)
}
  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=?)
}
  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
}
}

db close
forcedelete test.db
forcedelete test.db-journal
sqlite3 db test.db







|





|





|







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 t2 USING INTEGER PRIMARY KEY (rowid=?)
}
  do_eqp_test misc7-14.2 {
    SELECT * FROM abc AS t2 WHERE a = 1;
} {
  QUERY PLAN
  `--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 t2 USING INDEX sqlite_autoindex_abc_1
}
}

db close
forcedelete test.db
forcedelete test.db-journal
sqlite3 db test.db
Changes to test/misc8.test.
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
  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 {
  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}

# The SQLITE_DBCONFIG_MAINDBNAME interface
#
db close
forcedelete test.db test2.db
sqlite3 db test.db
do_execsql_test misc8-4.0 {







|









|







96
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_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;
} {1 {no such column: rowid}}

# The SQLITE_DBCONFIG_MAINDBNAME interface
#
db close
forcedelete test.db test2.db
sqlite3 db test.db
do_execsql_test misc8-4.0 {
Changes to test/notnull2.test.
93
94
95
96
97
98
99
100
101











  CREATE TABLE T3(k, v);
}

do_execsql_test 2.1 {
  SELECT * FROM (SELECT a, b FROM t1) LEFT JOIN t3 ON a IS NULL;
}

finish_test



















|

>
>
>
>
>
>
>
>
>
>
>
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  CREATE TABLE T3(k, v);
}

do_execsql_test 2.1 {
  SELECT * FROM (SELECT a, b FROM t1) LEFT JOIN t3 ON a IS NULL;
}



#-------------------------------------------------------------------------
reset_db
do_execsql_test 3.0 {
  CREATE TABLE t0(c0 PRIMARY KEY);
  INSERT INTO t0(c0) VALUES (0);
}
do_execsql_test 3.1 {
  SELECT * FROM t0 WHERE ((c0 NOT NULL) AND 1) OR (c0 == NULL);
} {0}

finish_test
Changes to test/notnullfault.test.
49
50
51
52
53
54
55
56
    WINDOW win AS (ORDER BY c IS NULL)
  }
} -test {
  faultsim_test_result {0 {}}
}

finish_test








<
49
50
51
52
53
54
55

    WINDOW win AS (ORDER BY c IS NULL)
  }
} -test {
  faultsim_test_result {0 {}}
}

finish_test

Changes to test/nulls1.test.
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
  2 1 11   2 2 12   2 {} 1 
  3 2 12   3 {} 1   3 {} 3
}
do_eqp_test 5.3 {
  SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a, b NULLS LAST
} {
  QUERY PLAN
  `--SEARCH TABLE t4 USING INDEX t4ab (a=?)
}

do_execsql_test 5.4 {
  SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a DESC, b DESC NULLS FIRST
} {
  3 {} 3   3 {} 1   3 2 12   
  2 {} 1   2 2 12   2 1 11   
  1 {} 1   1 2 12   1 1 11   
}
do_eqp_test 5.5 {
  SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a DESC, b DESC NULLS FIRST
} {
  QUERY PLAN
  `--SEARCH TABLE t4 USING INDEX t4ab (a=?)
}

#-------------------------------------------------------------------------
#
do_execsql_test 6.0 {
  CREATE TABLE t5(a, b, c);
  WITH s(i) AS (







|













|







180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
  2 1 11   2 2 12   2 {} 1 
  3 2 12   3 {} 1   3 {} 3
}
do_eqp_test 5.3 {
  SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a, b NULLS LAST
} {
  QUERY PLAN
  `--SEARCH 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 (
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  CREATE INDEX t5ab ON t5(a, b, c);
  SELECT a,b FROM t5 WHERE a=1 ORDER BY b NULLS LAST, c;
} $res1
do_eqp_test 6.1.2 {
  SELECT a,b FROM t5 WHERE a=1 ORDER BY b NULLS LAST, c;
} {
  QUERY PLAN
  `--SEARCH TABLE t5 USING COVERING INDEX t5ab (a=?)
}
do_execsql_test 6.2.1 {
  SELECT a,b FROM t5 WHERE a=1 ORDER BY b DESC NULLS FIRST, c DESC 
} $res2
do_eqp_test 6.2.2 {
  SELECT a,b FROM t5 WHERE a=1 ORDER BY b DESC NULLS FIRST, c DESC 
} {
  QUERY PLAN
  `--SEARCH TABLE t5 USING COVERING INDEX t5ab (a=?)
}

#-------------------------------------------------------------------------
do_execsql_test 7.0 {
  CREATE TABLE t71(a, b, c);
  CREATE INDEX t71abc ON t71(a, b, c);








|








|







220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  CREATE INDEX t5ab ON t5(a, b, c);
  SELECT a,b FROM t5 WHERE a=1 ORDER BY b NULLS LAST, c;
} $res1
do_eqp_test 6.1.2 {
  SELECT a,b FROM t5 WHERE a=1 ORDER BY b NULLS LAST, c;
} {
  QUERY PLAN
  `--SEARCH 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);

290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
  1 10 a 1 10 b 1 10 c 1 10 d 1 10 NULL 1 10 NULL
  2 10 a 2 10 b 2 10 c 2 10 d 2 10 NULL 2 10 NULL
}

do_eqp_test 9.4 {
  SELECT c1, c2, ifnull(c3, 'NULL') FROM v0 
  WHERE c2=10 ORDER BY c1, c3 NULLS LAST
} {SEARCH TABLE v0 USING COVERING INDEX v3 (ANY(c1) AND c2=?)}


# 2020-03-01 ticket e12a0ae526bb51c7
# NULLS LAST on a LEFT JOIN
#
reset_db
do_execsql_test 10.10 {







|







290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
  1 10 a 1 10 b 1 10 c 1 10 d 1 10 NULL 1 10 NULL
  2 10 a 2 10 b 2 10 c 2 10 d 2 10 NULL 2 10 NULL
}

do_eqp_test 9.4 {
  SELECT c1, c2, ifnull(c3, 'NULL') FROM v0 
  WHERE c2=10 ORDER BY c1, c3 NULLS LAST
} {SEARCH v0 USING COVERING INDEX v3 (ANY(c1) AND c2=?)}


# 2020-03-01 ticket e12a0ae526bb51c7
# NULLS LAST on a LEFT JOIN
#
reset_db
do_execsql_test 10.10 {
Changes to test/optfuzz.c.
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
** 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







<







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

#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.
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
  CREATE INDEX i1 ON t1(a);
}

do_eqp_test 8.1 {
  SELECT * FROM t1 ORDER BY a, b;
} {
  QUERY PLAN
  |--SCAN TABLE t1 USING INDEX i1
  `--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
  )







|







512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
  CREATE INDEX i1 ON t1(a);
}

do_eqp_test 8.1 {
  SELECT * FROM t1 ORDER BY a, b;
} {
  QUERY PLAN
  |--SCAN t1 USING INDEX i1
  `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}

do_execsql_test 8.2 {
  WITH cnt(i) AS (
    SELECT 1 UNION ALL SELECT i+1 FROM cnt WHERE i<10000
  )
Changes to test/permutations.test.
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
  unregister_jt_vfs
} -files [test_set $::allquicktests -exclude {
  wal* incrvacuum.test ioerr.test corrupt4.test io.test crash8.test 
  async4.test bigfile.test backcompat.test e_wal* fstat.test mmap2.test
  pager1.test syscall.test tkt3457.test *malloc* mmap* multiplex* nolock*
  pager2.test *fault* rowal* snapshot* superlock* symlink.test
  delete_db.test shmlock.test chunksize.test
  busy2.test avfs.test
}]

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







|







985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
  unregister_jt_vfs
} -files [test_set $::allquicktests -exclude {
  wal* incrvacuum.test ioerr.test corrupt4.test io.test crash8.test 
  async4.test bigfile.test backcompat.test e_wal* fstat.test mmap2.test
  pager1.test syscall.test tkt3457.test *malloc* mmap* multiplex* nolock*
  pager2.test *fault* rowal* snapshot* superlock* symlink.test
  delete_db.test shmlock.test chunksize.test
  busy2.test avfs.test external_reader.test
}]

if {[info commands register_demovfs] != ""} {
  test_suite "demovfs" -description {
    Check that the demovfs (code in test_demovfs.c) more or less works.
  } -initialize {
    register_demovfs
Changes to test/releasetest.tcl.
46
47
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
}

array set ::Configs [strip_comments {
  "Default" {
    -O2
    --disable-amalgamation --disable-shared
    --enable-session
    -DSQLITE_ENABLE_DESERIALIZE
  }
  "Sanitize" {
    CC=clang -fsanitize=undefined
    -DSQLITE_ENABLE_STAT4

    --enable-session
  }
  "Stdcall" {
    -DUSE_STDCALL=1
    -O2
  }
  "Have-Not" {







<




>







46
47
48
49
50
51
52

53
54
55
56
57
58
59
60
61
62
63
64
}

array set ::Configs [strip_comments {
  "Default" {
    -O2
    --disable-amalgamation --disable-shared
    --enable-session

  }
  "Sanitize" {
    CC=clang -fsanitize=undefined
    -DSQLITE_ENABLE_STAT4
    -DCONFIG_SLOWDOWN_FACTOR=5.0
    --enable-session
  }
  "Stdcall" {
    -DUSE_STDCALL=1
    -O2
  }
  "Have-Not" {
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
    -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" {







<







175
176
177
178
179
180
181

182
183
184
185
186
187
188
    -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-json1 --enable-fts5 --enable-session
  }
  "Locking-Style" {
    -O2
    -DSQLITE_ENABLE_LOCKING_STYLE=1
  }
  "Apple" {
250
251
252
253
254
255
256

257
258
259
260
261
262
263
    -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.







>







249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
    -DHAVE_USLEEP=1
  }
  "Valgrind" {
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_ENABLE_FTS4
    -DSQLITE_ENABLE_RTREE
    -DSQLITE_ENABLE_HIDDEN_COLUMNS
    -DCONFIG_SLOWDOWN_FACTOR=8.0
    --enable-json1
  }

  # The next group of configurations are used only by the
  # Failure-Detection platform.  They are all the same, but we need
  # different names for them all so that they results appear in separate
  # subdirectories.
Changes to test/releasetest_data.tcl.
47
48
49
50
51
52
53
54
55
56
57
58

59
60
61
62
63
64
65
}

array set ::Configs [strip_comments {
  "Default" {
    -O2
    --disable-amalgamation --disable-shared
    --enable-session
    -DSQLITE_ENABLE_DESERIALIZE
  }
  "Sanitize" {
    CC=clang -fsanitize=address,undefined
    -DSQLITE_ENABLE_STAT4

    --enable-debug
    --enable-all
  }
  "Stdcall" {
    -DUSE_STDCALL=1
    -O2
  }







<




>







47
48
49
50
51
52
53

54
55
56
57
58
59
60
61
62
63
64
65
}

array set ::Configs [strip_comments {
  "Default" {
    -O2
    --disable-amalgamation --disable-shared
    --enable-session

  }
  "Sanitize" {
    CC=clang -fsanitize=address,undefined
    -DSQLITE_ENABLE_STAT4
    -DCONFIG_SLOWDOWN_FACTOR=5.0
    --enable-debug
    --enable-all
  }
  "Stdcall" {
    -DUSE_STDCALL=1
    -O2
  }
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
    -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" {







<







183
184
185
186
187
188
189

190
191
192
193
194
195
196
    -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-json1 --enable-fts5 --enable-session
  }
  "Locking-Style" {
    -O2
    -DSQLITE_ENABLE_LOCKING_STYLE=1
  }
  "Apple" {
254
255
256
257
258
259
260

261
262
263
264
265
266
267
    -DSQLITE_OMIT_LOOKASIDE=1
  }
  "Valgrind" {
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_ENABLE_FTS4
    -DSQLITE_ENABLE_RTREE
    -DSQLITE_ENABLE_HIDDEN_COLUMNS

    --enable-json1
  }

  "Windows-Memdebug" {
    MEMDEBUG=1
    DEBUG=3
  }







>







253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
    -DSQLITE_OMIT_LOOKASIDE=1
  }
  "Valgrind" {
    -DSQLITE_ENABLE_STAT4
    -DSQLITE_ENABLE_FTS4
    -DSQLITE_ENABLE_RTREE
    -DSQLITE_ENABLE_HIDDEN_COLUMNS
    -DCONFIG_SLOWDOWN_FACTOR=8.0
    --enable-json1
  }

  "Windows-Memdebug" {
    MEMDEBUG=1
    DEBUG=3
  }
623
624
625
626
627
628
629
630
631
} elseif {[string match ${cmd}* platforms] && $n==0} {
  main_platforms
} elseif {[string match ${cmd}* tests]} {
  main_tests {*}[lrange $argv 1 end]
} else {
  usage
}









<
<
623
624
625
626
627
628
629


} 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/returning1.test.
111
112
113
114
115
116
117





















































































































































































118




















119

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






















































































































































































finish_test





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
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
} {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"} *}

finish_test
Changes to test/rollback2.test.
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}
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







|







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







|







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 t1 USING INDEX i1}
do_rollback_test 4.3 -setup {
  BEGIN;
    DELETE FROM t1 WHERE (i%2)==1;
} -select {
  SELECT i FROM t1 WHERE (i%2)==0 ORDER BY h ASC;
} -result {
  2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40
Changes to test/rowvalue.test.
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
  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=?)"

  2 "SELECT * FROM xy WHERE (k, j) < (2, 3)" {1 1 1 2 2 2}
    "SCAN TABLE xy"

  3 "SELECT * FROM xy WHERE (i, j) < (2, 3)" {1 1 1 2 2 2}
    "SEARCH TABLE 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>?)"

  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>?)"

} {
  do_eqp_test 7.$tn.1 $sql $eqp
  do_execsql_test 7.$tn.2 $sql $res
}

do_execsql_test 8.0 {







|


|


|


|


|







171
172
173
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 xy USING INTEGER PRIMARY KEY (rowid=?)"

  2 "SELECT * FROM xy WHERE (k, j) < (2, 3)" {1 1 1 2 2 2}
    "SCAN xy"

  3 "SELECT * FROM xy WHERE (i, j) < (2, 3)" {1 1 1 2 2 2}
    "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 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 xy USING INTEGER PRIMARY KEY (rowid>?)"

} {
  do_eqp_test 7.$tn.1 $sql $eqp
  do_execsql_test 7.$tn.2 $sql $res
}

do_execsql_test 8.0 {
Changes to test/rowvalue4.test.
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

    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=?)}

  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=?)}

  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>?)}

  do_eqp_test 3.2.1 { SELECT * FROM c1 WHERE a=1 AND c>1 } \
     {SEARCH TABLE 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=?)}

  do_eqp_test 3.2.3 { SELECT * FROM c1 WHERE a=1 AND c>=1 } \
     {SEARCH TABLE 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=?)}

  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)>(?,?))}

  do_eqp_test 3.2.6 { SELECT * FROM c1 WHERE a=1 AND (c, +b)>(1, 'c') } \
     {SEARCH TABLE c1 USING INDEX c1ab (a=?)}

}

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

do_execsql_test 5.0 {
  CREATE TABLE d1(x, y);







|


|


|


|


|


|


|


|


|







181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
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 c1 USING INDEX c1cd (c=?)}

  do_eqp_test 3.1.2 { SELECT * FROM c1 WHERE a=1 AND b>'d' AND c=2 } \
     {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 c1 USING INDEX c1ab (a=? AND b>?)}

  do_eqp_test 3.2.1 { SELECT * FROM c1 WHERE a=1 AND c>1 } \
     {SEARCH c1 USING INDEX c1cd (c>?)}

  do_eqp_test 3.2.2 { SELECT * FROM c1 WHERE a=1 AND c>0 } \
     {SEARCH c1 USING INDEX c1ab (a=?)}

  do_eqp_test 3.2.3 { SELECT * FROM c1 WHERE a=1 AND c>=1 } \
     {SEARCH c1 USING INDEX c1ab (a=?)}

  do_eqp_test 3.2.4 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'c') } \
     {SEARCH c1 USING INDEX c1ab (a=?)}

  do_eqp_test 3.2.5 { SELECT * FROM c1 WHERE a=1 AND (c, d)>(1, 'o') } \
     {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 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

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 xxxxxx
  |  `--SCAN TABLE d1
  `--LIST SUBQUERY xxxxxx
     `--SCAN TABLE 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)>(?,?))}

do_eqp_test 6.2 {
  SELECT * FROM e1 WHERE (a, b) < (?, ?)
} {SEARCH TABLE 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)>(?,?))}

do_eqp_test 6.4 {
  SELECT * FROM e1 WHERE c = ? AND (d, e) < (?, ?)
} {SEARCH TABLE 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)<(?,?))}

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

do_execsql_test 7.1 {
  CREATE TABLE f1(a, b, c);
  CREATE INDEX f1ab ON f1(a, b);
}







|

|

|










|



|



|



|



|







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 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 e1 USING INDEX e1ab ((a,b)>(?,?))}

do_eqp_test 6.2 {
  SELECT * FROM e1 WHERE (a, b) < (?, ?)
} {SEARCH e1 USING INDEX e1ab ((a,b)<(?,?))}

do_eqp_test 6.3 {
  SELECT * FROM e1 WHERE 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 e1 USING INDEX e1cde (c=? AND (d,e)<(?,?))}

do_eqp_test 6.5 {
  SELECT * FROM e1 WHERE (d, e) BETWEEN (?, ?) AND (?, ?) AND c = ?
} {SEARCH e1 USING INDEX e1cde (c=? AND (d,e)>(?,?) AND (d,e)<(?,?))}

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

do_execsql_test 7.1 {
  CREATE TABLE f1(a, b, c);
  CREATE INDEX f1ab ON f1(a, b);
}
Changes to test/scanstatus.test.
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  }

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

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

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

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

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

#-------------------------------------------------------------------------
# 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=?)}
}

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=?)}
}

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<?)}
}

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>?)}
}

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<?)}
}

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<?)}
}

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=?)}
}

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=?)}
}

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=?)}
}

#-------------------------------------------------------------------------
# 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=?)}
  nLoop 1 nVisit 1 nEst 10.0 zName a1bc 
  zExplain {SEARCH TABLE 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<?)}
  nLoop 1 nVisit 21 nEst 16384.0 zName a1bc
  zExplain {SEARCH TABLE 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<?)}
  nLoop 10 nVisit 90 nEst 16384.0 zName a1a
  zExplain {SEARCH TABLE a1 AS 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=?)}
}

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=?)}
}

#-------------------------------------------------------------------------
# Test that scanstatus() data is not available for searches performed
# by triggers.
#
# It is available for searches performed as part of FK processing, but 







|
|







|
|








|
|








|
|








|
|



















|







|







|







|







|












|







|







|







|



















|

|







|

|








|

|







|







|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  }

  uplevel [list do_test $tn [list set {} $ret] [list {*}$res]]
}

do_execsql_test 1.1 { SELECT count(*) FROM t1, t2; } 6
do_scanstatus_test 1.2 {
  nLoop 1 nVisit 2 nEst 1048576.0 zName t1 zExplain {SCAN 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 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 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 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 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 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 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 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 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 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 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 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 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 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 a1 USING INDEX a1a (a=?)}
  nLoop 1 nVisit 1 nEst 10.0 zName a1bc 
  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 a1 USING INDEX a1a (a>? AND a<?)}
  nLoop 1 nVisit 21 nEst 16384.0 zName a1bc
  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 y USING COVERING INDEX a1bc (b>? AND b<?)}
  nLoop 10 nVisit 90 nEst 16384.0 zName a1a
  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 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 a1 USING INTEGER PRIMARY KEY (rowid=?)}
}

#-------------------------------------------------------------------------
# Test that scanstatus() data is not available for searches performed
# by triggers.
#
# It is available for searches performed as part of FK processing, but 
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
  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=?)}

  nLoop 1 nVisit 3 nEst 262144.0 zName c1 zExplain {SCAN TABLE c1}
}

#-------------------------------------------------------------------------
# Further tests of different scan types.
#
reset_db
proc tochar {i} {







|

|







262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
  CREATE TABLE c1(y REFERENCES p1);
  INSERT INTO c1 VALUES(1), (2), (3);
  PRAGMA foreign_keys=on;
}
do_execsql_test    4.2.1 { DELETE FROM p1 WHERE x=4 }
do_scanstatus_test 4.2.2 { 
  nLoop 1 nVisit 1 nEst 1.0 zName sqlite_autoindex_p1_1 
  zExplain {SEARCH p1 USING INDEX sqlite_autoindex_p1_1 (x=?)}

  nLoop 1 nVisit 3 nEst 262144.0 zName c1 zExplain {SCAN c1}
}

#-------------------------------------------------------------------------
# Further tests of different scan types.
#
reset_db
proc tochar {i} {
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
}

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 2 nEst 8.0 zName sqlite_autoindex_t1_1
  zExplain {SEARCH TABLE 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=?)}
}

do_eqp_test 5.3.1 {
  SELECT count(*) FROM t2 WHERE y = 'j';
} {SEARCH TABLE 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=?)}
}

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=?)
}
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 10 nVisit 200 nEst 56.0 zName t2xy 
  zExplain {SEARCH TABLE 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=?)
}
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 501 nVisit 200 nEst 20.0 zName auto-index zExplain
  {SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)}
}

#-------------------------------------------------------------------------
# Virtual table scans
#
ifcapable fts3 {
  do_execsql_test 6.0 {







|

|







|




|





|






|
|






|

|






|
|





|

|







309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
}

do_execsql_test 5.1.1 {
  SELECT count(*) FROM t1 WHERE a IN (SELECT b FROM t1 AS ii)
} {2}
do_scanstatus_test 5.1.2 { 
  nLoop 1 nVisit 10 nEst 10.0 zName t1bc 
  zExplain {SCAN ii USING COVERING INDEX t1bc}
  nLoop 1 nVisit 2 nEst 8.0 zName sqlite_autoindex_t1_1
  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 t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
}

do_eqp_test 5.3.1 {
  SELECT count(*) FROM t2 WHERE y = 'j';
} {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 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 t1 USING COVERING INDEX t1bc
  `--SEARCH t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)
}
do_execsql_test 5.4.2 {
  SELECT count(*) FROM t1, t2 WHERE y = c;
} {200}
do_scanstatus_test 5.4.3 { 
  nLoop 1 nVisit 10 nEst 10.0 zName t1bc 
  zExplain {SCAN t1 USING COVERING INDEX t1bc}
  nLoop 10 nVisit 200 nEst 56.0 zName t2xy 
  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 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 t3}
  nLoop 501 nVisit 200 nEst 20.0 zName auto-index zExplain
  {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
    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:}
  }
}


finish_test







|





388
389
390
391
392
393
394
395
396
397
398
399
400
    INSERT INTO ft1 VALUES('a d e f b j j c g d');
  }
  do_execsql_test 6.1.1 {
    SELECT count(*) FROM ft1 WHERE ft1 MATCH 'd'
  } {6}
  do_scanstatus_test 6.1.2 { 
    nLoop 1 nVisit 6 nEst 24.0 zName ft1 zExplain 
    {SCAN ft1 VIRTUAL TABLE INDEX 3:}
  }
}


finish_test
Changes to test/select4.test.
1021
1022
1023
1024
1025
1026
1027














1028
1029
  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}
















finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>


1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
  SELECT * FROM t1;
} {123}
do_execsql_test select4-18.3 {
  SELECT * FROM t1 AS z1 JOIN t1 AS z2 USING(aa)
   WHERE abs(z1.aa)=z2.aa AND z1.aa=123;
} {123}

# 2021-03-31 Fix an assert() problem in the logic at the end of sqlite3Select()
# that validates AggInfo.  The checks to ensure that AggInfo.aCol[].pCExpr
# references a valid expression was looking at an expression that had been
# deleted by the truth optimization in sqlite3ExprAnd() which was invoked by
# the push-down optimization.  This is harmless in delivery builds, as that code
# only runs with SQLITE_DEBUG.  But it should still be fixed.  The problem
# was discovered by dbsqlfuzz (crash-dece7b67a3552ed7e571a7bda903afd1f7bd9b21)
#
reset_db
do_execsql_test select4-19.1 {
  CREATE TABLE t1(x);
  INSERT INTO t1 VALUES(99);
  SELECT sum((SELECT 1 FROM (SELECT 2 WHERE x IS NULL) WHERE 0)) FROM t1;
} {{}}

finish_test
Changes to test/select5.test.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#    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 {







<







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


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









 
finish_test







|
|
>
>
>
>
>
>
|

246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
} {two 3 one 6}
do_test select5-8.8 {
  execsql {
    SELECT a, count(*) FROM t8a, t8b GROUP BY a ORDER BY 2;
  }
} {two 3 one 9}

# 2021-04-26 forum https://sqlite.org/forum/forumpost/74330094d8
reset_db
do_execsql_test select5-9.1 {
  CREATE TABLE t1(a INT, b INT);
  INSERT INTO t1(a,b) VALUES(1,null),(null,null),(1,null);
  CREATE UNIQUE INDEX t1b ON t1(abs(b));
  SELECT quote(a), quote(b), '|' FROM t1 GROUP BY a, abs(b);
} {NULL NULL | 1 NULL |}

finish_test
Changes to test/select9.test.
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
       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 "*"
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"
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.

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







|





|





|







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/}  ;# 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/}  ;# 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/}   ;# 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
  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
     |  `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
     `--RIGHT
        |--SCAN TABLE 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()







|


|







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 t5 USING INDEX i2
     |  `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
     `--RIGHT
        |--SCAN t4 USING INDEX i1
        `--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
}

do_execsql_test 4.1.3 {
  SELECT c, d FROM t5 
  UNION ALL
  SELECT a, b FROM t4 WHERE f()==f()
1463
1464
1465
1466
1467
1468
1469
1470















1471
  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;
} {}
















finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
  SELECT * FROM t1, t2 WHERE c1=(SELECT 123 INTERSECT SELECT c2 FROM t5) AND c1=123;
} {123 123}
do_execsql_test 7.4 {
  CREATE TABLE a(b);
  CREATE VIEW c(d) AS SELECT b FROM a ORDER BY b;
  SELECT sum(d) OVER( PARTITION BY(SELECT 0 FROM c JOIN a WHERE b =(SELECT b INTERSECT SELECT d FROM c) AND b = 123)) FROM c;
} {}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 8.0 {
  CREATE TABLE x1(x);
  CREATE TABLE t1(a, b, c, d);
  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t1b ON t1(b);
}

do_execsql_test 8.1 {
      SELECT 'ABCD' FROM t1 
      WHERE (a=? OR b=?) 
      AND (0 OR (SELECT 'xyz' INTERSECT SELECT a ORDER BY 1))
} {}

finish_test
Changes to test/selectD.test.
165
166
167
168
169
170
171
172
173
174
  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*/}

finish_test







|


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 x2 USING AUTOMATIC/}

finish_test
Changes to test/skipscan1.test.
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
} {/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}/}
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);








|







337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
} {/USING INDEX t9a_ab .ANY.a. AND b=./}


optimization_control db skip-scan 0
do_execsql_test skipscan1-9.3 {
  EXPLAIN QUERY PLAN
  SELECT  * FROM t9a WHERE b IN (SELECT x FROM t9b WHERE y!=5);
} {/{SCAN t9a}/}
optimization_control db skip-scan 1

do_execsql_test skipscan1-2.1 {
  CREATE TABLE t6(a TEXT, b INT, c INT, d INT);
  CREATE INDEX t6abc ON t6(a,b,c);
  INSERT INTO t6 VALUES('abc',123,4,5);

390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
    FROM t1 WHERE t1.c3 = 1;
} {3 0 1 NULL | 0 4 1 NULL | 5 6 1 NULL |}
do_eqp_test skipscan1-3.2 {
  SELECT DISTINCT quote(c1), quote(c2), quote(c3), quote(c4), '|'
    FROM t1 WHERE t1.c3 = 1;
} {
  QUERY PLAN
  |--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (ANY(c4) AND c3=?)
  `--USE TEMP B-TREE FOR DISTINCT
}

# 2020-01-06 ticket 304017f5f04a0035
#
reset_db
do_execsql_test skipscan1-4.10 {







|







390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
    FROM t1 WHERE t1.c3 = 1;
} {3 0 1 NULL | 0 4 1 NULL | 5 6 1 NULL |}
do_eqp_test skipscan1-3.2 {
  SELECT DISTINCT quote(c1), quote(c2), quote(c3), quote(c4), '|'
    FROM t1 WHERE t1.c3 = 1;
} {
  QUERY PLAN
  |--SEARCH t1 USING INDEX sqlite_autoindex_t1_1 (ANY(c4) AND c3=?)
  `--USE TEMP B-TREE FOR DISTINCT
}

# 2020-01-06 ticket 304017f5f04a0035
#
reset_db
do_execsql_test skipscan1-4.10 {
Changes to test/skipscan2.test.
195
196
197
198
199
200
201
202
203
204
205
206
  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=?)}



finish_test







|




195
196
197
198
199
200
201
202
203
204
205
206
  for {set i 0} {$i < 1000} {incr i} {
    execsql { INSERT INTO t3 VALUES($i%2, $i, 'xyz') }
  }
  execsql { ANALYZE }
} {}
do_eqp_test skipscan2-3.3eqp {
  SELECT * FROM t3 WHERE b=42;
} {SEARCH t3 USING PRIMARY KEY (ANY(a) AND b=?)}



finish_test
Changes to test/skipscan5.test.
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  }
  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*/}
  4  "b > 18 AND b < 25"       {/*ANY(a) AND b>? AND b<?*/}
  5  "b > 16"                  {/*ANY(a) AND b>?*/}
  6  "b > 5"                   {/*SCAN TABLE t1*/}
  7  "b < 15"                  {/*SCAN TABLE t1*/}
  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*/}
  13 "b > '18' AND b < '25'"   {/*ANY(a) AND b>? AND b<?*/}
  14 "b > '16'"                {/*ANY(a) AND b>?*/}
  15 "b > '5'"                 {/*SCAN TABLE t1*/}
  16 "b < '15'"                {/*SCAN TABLE t1*/}
  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
}








|


|
|




|


|
|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  }
  execsql ANALYZE
} {}

foreach {tn q res} {
  1  "b = 5"                   {/*ANY(a) AND b=?*/}
  2  "b > 12 AND b < 16"       {/*ANY(a) AND b>? AND b<?*/}
  3  "b > 2 AND b < 16"        {/*SCAN t1*/}
  4  "b > 18 AND b < 25"       {/*ANY(a) AND b>? AND b<?*/}
  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 t1*/}
  13 "b > '18' AND b < '25'"   {/*ANY(a) AND b>? AND b<?*/}
  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
      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*/}
    3 { c > 'q' }                     {/*ANY(a) AND ANY(b) AND c>?*/}
    4 { c > 'e' }                     {/*SCAN TABLE t2*/}
    5 { c < 'q' }                     {/*SCAN TABLE 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
  }

}







|

|
|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
      execsql { INSERT INTO t2 VALUES($a, $b, $c, $d) }
    }
    execsql ANALYZE
  } {}

  foreach {tn2 q res} {
    1 { c BETWEEN 'd' AND 'e' }       {/*ANY(a) AND ANY(b) AND c>? AND c<?*/}
    2 { c BETWEEN 'b' AND 'r' }       {/*SCAN t2*/}
    3 { c > 'q' }                     {/*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
    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*/}
  4 "b > X'5555'"                      {/*ANY(a) AND b>?*/}
  5 "b > 'zzz'"                        {/*ANY(a) AND b>?*/}
  6 "b < 'zzz'"                        {/*SCAN TABLE t3*/}
} {
  set sql "EXPLAIN QUERY PLAN SELECT * FROM t3 WHERE $q" 
  do_execsql_test 3.3.$tn $sql $res
}

finish_test







|
|


|






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 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 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
  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=?)}

# 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=?)}

finish_test







|






|


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 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 t2 USING INDEX t2_a (a=?)}

finish_test
Changes to test/tabfunc01.test.
222
223
224
225
226
227
228












































229
230
231
232
233
234
235
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 |}













































# Free up memory allocations
intarray_addr
int64array_addr
doublearray_addr
textarray_addr








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
do_test tabfunc01-751 {
  db eval {
    SELECT aa.value, bb.value, '|'
      FROM carray(inttoptr($PTR4),5,'double') AS aa
      LEFT JOIN carray(inttoptr($PTR5),5,'char*') AS bb ON aa.rowid=bb.rowid;
  }
} {5.0 x5 | 7.0 x7 | 13.0 x13 | 17.0 x17 | 23.0 x23 |}

ifcapable altertable {
  do_test tabfunc01-800 {
    catchsql {
      ALTER TABLE generate_series ADD COLUMN col2;
    }
  } {1 {virtual tables may not be altered}}
  do_test tabfunc01-810 {
    catchsql {
      ALTER TABLE generate_series RENAME TO flubber;
    }
  } {1 {table generate_series may not be altered}}
  do_test tabfunc01-820 {
    catchsql {
      ALTER TABLE generate_series RENAME  start TO flubber;
    }
  } {1 {table generate_series may not be altered}}
  do_test tabfunc01-830 {
    catchsql {
      ALTER TABLE generate_series DROP COLUMN start;
    }
  } {1 {table generate_series may not be altered}}
  do_test tabfunc01-900 {
    catchsql {
      ALTER TABLE pragma_compile_options ADD COLUMN col2;
    }
  } {1 {virtual tables may not be altered}}
  do_test tabfunc01-910 {
    catchsql {
      ALTER TABLE pragma_compile_options RENAME TO flubber;
    }
  } {1 {table pragma_compile_options may not be altered}}
  do_test tabfunc01-920 {
    catchsql {
      ALTER TABLE pragma_compile_options RENAME  start TO flubber;
    }
  } {1 {table pragma_compile_options may not be altered}}
  do_test tabfunc01-930 {
    catchsql {
      ALTER TABLE pragma_compile_options DROP COLUMN start;
    }
  } {1 {table pragma_compile_options may not be altered}}
}


# Free up memory allocations
intarray_addr
int64array_addr
doublearray_addr
textarray_addr

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

do_eqp_test 2.2 { SELECT DISTINCT y FROM t2 } \
  {SCAN TABLE 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=?)}

do_eqp_test 2.4 { SELECT DISTINCT x, y FROM t2 WHERE x=10 } \
  {SEARCH TABLE t2 USING INDEX t2x (x=?)}


finish_test







|


|


|


|



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 t2 USING COVERING INDEX t2x}

do_eqp_test 2.2 { SELECT DISTINCT y FROM t2 } \
  {SCAN t2 USING COVERING INDEX t2y}

do_eqp_test 2.3 { SELECT DISTINCT x, y FROM t2 WHERE y=10 } \
  {SEARCH t2 USING INDEX t2y (y=?)}

do_eqp_test 2.4 { SELECT DISTINCT x, y FROM t2 WHERE x=10 } \
  {SEARCH t2 USING INDEX t2x (x=?)}


finish_test
Changes to test/tkt-78e04e52ea.test.
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
do_test tkt-78e04-1.3 {
  execsql {
    CREATE INDEX i1 ON ""("" COLLATE nocase);
  }
} {}
do_test tkt-78e04-1.4 {
 db eval {EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE '1e5%';}
} {/*SCAN TABLE  USING COVERING INDEX i1*/}
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=?)*/}
do_test tkt-78e04-2.2 {
  execsql {
    DROP INDEX "";
    EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE x=2;
  }
} {/*SCAN TABLE t2*/}

finish_test







|












|





|


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
do_test tkt-78e04-1.3 {
  execsql {
    CREATE INDEX i1 ON ""("" COLLATE nocase);
  }
} {}
do_test tkt-78e04-1.4 {
 db eval {EXPLAIN QUERY PLAN SELECT "" FROM "" WHERE "" LIKE '1e5%';}
} {/*SCAN  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 t2 USING COVERING INDEX  (x=?)*/}
do_test tkt-78e04-2.2 {
  execsql {
    DROP INDEX "";
    EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE x=2;
  }
} {/*SCAN t2*/}

finish_test
Changes to test/tkt-b75a9ca6b0.test.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  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 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}








|
|







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 t1 USING COVERING INDEX i1}
set tblscan {SCAN t1}
set grpsort {USE TEMP B-TREE FOR GROUP BY}
set sort    {USE TEMP B-TREE FOR ORDER BY}

foreach {tn q res eqp} [subst -nocommands {
  1 "SELECT * FROM t1 GROUP BY x, y ORDER BY x,y"
  {1 3  2 2  3 1} {$idxscan}

Changes to test/tkt3442.test.
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

# These tests perform an EXPLAIN QUERY PLAN on both versions of the 
# SELECT referenced in ticket #3442 (both '5000' and "5000") 
# and verify that the query plan is the same.
#
do_eqp_test tkt3442-1.2 {
  SELECT node FROM listhash WHERE id='5000' LIMIT 1;
} {SEARCH TABLE listhash USING INDEX ididx (id=?)}
do_eqp_test tkt3442-1.3 {
  SELECT node FROM listhash WHERE id="5000" LIMIT 1;
} {SEARCH TABLE 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=?)}

do_test tkt3442-1.5 {
  catchsql {
    SELECT node FROM listhash WHERE id=[5000] LIMIT 1;
  }
} {1 {no such column: 5000}}








|


|






|







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

# These tests perform an EXPLAIN QUERY PLAN on both versions of the 
# SELECT referenced in ticket #3442 (both '5000' and "5000") 
# and verify that the query plan is the same.
#
do_eqp_test tkt3442-1.2 {
  SELECT node FROM listhash WHERE id='5000' LIMIT 1;
} {SEARCH listhash USING INDEX ididx (id=?)}
do_eqp_test tkt3442-1.3 {
  SELECT node FROM listhash WHERE id="5000" LIMIT 1;
} {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 listhash USING INDEX ididx (id=?)}

do_test tkt3442-1.5 {
  catchsql {
    SELECT node FROM listhash WHERE id=[5000] LIMIT 1;
  }
} {1 {no such column: 5000}}

Changes to test/tpch01.test.
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
                               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*/}
do_test tpch01-1.1b {
  set ::eqpres
} {/.* customer .* nation AS n1 .*/}
do_test tpch01-1.1c {
  set ::eqpres
} {/.* supplier .* nation AS 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=?)
  |--USE TEMP B-TREE FOR GROUP BY
  `--USE TEMP B-TREE FOR ORDER BY
}

finish_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
                               and p_type = 'LARGE PLATED STEEL'
               ) as all_nations
       group by
               o_year
       order by
               o_year;}]
  set ::eqpres
} {/*SEARCH part USING INDEX bootleg_pti *SEARCH lineitem USING INDEX lpki2*/}
do_test tpch01-1.1b {
  set ::eqpres
} {/.* customer .* n1 .*/}
do_test tpch01-1.1c {
  set ::eqpres
} {/.* 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 orders USING INDEX odi (O_ORDERDATE>? AND O_ORDERDATE<?)
  |--SEARCH customer USING INDEX cpki (C_CUSTKEY=?)
  |--SEARCH nation USING INDEX npki (N_NATIONKEY=?)
  |--SEARCH lineitem USING INDEX lpki (L_ORDERKEY=?)
  |--USE TEMP B-TREE FOR GROUP BY
  `--USE TEMP B-TREE FOR ORDER BY
}

finish_test
Changes to test/transitive1.test.
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354



























355
356
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/}
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/}




























finish_test







|






|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
do_execsql_test transitive1-560 {
  CREATE INDEX c1x ON c1(x);
  SELECT * FROM c1 WHERE x=y AND y=z AND z='abc';
} {ABC ABC abc}
do_execsql_test transitive1-560eqp {
  EXPLAIN QUERY PLAN
  SELECT * FROM c1 WHERE x=y AND y=z AND z='abc';
} {/SCAN 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 c1 USING INDEX c1x/}

# 2021-05-04 forum https://sqlite.org/forum/forumpost/eb8613976a
reset_db
do_execsql_test transitive1-600 {
  CREATE TABLE t0(a0 INT, b1 INT);
  CREATE INDEX t0b1 ON t0(b1);
  CREATE TABLE t1(w,x,y,z3 INT);
  INSERT INTO t0(a0, b1) VALUES (0,1);
  INSERT INTO t1(w,x,y,z3) VALUES (7,8,9,1);
} {}
do_execsql_test transitive1-610 {
  SELECT ALL * FROM t0,t1 WHERE b1=z3 AND a0=z3;
} {}
do_execsql_test transitive1-620 {
  SELECT ALL * FROM t0,t1 WHERE likely(b1=z3) AND a0=z3;
} {}
do_execsql_test transitive1-630 {
  DROP TABLE t0;
  DROP TABLE t1;
  CREATE TABLE t0(c0 INT, c1 INT UNIQUE);
  CREATE TABLE t1(c0 INT);
  INSERT INTO t0(c0, c1) VALUES (0, 1);
  INSERT INTO t1(c0) VALUES (1);
  SELECT ALL * FROM t1 NATURAL JOIN t0 WHERE (t1.c0=t0.c1);
  SELECT ALL * FROM t1 NATURAL JOIN t0 WHERE (likely(t1.c0=t0.c1));
  SELECT ALL * FROM t1,t0 WHERE (likely(t1.c0=t0.c1) AND t1.c0=t0.c0);
} {}

finish_test
Changes to test/trigger2.test.
45
46
47
48
49
50
51

52
53
54
55
56
57
58
# trigger2-6.2[a-f]: UPDATE statements
#
# 7. & 8. Triggers on views fire correctly.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

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







>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# trigger2-6.2[a-f]: UPDATE statements
#
# 7. & 8. Triggers on views fire correctly.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix trigger2
ifcapable {!trigger} {
  finish_test
  return
}

# The tests in this file were written before SQLite supported recursive
# trigger invocation, and some tests depend on that to pass. So disable
765
766
767
768
769
770
771









772







773

774

  END;
  INSERT INTO v2(a,d) VALUES(11,14);
  SELECT * FROM t1;
} {11 {} {} 14}
 
} ;# ifcapable view










integrity_check trigger2-999









finish_test








>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>

>

>
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
  END;
  INSERT INTO v2(a,d) VALUES(11,14);
  SELECT * FROM t1;
} {11 {} {} 14}
 
} ;# ifcapable view

#-------------------------------------------------------------------------
reset_db
do_execsql_test 11.1 {
  CREATE TABLE t1(a INT PRIMARY KEY, b, c REAL, d, e);
  CREATE TABLE t2(a INT, b, c REAL, d, e, PRIMARY KEY(a,b)) WITHOUT ROWID;
  CREATE UNIQUE INDEX t2c ON t2(c);
  CREATE UNIQUE INDEX t2d ON t2(d);
  CREATE UNIQUE INDEX t2e ON t2(e);
}

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

  CREATE TRIGGER tr3 INSTEAD OF INSERT ON v1 BEGIN
    INSERT INTO log VALUES('insert');
  END;
}

do_execsql_test 4.2 {
  DELETE FROM v1 WHERE rowid=1;
} {}

do_execsql_test 4.3 {
  UPDATE v1 SET a=b WHERE rowid=2;
} {}




finish_test







|

|

|

<
|
<
<


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_catchsql_test 4.2 {
  DELETE FROM v1 WHERE rowid=1;
} {1 {no such column: rowid}}

do_catchsql_test 4.3 {
  UPDATE v1 SET a=b WHERE rowid=2;

} {1 {no such column: rowid}}



finish_test
Changes to test/triggerupfrom.test.
167
168
169
170
171
172
173
174
  (2,two)->(twelve,two)
  (4,four)->(fourteen,four)
}



finish_test








<
167
168
169
170
171
172
173

  (2,two)->(twelve,two)
  (4,four)->(fourteen,four)
}



finish_test

Changes to test/unionall.test.
351
352
353
354
355
356
357









358
  )
  SELECT * FROM t5, x, y;
} {
  9 10 1000 100     9 10 1000 400
  9 10 800 100      9 10 800 400
}










finish_test







>
>
>
>
>
>
>
>
>

351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
  )
  SELECT * FROM t5, x, y;
} {
  9 10 1000 100     9 10 1000 400
  9 10 800 100      9 10 800 400
}

# 2021-04-26 dbsqlfuzz 88ed5c66789fced139d148aed823cba7c0926dd7
reset_db
do_execsql_test 7.1 {
  WITH c1(x) AS (VALUES(0) UNION ALL SELECT 100+x FROM c1 WHERE x<100 UNION ALL SELECT 1+x FROM c1 WHERE x<1)
  SELECT x, y, '|'
    FROM c1 AS x1, (SELECT x+1 AS y FROM c1 WHERE x<1 UNION ALL SELECT 1+x FROM c1 WHERE 1<x) AS x2
   ORDER BY x, y;
} {0 1 | 0 101 | 0 102 | 1 1 | 1 101 | 1 102 | 100 1 | 100 101 | 100 102 | 101 1 | 101 101 | 101 102 |}

finish_test
Changes to test/unionall2.test.
30
31
32
33
34
35
36



















37
38
39
    UNION ALL
    SELECT * FROM v1, v2
}

do_execsql_test 1.1 {
  SELECT 1 FROM vA, vA, vA, vA, vA, vA, vA, vA, vA, vA
}





















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
    UNION ALL
    SELECT * FROM v1, v2
}

do_execsql_test 1.1 {
  SELECT 1 FROM vA, vA, vA, vA, vA, vA, vA, vA, vA, vA
}

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

do_execsql_test 2.1 {
  CREATE TABLE y1(a INTEGER, b);
  CREATE TABLE y2(c INTEGER, d);

  CREATE TABLE x3_a(a INTEGER PRIMARY KEY, b TEXT);
  CREATE TABLE x3_b(c INTEGER PRIMARY KEY, d TEXT);
}

do_execsql_test 2.2 {

  SELECT * FROM y1 CROSS JOIN y2 WHERE y1.a=y2.c AND y2.c IN (
    SELECT a FROM x3_a UNION ALL
    SELECT c FROM x3_b ORDER BY 1
  )
}



finish_test
Changes to test/unordered.test.
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  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}
    2   "SELECT * FROM t1 WHERE a > 100"
        {SEARCH TABLE t1 USING INDEX i1 (a>?)}
        {SCAN TABLE 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}
    4   "SELECT max(a) FROM t1"
        {SEARCH TABLE t1 USING COVERING INDEX i1}
        {SEARCH TABLE 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}

    6   "SELECT * FROM t1 WHERE a = ?"
        {SEARCH TABLE t1 USING INDEX i1 (a=?)}
        {SEARCH TABLE t1 USING INDEX i1 (a=?)}
    7   "SELECT count(*) FROM t1"
        {SCAN TABLE t1 USING COVERING INDEX i1}
        {SCAN TABLE t1}
  } {
    do_eqp_test 1.$idxmode.$tn $sql $r($idxmode)
  }
}

finish_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
  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 t1 USING INDEX i1}
        {SCAN t1*USE TEMP B-TREE FOR ORDER BY}
    2   "SELECT * FROM t1 WHERE a > 100"
        {SEARCH t1 USING INDEX i1 (a>?)}
        {SCAN t1}
    3   "SELECT * FROM t1 WHERE a = ? ORDER BY rowid"
        {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 t1 USING COVERING INDEX i1}
        {SEARCH t1}
    5   "SELECT group_concat(b) FROM t1 GROUP BY a"
        {SCAN t1 USING INDEX i1}
        {SCAN t1*USE TEMP B-TREE FOR GROUP BY}

    6   "SELECT * FROM t1 WHERE a = ?"
        {SEARCH t1 USING INDEX i1 (a=?)}
        {SEARCH t1 USING INDEX i1 (a=?)}
    7   "SELECT count(*) FROM t1"
        {SCAN t1 USING COVERING INDEX i1}
        {SCAN t1}
  } {
    do_eqp_test 1.$idxmode.$tn $sql $r($idxmode)
  }
}

finish_test
Changes to test/upfrom1.test.
170
171
172
173
174
175
176
































177
178
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;
} {}

































finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
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
Changes to test/upfrom2.test.
363
364
365
366
367
368
369
370
371
} {
  do_catchsql_test 5.$tn $update \
    "1 {target object/alias may not appear in FROM clause: $nm}"
}


finish_test









<
<
363
364
365
366
367
368
369


} {
  do_catchsql_test 5.$tn $update \
    "1 {target object/alias may not appear in FROM clause: $nm}"
}


finish_test


Changes to test/upfrom3.test.
255
256
257
258
259
260
261
262
      SELECT * FROM c1
    } {a 1  b 12  c 112}

  }]
}

finish_test








<
255
256
257
258
259
260
261

      SELECT * FROM c1
    } {a 1  b 12  c 112}

  }]
}

finish_test

Changes to test/upfromfault.test.
133
134
135
136
137
138
139
140
      error "unexpected result: $res"
    }
  }
}


finish_test








<
133
134
135
136
137
138
139

      error "unexpected result: $res"
    }
  }
}


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
Changes to test/vtab1.test.
979
980
981
982
983
984
985

986
987
988
989
990
991
992
} [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 ""

  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'} \







>







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'} \
Changes to test/walsetlk.test.
191
192
193
194
195
196
197
198
} {wal}

do_test 3.1 {
  list [catch { db2 eval {BEGIN EXCLUSIVE} } msg] $msg
} {1 {database is locked}}

finish_test








<
191
192
193
194
195
196
197

} {wal}

do_test 3.1 {
  list [catch { db2 eval {BEGIN EXCLUSIVE} } msg] $msg
} {1 {database is locked}}

finish_test

Changes to test/where.test.
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  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=?)*}
do_eqp_test where-1.1.2b {
  SELECT x, y, w FROM t1 WHERE w IS 10
} {*SEARCH TABLE 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*}
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=?)*}
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 {







|


|











|





|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  count {SELECT x, y, w FROM t1 WHERE w=10}
} {3 121 10 3}
do_test where-1.1.1b {
  count {SELECT x, y, w FROM t1 WHERE w IS 10}
} {3 121 10 3}
do_eqp_test where-1.1.2 {
  SELECT x, y, w FROM t1 WHERE w=10
} {*SEARCH t1 USING INDEX i1w (w=?)*}
do_eqp_test where-1.1.2b {
  SELECT x, y, w FROM t1 WHERE w IS 10
} {*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 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 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
  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=?)*}
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=?)*}
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=?)*}
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=?)*}
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=?)*}
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=?)*}
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 {







|


|





|





|











|


|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  count {SELECT w, x, y FROM t1 WHERE 11=w AND x>2}
} {11 3 144 3}
do_test where-1.4.1b {
  count {SELECT w, x, y FROM t1 WHERE 11 IS w AND x>2}
} {11 3 144 3}
do_eqp_test where-1.4.2 {
  SELECT w, x, y FROM t1 WHERE 11=w AND x>2
} {*SEARCH 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 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 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 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 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 t1 USING COVERING INDEX i1xy (x=? AND y=?)*}
do_test where-1.9 {
  count {SELECT x, y FROM t1 WHERE y=144 AND w>10 AND x=3}
} {3 144 3}
do_test where-1.10 {
  count {SELECT x, y FROM t1 WHERE x=3 AND w>=10 AND y=121}
} {3 121 3}
do_test where-1.11 {
Changes to test/where2.test.
72
73
74
75
76
77
78


79
80
81
82
83
84
85
86
87
88
89
  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]} {
      lappend data $tab $idx
    } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} {
      lappend data $tab *
    }
  }
  return $data   
}









>
>
|
|

|







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
    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
        $x all ss as tab idx]} {
      lappend data $tab $idx
    } 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
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 .*/}
}

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







|







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 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
#
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 { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
        $x all as tab idx]} {
      lappend data $tab $idx
    } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} {
      lappend data $tab *
    }
  }
  return $data   
}









>
>
|
|

|







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
    } elseif {[regexp {(SCAN|SEARCH) (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \
        $x all ss as tab idx]} {
      lappend data $tab $idx
    } 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
  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=?)
}
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=?)
}
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}
}
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}
}
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}
}
} ;# endif

# Verify that a performance regression encountered by firefox
# has been fixed.
#
do_execsql_test where3-5.0 {







|
|





|
|




















|
|
|





|
|
|





|
|
|







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 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 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 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 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 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
     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=?)
  `--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=?)
  `--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=?)
  `--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=?)
  `--USE TEMP B-TREE FOR ORDER BY
}

# Name resolution with NATURAL JOIN and USING
#
do_test where3-6.setup {
  db eval {







|
|











|
|











|
|











|
|







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 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 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 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 aaa USING INDEX aaa_333 (fk=?)
  |--SEARCH bbb USING INTEGER PRIMARY KEY (rowid=?)
  `--USE TEMP B-TREE FOR ORDER BY
}

# Name resolution with NATURAL JOIN and USING
#
do_test where3-6.setup {
  db eval {
Changes to test/where7.test.
23350
23351
23352
23353
23354
23355
23356
23357
23358
23359
23360
23361
23362
23363
23364
      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=?)
  |  `--INDEX 2
  |     `--SEARCH TABLE t301 USING INTEGER PRIMARY KEY (rowid=?)
  |--SEARCH TABLE t302 USING INDEX t302_c8_c3 (c8=? AND c3>?)
  `--USE TEMP B-TREE FOR ORDER BY
}

finish_test







|

|
|




23350
23351
23352
23353
23354
23355
23356
23357
23358
23359
23360
23361
23362
23363
23364
      AND (t301.c4 = 1407449685622784
           OR t301.c8 = 1407424651264000)
   ORDER BY t302.c5 LIMIT 200;
} {
  QUERY PLAN
  |--MULTI-INDEX OR
  |  |--INDEX 1
  |  |  `--SEARCH 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
}

finish_test
Changes to test/where9.test.
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390

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=?)
    `--MULTI-INDEX OR
       |--INDEX 1
       |  `--SEARCH TABLE t2 USING INDEX t2d (d=?)
       `--INDEX 3
          `--SEARCH TABLE 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=?)
    `--MULTI-INDEX OR
       |--INDEX 1
       |  `--SEARCH TABLE t2 USING INDEX t2d (d=?)
       `--INDEX 2
          `--SEARCH TABLE t2 USING COVERING INDEX t2f (f=?)
  }]
} 

# Make sure that INDEXED BY and multi-index OR clauses play well with
# one another.
#
do_test where9-4.1 {







|


|

|







|


|

|







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 t1 USING INTEGER PRIMARY KEY (rowid=?)
    `--MULTI-INDEX OR
       |--INDEX 1
       |  `--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 t1 USING INTEGER PRIMARY KEY (rowid=?)
    `--MULTI-INDEX OR
       |--INDEX 1
       |  `--SEARCH t2 USING INDEX t2d (d=?)
       `--INDEX 2
          `--SEARCH t2 USING COVERING INDEX t2f (f=?)
  }]
} 

# Make sure that INDEXED BY and multi-index OR clauses play well with
# one another.
#
do_test where9-4.1 {
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
#
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=?)
     `--INDEX 2
        `--SEARCH TABLE 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=?)}

# 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>?)}

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







|

|






|






|







457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
#
do_eqp_test where9-5.1 {
  SELECT a FROM t1 WHERE b>1000 AND (c=31031 OR d IS NULL)
} {
  QUERY PLAN
  `--MULTI-INDEX OR
     |--INDEX 1
     |  `--SEARCH 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 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 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}
978
979
980
981
982
983
984







985










986
987
    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}




















finish_test







>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>


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/whereE.test.
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  INSERT INTO t2 SELECT x+32, (x+32)*11 FROM t2;
  INSERT INTO t2 SELECT x+64, (x+32)*11 FROM t2;
  ALTER TABLE t2 ADD COLUMN z;
  UPDATE t2 SET z=2;
  CREATE UNIQUE INDEX t2zx ON t2(z,x);

  EXPLAIN QUERY PLAN SELECT x FROM t1, t2 WHERE a=z AND c=x;
} {/.*SCAN TABLE t1.*SEARCH TABLE t2.*/}
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.*/}
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.*/}
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.*/}

finish_test







|


|



|


|


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
  INSERT INTO t2 SELECT x+32, (x+32)*11 FROM t2;
  INSERT INTO t2 SELECT x+64, (x+32)*11 FROM t2;
  ALTER TABLE t2 ADD COLUMN z;
  UPDATE t2 SET z=2;
  CREATE UNIQUE INDEX t2zx ON t2(z,x);

  EXPLAIN QUERY PLAN SELECT x FROM t1, t2 WHERE a=z AND c=x;
} {/.*SCAN t1.*SEARCH t2.*/}
do_execsql_test 1.2 {
  EXPLAIN QUERY PLAN SELECT x FROM t2, t1 WHERE a=z AND c=x;
} {/.*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 t1.*SEARCH t2.*/}
do_execsql_test 1.4 {
  EXPLAIN QUERY PLAN SELECT x FROM t2, t1 WHERE a=z AND c=x;
} {/.*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
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.*/}
}

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

do_execsql_test 3.0 {
  DROP TABLE t1;
  DROP TABLE t2;
  CREATE TABLE t1(a, b, c);
  CREATE TABLE t2(d, e, f);







|




















|







59
60
61
62
63
64
65
66
67
68
69
70
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 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 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
     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.*/}
}

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=?;







|







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 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
#
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=..*/}
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=..*/}
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=..*/}
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=..*/}

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







|


|


|


|







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 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 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 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 a.*SEARCH b USING INDEX .*b_1 .b1=..*/}

# Ticket [1e64dd782a126f48d78c43a664844a41d0e6334e]:
# Incorrect result in a nested GROUP BY/DISTINCT due to the use of an OP_SCopy
# where an OP_Copy was needed.
#
do_execsql_test whereG-4.0 {
  CREATE TABLE t4(x);
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244

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>?)}
do_eqp_test 5.1.3 {
  SELECT * FROM t1 WHERE likelihood(a>?, 0.9)
} {SCAN TABLE t1}
do_eqp_test 5.1.4 {
  SELECT * FROM t1 WHERE likely(a>?)
} {SCAN TABLE 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>?)}
do_eqp_test 5.2.3 {
  SELECT * FROM t1 WHERE likelihood(b>?, 0.9)
} {SCAN TABLE t1}
do_eqp_test 5.2.4 {
  SELECT * FROM t1 WHERE likely(b>?)
} {SCAN TABLE t1}

ifcapable stat4 {
  do_eqp_test 5.3.1.stat4 {
    SELECT * FROM t1 WHERE a=?
  } {SCAN TABLE t1}
} else {
  do_eqp_test 5.3.1 {
    SELECT * FROM t1 WHERE a=?
  } {SEARCH TABLE t1 USING INDEX i1}
}
do_eqp_test 5.3.2 {
  SELECT * FROM t1 WHERE likelihood(a=?, 0.9)
} {SCAN TABLE t1}
do_eqp_test 5.3.3 {
  SELECT * FROM t1 WHERE likely(a=?)
} {SCAN TABLE 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);







|


|


|










|


|


|




|



|



|


|







191
192
193
194
195
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 t1 USING INDEX i1 (a>?)}
do_eqp_test 5.1.3 {
  SELECT * FROM t1 WHERE likelihood(a>?, 0.9)
} {SCAN t1}
do_eqp_test 5.1.4 {
  SELECT * FROM t1 WHERE likely(a>?)
} {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 t1 USING INDEX i1 (ANY(a) AND b>?)}
do_eqp_test 5.2.3 {
  SELECT * FROM t1 WHERE likelihood(b>?, 0.9)
} {SCAN t1}
do_eqp_test 5.2.4 {
  SELECT * FROM t1 WHERE likely(b>?)
} {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 t1 USING INDEX i1}
}
do_eqp_test 5.3.2 {
  SELECT * FROM t1 WHERE likelihood(a=?, 0.9)
} {SCAN t1}
do_eqp_test 5.3.3 {
  SELECT * FROM t1 WHERE likely(a=?)
} {SCAN t1}

# 2015-06-18
# Ticket [https://www.sqlite.org/see/tktview/472f0742a1868fb58862bc588ed70]
#
do_execsql_test 6.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(i int, x, y, z);
329
330
331
332
333
334
335
336

































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


































finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
reset_db
do_execsql_test 10.1 {
  CREATE TABLE a(b TEXT);  INSERT INTO a VALUES(0),(4),(9);
  CREATE TABLE c(d NUM);
  CREATE VIEW f(g, h) AS SELECT b, 0 FROM a UNION SELECT d, d FROM c;
  SELECT g = g FROM f GROUP BY h;
} {1}

reset_db
do_execsql_test 11.0 {
  CREATE TABLE t1(x PRIMARY KEY, y);
  INSERT INTO t1 VALUES('AAA', 'BBB');

  CREATE TABLE t2(z);
  INSERT INTO t2 VALUES('t2');

  CREATE TABLE t3(x PRIMARY KEY, y);
  INSERT INTO t3 VALUES('AAA', 'AAA');
}

do_execsql_test 11.1.1 {
  SELECT * FROM t1 JOIN t2 ON unlikely(x=y) AND y='AAA'
}
do_execsql_test 11.1.2 {
  SELECT * FROM t1 JOIN t2 ON likely(x=y) AND y='AAA'
}
do_execsql_test 11.1.3 {
  SELECT * FROM t1 JOIN t2 ON x=y AND y='AAA'
}

do_execsql_test 11.2.1 {
  SELECT * FROM t3 JOIN t2 ON unlikely(x=y) AND y='AAA'
} {AAA AAA t2}
do_execsql_test 11.2.2 {
  SELECT * FROM t3 JOIN t2 ON likely(x=y) AND y='AAA'
} {AAA AAA t2}
do_execsql_test 11.2.3 {
  SELECT * FROM t3 JOIN t2 ON x=y AND y='AAA'
} {AAA AAA t2}


finish_test
Changes to test/whereI.test.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

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=?)
     `--INDEX 2
        `--SEARCH TABLE 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 {







|

|







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 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 {
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=?)
     `--INDEX 2
        `--SEARCH TABLE 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 {







|

|







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

# 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<?)}

# 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<?)}

###########################################################################################

# Reset the database and setup for a test case derived from actual SQLite users
#
db close
sqlite3 db test.db







|







|







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


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







|







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

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

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

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

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

finish_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
    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 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 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 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 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 t1 USING INDEX t1bc/}

finish_test
Changes to test/whereL.test.
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
}
do_eqp_test 110 {
  SELECT * FROM t1, v4 WHERE t1.a=?1 AND v4.a=t1.a;
} {
  QUERY PLAN
  `--COMPOUND QUERY
     |--LEFT-MOST SUBQUERY
     |  |--SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
     |  `--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
     `--UNION ALL
        |--SEARCH TABLE t3 USING INDEX sqlite_autoindex_t3_1 (a=?)
        `--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
}

# The scan of the t1 table goes first since that enables the ORDER BY
# sort to be omitted.  This would not be possible without constant
# propagation because without it the t1 table would depend on t3.
#
do_eqp_test 120 {
  SELECT * FROM t1, t2, t3
   WHERE t1.a=t2.a AND t2.a=t3.j AND t3.j=5
  ORDER BY t1.a;
} {
  QUERY PLAN
  |--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
  |--SEARCH TABLE t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
  `--SCAN TABLE t3
}

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







|
|

|
|












|
|
|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
}
do_eqp_test 110 {
  SELECT * FROM t1, v4 WHERE t1.a=?1 AND v4.a=t1.a;
} {
  QUERY PLAN
  `--COMPOUND QUERY
     |--LEFT-MOST SUBQUERY
     |  |--SEARCH 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=?)
        `--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 t1 USING INDEX sqlite_autoindex_t1_1 (a=?)
  |--SEARCH t2 USING INDEX sqlite_autoindex_t2_1 (a=?)
  `--SCAN t3
}

# Constant propagation in the face of collating sequences:
#
do_execsql_test 200 {
  CREATE TABLE c3(x COLLATE binary, y COLLATE nocase, z COLLATE binary);
  CREATE INDEX c3x ON c3(x);
Changes to test/wherefault.test.
51
52
53
54
55
56
57
























58
59
    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;
}

























finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
    set iii [expr $i*$i]
    db eval { INSERT INTO t1 VALUES($i, $ii, $iii) }
  }
  db eval COMMIT
} -sqlbody {
  SELECT count(*) FROM t1 WHERE a BETWEEN 5 AND 995 OR b BETWEEN 5 AND 900000;
}

reset_db
do_execsql_test 3.0 {
  PRAGMA writable_schema = 1;
  BEGIN TRANSACTION;    
    CREATE TABLE t1(
      a INT AS (c*11),
      b TEXT AS (substr(d,1,3)) STORED, 
      c INTEGEB PRIMARI KEY, d TEXT
    );
    CREATE INDEX t1a ON t1(a);
  COMMIT;
}
faultsim_save_and_close

do_faultsim_test 3.1 -faults oom* -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    SELECT * FROM (SELECT a FROM t1 NATURAL JOIN t1 WHERE a IN (SELECT b FROM t1 ORDER BY b)) WHERE (SELECT a FROM t1 NATURAL JOIN (SELECT * FROM (SELECT a FROM t1 NATURAL JOIN t1 WHERE a IN (SELECT CASE b WHEN 82 THEN 207 WHEN 869 THEN 406 WHEN 85 THEN 83 WHEN 705 THEN 698 ELSE 1992229051 END%5 FROM t1 ORDER BY b)) WHERE (SELECT a FROM t1 NATURAL JOIN (SELECT b FROM t1 ORDER BY b) WHERE a IN (SELECT b FROM t1 ORDER BY b))) WHERE a );
  }
} -test {
  faultsim_test_result {0 {}}
}

finish_test
Changes to test/wherelimit.test.
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
  } {36}
  do_test wherelimit-3.1 {
    execsql {UPDATE t1 SET y=1 WHERE x=1}
    execsql {SELECT count(*) FROM t1 WHERE y=1}
  } {11}
  create_test_data 6
  do_test wherelimit-3.2 {
    execsql {UPDATE t1 SET y=1 WHERE x=1 RETURNING x, old.y, '|' LIMIT 5}
  } {1 1 | 1 2 | 1 3 | 1 4 | 1 5 |}
  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}







|
|







233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
  } {36}
  do_test wherelimit-3.1 {
    execsql {UPDATE t1 SET y=1 WHERE x=1}
    execsql {SELECT count(*) FROM t1 WHERE y=1}
  } {11}
  create_test_data 6
  do_test wherelimit-3.2 {
    execsql {UPDATE t1 SET y=1 WHERE x=1 RETURNING x, y, '|' LIMIT 5}
  } {1 1 | 1 1 | 1 1 | 1 1 | 1 1 |}
  do_test wherelimit-3.2cnt {
    execsql {SELECT count(*) FROM t1 WHERE y=1}
  } {10}
  do_test wherelimit-3.3 {
    # limit 5
    execsql {UPDATE t1 SET y=2 WHERE x=2 ORDER BY x LIMIT 5}
    execsql {SELECT count(*) FROM t1 WHERE y=2}
Changes to test/window1.test.
370
371
372
373
374
375
376
































377
378
379
380
381
382
383
  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_execsql_test 10.0 {
  CREATE TABLE sales(emp TEXT PRIMARY KEY, region, total);
  INSERT INTO sales VALUES
      ('Alice',     'North', 34),
      ('Frank',     'South', 22),







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
  WITH aaa(x, y, z) AS (
    SELECT x, y, max(y) OVER xyz FROM t4
    WINDOW xyz AS (ORDER BY x)
  )
  SELECT *, min(z) OVER (ORDER BY x) FROM aaa ORDER BY 1;
} {1 g g g   2 i i g   3 l l g   4 g l g   5 a l g   6 m m g}

do_catchsql_test 9.4 {
  -- 2021-04-17 dbsqlfuzz d9cf66100064952b66951845dfab41de1c124611
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a,b,c,d);
  DROP TABLE IF EXISTS t2;
  CREATE TABLE t2(x,y);
  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    INSERT INTO t2(x,y)
      SELECT a, max(d) OVER w1 FROM t1
        WINDOW w1 AS (PARTITION BY EXISTS(SELECT 1 FROM t1 WHERE c=?1) );
  END;
} {1 {trigger cannot use variables}}

do_catchsql_test 9.4.2 {
  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    INSERT INTO t1(a,b) 
        SELECT a, max(d) OVER w1 FROM t1
        WINDOW w1 AS (
          ORDER BY a ROWS BETWEEN ? PRECEDING AND UNBOUNDED FOLLOWING
        );
  END;
} {1 {trigger cannot use variables}}
do_catchsql_test 9.4.3 {
  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
    INSERT INTO t1(a,b) 
        SELECT a, max(d) OVER w1 FROM t1
        WINDOW w1 AS (
          ORDER BY a ROWS BETWEEN UNBOUNDED PRECEDING AND ? FOLLOWING
        );
  END;
} {1 {trigger cannot use variables}}

#-------------------------------------------------------------------------
#
do_execsql_test 10.0 {
  CREATE TABLE sales(emp TEXT PRIMARY KEY, region, total);
  INSERT INTO sales VALUES
      ('Alice',     'North', 34),
      ('Frank',     'South', 22),
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
















































1891
1892
1893
1894
1895
1896
1897

# 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_execsql_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);
} {{} {} {}}

















































#-------------------------------------------------------------------------
reset_db
do_execsql_test 62.1 {
  CREATE TABLE t1(a VARCHAR(20), b FLOAT);
  INSERT INTO t1 VALUES('1',10.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
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

# 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);
}
1996
1997
1998
1999
2000
2001
2002
2003














































































2004

do_execsql_test 65.4 {
  SELECT COUNT() OVER () LIKE lead(102030) OVER(
      ORDER BY sum('abcdef' COLLATE nocase) IN (SELECT 54321) 
  )
  FROM t1;
} {{}}















































































finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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

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()}}

finish_test
Changes to test/window8.tcl.
414
415
416
417
418
419
420






































































421
422
423
424
425
  SELECT $f (a) OVER win FROM t2
  WINDOW win AS (
      ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING
  );
"
}









































































finish_test









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





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


Changes to test/window8.test.
6464
6465
6466
6467
6468
6469
6470







































































6471
6472

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








































































finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


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

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
Changes to test/window9.test.
260
261
262
263
264
265
266

















267
268
do_execsql_test 8.4 {
  SELECT(
      SELECT x UNION 
      SELECT sum( avg((SELECT x FROM v1)) ) OVER()
  )
  FROM v1;
} {0.0 0.0}


















finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
do_execsql_test 8.4 {
  SELECT(
      SELECT x UNION 
      SELECT sum( avg((SELECT x FROM v1)) ) OVER()
  )
  FROM v1;
} {0.0 0.0}

#--------------------------------------------------------------------------
reset_db
do_execsql_test 9.0 {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES(NULL,'bb',356);
  INSERT INTO t1 VALUES('CB','aa',158);
  INSERT INTO t1 VALUES('BB','aa',399);
  INSERT INTO t1 VALUES('FF','bb',938);
}

do_catchsql_test 9.1 {
  SELECT sum(c) OVER (
    ORDER BY c RANGE BETWEEN 0 PRECEDING AND '-700' PRECEDING
  )
  FROM t1
} {1 {frame ending offset must be a non-negative number}}

finish_test
Changes to test/windowfault.test.
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
do_execsql_test 12.0 {
  CREATE TABLE t1(a, b, c);
} {}
do_faultsim_test 12 -faults oom* -prep {
} -body {
  execsql {
    WITH v(a, b, row_number) AS (
      SELECT a, b, row_number() OVER (PARTITION BY a ORDER BY b) FROM t1
    )
    SELECT * FROM v WHERE a=2
  }
} -test {
  faultsim_test_result {0 {}}
}








|







280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
do_execsql_test 12.0 {
  CREATE TABLE t1(a, b, c);
} {}
do_faultsim_test 12 -faults oom* -prep {
} -body {
  execsql {
    WITH v(a, b, row_number) AS (
      SELECT a, b, row_number() OVER (PARTITION BY a COLLATE nocase ORDER BY b) FROM t1
    )
    SELECT * FROM v WHERE a=2
  }
} -test {
  faultsim_test_result {0 {}}
}

Changes to test/windowpushd.test.
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  SELECT * FROM lll WHERE grp_id=2
} {
  1 2 1 2 2 11 3 2 14 4 2 16 5 2 18 6 2 20 
}

do_eqp_test 1.4 {
  SELECT * FROM lll WHERE grp_id=2
} {SEARCH TABLE t1 USING COVERING INDEX i1 (grp_id=?)}

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







|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  SELECT * FROM lll WHERE grp_id=2
} {
  1 2 1 2 2 11 3 2 14 4 2 16 5 2 18 6 2 20 
}

do_eqp_test 1.4 {
  SELECT * FROM lll WHERE grp_id=2
} {SEARCH t1 USING COVERING INDEX i1 (grp_id=?)}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 2.0 {
  CREATE TABLE t1(a, b, c, d);
  INSERT INTO t1 VALUES('A', 'C', 1,  0.1);
  INSERT INTO t1 VALUES('A', 'D', 2,  0.2);
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
    C 0.1 1.0 1 C 0.4 1.0 2 C 0.7 1.0 3 C 1.0 1.0 4 
    D 0.2 1.1 1 D 0.5 1.1 2 D 0.8 1.1 3 D 1.1 1.1 4 
  }

  if {$tn==1} {
    do_eqp_test 2.$tn.3.3 {
      SELECT * FROM v3 WHERE b='E'
    } {SEARCH TABLE t1 USING INDEX i2 (b=?)}
    do_eqp_test 2.$tn.3.4 {
      SELECT * FROM v3 WHERE b>'C'
    } {SEARCH TABLE t1 USING INDEX i2 (b>?)}
  }

  do_execsql_test 2.$tn.3.5 { SELECT * FROM v3 WHERE d<0.55; } { 
    C 0.1 1.0 1 C 0.4 1.0 2
    D 0.2 1.1 1 D 0.5 1.1 2
    E 0.3 1.2 1
  }
  if {$tn==1} {
    do_eqp_test 2.$tn.3.6 {
      SELECT * FROM v3 WHERE d<0.55
    } {SCAN TABLE t1 USING INDEX i2}
  }

  do_execsql_test 2.$tn.4.1 {
    SELECT * FROM (
      SELECT x, sum(y) AS s, max(z) AS m 
      FROM t2 GROUP BY x
    )







|


|










|







154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
    C 0.1 1.0 1 C 0.4 1.0 2 C 0.7 1.0 3 C 1.0 1.0 4 
    D 0.2 1.1 1 D 0.5 1.1 2 D 0.8 1.1 3 D 1.1 1.1 4 
  }

  if {$tn==1} {
    do_eqp_test 2.$tn.3.3 {
      SELECT * FROM v3 WHERE b='E'
    } {SEARCH 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
    )
230
231
232
233
234
235
236
237

}




finish_test








<
230
231
232
233
234
235
236


}




finish_test

Changes to test/with1.test.
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
  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
  |  `--SCAN CONSTANT ROW
  |--SCAN SUBQUERY xxxxxx
  `--SCAN SUBQUERY xxxxxx
}

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







|

|
|







1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
  WITH
    x1(a) AS (values(100))
  INSERT INTO t1(x)
    SELECT * FROM (WITH x2(y) AS (SELECT * FROM x1) SELECT y+a FROM x1, x2);
  SELECT * FROM t1;
} {
  QUERY PLAN
  |--MATERIALIZE x1
  |  `--SCAN CONSTANT ROW
  |--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.
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
# 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.
#






reset_db

do_execsql_test 25.1 {
  CREATE TABLE dual(dummy);
  INSERT INTO dual(dummy) VALUES('X');
  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}}







>
>
>
>
>
>
|
>
|
<
<
|
|
|
|
|
|
|
|
|
|
>







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
# 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}}
1203
1204
1205
1206
1207
1208
1209
























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

























finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
      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/with3.test.
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  }

  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
    |  |--SETUP
    |  |  `--SCAN CONSTANT ROW
    |  `--RECURSIVE STEP
    |     `--SCAN TABLE cnt
    |--SCAN SUBQUERY xxxxxx
    `--SEARCH TABLE 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
    |  |--SETUP
    |  |  `--SCAN CONSTANT ROW
    |  `--RECURSIVE STEP
    |     `--SCAN TABLE cnt
    |--SCAN TABLE y1
    `--SEARCH SUBQUERY xxxxxx 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
  |  |--SETUP
  |  |  |--SCAN CONSTANT ROW
  |  |  `--SCALAR SUBQUERY xxxxxx
  |  |     `--SCAN TABLE 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=?)
}

do_execsql_test 4.0 {
  WITH t5(t5col1) AS (
    SELECT (
      WITH t3(t3col1) AS (
        WITH t2 AS (







|



|
|
|







|



|
|
|















|



|

|
|
|
|
|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  }

  do_eqp_test 3.1.2 {
    WITH cnt(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM cnt LIMIT 1)
    SELECT * FROM cnt, y1 WHERE i=a
  } [string map {"\n  " \n} {
    QUERY PLAN
    |--MATERIALIZE cnt
    |  |--SETUP
    |  |  `--SCAN CONSTANT ROW
    |  `--RECURSIVE STEP
    |     `--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 cnt
    |  |--SETUP
    |  |  `--SCAN CONSTANT ROW
    |  `--RECURSIVE STEP
    |     `--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 c
  |  |--SETUP
  |  |  |--SCAN CONSTANT ROW
  |  |  `--SCALAR SUBQUERY xxxxxx
  |  |     `--SCAN w2
  |  `--RECURSIVE STEP
  |     |--SCAN w1
  |     `--SCAN c
  |--SCAN c
  |--SEARCH w2 USING INTEGER PRIMARY KEY (rowid=?)
  `--SEARCH w1 USING INTEGER PRIMARY KEY (rowid=?)
}

do_execsql_test 4.0 {
  WITH t5(t5col1) AS (
    SELECT (
      WITH t3(t3col1) AS (
        WITH t2 AS (
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#
do_eqp_test 5.1 {
  WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<1)
  SELECT x1.x||x2.x||x3.x||x4.x FROM c AS x1, c AS x2, c AS x3, c AS x4
  ORDER BY 1;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  |--SETUP
  |  |  `--SCAN CONSTANT ROW
  |  `--RECURSIVE STEP
  |     `--SCAN TABLE c
  |--SCAN SUBQUERY xxxxxx AS x1
  |--SCAN SUBQUERY xxxxxx AS x2
  |--SCAN SUBQUERY xxxxxx AS x3
  |--SCAN SUBQUERY xxxxxx AS x4
  `--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}







|



|
|
|
|
|







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#
do_eqp_test 5.1 {
  WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<1)
  SELECT x1.x||x2.x||x3.x||x4.x FROM c AS x1, c AS x2, c AS x3, c AS x4
  ORDER BY 1;
} {
  QUERY PLAN
  |--MATERIALIZE 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}
Changes to test/with6.test.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
  SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {000 001 010 011 100 101 110 111}
do_eqp_test 101 {
  WITH c(x) AS (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  `--SCAN 2 CONSTANT ROWS
  |--SCAN SUBQUERY xxxxxx AS c1
  |--SCAN SUBQUERY xxxxxx AS c2
  `--SCAN SUBQUERY xxxxxx AS c3
}

do_execsql_test 110 {
  WITH c(x) AS MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {000 001 010 011 100 101 110 111}
do_eqp_test 111 {
  WITH c(x) AS MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  `--SCAN 2 CONSTANT ROWS
  |--SCAN SUBQUERY xxxxxx AS c1
  |--SCAN SUBQUERY xxxxxx AS c2
  `--SCAN SUBQUERY xxxxxx AS c3
}

# Even though the CTE is not materialized, the self-join optimization
# kicks in and does the materialization for us.
#
do_execsql_test 120 {
  WITH c(x) AS NOT MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {000 001 010 011 100 101 110 111}
do_eqp_test 121 {
  WITH c(x) AS NOT MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  `--SCAN 2 CONSTANT ROWS
  |--SCAN SUBQUERY xxxxxx AS c1
  |--SCAN SUBQUERY xxxxxx AS c2
  `--SCAN SUBQUERY xxxxxx AS c3
}

do_execsql_test 130 {
  WITH c(x) AS NOT MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x
    FROM (SELECT x FROM c LIMIT 5) AS c1,
         (SELECT x FROM c LIMIT 5) AS c2,
         (SELECT x FROM c LIMIT 5) AS c3;
} {000 001 010 011 100 101 110 111}
do_eqp_test 131 {
  WITH c(x) AS NOT MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x
    FROM (SELECT x FROM c LIMIT 5) AS c1,
         (SELECT x FROM c LIMIT 5) AS c2,
         (SELECT x FROM c LIMIT 5) AS c3;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  |--CO-ROUTINE xxxxxx
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--SCAN SUBQUERY xxxxxx
  |--MATERIALIZE xxxxxx
  |  |--CO-ROUTINE xxxxxx
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--SCAN SUBQUERY xxxxxx
  |--MATERIALIZE xxxxxx
  |  |--CO-ROUTINE xxxxxx
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--SCAN SUBQUERY xxxxxx
  |--SCAN SUBQUERY xxxxxx AS c1
  |--SCAN SUBQUERY xxxxxx AS c2
  `--SCAN SUBQUERY xxxxxx AS 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 {







|

|
|
|











|

|
|
|














|

|
|
|

















|
|

|
|
|

|
|
|

|
|
|
|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
  SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {000 001 010 011 100 101 110 111}
do_eqp_test 101 {
  WITH c(x) AS (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x FROM c c1, c c2, c c3;
} {
  QUERY PLAN
  |--MATERIALIZE 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
  |--MATERIALIZE 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 {
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
  WITH c(x) AS MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x
    FROM (SELECT x FROM c LIMIT 5) AS c1,
         (SELECT x FROM c LIMIT 6) AS c2,
         (SELECT x FROM c LIMIT 7) AS c3;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  |--MATERIALIZE xxxxxx
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--SCAN SUBQUERY xxxxxx
  |--MATERIALIZE xxxxxx
  |  `--SCAN SUBQUERY xxxxxx
  |--MATERIALIZE xxxxxx
  |  `--SCAN SUBQUERY xxxxxx
  |--SCAN SUBQUERY xxxxxx AS c1
  |--SCAN SUBQUERY xxxxxx AS c2
  `--SCAN SUBQUERY xxxxxx AS c3
}

do_execsql_test 150 {
  WITH c(x) AS (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x
    FROM (SELECT x FROM c LIMIT 5) AS c1,
         (SELECT x FROM c LIMIT 6) AS c2,
         (SELECT x FROM c LIMIT 7) AS c3;
} {000 001 010 011 100 101 110 111}
do_eqp_test 151 {
  WITH c(x) AS (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x
    FROM (SELECT x FROM c LIMIT 5) AS c1,
         (SELECT x FROM c LIMIT 6) AS c2,
         (SELECT x FROM c LIMIT 7) AS c3;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  |--MATERIALIZE xxxxxx
  |  |  `--SCAN 2 CONSTANT ROWS
  |  `--SCAN SUBQUERY xxxxxx
  |--MATERIALIZE xxxxxx
  |  `--SCAN SUBQUERY xxxxxx
  |--MATERIALIZE xxxxxx
  |  `--SCAN SUBQUERY xxxxxx
  |--SCAN SUBQUERY xxxxxx AS c1
  |--SCAN SUBQUERY xxxxxx AS c2
  `--SCAN SUBQUERY xxxxxx AS c3
}

do_execsql_test 160 {
  WITH c(x) AS (VALUES(0),(1))
  SELECT c2.x + 100*(SELECT sum(x+1) FROM c WHERE c.x<=c2.x)
    FROM c AS c2 WHERE c2.x<10;
} {100 301}
do_eqp_test 161 {
  WITH c(x) AS (VALUES(0),(1))
  SELECT c2.x + 100*(SELECT sum(x+1) FROM c WHERE c.x<=c2.x)
    FROM c AS c2 WHERE c2.x<10;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  `--SCAN 2 CONSTANT ROWS
  |--SCAN SUBQUERY xxxxxx AS c2
  `--CORRELATED SCALAR SUBQUERY xxxxxx
     `--SCAN SUBQUERY xxxxxx
}

do_execsql_test 170 {
  WITH c(x) AS NOT MATERIALIZED (VALUES(0),(1))
  SELECT c2.x + 100*(SELECT sum(x+1) FROM c WHERE c.x<=c2.x)
    FROM c AS c2 WHERE c2.x<10;
} {100 301}
do_eqp_test 171 {
  WITH c(x) AS NOT MATERIALIZED (VALUES(0),(1))
  SELECT c2.x + 100*(SELECT sum(x+1) FROM c WHERE c.x<=c2.x)
    FROM c AS c2 WHERE c2.x<10;
} {
  QUERY PLAN
  |--CO-ROUTINE xxxxxx
  |  `--SCAN 2 CONSTANT ROWS
  |--SCAN SUBQUERY xxxxxx AS c2
  `--CORRELATED SCALAR SUBQUERY xxxxxx
     |--CO-ROUTINE xxxxxx
     |  `--SCAN 2 CONSTANT ROWS
     `--SCAN SUBQUERY xxxxxx
}


do_execsql_test 200 {
  CREATE TABLE t1(x);
  INSERT INTO t1(x) VALUES(4);
  CREATE VIEW t2(y) AS







|
|

|
|
|
|
|
|
|
|

















|
|

|
|
|
|
|
|
|
|













|

|

|













|

|

|

|







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
  WITH c(x) AS MATERIALIZED (VALUES(0),(1))
  SELECT c1.x||c2.x||c3.x
    FROM (SELECT x FROM c LIMIT 5) AS c1,
         (SELECT x FROM c LIMIT 6) AS c2,
         (SELECT x FROM c LIMIT 7) AS c3;
} {
  QUERY PLAN
  |--MATERIALIZE 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
  |--MATERIALIZE 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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
           (SELECT z FROM c LIMIT 5) AS c2;
  SELECT y FROM t2 ORDER BY y;
} {40404 40405 40406 40504 40505 40506 40604 40605 40606}
do_eqp_test 211 {
  SELECT y FROM t2 ORDER BY y;
} {
  QUERY PLAN
  |--MATERIALIZE xxxxxx
  |  |--MATERIALIZE xxxxxx
  |  |  `--SCAN 3 CONSTANT ROWS
  |  `--SCAN SUBQUERY xxxxxx
  |--MATERIALIZE xxxxxx
  |  `--SCAN SUBQUERY xxxxxx
  |--SCAN SUBQUERY xxxxxx AS c1
  |--SCAN SUBQUERY xxxxxx AS c2
  |--SCAN TABLE t1
  `--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







|
|

|
|
|
|
|
|







224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
           (SELECT z FROM c LIMIT 5) AS c2;
  SELECT y FROM t2 ORDER BY y;
} {40404 40405 40406 40504 40505 40506 40604 40605 40606}
do_eqp_test 211 {
  SELECT y FROM t2 ORDER BY y;
} {
  QUERY PLAN
  |--MATERIALIZE c1
  |  |--MATERIALIZE c
  |  |  `--SCAN 3 CONSTANT ROWS
  |  `--SCAN c
  |--MATERIALIZE c2
  |  `--SCAN c
  |--SCAN c1
  |--SCAN c2
  |--SCAN t1
  `--USE TEMP B-TREE FOR ORDER BY
}
do_execsql_test 220 {
  DROP VIEW t2;
  CREATE VIEW t2(y) AS
    WITH c(z) AS MATERIALIZED (VALUES(4),(5),(6))
    SELECT c1.z+c2.z*100+t1.x*10000
Changes to test/without_rowid1.test.
448
449
450
451
452
453
454













455
456
    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}













  
finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>


448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
    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
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=/}
  
finish_test
Changes to test/without_rowid6.test.
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
} {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>../}
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>../}
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>../}
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>../}
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







|


















|

















|



















|










60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
} {4 1}
do_execsql_test_if_vtab without_rowid6-201 {
  SELECT name, key FROM pragma_index_xinfo('t1');
} {b 1 a 0 c 0}
do_execsql_test without_rowid6-210 {
  EXPLAIN QUERY PLAN
  SELECT a FROM t1 WHERE b>3 ORDER BY b;
} {/SEARCH 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 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 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 t1 USING PRIMARY KEY .b>../}
do_execsql_test without_rowid6-520 {
  PRAGMA index_list(t1);
} {/sqlite_autoindex_t1_1 1 pk/}

do_catchsql_test without_rowid6-600 {
  CREATE TABLE t6(a,b,c,PRIMARY KEY(a,rowid,b))WITHOUT ROWID;
} {1 {no such column: rowid}}


finish_test
Changes to test/zipfile.test.
838
839
840
841
842
843
844












845
846
#
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}}













finish_test







>
>
>
>
>
>
>
>
>
>
>
>


838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
#
do_catchsql_test 16.10 {
  DELETE FROM zipfile;
} {1 {zipfile: missing filename}}
do_catchsql_test 16.20 {
  REPLACE INTO zipfile VALUES(null,null,null,null,null,123,null);
} {1 {zipfile: missing filename}}

# 2021-04-22 forum https://sqlite.org/forum/forumpost/d82289d69f
do_execsql_test 17.1 {
  WITH vlist(x) AS (
     VALUES(9223372036854775807),
           (-9223372036854775808),
           (9223372036854775806),
           (-9223372036854775807)
  )
  SELECT DISTINCT typeof(zipfile(0,0,x,0)) FROM vlist;
} {blob}
  

finish_test
Changes to tool/lemon.c.
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
      }
      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
      **
      ** 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]) ){







|







2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
      }
      break;
    case WAITING_FOR_TOKEN_NAME:
      /* Tokens do not have to be declared before use.  But they can be
      ** in order to control their assigned integer number.  The number for
      ** each token is assigned when it is first seen.  So by including
      **
      **     %token ONE TWO THREE.
      **
      ** early in the grammar file, that assigns small consecutive values
      ** to each of the tokens ONE TWO and THREE.
      */
      if( x[0]=='.' ){
        psp->state = WAITING_FOR_DECL_OR_RULE;
      }else if( !ISUPPER(x[0]) ){
Changes to tool/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
#!/usr/bin/tclsh
#
# To build the
#
#   const char **azCompileOpt[]
#
# declaration used in src/ctime.c, run this script.

#

# All Boolean compile time options.


#
set boolean_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_CEROD
  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_FTS3
  SQLITE_ENABLE_FTS3_PARENTHESIS
  SQLITE_ENABLE_FTS3_TOKENIZER
  SQLITE_ENABLE_FTS4
  SQLITE_ENABLE_FTS5

  SQLITE_ENABLE_HIDDEN_COLUMNS
  SQLITE_ENABLE_ICU
  SQLITE_ENABLE_IOTRACE
  SQLITE_ENABLE_JSON1
  SQLITE_ENABLE_LOAD_EXTENSION
  SQLITE_ENABLE_LOCKING_STYLE

  SQLITE_ENABLE_MEMORY_MANAGEMENT
  SQLITE_ENABLE_MEMSYS3
  SQLITE_ENABLE_MEMSYS5
  SQLITE_ENABLE_MULTIPLEX

  SQLITE_ENABLE_NULL_TRIM

  SQLITE_ENABLE_OVERSIZE_CELL_CHECK
  SQLITE_ENABLE_PREUPDATE_HOOK

  SQLITE_ENABLE_RBU
  SQLITE_ENABLE_RTREE
  SQLITE_ENABLE_SELECTTRACE
  SQLITE_ENABLE_SESSION
  SQLITE_ENABLE_SNAPSHOT

  SQLITE_ENABLE_SQLLOG

  SQLITE_ENABLE_STMT_SCANSTATUS

  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_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_LIKE_OPTIMIZATION
  SQLITE_OMIT_LOAD_EXTENSION
  SQLITE_OMIT_LOCALTIME
  SQLITE_OMIT_LOOKASIDE
  SQLITE_OMIT_MEMORYDB
  SQLITE_OMIT_OR_OPTIMIZATION
  SQLITE_OMIT_PAGER_PRAGMAS






|
>


|
>
>

|
>
>
>
>
>
>
>
>
>
>



<











<














>
|




|
|
|
|





>






>




>

>


>





>

>

>











<
<











<

















<






|
|
|









>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107


108
109
110
111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/usr/bin/tclsh
#
# To build the
#
#   const char **azCompileOpt[]
#
# definition used in src/ctime.c, run this script from
# the checkout root. It alters src/ctime.c in-place.
#

# 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_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_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_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_BYTECODE_VTAB
  SQLITE_ENABLE_COLUMN_METADATA
  SQLITE_ENABLE_COLUMN_USED_MASK
  SQLITE_ENABLE_COSTMULT
  SQLITE_ENABLE_CURSOR_HINTS
  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_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_QPSG
  SQLITE_ENABLE_RBU
  SQLITE_ENABLE_RTREE
  SQLITE_ENABLE_SELECTTRACE
  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_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_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_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_CAST
  SQLITE_OMIT_CHECK
  SQLITE_OMIT_COMPLETE
  SQLITE_OMIT_COMPOUND_SELECT
  SQLITE_OMIT_CONFLICT_CLAUSE
  SQLITE_OMIT_CTE
  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_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
  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.








#
set value_options {
  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_ENABLE_8_3_NAMES

  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







<











<








<













|
>
>
>
>
>
>
>
>








<











>







169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
184
185
186

187
188
189
190
191
192
193
194

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

  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(THREADSAFE) {
#if defined(SQLITE_THREADSAFE)
  "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
#elif defined(THREADSAFE)
  "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
#else
  "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 b $boolean_options {
  set name [trim_name $b]
  set options($name) [subst {
#if $b
  "$name",
#endif
}]
}
  
foreach v $value_options {
  set name [trim_name $v]
  set options($name) [subst {
#ifdef $v
  "$name=" CTIMEOPT_VAL($v),
#endif
}]
}




























































foreach o [lsort [array names options]] {
  puts [string trim $options($o)]
}











<
<
<
<
<
<
<
















>
>
>
>
>
>
>
>
>
>
>
>
>






|











>
>
>
>
>
>
>
>
>
>
>
>
>
|
















|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|

|
>

>
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
  SQLITE_STAT4_SAMPLES
  SQLITE_STMTJRNL_SPILL
  SQLITE_TEMP_STORE
}

# Options that require custom code.
#







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",
#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_defnil_options {
  set name [trim_name $b]
  set options($name) [subst {
#if $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
}]
}

# Split a string on a regex, return all parts in order.
# Any elements with an even index may be empty.
# Elements with odd indices will match the regex.
proc split_on_re {re str {nrepps 1}} {
  set chunks {}
  set cix 0
  set resm [regexp -all -inline -indices $re $str]
  if {[llength $resm]==0} {
    return $str
  }
  set rix 0
  while {$rix < [llength $resm]} {
    set mre [lindex $resm $rix]
    incr rix $nrepps
    set mbx [lindex $mre 0]
    set mex [lindex $mre 1]
    lappend chunks [string range $str $cix [expr $mbx - 1]]
    lappend chunks [string range $str $mbx $mex]
    set cix [expr $mex + 1]
  }
  lappend chunks [string range $str $cix end]
  return $chunks
}


set ctime_c "src/ctime.c"
if {[catch {set cfd [open $ctime_c r]}]!=0} {
  puts stderr "File '$ctime_c' unreadable. Run this script from checkout root."
  exit 1;
}

set ctfc [read $cfd]
close $cfd

set re {/\*\s+\*+\s*((BEGIN)|(END)) CODE GENERATED BY (\S+)\s+\*/\s+}
set renpp 5

set ctfcChunks [split_on_re $re $ctfc $renpp]
if {[llength $ctfcChunks] != 5} {
  puts stderr "File '$ctime_c' has too few generated code markers."
  exit 1;
}

if {[catch {set cfd [open $ctime_c w]}]!=0} {
  puts stderr "File '$ctime_c' unwritable."
  exit 1;
}

puts -nonewline $cfd [lindex $ctfcChunks 0]
puts -nonewline $cfd [lindex $ctfcChunks 1]
foreach o [lsort [array names options]] {
  puts $cfd [string trim $options($o)]
}
puts -nonewline $cfd [lindex $ctfcChunks 3]
puts -nonewline $cfd [lindex $ctfcChunks 4]

close $cfd
Changes to tool/mkopcodeh.tcl.
141
142
143
144
145
146
147
148


149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
  set out2($name) 0
  set out3($name) 0
  set op($name) -1
  set order($nOp) $name
  incr nOp
}

# The following are the opcodes that are processed by resolveP2Values()


#
set rp2v_ops {
  OP_Transaction
  OP_AutoCommit
  OP_Savepoint
  OP_Checkpoint
  OP_Vacuum
  OP_JournalMode
  OP_VUpdate
  OP_VFilter
  OP_Next
  OP_NextIfOpen
  OP_SorterNext
  OP_Prev
  OP_PrevIfOpen
}

# Assign small 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
  }
}


# 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







|
>
>











<


<


|













>







141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

162
163

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  set out2($name) 0
  set out3($name) 0
  set op($name) -1
  set order($nOp) $name
  incr nOp
}

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

}

# 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
307
308
309
310
311
312
313
314
315
316
317
318
319
320
  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 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 */"







|






308
309
310
311
312
313
314
315
316
317
318
319
320
321
  puts -nonewline [format " 0x%02x," $bv($i)]
  if {$i%8==7} {
    puts "\\"
  }
}
puts "\175"
puts ""
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/omittest.tcl.
202
203
204
205
206
207
208

209
210
211
212
213
214
215
    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_DISKIO \
    SQLITE_OMIT_EXPLAIN \
    SQLITE_OMIT_FLAG_PRAGMAS \
    SQLITE_OMIT_FLOATING_POINT \
    SQLITE_OMIT_FOREIGN_KEY \
    SQLITE_OMIT_GENERATED_COLUMNS \
    SQLITE_OMIT_GET_TABLE \







>







202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
    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 \
250
251
252
253
254
255
256

257
258
259
260
261
262
263
    SQLITE_OMIT_WAL \
    SQLITE_OMIT_WINDOWFUNC \
    SQLITE_OMIT_WSD \
    SQLITE_OMIT_XFER_OPT \
  ]

  set ::ENABLE_SYMBOLS [list \

    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 \







>







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    SQLITE_OMIT_WAL \
    SQLITE_OMIT_WINDOWFUNC \
    SQLITE_OMIT_WSD \
    SQLITE_OMIT_XFER_OPT \
  ]

  set ::ENABLE_SYMBOLS [list \
    SQLITE_ALLOW_ROWID_IN_VIEW \
    SQLITE_DISABLE_DIRSYNC \
    SQLITE_DISABLE_LFS \
    SQLITE_ENABLE_ATOMIC_WRITE \
    SQLITE_ENABLE_COLUMN_METADATA \
    SQLITE_ENABLE_EXPENSIVE_ASSERT \
    SQLITE_ENABLE_FTS3 \
    SQLITE_ENABLE_FTS3_PARENTHESIS \
Changes to tool/showdb.c.
908
909
910
911
912
913
914

915
916
917




918




919
920
921
922
923
924
925
  }else{
    page_usage_msg(pgno, "orphaned %s, %s", zType, zEntry);
  }
  if( a[hdr]==2 || a[hdr]==5 ){
    int cellstart = hdr+12;
    u32 child;
    for(i=0; i<nCell; i++){

      u32 ofst;

      ofst = cellstart + i*2;




      ofst = a[ofst]*256 + a[ofst+1];




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







>


|
>
>
>
>
|
>
>
>
>







908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
  }else{
    page_usage_msg(pgno, "orphaned %s, %s", zType, zEntry);
  }
  if( a[hdr]==2 || a[hdr]==5 ){
    int cellstart = hdr+12;
    u32 child;
    for(i=0; i<nCell; i++){
      u32 cellidx;
      u32 ofst;

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