summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/md4c.pri1
-rw-r--r--src/3rdparty/sqlite/patches/0001-Fix-CVE-2019-19244-in-SQLite.patch26
-rw-r--r--src/3rdparty/sqlite/patches/0002-Fix-CVE-2019-19242-in-SQLite.patch31
-rw-r--r--src/3rdparty/sqlite/patches/0003-Fix-CVE-2019-19603-in-SQLite.patch95
-rw-r--r--src/3rdparty/sqlite/patches/0004-Fix-CVE-2019-19646-in-SQLite.patch29
-rw-r--r--src/3rdparty/sqlite/patches/0005-Fix-CVE-2019-19645-in-SQLite.patch83
-rw-r--r--src/3rdparty/sqlite/qt_attribution.json4
-rw-r--r--src/3rdparty/sqlite/sqlite3.c13888
-rw-r--r--src/3rdparty/sqlite/sqlite3.h545
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java128
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java4
-rw-r--r--src/corelib/.prev_CMakeLists.txt1
-rw-r--r--src/corelib/CMakeLists.txt1
-rw-r--r--src/corelib/Qt6CoreMacros.cmake9
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp4
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp2
-rw-r--r--src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp5
-rw-r--r--src/corelib/global/qfloat16.cpp2
-rw-r--r--src/corelib/global/qfloat16tables.cpp2
-rw-r--r--src/corelib/global/qlogging.cpp30
-rw-r--r--src/corelib/global/qnamespace.h22
-rw-r--r--src/corelib/global/qnamespace.qdoc45
-rw-r--r--src/corelib/io/io.pri4
-rw-r--r--src/corelib/io/qfile.cpp60
-rw-r--r--src/corelib/io/qfile.h3
-rw-r--r--src/corelib/io/qfileinfo.cpp2
-rw-r--r--src/corelib/io/qfilesystemengine_mac.mm83
-rw-r--r--src/corelib/io/qfilesystemengine_p.h3
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp212
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp198
-rw-r--r--src/corelib/io/qiodevice.cpp2
-rw-r--r--src/corelib/io/qlockfile_unix.cpp3
-rw-r--r--src/corelib/io/qstorageinfo_unix.cpp21
-rw-r--r--src/corelib/io/qurl.cpp7
-rw-r--r--src/corelib/io/qurl.h4
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp3
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm2
-rw-r--r--src/corelib/kernel/qmetatype.h88
-rw-r--r--src/corelib/kernel/qmimedata.cpp53
-rw-r--r--src/corelib/kernel/qsignalmapper.cpp115
-rw-r--r--src/corelib/kernel/qsignalmapper.h10
-rw-r--r--src/corelib/kernel/qtranslator.cpp42
-rw-r--r--src/corelib/kernel/qtranslator.h3
-rw-r--r--src/corelib/kernel/qvariant.cpp4
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp4
-rw-r--r--src/corelib/plugin/qpluginloader.cpp2
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp20
-rw-r--r--src/corelib/statemachine/qstatemachine.h11
-rw-r--r--src/corelib/text/qcollator_icu.cpp7
-rw-r--r--src/corelib/text/qcollator_macx.cpp7
-rw-r--r--src/corelib/text/qcollator_posix.cpp7
-rw-r--r--src/corelib/text/qcollator_win.cpp7
-rw-r--r--src/corelib/text/qlocale.cpp62
-rw-r--r--src/corelib/text/qlocale.h8
-rw-r--r--src/corelib/text/qlocale_mac.mm20
-rw-r--r--src/corelib/text/qlocale_p.h2
-rw-r--r--src/corelib/text/qlocale_win.cpp69
-rw-r--r--src/corelib/thread/qrunnable.cpp27
-rw-r--r--src/corelib/thread/qrunnable.h2
-rw-r--r--src/corelib/thread/qthreadpool.cpp32
-rw-r--r--src/corelib/thread/qthreadpool.h5
-rw-r--r--src/corelib/time/qcalendar.cpp11
-rw-r--r--src/corelib/time/qdatetime.cpp289
-rw-r--r--src/corelib/time/qdatetime.h16
-rw-r--r--src/corelib/time/qdatetimeparser.cpp39
-rw-r--r--src/corelib/time/qtimezoneprivate_win.cpp2
-rw-r--r--src/corelib/tools/qbitarray.cpp2
-rw-r--r--src/corelib/tools/qcontainerfwd.h2
-rw-r--r--src/corelib/tools/qhash.h2
-rw-r--r--src/corelib/tools/qiterator.qdoc2
-rw-r--r--src/corelib/tools/qlinkedlist.cpp14
-rw-r--r--src/corelib/tools/qlinkedlist.h24
-rw-r--r--src/corelib/tools/qmap.cpp2
-rw-r--r--src/corelib/tools/qscopeguard.h32
-rw-r--r--src/corelib/tools/qscopeguard.qdoc41
-rw-r--r--src/gui/.prev_CMakeLists.txt4
-rw-r--r--src/gui/CMakeLists.txt4
-rw-r--r--src/gui/accessible/qaccessible.h4
-rw-r--r--src/gui/image/image.pri2
-rw-r--r--src/gui/image/qicon.cpp2
-rw-r--r--src/gui/image/qimage.cpp4
-rw-r--r--src/gui/image/qimagereader.cpp2
-rw-r--r--src/gui/image/qimagereader.h4
-rw-r--r--src/gui/image/qimagewriter.cpp2
-rw-r--r--src/gui/image/qimagewriter.h4
-rw-r--r--src/gui/image/qpnghandler.cpp2
-rw-r--r--src/gui/kernel/qcursor.cpp4
-rw-r--r--src/gui/kernel/qcursor.h8
-rw-r--r--src/gui/kernel/qhighdpiscaling.cpp2
-rw-r--r--src/gui/kernel/qpixelformat.cpp2
-rw-r--r--src/gui/kernel/qplatformwindow.cpp29
-rw-r--r--src/gui/kernel/qplatformwindow.h4
-rw-r--r--src/gui/kernel/qscreen.cpp2
-rw-r--r--src/gui/kernel/qwindow.cpp72
-rw-r--r--src/gui/kernel/qwindow.h2
-rw-r--r--src/gui/painting/painting.pri2
-rw-r--r--src/gui/painting/qbackingstore.cpp2
-rw-r--r--src/gui/painting/qcolorspace.cpp28
-rw-r--r--src/gui/rhi/qrhi.cpp59
-rw-r--r--src/gui/rhi/qrhi_p.h17
-rw-r--r--src/gui/rhi/qrhi_p_p.h7
-rw-r--r--src/gui/rhi/qrhid3d11.cpp11
-rw-r--r--src/gui/rhi/qrhid3d11_p_p.h9
-rw-r--r--src/gui/rhi/qrhigles2.cpp17
-rw-r--r--src/gui/rhi/qrhigles2_p_p.h9
-rw-r--r--src/gui/rhi/qrhimetal.mm151
-rw-r--r--src/gui/rhi/qrhimetal_p_p.h10
-rw-r--r--src/gui/rhi/qrhinull.cpp8
-rw-r--r--src/gui/rhi/qrhinull_p_p.h9
-rw-r--r--src/gui/rhi/qrhivulkan.cpp41
-rw-r--r--src/gui/rhi/qrhivulkan_p_p.h9
-rw-r--r--src/gui/text/qtextengine.cpp3
-rw-r--r--src/gui/text/qtextmarkdownimporter.cpp8
-rw-r--r--src/gui/text/qtextmarkdownwriter.cpp76
-rw-r--r--src/network/access/qftp.cpp8
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp6
-rw-r--r--src/network/access/qhttpnetworkconnection_p.h4
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp4
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel_p.h2
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp4
-rw-r--r--src/network/access/qhttpthreaddelegate_p.h2
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp2
-rw-r--r--src/network/access/qnetworkaccessftpbackend.cpp2
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp33
-rw-r--r--src/network/access/qnetworkaccessmanager.h26
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h12
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp18
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h8
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp14
-rw-r--r--src/network/access/qnetworkreplyimpl_p.h6
-rw-r--r--src/network/doc/snippets/network/tcpwait.cpp2
-rw-r--r--src/network/doc/snippets/snippets.pro7
-rw-r--r--src/network/kernel/qnetworkproxy.cpp7
-rw-r--r--src/network/socket/qabstractsocket.cpp13
-rw-r--r--src/network/socket/qhttpsocketengine.cpp2
-rw-r--r--src/network/socket/qlocalsocket.cpp41
-rw-r--r--src/network/socket/qlocalsocket.h11
-rw-r--r--src/network/socket/qlocalsocket_p.h4
-rw-r--r--src/network/socket/qlocalsocket_tcp.cpp23
-rw-r--r--src/network/socket/qlocalsocket_unix.cpp41
-rw-r--r--src/network/socket/qlocalsocket_win.cpp13
-rw-r--r--src/network/socket/qsocks5socketengine.cpp4
-rw-r--r--src/network/socket/qtcpserver.cpp4
-rw-r--r--src/network/ssl/qsslconfiguration.cpp10
-rw-r--r--src/network/ssl/qsslconfiguration.h2
-rw-r--r--src/network/ssl/qsslcontext_openssl.cpp21
-rw-r--r--src/network/ssl/qsslpresharedkeyauthenticator.cpp2
-rw-r--r--src/network/ssl/qsslsocket.cpp25
-rw-r--r--src/network/ssl/qsslsocket.h1
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp70
-rw-r--r--src/network/ssl/qsslsocket_openssl_p.h1
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp4
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h18
-rw-r--r--src/opengl/qopengltexture.cpp4
-rw-r--r--src/opengl/qopenglwidget.cpp2
-rw-r--r--src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp9
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm30
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp34
-rw-r--r--src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp7
-rw-r--r--src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp4
-rw-r--r--src/plugins/platforms/android/qandroidplatformfiledialoghelper.h2
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp13
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm16
-rw-r--r--src/plugins/platforms/ios/qiostextinputoverlay.mm2
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm2
-rw-r--r--src/plugins/platforms/qnx/qqnxnativeinterface.cpp5
-rw-r--r--src/plugins/platforms/wasm/qwasmclipboard.cpp5
-rw-r--r--src/plugins/platforms/wasm/qwasmclipboard.h3
-rw-r--r--src/plugins/platforms/wasm/qwasmcursor.cpp4
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.cpp29
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.cpp69
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.h10
-rw-r--r--src/plugins/platforms/wasm/qwasmopenglcontext.cpp3
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.cpp33
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.h7
-rw-r--r--src/plugins/platforms/wasm/qwasmstring.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp47
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp13
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp11
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp61
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h9
-rw-r--r--src/plugins/sqldrivers/ibase/qsql_ibase.cpp4
-rw-r--r--src/plugins/sqldrivers/mysql/mysql.json2
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm39
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle.cpp264
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h4
-rw-r--r--src/printsupport/doc/snippets/printing-qprinter/errors.cpp6
-rw-r--r--src/printsupport/doc/snippets/printing-qprinter/object.cpp7
-rw-r--r--src/printsupport/doc/snippets/widgetprinting.cpp22
-rw-r--r--src/sql/doc/src/sql-driver.qdoc4
-rw-r--r--src/testlib/.prev_CMakeLists.txt5
-rw-r--r--src/testlib/CMakeLists.txt5
-rw-r--r--src/testlib/doc/src/qttestlib-manual.qdoc8
-rw-r--r--src/testlib/qjunittestlogger.cpp (renamed from src/testlib/qxunittestlogger.cpp)30
-rw-r--r--src/testlib/qjunittestlogger_p.h (renamed from src/testlib/qxunittestlogger_p.h)16
-rw-r--r--src/testlib/qtestcase.cpp441
-rw-r--r--src/testlib/qtestjunitstreamer.cpp (renamed from src/testlib/qtestxunitstreamer.cpp)26
-rw-r--r--src/testlib/qtestjunitstreamer_p.h (renamed from src/testlib/qtestxunitstreamer_p.h)15
-rw-r--r--src/testlib/qtestlog.cpp8
-rw-r--r--src/testlib/qtestlog_p.h6
-rw-r--r--src/testlib/qtestutil_macos.mm28
-rw-r--r--src/testlib/qtestutil_macos_p.h1
-rw-r--r--src/testlib/testlib.pro10
-rw-r--r--src/tools/androiddeployqt/main.cpp5
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.cpp2
-rw-r--r--src/tools/uic/python/pythonwriteimports.cpp8
-rw-r--r--src/widgets/dialogs/qfilesystemmodel.cpp2
-rw-r--r--src/widgets/dialogs/qinputdialog.cpp3
-rw-r--r--src/widgets/dialogs/qinputdialog.h11
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp17
-rw-r--r--src/widgets/itemviews/qdirmodel.cpp2
-rw-r--r--src/widgets/kernel/qwidget.cpp6
-rw-r--r--src/widgets/styles/qcommonstyle.cpp9
-rw-r--r--src/widgets/styles/qfusionstyle.cpp2
-rw-r--r--src/widgets/styles/qstyle.cpp2
-rw-r--r--src/widgets/styles/qstyle.h2
-rw-r--r--src/widgets/styles/qstyleoption.cpp2
-rw-r--r--src/widgets/styles/qwindowsstyle.cpp2
-rw-r--r--src/widgets/widgets/qcombobox.cpp23
-rw-r--r--src/widgets/widgets/qcombobox.h5
-rw-r--r--src/widgets/widgets/qlabel.cpp4
-rw-r--r--src/widgets/widgets/qlabel.h8
-rw-r--r--src/widgets/widgets/qpushbutton.cpp11
-rw-r--r--src/widgets/widgets/qpushbutton.h1
-rw-r--r--src/widgets/widgets/qsizegrip.cpp16
-rw-r--r--src/widgets/widgets/qtextedit.cpp1
230 files changed, 12185 insertions, 7124 deletions
diff --git a/src/3rdparty/md4c.pri b/src/3rdparty/md4c.pri
index e0150dc6ed..8de2991ac2 100644
--- a/src/3rdparty/md4c.pri
+++ b/src/3rdparty/md4c.pri
@@ -1,3 +1,4 @@
INCLUDEPATH += $$PWD/md4c
HEADERS += $$PWD/md4c/md4c.h
SOURCES += $$PWD/md4c/md4c.c
+DEFINES += MD4C_USE_UTF8
diff --git a/src/3rdparty/sqlite/patches/0001-Fix-CVE-2019-19244-in-SQLite.patch b/src/3rdparty/sqlite/patches/0001-Fix-CVE-2019-19244-in-SQLite.patch
deleted file mode 100644
index 9906292860..0000000000
--- a/src/3rdparty/sqlite/patches/0001-Fix-CVE-2019-19244-in-SQLite.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 676425e522e08eb0e7dfaacdac79a5de27542322 Mon Sep 17 00:00:00 2001
-From: Andy Shaw <andy.shaw@qt.io>
-Date: Wed, 11 Dec 2019 10:51:22 +0100
-Subject: [PATCH 53/53] Fix CVE-2019-19244 in SQLite
-
-Fixes: QTBUG-80635
-Change-Id: I718349e28ec76ea164dd50f2a985f2074dd6bdbd
----
- src/3rdparty/sqlite/sqlite3.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
-index 8fd740b300..bd647ca1c2 100644
---- a/src/3rdparty/sqlite/sqlite3.c
-+++ b/src/3rdparty/sqlite/sqlite3.c
-@@ -131679,6 +131679,7 @@ SQLITE_PRIVATE int sqlite3Select(
- */
- if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
- && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
-+ && p->pWin==0
- ){
- p->selFlags &= ~SF_Distinct;
- pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
---
-2.21.0 (Apple Git-122.2)
-
diff --git a/src/3rdparty/sqlite/patches/0002-Fix-CVE-2019-19242-in-SQLite.patch b/src/3rdparty/sqlite/patches/0002-Fix-CVE-2019-19242-in-SQLite.patch
deleted file mode 100644
index 92739192e4..0000000000
--- a/src/3rdparty/sqlite/patches/0002-Fix-CVE-2019-19242-in-SQLite.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 7905740b8e79479298e83d8e559fc49b46cf980e Mon Sep 17 00:00:00 2001
-From: Andy Shaw <andy.shaw@qt.io>
-Date: Thu, 19 Dec 2019 21:59:09 +0100
-Subject: [PATCH] Fix CVE-2019-19242 in SQLite
-
-Change-Id: I78a72a574da5cf3503950afe47146ae6424f00c6
----
- src/3rdparty/sqlite/sqlite3.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
-index bd647ca1c2..d3e0c065b6 100644
---- a/src/3rdparty/sqlite/sqlite3.c
-+++ b/src/3rdparty/sqlite/sqlite3.c
-@@ -101055,7 +101055,12 @@ expr_code_doover:
- ** constant.
- */
- int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
-- int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
-+ int aff;
-+ if( pExpr->y.pTab ){
-+ aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
-+ }else{
-+ aff = pExpr->affExpr;
-+ }
- if( aff>SQLITE_AFF_BLOB ){
- static const char zAff[] = "B\000C\000D\000E";
- assert( SQLITE_AFF_BLOB=='A' );
---
-2.21.0 (Apple Git-122.2)
-
diff --git a/src/3rdparty/sqlite/patches/0003-Fix-CVE-2019-19603-in-SQLite.patch b/src/3rdparty/sqlite/patches/0003-Fix-CVE-2019-19603-in-SQLite.patch
deleted file mode 100644
index 1b8deaa4a1..0000000000
--- a/src/3rdparty/sqlite/patches/0003-Fix-CVE-2019-19603-in-SQLite.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-From 11a2f4647b67494fb731a6fd793f1b28074631d3 Mon Sep 17 00:00:00 2001
-From: Andy Shaw <andy.shaw@qt.io>
-Date: Thu, 19 Dec 2019 22:31:15 +0100
-Subject: [PATCH] Fix CVE-2019-19603 in SQLite
-
-This includes the patch needed to fix this CVE and a supporting one to
-include a new function added that it depends on.
-
-Task-number: QTBUG-80903
-Change-Id: Ic7639d50c89a3ee7d45426588c3ab0efd0eebb72
----
- src/3rdparty/sqlite/sqlite3.c | 32 ++++++++++++++++++++++++++------
- 1 file changed, 26 insertions(+), 6 deletions(-)
-
-diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
-index d3e0c065b6..a430554db7 100644
---- a/src/3rdparty/sqlite/sqlite3.c
-+++ b/src/3rdparty/sqlite/sqlite3.c
-@@ -19519,6 +19519,12 @@ SQLITE_PRIVATE Module *sqlite3VtabCreateModule(
- );
- # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
- #endif
-+SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db);
-+#ifndef SQLITE_OMIT_VIRTUALTABLE
-+SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
-+#else
-+# define sqlite3ShadowTableName(A,B) 0
-+#endif
- SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
- SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
- SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
-@@ -108483,6 +108489,22 @@ SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3 *db){
- return (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==SQLITE_WriteSchema;
- }
-
-+/*
-+ ** Return TRUE if shadow tables should be read-only in the current
-+ ** context.
-+ */
-+int sqlite3ReadOnlyShadowTables(sqlite3 *db){
-+#ifndef SQLITE_OMIT_VIRTUALTABLE
-+ if( (db->flags & SQLITE_Defensive)!=0
-+ && db->pVtabCtx==0
-+ && db->nVdbeExec==0
-+ ){
-+ return 1;
-+ }
-+#endif
-+ return 0;
-+}
-+
- /*
- ** This routine is used to check if the UTF-8 string zName is a legal
- ** unqualified name for a new schema object (table, index, view or
-@@ -108516,8 +108538,8 @@ SQLITE_PRIVATE int sqlite3CheckObjectName(
- }
- }
- }else{
-- if( pParse->nested==0
-- && 0==sqlite3StrNICmp(zName, "sqlite_", 7)
-+ if( (pParse->nested==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7))
-+ || (sqlite3ReadOnlyShadowTables(db) && sqlite3ShadowTableName(db, zName))
- ){
- sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s",
- zName);
-@@ -109662,7 +109684,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
- ** zName is temporarily modified while this routine is running, but is
- ** restored to its original value prior to this routine returning.
- */
--static int isShadowTableName(sqlite3 *db, char *zName){
-+int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
- char *zTail; /* Pointer to the last "_" in zName */
- Table *pTab; /* Table that zName is a shadow of */
- Module *pMod; /* Module for the virtual table */
-@@ -109680,8 +109702,6 @@ static int isShadowTableName(sqlite3 *db, char *zName){
- if( pMod->pModule->xShadowName==0 ) return 0;
- return pMod->pModule->xShadowName(zTail+1);
- }
--#else
--# define isShadowTableName(x,y) 0
- #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
-
- /*
-@@ -109723,7 +109743,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
- p = pParse->pNewTable;
- if( p==0 ) return;
-
-- if( pSelect==0 && isShadowTableName(db, p->zName) ){
-+ if( pSelect==0 && sqlite3ShadowTableName(db, p->zName) ){
- p->tabFlags |= TF_Shadow;
- }
-
---
-2.21.0 (Apple Git-122.2)
-
diff --git a/src/3rdparty/sqlite/patches/0004-Fix-CVE-2019-19646-in-SQLite.patch b/src/3rdparty/sqlite/patches/0004-Fix-CVE-2019-19646-in-SQLite.patch
deleted file mode 100644
index db436ab4f6..0000000000
--- a/src/3rdparty/sqlite/patches/0004-Fix-CVE-2019-19646-in-SQLite.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From a83bbce4d6f31d93ea4d2a681aa52c148f148e26 Mon Sep 17 00:00:00 2001
-From: Andy Shaw <andy.shaw@qt.io>
-Date: Thu, 2 Jan 2020 09:07:08 +0100
-Subject: [PATCH] Fix CVE-2019-19646 in SQLite
-
-Task-number: QTBUG-81020
-Change-Id: I7176db20d4a44b1fb443a6108675f719e9643343
----
- src/3rdparty/sqlite/sqlite3.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
-index 57e61b8313..980a149b1a 100644
---- a/src/3rdparty/sqlite/sqlite3.c
-+++ b/src/3rdparty/sqlite/sqlite3.c
-@@ -123765,7 +123765,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
- if( j==pTab->iPKey ) continue;
- if( pTab->aCol[j].notNull==0 ) continue;
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
-- sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
-+ if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){
-+ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
-+ }
- jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
- zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
- pTab->aCol[j].zName);
---
-2.21.0 (Apple Git-122.2)
-
diff --git a/src/3rdparty/sqlite/patches/0005-Fix-CVE-2019-19645-in-SQLite.patch b/src/3rdparty/sqlite/patches/0005-Fix-CVE-2019-19645-in-SQLite.patch
deleted file mode 100644
index e92c566881..0000000000
--- a/src/3rdparty/sqlite/patches/0005-Fix-CVE-2019-19645-in-SQLite.patch
+++ /dev/null
@@ -1,83 +0,0 @@
-From 78c972eec5bab03a408b8ba1373572bcfe2db630 Mon Sep 17 00:00:00 2001
-From: Andy Shaw <andy.shaw@qt.io>
-Date: Thu, 2 Jan 2020 08:47:23 +0100
-Subject: [PATCH] Fix CVE-2019-19645 in SQLite
-
-Task-number: QTBUG-81020
-Change-Id: I58b1dd9e7a90ba998c3af7f25a4627d8bdd70970
----
- src/3rdparty/sqlite/sqlite3.c | 11 ++++++++++-
- 1 file changed, 10 insertions(+), 1 deletion(-)
-
-diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
-index d3e0c065b6..57e61b8313 100644
---- a/src/3rdparty/sqlite/sqlite3.c
-+++ b/src/3rdparty/sqlite/sqlite3.c
-@@ -17946,6 +17946,7 @@ struct Select {
- #define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
- #define SF_ComplexResult 0x40000 /* Result contains subquery or function */
- #define SF_WhereBegin 0x80000 /* Really a WhereBegin() call. Debug Only */
-+#define SF_View 0x0200000 /* SELECT statement is a view */
-
- /*
- ** The results of a SELECT can be distributed in several ways, as defined
-@@ -103920,6 +103921,7 @@ static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){
- static int renameUnmapSelectCb(Walker *pWalker, Select *p){
- Parse *pParse = pWalker->pParse;
- int i;
-+ if( p->selFlags & SF_View ) return WRC_Prune;
- if( ALWAYS(p->pEList) ){
- ExprList *pList = p->pEList;
- for(i=0; i<pList->nExpr; i++){
-@@ -104024,6 +104026,7 @@ static void renameWalkWith(Walker *pWalker, Select *pSelect){
- ** descend into sub-select statements.
- */
- static int renameColumnSelectCb(Walker *pWalker, Select *p){
-+ if( p->selFlags & SF_View ) return WRC_Prune;
- renameWalkWith(pWalker, p);
- return WRC_Continue;
- }
-@@ -104489,8 +104492,9 @@ static void renameColumnFunc(
- if( sParse.pNewTable ){
- Select *pSelect = sParse.pNewTable->pSelect;
- if( pSelect ){
-+ pSelect->selFlags &= ~SF_View;
- sParse.rc = SQLITE_OK;
-- sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, 0);
-+ sqlite3SelectPrep(&sParse, pSelect, 0);
- rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
- if( rc==SQLITE_OK ){
- sqlite3WalkSelect(&sWalker, pSelect);
-@@ -104602,6 +104606,7 @@ 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;
-@@ -104681,10 +104686,13 @@ static void renameTableFunc(
-
- if( pTab->pSelect ){
- if( isLegacy==0 ){
-+ Select *pSelect = pTab->pSelect;
- NameContext sNC;
- memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = &sParse;
-
-+ assert( pSelect->selFlags & SF_View );
-+ pSelect->selFlags &= ~SF_View;
- sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
- if( sParse.nErr ) rc = sParse.rc;
- sqlite3WalkSelect(&sWalker, pTab->pSelect);
-@@ -109994,6 +110002,7 @@ SQLITE_PRIVATE void sqlite3CreateView(
- ** allocated rather than point to the input string - which means that
- ** they will persist after the current sqlite3_exec() call returns.
- */
-+ pSelect->selFlags |= SF_View;
- if( IN_RENAME_OBJECT ){
- p->pSelect = pSelect;
- pSelect = 0;
---
-2.21.0 (Apple Git-122.2)
-
diff --git a/src/3rdparty/sqlite/qt_attribution.json b/src/3rdparty/sqlite/qt_attribution.json
index 4d0851e9b9..e60605a5e8 100644
--- a/src/3rdparty/sqlite/qt_attribution.json
+++ b/src/3rdparty/sqlite/qt_attribution.json
@@ -6,8 +6,8 @@
"Description": "SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine.",
"Homepage": "https://www.sqlite.org/",
- "Version": "3.30.1",
- "DownloadLocation": "https://www.sqlite.org/2019/sqlite-amalgamation-3300100.zip",
+ "Version": "3.31.1",
+ "DownloadLocation": "https://www.sqlite.org/2020/sqlite-amalgamation-3310100.zip",
"License": "Public Domain",
"Copyright": "The authors disclaim copyright to the source code. However, a license can be obtained if needed."
}
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
index d5b43857ad..55dc686ee0 100644
--- a/src/3rdparty/sqlite/sqlite3.c
+++ b/src/3rdparty/sqlite/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.30.1. By combining all the individual C code files into this
+** version 3.31.1. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -1165,9 +1165,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.30.1"
-#define SQLITE_VERSION_NUMBER 3030001
-#define SQLITE_SOURCE_ID "2019-10-10 20:19:45 18db032d058f1436ce3dea84081f4ee5a0f2259ad97301d43c426bc7f3df1b0b"
+#define SQLITE_VERSION "3.31.1"
+#define SQLITE_VERSION_NUMBER 3031001
+#define SQLITE_SOURCE_ID "2020-01-27 19:55:54 3bfa9cc97da10598521b342961df8f5f68c7388fa117345eeb516eaa837bb4d6"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -1558,6 +1558,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
+#define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
@@ -1577,11 +1578,13 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8))
#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8))
+#define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8))
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8))
+#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8))
/*
** CAPI3REF: Flags For File Open Operations
@@ -1610,6 +1613,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
+#define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */
/* Reserved: 0x00F00000 */
@@ -2021,16 +2025,16 @@ struct sqlite3_io_methods {
** ^The [SQLITE_FCNTL_BUSYHANDLER]
** file-control may be invoked by SQLite on the database file handle
** shortly after it is opened in order to provide a custom VFS with access
-** to the connections busy-handler callback. The argument is of type (void **)
+** to the connection's busy-handler callback. The argument is of type (void**)
** - an array of two (void *) values. The first (void *) actually points
-** to a function of type (int (*)(void *)). In order to invoke the connections
+** to a function of type (int (*)(void *)). In order to invoke the connection's
** busy-handler, this function should be invoked with the second (void *) in
** the array as the only argument. If it returns non-zero, then the operation
** should be retried. If it returns zero, the custom VFS should abandon the
** current operation.
**
** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
-** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
+** ^Applications can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
** to have SQLite generate a
** temporary filename using the same algorithm that is followed to generate
** temporary filenames for TEMP tables and other internal uses. The
@@ -2143,12 +2147,18 @@ struct sqlite3_io_methods {
** not provide a mechanism to detect changes to MAIN only. Also, the
** [sqlite3_total_changes()] interface responds to internal changes only and
** omits changes made by other database connections. The
-** [PRAGMA data_version] command provide a mechanism to detect changes to
+** [PRAGMA data_version] command provides a mechanism to detect changes to
** a single attached database that occur due to other database connections,
** but omits changes implemented by the database connection on which it is
** called. This file control is the only mechanism to detect changes that
** happen either internally or externally and that are associated with
** a particular attached database.
+**
+** <li>[[SQLITE_FCNTL_CKPT_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
@@ -2186,6 +2196,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_LOCK_TIMEOUT 34
#define SQLITE_FCNTL_DATA_VERSION 35
#define SQLITE_FCNTL_SIZE_LIMIT 36
+#define SQLITE_FCNTL_CKPT_DONE 37
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -2231,10 +2242,10 @@ typedef struct sqlite3_api_routines sqlite3_api_routines;
** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields
** may be appended to the sqlite3_vfs object and the iVersion value
** may increase again in future versions of SQLite.
-** Note that the structure
-** of the sqlite3_vfs object changes in the transition from
+** Note that due to an oversight, the structure
+** of the sqlite3_vfs object changed in the transition from
** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0]
-** and yet the iVersion field was not modified.
+** and yet the iVersion field was not increased.
**
** The szOsFile field is the size of the subclassed [sqlite3_file]
** structure used by this VFS. mxPathname is the maximum length of
@@ -2325,7 +2336,7 @@ typedef struct sqlite3_api_routines sqlite3_api_routines;
** for exclusive access.
**
** ^At least szOsFile bytes of memory are allocated by SQLite
-** to hold the [sqlite3_file] structure passed as the third
+** to hold the [sqlite3_file] structure passed as the third
** argument to xOpen. The xOpen method does not have to
** allocate the structure; it should just fill it in. Note that
** the xOpen method must set the sqlite3_file.pMethods to either
@@ -2662,7 +2673,7 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
** that causes the corresponding memory allocation to fail.
**
** The xInit method initializes the memory allocator. For example,
-** it might allocate any require mutexes or initialize internal data
+** it might allocate any required mutexes or initialize internal data
** structures. The xShutdown method is invoked (indirectly) by
** [sqlite3_shutdown()] and should deallocate any resources acquired
** by xInit. The pAppData pointer is used as the only parameter to
@@ -2784,6 +2795,7 @@ struct sqlite3_mem_methods {
** memory allocation statistics. ^(When memory allocation statistics are
** disabled, the following SQLite interfaces become non-operational:
** <ul>
+** <li> [sqlite3_hard_heap_limit64()]
** <li> [sqlite3_memory_used()]
** <li> [sqlite3_memory_highwater()]
** <li> [sqlite3_soft_heap_limit64()]
@@ -2802,7 +2814,7 @@ struct sqlite3_mem_methods {
** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool
** that SQLite can use for the database page cache with the default page
** cache implementation.
-** This configuration option is a no-op if an application-define page
+** This configuration option is a no-op if an application-defined page
** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2].
** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
** 8-byte aligned memory (pMem), the size of each page cache line (sz),
@@ -3287,7 +3299,7 @@ struct sqlite3_mem_methods {
** [[SQLITE_DBCONFIG_DQS_DML]]
** <dt>SQLITE_DBCONFIG_DQS_DML</td>
** <dd>The SQLITE_DBCONFIG_DQS_DML option activates or deactivates
-** the legacy [double-quoted string literal] misfeature for DML statement
+** the legacy [double-quoted string literal] misfeature for DML statements
** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The
** default value of this setting is determined by the [-DSQLITE_DQS]
** compile-time option.
@@ -3301,6 +3313,49 @@ struct sqlite3_mem_methods {
** default value of this setting is determined by the [-DSQLITE_DQS]
** compile-time option.
** </dd>
+**
+** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]]
+** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</td>
+** <dd>The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to
+** assume that database schemas (the contents of the [sqlite_master] tables)
+** are untainted by malicious content.
+** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite
+** takes additional defensive steps to protect the application from harm
+** including:
+** <ul>
+** <li> Prohibit the use of SQL functions inside triggers, views,
+** CHECK constraints, DEFAULT clauses, expression indexes,
+** partial indexes, or generated columns
+** unless those functions are tagged with [SQLITE_INNOCUOUS].
+** <li> Prohibit the use of virtual tables inside of triggers or views
+** unless those virtual tables are tagged with [SQLITE_VTAB_INNOCUOUS].
+** </ul>
+** This setting defaults to "on" for legacy compatibility, however
+** all applications are advised to turn it off if possible. This setting
+** can also be controlled using the [PRAGMA trusted_schema] statement.
+** </dd>
+**
+** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]]
+** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</td>
+** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates
+** the legacy file format flag. When activated, this flag causes all newly
+** created database file to have a schema format version number (the 4-byte
+** integer found at offset 44 into the database header) of 1. This in turn
+** means that the resulting database file will be readable and writable by
+** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting,
+** newly created databases are generally not understandable by SQLite versions
+** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there
+** is now scarcely any need to generated database files that are compatible
+** all the way back to version 3.0.0, and so this setting is of little
+** practical use, but is provided so that SQLite can continue to claim the
+** ability to generate new database files that are compatible with version
+** 3.0.0.
+** <p>Note that when the SQLITE_DBCONFIG_LEGACY_FILE_FORMAT setting is on,
+** the [VACUUM] command will fail with an obscure error when attempting to
+** process a table with generated columns and a descending index. This is
+** not considered a bug since SQLite versions 3.3.0 and earlier do not support
+** either generated columns or decending indexes.
+** </dd>
** </dl>
*/
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
@@ -3319,7 +3374,9 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */
#define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */
-#define SQLITE_DBCONFIG_MAX 1015 /* Largest DBCONFIG */
+#define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */
+#define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */
+#define SQLITE_DBCONFIG_MAX 1017 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
@@ -3525,7 +3582,7 @@ SQLITE_API int sqlite3_total_changes(sqlite3*);
** ^The sqlite3_interrupt(D) call is in effect until all currently running
** SQL statements on [database connection] D complete. ^Any new SQL statements
** that are started after the sqlite3_interrupt() call and before the
-** running statements reaches zero are interrupted as if they had been
+** running statement count reaches zero are interrupted as if they had been
** running prior to the sqlite3_interrupt() call. ^New SQL statements
** that are started after the running statement count reaches zero are
** not effected by the sqlite3_interrupt().
@@ -3693,9 +3750,9 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
** Cindy | 21
** </pre></blockquote>
**
-** There are two column (M==2) and three rows (N==3). Thus the
+** There are two columns (M==2) and three rows (N==3). Thus the
** result table has 8 entries. Suppose the result table is stored
-** in an array names azResult. Then azResult holds this content:
+** in an array named azResult. Then azResult holds this content:
**
** <blockquote><pre>
** azResult&#91;0] = "Name";
@@ -3788,7 +3845,7 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
**
** The SQLite core uses these three routines for all of its own
** internal memory allocation needs. "Core" in the previous sentence
-** does not include operating-system specific VFS implementation. The
+** does not include operating-system specific [VFS] implementation. The
** Windows VFS uses native malloc() and free() for some operations.
**
** ^The sqlite3_malloc() routine returns a pointer to a block
@@ -3849,19 +3906,6 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time
** option is used.
**
-** In SQLite version 3.5.0 and 3.5.1, it was possible to define
-** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in
-** implementation of these routines to be omitted. That capability
-** is no longer provided. Only built-in memory allocators can be used.
-**
-** Prior to SQLite version 3.7.10, the Windows OS interface layer called
-** the system malloc() and free() directly when converting
-** filenames between the UTF-8 encoding used by SQLite
-** and whatever filename encoding is used by the particular Windows
-** installation. Memory allocation errors were detected, but
-** they were reported back as [SQLITE_CANTOPEN] or
-** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
-**
** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
** must be either NULL or else pointers obtained from a prior
** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have
@@ -3910,7 +3954,7 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
** SQLite contains a high-quality pseudo-random number generator (PRNG) used to
** select random [ROWID | ROWIDs] when inserting new records into a table that
** already uses the largest possible [ROWID]. The PRNG is also used for
-** the build-in random() and randomblob() SQL functions. This interface allows
+** the built-in random() and randomblob() SQL functions. This interface allows
** applications to access the same PRNG for other purposes.
**
** ^A call to this routine stores N bytes of randomness into buffer P.
@@ -4284,10 +4328,8 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** The sqlite3_open_v2() interface works like sqlite3_open()
** except that it accepts two additional parameters for additional control
** over the new database connection. ^(The flags parameter to
-** sqlite3_open_v2() can take one of
-** the following three values, optionally combined with the
-** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
-** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
+** sqlite3_open_v2() must include, at a minimum, one of the following
+** three flag combinations:)^
**
** <dl>
** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
@@ -4305,23 +4347,51 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** sqlite3_open() and sqlite3_open16().</dd>)^
** </dl>
**
+** In addition to the required flags, the following optional flags are
+** also supported:
+**
+** <dl>
+** ^(<dt>[SQLITE_OPEN_URI]</dt>
+** <dd>The filename can be interpreted as a URI if this flag is set.</dd>)^
+**
+** ^(<dt>[SQLITE_OPEN_MEMORY]</dt>
+** <dd>The database will be opened as an in-memory database. The database
+** is named by the "filename" argument for the purposes of cache-sharing,
+** if shared cache mode is enabled, but the "filename" is otherwise ignored.
+** </dd>)^
+**
+** ^(<dt>[SQLITE_OPEN_NOMUTEX]</dt>
+** <dd>The new database connection will use the "multi-thread"
+** [threading mode].)^ This means that separate threads are allowed
+** to use SQLite at the same time, as long as each thread is using
+** a different [database connection].
+**
+** ^(<dt>[SQLITE_OPEN_FULLMUTEX]</dt>
+** <dd>The new database connection will use the "serialized"
+** [threading mode].)^ This means the multiple threads can safely
+** attempt to use the same database connection at the same time.
+** (Mutexes will block any actual concurrency, but in this mode
+** there is no harm in trying.)
+**
+** ^(<dt>[SQLITE_OPEN_SHAREDCACHE]</dt>
+** <dd>The database is opened [shared cache] enabled, overriding
+** the default shared cache setting provided by
+** [sqlite3_enable_shared_cache()].)^
+**
+** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt>
+** <dd>The database is opened [shared cache] disabled, overriding
+** the default shared cache setting provided by
+** [sqlite3_enable_shared_cache()].)^
+**
+** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
+** <dd>The database filename is not allowed to be a symbolic link</dd>
+** </dl>)^
+**
** If the 3rd parameter to sqlite3_open_v2() is not one of the
-** combinations shown above optionally combined with other
+** required combinations shown above optionally combined with other
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
** then the behavior is undefined.
**
-** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
-** opens in the multi-thread [threading mode] as long as the single-thread
-** mode has not been set at compile-time or start-time. ^If the
-** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens
-** in the serialized [threading mode] unless single-thread was
-** previously selected at compile-time or start-time.
-** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
-** eligible to use [shared cache mode], regardless of whether or not shared
-** cache is enabled using [sqlite3_enable_shared_cache()]. ^The
-** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
-** participate in [shared cache mode] even if it is enabled.
-**
** ^The fourth parameter to sqlite3_open_v2() is the name of the
** [sqlite3_vfs] object that defines the operating system interface that
** the new database connection should use. ^If the fourth parameter is
@@ -4501,17 +4571,16 @@ SQLITE_API int sqlite3_open_v2(
/*
** CAPI3REF: Obtain Values For URI Parameters
**
-** These are utility routines, useful to VFS implementations, that check
-** to see if a database file was a URI that contained a specific query
+** These are utility routines, useful to [VFS|custom VFS implementations],
+** that check if a database file was a URI that contained a specific query
** parameter, and if so obtains the value of that query parameter.
**
** If F is the database filename pointer passed into the xOpen() method of
-** a VFS implementation when the flags parameter to xOpen() has one or
-** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
-** P is the name of the query parameter, then
+** a VFS implementation or it is the return value of [sqlite3_db_filename()]
+** and if P is the name of the query parameter, then
** sqlite3_uri_parameter(F,P) returns the value of the P
** parameter if it exists or a NULL pointer if P does not appear as a
-** query parameter on F. If P is a query parameter of F
+** query parameter on F. If P is a query parameter of F and it
** has no explicit value, then sqlite3_uri_parameter(F,P) returns
** a pointer to an empty string.
**
@@ -4523,25 +4592,72 @@ SQLITE_API int sqlite3_open_v2(
** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of
** query parameter P is one of "no", "false", or "off" in any case or
** if the value begins with a numeric zero. If P is not a query
-** parameter on F or if the value of P is does not match any of the
+** parameter on F or if the value of P does not match any of the
** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0).
**
** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
** 64-bit signed integer and returns that integer, or D if P does not
** exist. If the value of P is something other than an integer, then
** zero is returned.
+**
+** The sqlite3_uri_key(F,N) returns a pointer to the name (not
+** the value) of the N-th query parameter for filename F, or a NULL
+** pointer if N is less than zero or greater than the number of query
+** parameters minus 1. The N value is zero-based so N should be 0 to obtain
+** the name of the first query parameter, 1 for the second parameter, and
+** so forth.
**
** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and
-** is not a database file pathname pointer that SQLite passed into the xOpen
-** VFS method, then the behavior of this routine is undefined and probably
-** undesirable.
+** is not a database file pathname pointer that the SQLite core passed
+** into the xOpen VFS method, then the behavior of this routine is undefined
+** and probably undesirable.
+**
+** Beginning with SQLite [version 3.31.0] ([dateof:3.31.0]) the input F
+** parameter can also be the name of a rollback journal file or WAL file
+** in addition to the main database file. Prior to version 3.31.0, these
+** routines would only work if F was the name of the main database file.
+** When the F parameter is the name of the rollback journal or WAL file,
+** it has access to all the same query parameters as were found on the
+** main database file.
**
** See the [URI filename] documentation for additional information.
*/
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
+SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N);
+
+/*
+** CAPI3REF: Translate filenames
+**
+** These routines are available to [VFS|custom VFS implementations] for
+** translating filenames between the main database file, the journal file,
+** and the WAL file.
+**
+** If F is the name of an sqlite database file, journal file, or WAL file
+** passed by the SQLite core into the VFS, then sqlite3_filename_database(F)
+** returns the name of the corresponding database file.
+**
+** If F is the name of an sqlite database file, journal file, or WAL file
+** passed by the SQLite core into the VFS, or if F is a database filename
+** obtained from [sqlite3_db_filename()], then sqlite3_filename_journal(F)
+** returns the name of the corresponding rollback journal file.
+**
+** If F is the name of an sqlite database file, journal file, or WAL file
+** that was passed by the SQLite core into the VFS, or if F is a database
+** filename obtained from [sqlite3_db_filename()], then
+** sqlite3_filename_wal(F) returns the name of the corresponding
+** WAL file.
+**
+** In all of the above, if F is not the name of a database, journal or WAL
+** filename passed into the VFS from the SQLite core and F is not the
+** return value from [sqlite3_db_filename()], then the result is
+** undefined and is likely a memory access violation.
+*/
+SQLITE_API const char *sqlite3_filename_database(const char*);
+SQLITE_API const char *sqlite3_filename_journal(const char*);
+SQLITE_API const char *sqlite3_filename_wal(const char*);
/*
@@ -4860,12 +4976,12 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** </li>
**
** <li>
-** ^If the specific value bound to [parameter | host parameter] in the
+** ^If the specific value bound to a [parameter | host parameter] in the
** WHERE clause might influence the choice of query plan for a statement,
** then the statement will be automatically recompiled, as if there had been
-** a schema change, on the first [sqlite3_step()] call following any change
+** a schema change, on the first [sqlite3_step()] call following any change
** to the [sqlite3_bind_text | bindings] of that [parameter].
-** ^The specific value of WHERE-clause [parameter] might influence the
+** ^The specific value of a WHERE-clause [parameter] might influence the
** choice of query plan if the parameter is the left-hand side of a [LIKE]
** or [GLOB] operator or if the parameter is compared to an indexed column
** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled.
@@ -5374,7 +5490,7 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
**
** ^If the Nth column returned by the statement is an expression or
** subquery and is not a column value, then all of these functions return
-** NULL. ^These routine might also return NULL if a memory allocation error
+** NULL. ^These routines might also return NULL if a memory allocation error
** occurs. ^Otherwise, they return the name of the attached database, table,
** or column that query result column was extracted from.
**
@@ -5384,10 +5500,6 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
** ^These APIs are only available if the library was compiled with the
** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol.
**
-** If two or more threads call one or more of these routines against the same
-** prepared statement and column at the same time then the results are
-** undefined.
-**
** If two or more threads call one or more
** [sqlite3_column_database_name | column metadata interfaces]
** for the same [prepared statement] and result column
@@ -5524,7 +5636,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt*);
** ^The sqlite3_data_count(P) interface returns the number of columns in the
** current row of the result set of [prepared statement] P.
** ^If prepared statement P does not have results ready to return
-** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
+** (via calls to the [sqlite3_column_int | sqlite3_column()] family of
** interfaces) then sqlite3_data_count(P) returns 0.
** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
@@ -5848,8 +5960,6 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Create Or Redefine SQL Functions
** KEYWORDS: {function creation routines}
-** KEYWORDS: {application-defined SQL function}
-** KEYWORDS: {application-defined SQL functions}
** METHOD: sqlite3
**
** ^These functions (collectively known as "function creation routines")
@@ -5905,9 +6015,20 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
**
** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY]
** flag, which if present prevents the function from being invoked from
-** within VIEWs or TRIGGERs. For security reasons, the [SQLITE_DIRECTONLY]
-** flag is recommended for any application-defined SQL function that has
-** side-effects.
+** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions,
+** index expressions, or the WHERE clause of partial indexes.
+**
+** <span style="background-color:#ffff90;">
+** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
+** all application-defined SQL functions that do not need to be
+** used inside of triggers, view, CHECK constraints, or other elements of
+** the database schema. This flags is especially recommended for SQL
+** functions that have side effects or reveal internal application state.
+** Without this flag, an attacker might be able to modify the schema of
+** a database file to include invocations of the function with parameters
+** chosen by the attacker, which the application will then execute when
+** the database file is opened and read.
+** </span>
**
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
** function can gain access to this pointer using [sqlite3_user_data()].)^
@@ -6026,18 +6147,53 @@ SQLITE_API int sqlite3_create_window_function(
** to [sqlite3_create_function()], [sqlite3_create_function16()], or
** [sqlite3_create_function_v2()].
**
-** The SQLITE_DETERMINISTIC flag means that the new function will always
-** maps the same inputs into the same output. The abs() function is
-** deterministic, for example, but randomblob() is not.
-**
+** <dl>
+** [[SQLITE_DETERMINISTIC]] <dt>SQLITE_DETERMINISTIC</dt><dd>
+** The SQLITE_DETERMINISTIC flag means that the new function always gives
+** the same output when the input parameters are the same.
+** The [abs|abs() function] is deterministic, for example, but
+** [randomblob|randomblob()] is not. Functions must
+** be deterministic in order to be used in certain contexts such as
+** with the WHERE clause of [partial indexes] or in [generated columns].
+** SQLite might also optimize deterministic functions by factoring them
+** out of inner loops.
+** </dd>
+**
+** [[SQLITE_DIRECTONLY]] <dt>SQLITE_DIRECTONLY</dt><dd>
** The SQLITE_DIRECTONLY flag means that the function may only be invoked
-** from top-level SQL, and cannot be used in VIEWs or TRIGGERs. This is
-** a security feature which is recommended for all
-** [application-defined SQL functions] that have side-effects. This flag
-** prevents an attacker from adding triggers and views to a schema then
-** tricking a high-privilege application into causing unintended side-effects
-** while performing ordinary queries.
+** from top-level SQL, and cannot be used in VIEWs or TRIGGERs nor in
+** schema structures such as [CHECK constraints], [DEFAULT clauses],
+** [expression indexes], [partial indexes], or [generated columns].
+** The SQLITE_DIRECTONLY flags is a security feature which is recommended
+** for all [application-defined SQL functions], and especially for functions
+** that have side-effects or that could potentially leak sensitive
+** information.
+** </dd>
+**
+** [[SQLITE_INNOCUOUS]] <dt>SQLITE_INNOCUOUS</dt><dd>
+** The SQLITE_INNOCUOUS flag means that the function is unlikely
+** to cause problems even if misused. An innocuous function should have
+** no side effects and should not depend on any values other than its
+** input parameters. The [abs|abs() function] is an example of an
+** innocuous function.
+** The [load_extension() SQL function] is not innocuous because of its
+** side effects.
+** <p> SQLITE_INNOCUOUS is similar to SQLITE_DETERMINISTIC, but is not
+** exactly the same. The [random|random() function] is an example of a
+** function that is innocuous but not deterministic.
+** <p>Some heightened security settings
+** ([SQLITE_DBCONFIG_TRUSTED_SCHEMA] and [PRAGMA trusted_schema=OFF])
+** disable the use of SQL functions inside views and triggers and in
+** schema structures such as [CHECK constraints], [DEFAULT clauses],
+** [expression indexes], [partial indexes], and [generated columns] unless
+** the function is tagged with SQLITE_INNOCUOUS. Most built-in functions
+** are innocuous. Developers are advised to avoid using the
+** SQLITE_INNOCUOUS flag for application-defined functions unless the
+** function has been carefully audited and found to be free of potentially
+** security-adverse side-effects and information-leaks.
+** </dd>
**
+** [[SQLITE_SUBTYPE]] <dt>SQLITE_SUBTYPE</dt><dd>
** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call
** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
** Specifying this flag makes no difference for scalar or aggregate user
@@ -6045,10 +6201,13 @@ SQLITE_API int sqlite3_create_window_function(
** function, then any sub-types belonging to arguments passed to the window
** function may be discarded before the window function is called (i.e.
** sqlite3_value_subtype() will always return 0).
+** </dd>
+** </dl>
*/
#define SQLITE_DETERMINISTIC 0x000000800
#define SQLITE_DIRECTONLY 0x000080000
#define SQLITE_SUBTYPE 0x000100000
+#define SQLITE_INNOCUOUS 0x000200000
/*
** CAPI3REF: Deprecated Functions
@@ -6107,8 +6266,8 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
**
** These routines extract type, size, and content information from
** [protected sqlite3_value] objects. Protected sqlite3_value objects
-** are used to pass parameter information into implementation of
-** [application-defined SQL functions] and [virtual tables].
+** are used to pass parameter information into the functions that
+** implement [application-defined SQL functions] and [virtual tables].
**
** These routines work only with [protected sqlite3_value] objects.
** Any attempt to use these routines on an [unprotected sqlite3_value]
@@ -6165,7 +6324,7 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** ^The sqlite3_value_frombind(X) interface returns non-zero if the
** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()]
** interfaces. ^If X comes from an SQL literal value, or a table column,
-** and expression, then sqlite3_value_frombind(X) returns zero.
+** or an expression, then sqlite3_value_frombind(X) returns zero.
**
** Please pay particular attention to the fact that the pointer returned
** from [sqlite3_value_blob()], [sqlite3_value_text()], or
@@ -6251,8 +6410,8 @@ SQLITE_API void sqlite3_value_free(sqlite3_value*);
** routine to allocate memory for storing their state.
**
** ^The first time the sqlite3_aggregate_context(C,N) routine is called
-** for a particular aggregate function, SQLite
-** allocates N of memory, zeroes out that memory, and returns a pointer
+** for a particular aggregate function, SQLite allocates
+** N bytes of memory, zeroes out that memory, and returns a pointer
** to the new memory. ^On second and subsequent calls to
** sqlite3_aggregate_context() for the same aggregate function instance,
** the same buffer is returned. Sqlite3_aggregate_context() is normally
@@ -6269,7 +6428,7 @@ SQLITE_API void sqlite3_value_free(sqlite3_value*);
**
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
** determined by the N parameter on first successful call. Changing the
-** value of N in subsequent call to sqlite3_aggregate_context() within
+** value of N in any subsequents call to sqlite3_aggregate_context() within
** the same aggregate function instance will not resize the memory
** allocation.)^ Within the xFinal callback, it is customary to set
** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
@@ -6580,7 +6739,7 @@ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);
** <li> [SQLITE_UTF16_ALIGNED].
** </ul>)^
** ^The eTextRep argument determines the encoding of strings passed
-** to the collating function callback, xCallback.
+** to the collating function callback, xCompare.
** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep
** force strings to be UTF16 with native byte order.
** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin
@@ -6589,18 +6748,19 @@ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);
** ^The fourth argument, pArg, is an application data pointer that is passed
** through as the first argument to the collating function callback.
**
-** ^The fifth argument, xCallback, is a pointer to the collating function.
+** ^The fifth argument, xCompare, is a pointer to the collating function.
** ^Multiple collating functions can be registered using the same name but
** with different eTextRep parameters and SQLite will use whichever
** function requires the least amount of data transformation.
-** ^If the xCallback argument is NULL then the collating function is
+** ^If the xCompare argument is NULL then the collating function is
** deleted. ^When all collating functions having the same name are deleted,
** that collation is no longer usable.
**
** ^The collating function callback is invoked with a copy of the pArg
** application data pointer and with two strings in the encoding specified
-** by the eTextRep argument. The collating function must return an
-** integer that is negative, zero, or positive
+** by the eTextRep argument. The two integer parameters to the collating
+** function callback are the length of the two strings, in bytes. The collating
+** function must return an integer that is negative, zero, or positive
** if the first string is less than, equal to, or greater than the second,
** respectively. A collating function must always return the same answer
** given the same inputs. If two or more collating functions are registered
@@ -6617,7 +6777,7 @@ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);
** </ol>
**
** If a collating function fails any of the above constraints and that
-** collating function is registered and used, then the behavior of SQLite
+** collating function is registered and used, then the behavior of SQLite
** is undefined.
**
** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation()
@@ -6944,16 +7104,31 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
** CAPI3REF: Return The Filename For A Database Connection
** METHOD: sqlite3
**
-** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
-** associated with database N of connection D. ^The main database file
-** has the name "main". If there is no attached database N on the database
+** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename
+** associated with database N of connection D.
+** ^If there is no attached database N on the database
** connection D, or if database N is a temporary or in-memory database, then
** this function will return either a NULL pointer or an empty string.
**
+** ^The string value returned by this routine is owned and managed by
+** the database connection. ^The value will be valid until the database N
+** is [DETACH]-ed or until the database connection closes.
+**
** ^The filename returned by this function is the output of the
** xFullPathname method of the [VFS]. ^In other words, the filename
** will be an absolute pathname, even if the filename used
** to open the database originally was a URI or relative pathname.
+**
+** If the filename pointer returned by this routine is not NULL, then it
+** can be used as the filename input parameter to these routines:
+** <ul>
+** <li> [sqlite3_uri_parameter()]
+** <li> [sqlite3_uri_boolean()]
+** <li> [sqlite3_uri_int64()]
+** <li> [sqlite3_filename_database()]
+** <li> [sqlite3_filename_journal()]
+** <li> [sqlite3_filename_wal()]
+** </ul>
*/
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
@@ -7103,15 +7278,19 @@ SQLITE_API void *sqlite3_update_hook(
**
** ^(The cache sharing mode set by this interface effects all subsequent
** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()].
-** Existing database connections continue use the sharing mode
+** Existing database connections continue to use the sharing mode
** that was in effect at the time they were opened.)^
**
** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled
** successfully. An [error code] is returned otherwise.)^
**
-** ^Shared cache is disabled by default. But this might change in
-** future releases of SQLite. Applications that care about shared
-** cache setting should set it explicitly.
+** ^Shared cache is disabled by default. It is recommended that it stay
+** that way. In other words, do not use this routine. This interface
+** continues to be provided for historical compatibility, but its use is
+** discouraged. Any use of shared cache is discouraged. If shared cache
+** must be used, it is recommended that shared cache only be enabled for
+** individual database connections using the [sqlite3_open_v2()] interface
+** with the [SQLITE_OPEN_SHAREDCACHE] flag.
**
** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0
** and will always return SQLITE_MISUSE. On those systems,
@@ -7158,6 +7337,9 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
/*
** CAPI3REF: Impose A Limit On Heap Size
**
+** These interfaces impose limits on the amount of heap memory that will be
+** by all database connections within a single process.
+**
** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
** soft limit on the amount of heap memory that may be allocated by SQLite.
** ^SQLite strives to keep heap memory utilization below the soft heap
@@ -7168,20 +7350,41 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** an [SQLITE_NOMEM] error. In other words, the soft heap limit
** is advisory only.
**
-** ^The return value from sqlite3_soft_heap_limit64() is the size of
-** the soft heap limit prior to the call, or negative in the case of an
-** error. ^If the argument N is negative
-** then no change is made to the soft heap limit. Hence, the current
-** size of the soft heap limit can be determined by invoking
-** sqlite3_soft_heap_limit64() with a negative argument.
-**
-** ^If the argument N is zero then the soft heap limit is disabled.
+** ^The sqlite3_hard_heap_limit64(N) interface sets a hard upper bound of
+** N bytes on the amount of memory that will be allocated. ^The
+** sqlite3_hard_heap_limit64(N) interface is similar to
+** sqlite3_soft_heap_limit64(N) except that memory allocations will fail
+** when the hard heap limit is reached.
**
-** ^(The soft heap limit is not enforced in the current implementation
+** ^The return value from both sqlite3_soft_heap_limit64() and
+** sqlite3_hard_heap_limit64() is the size of
+** the heap limit prior to the call, or negative in the case of an
+** error. ^If the argument N is negative
+** then no change is made to the heap limit. Hence, the current
+** size of heap limits can be determined by invoking
+** sqlite3_soft_heap_limit64(-1) or sqlite3_hard_heap_limit(-1).
+**
+** ^Setting the heap limits to zero disables the heap limiter mechanism.
+**
+** ^The soft heap limit may not be greater than the hard heap limit.
+** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N)
+** is invoked with a value of N that is greater than the hard heap limit,
+** the the soft heap limit is set to the value of the hard heap limit.
+** ^The soft heap limit is automatically enabled whenever the hard heap
+** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and
+** the soft heap limit is outside the range of 1..N, then the soft heap
+** limit is set to N. ^Invoking sqlite3_soft_heap_limit64(0) when the
+** hard heap limit is enabled makes the soft heap limit equal to the
+** hard heap limit.
+**
+** The memory allocation limits can also be adjusted using
+** [PRAGMA soft_heap_limit] and [PRAGMA hard_heap_limit].
+**
+** ^(The heap limits are not enforced in the current implementation
** if one or more of following conditions are true:
**
** <ul>
-** <li> The soft heap limit is set to zero.
+** <li> The limit value is set to zero.
** <li> Memory accounting is disabled using a combination of the
** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
@@ -7192,21 +7395,11 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** from the heap.
** </ul>)^
**
-** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]),
-** the soft heap limit is enforced
-** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT]
-** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT],
-** the soft heap limit is enforced on every memory allocation. Without
-** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced
-** when memory is allocated by the page cache. Testing suggests that because
-** the page cache is the predominate memory user in SQLite, most
-** applications will achieve adequate soft heap limit enforcement without
-** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT].
-**
-** The circumstances under which SQLite will enforce the soft heap limit may
+** The circumstances under which SQLite will enforce the heap limits may
** changes in future releases of SQLite.
*/
SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
+SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N);
/*
** CAPI3REF: Deprecated Soft Heap Limit Interface
@@ -7230,7 +7423,7 @@ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
** interface returns SQLITE_OK and fills in the non-NULL pointers in
** the final five arguments with appropriate values if the specified
** column exists. ^The sqlite3_table_column_metadata() interface returns
-** SQLITE_ERROR and if the specified column does not exist.
+** SQLITE_ERROR if the specified column does not exist.
** ^If the column-name parameter to sqlite3_table_column_metadata() is a
** NULL pointer, then this routine simply checks for the existence of the
** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
@@ -7372,7 +7565,7 @@ SQLITE_API int sqlite3_load_extension(
** to enable or disable only the C-API.)^
**
** <b>Security warning:</b> It is recommended that extension loading
-** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
+** be enabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
** rather than this interface, so the [load_extension()] SQL function
** remains disabled. This will prevent SQL injections from giving attackers
** access to extension loading capabilities.
@@ -7459,7 +7652,7 @@ typedef struct sqlite3_module sqlite3_module;
** KEYWORDS: sqlite3_module {virtual table module}
**
** This structure, sometimes called a "virtual table module",
-** defines the implementation of a [virtual tables].
+** defines the implementation of a [virtual table].
** This structure consists mostly of methods for the module.
**
** ^A virtual table module is created by filling in a persistent
@@ -7556,7 +7749,13 @@ struct sqlite3_module {
** the right-hand side of the corresponding aConstraint[] is evaluated
** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit
** is true, then the constraint is assumed to be fully handled by the
-** virtual table and is not checked again by SQLite.)^
+** virtual table and might not be checked again by the byte code.)^ ^(The
+** aConstraintUsage[].omit flag is an optimization hint. When the omit flag
+** is left in its default setting of false, the constraint will always be
+** checked separately in byte code. If the omit flag is change to true, then
+** the constraint may or may not be checked in byte code. In other words,
+** when the omit flag is true there is no guarantee that the constraint will
+** not be checked again using byte code.)^
**
** ^The idxNum and idxPtr values are recorded and passed into the
** [xFilter] method.
@@ -7596,7 +7795,7 @@ struct sqlite3_module {
** If a virtual table extension is
** used with an SQLite version earlier than 3.8.2, the results of attempting
** to read or write the estimatedRows field are undefined (but are likely
-** to included crashing the application). The estimatedRows field should
+** to include crashing the application). The estimatedRows field should
** therefore only be used if [sqlite3_libversion_number()] returns a
** value greater than or equal to 3008002. Similarly, the idxFlags field
** was added for [version 3.9.0] ([dateof:3.9.0]).
@@ -7648,7 +7847,7 @@ struct sqlite3_index_info {
/*
** CAPI3REF: Virtual Table Constraint Operator Codes
**
-** These macros defined the allowed values for the
+** These macros define the allowed values for the
** [sqlite3_index_info].aConstraint[].op field. Each value represents
** an operator that is part of a constraint term in the wHERE clause of
** a query that uses a [virtual table].
@@ -8258,7 +8457,7 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
** The only difference is that the public sqlite3_XXX functions enumerated
** above silently ignore any invocations that pass a NULL pointer instead
** of a valid mutex handle. The implementations of the methods defined
-** by this structure are not required to handle this case, the results
+** by this structure are not required to handle this case. The results
** of passing a NULL pointer instead of a valid mutex handle are undefined
** (i.e. it is acceptable to provide an implementation that segfaults if
** it is passed a NULL pointer).
@@ -8731,7 +8930,7 @@ SQLITE_API int sqlite3_status64(
**
** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
-** handed to [pagecache memory allocator]. Only the value returned in the
+** handed to the [pagecache memory allocator]. Only the value returned in the
** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
@@ -8807,7 +9006,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** checked out.</dd>)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
-** <dd>This parameter returns the number malloc attempts that were
+** <dd>This parameter returns the number of malloc attempts that were
** satisfied using lookaside memory. Only the high-water value is meaningful;
** the current value is always zero.)^
**
@@ -8889,7 +9088,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** cache overflowing. Transactions are more efficient if they are written
** to disk all at once. When pages spill mid-transaction, that introduces
** additional overhead. This parameter can be used help identify
-** inefficiencies that can be resolve by increasing the cache size.
+** inefficiencies that can be resolved by increasing the cache size.
** </dd>
**
** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
@@ -8978,7 +9177,7 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
**
** [[SQLITE_STMTSTATUS_REPREPARE]] <dt>SQLITE_STMTSTATUS_REPREPARE</dt>
** <dd>^This is the number of times that the prepare statement has been
-** automatically regenerated due to schema changes or change to
+** automatically regenerated due to schema changes or changes to
** [bound parameters] that might affect the query plan.
**
** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt>
@@ -9149,7 +9348,7 @@ struct sqlite3_pcache_page {
**
** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite
** will only use a createFlag of 2 after a prior call with a createFlag of 1
-** failed.)^ In between the to xFetch() calls, SQLite may
+** failed.)^ In between the xFetch() calls, SQLite may
** attempt to unpin one or more cache pages by spilling the content of
** pinned pages to disk and synching the operating system disk cache.
**
@@ -9467,7 +9666,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
** the first argument to register for a callback that will be invoked
** when the blocking connections current transaction is concluded. ^The
** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
-** call that concludes the blocking connections transaction.
+** call that concludes the blocking connection's transaction.
**
** ^(If sqlite3_unlock_notify() is called in a multi-threaded application,
** there is a chance that the blocking connection will have already
@@ -9505,7 +9704,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
** an unlock-notify callback is a pointer to an array of void* pointers,
** and the second is the number of entries in the array.
**
-** When a blocking connections transaction is concluded, there may be
+** When a blocking connection's transaction is concluded, there may be
** more than one blocked connection that has registered for an unlock-notify
** callback. ^If two or more such blocked connections have specified the
** same callback function, then instead of invoking the callback function
@@ -9853,14 +10052,20 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
** If this interface is invoked outside the context of an xConnect or
** xCreate virtual table method then the behavior is undefined.
**
-** At present, there is only one option that may be configured using
-** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
-** may be added in the future.
+** In the call sqlite3_vtab_config(D,C,...) the D parameter is the
+** [database connection] in which the virtual table is being created and
+** which is passed in as the first argument to the [xConnect] or [xCreate]
+** method that is invoking sqlite3_vtab_config(). The C parameter is one
+** of the [virtual table configuration options]. The presence and meaning
+** of parameters after C depend on which [virtual table configuration option]
+** is used.
*/
SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
/*
** CAPI3REF: Virtual Table Configuration Options
+** KEYWORDS: {virtual table configuration options}
+** KEYWORDS: {virtual table configuration option}
**
** These macros define the various options to the
** [sqlite3_vtab_config()] interface that [virtual table] implementations
@@ -9868,7 +10073,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
**
** <dl>
** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]]
-** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
+** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT</dt>
** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
** where X is an integer. If X is zero, then the [virtual table] whose
@@ -9897,9 +10102,31 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
** return SQLITE_OK. Or, if this is not possible, it may return
** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
** constraint handling.
+** </dd>
+**
+** [[SQLITE_VTAB_DIRECTONLY]]<dt>SQLITE_VTAB_DIRECTONLY</dt>
+** <dd>Calls of the form
+** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the
+** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
+** prohibits that virtual table from being used from within triggers and
+** views.
+** </dd>
+**
+** [[SQLITE_VTAB_INNOCUOUS]]<dt>SQLITE_VTAB_INNOCUOUS</dt>
+** <dd>Calls of the form
+** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the
+** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
+** identify that virtual table as being safe to use from within triggers
+** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the
+** virtual table can do no serious harm even if it is controlled by a
+** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS
+** flag unless absolutely necessary.
+** </dd>
** </dl>
*/
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
+#define SQLITE_VTAB_INNOCUOUS 2
+#define SQLITE_VTAB_DIRECTONLY 3
/*
** CAPI3REF: Determine The Virtual Table Conflict Policy
@@ -9979,15 +10206,15 @@ SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_
**
** <dl>
** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt>
-** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be
+** <dd>^The [sqlite3_int64] variable pointed to by the V parameter will be
** set to the total number of times that the X-th loop has run.</dd>
**
** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt>
-** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set
+** <dd>^The [sqlite3_int64] variable pointed to by the V parameter will be set
** to the total number of rows examined by all iterations of the X-th loop.</dd>
**
** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt>
-** <dd>^The "double" variable pointed to by the T parameter will be set to the
+** <dd>^The "double" variable pointed to by the V parameter will be set to the
** query planner's estimate for the average number of rows output from each
** iteration of the X-th loop. If the query planner's estimates was accurate,
** then this value will approximate the quotient NVISIT/NLOOP and the
@@ -9995,17 +10222,17 @@ SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_
** be the NLOOP value for the current loop.
**
** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt>
-** <dd>^The "const char *" variable pointed to by the T parameter will be set
+** <dd>^The "const char *" variable pointed to by the V parameter will be set
** to a zero-terminated UTF-8 string containing the name of the index or table
** used for the X-th loop.
**
** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt>
-** <dd>^The "const char *" variable pointed to by the T parameter will be set
+** <dd>^The "const char *" variable pointed to by the V parameter will be set
** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN]
** description for the X-th loop.
**
** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt>
-** <dd>^The "int" variable pointed to by the T parameter will be set to the
+** <dd>^The "int" variable pointed to by the V parameter will be set to the
** "select-id" for the X-th loop. The select-id identifies which query or
** subquery the loop is part of. The main query has a select-id of zero.
** The select-id is the same value as is output in the first column
@@ -10860,7 +11087,7 @@ SQLITE_API int sqlite3session_attach(
** The second argument (xFilter) is the "filter callback". For changes to rows
** in tables that are not attached to the Session object, the filter is called
** to determine whether changes to the table's rows should be tracked or not.
-** If xFilter returns 0, changes is not tracked. Note that once a table is
+** If xFilter returns 0, changes are not tracked. Note that once a table is
** attached, xFilter will not be called again.
*/
SQLITE_API void sqlite3session_table_filter(
@@ -11034,7 +11261,7 @@ SQLITE_API int sqlite3session_changeset(
** It an error if database zFrom does not exist or does not contain the
** required compatible table.
**
-** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite
+** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite
** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg
** may be set to point to a buffer containing an English language error
** message. It is the responsibility of the caller to free this buffer using
@@ -11171,7 +11398,7 @@ SQLITE_API int sqlite3changeset_start_v2(
** CAPI3REF: Advance A Changeset Iterator
** METHOD: sqlite3_changeset_iter
**
-** This function may only be used with iterators created by function
+** This function may only be used with iterators created by the function
** [sqlite3changeset_start()]. If it is called on an iterator passed to
** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE
** is returned and the call has no effect.
@@ -11587,8 +11814,8 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
** case, this function fails with SQLITE_SCHEMA. If the input changeset
** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is
** returned. Or, if an out-of-memory condition occurs during processing, this
-** function returns SQLITE_NOMEM. In all cases, if an error occurs the
-** final contents of the changegroup is undefined.
+** function returns SQLITE_NOMEM. In all cases, if an error occurs the state
+** of the final contents of the changegroup is undefined.
**
** If no error occurs, SQLITE_OK is returned.
*/
@@ -11763,7 +11990,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
**
** It is safe to execute SQL statements, including those that write to the
** table that the callback related to, from within the xConflict callback.
-** This can be used to further customize the applications conflict
+** This can be used to further customize the application's conflict
** resolution strategy.
**
** All changes made by these functions are enclosed in a savepoint transaction.
@@ -12073,7 +12300,7 @@ SQLITE_API int sqlite3rebaser_configure(
**
** Argument pIn must point to a buffer containing a changeset nIn bytes
** in size. This function allocates and populates a buffer with a copy
-** of the changeset rebased rebased according to the configuration of the
+** of the changeset rebased according to the configuration of the
** rebaser object passed as the first argument. If successful, (*ppOut)
** is set to point to the new buffer containing the rebased changeset and
** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the
@@ -12481,7 +12708,7 @@ struct Fts5PhraseIter {
**
** xSetAuxdata(pFts5, pAux, xDelete)
**
-** Save the pointer passed as the second argument as the extension functions
+** Save the pointer passed as the second argument as the extension function's
** "auxiliary data". The pointer may then be retrieved by the current or any
** future invocation of the same fts5 extension function made as part of
** the same MATCH query using the xGetAuxdata() API.
@@ -12723,8 +12950,8 @@ struct Fts5ExtensionApi {
**
** There are several ways to approach this in FTS5:
**
-** <ol><li> By mapping all synonyms to a single token. In this case, the
-** In the above example, this means that the tokenizer returns the
+** <ol><li> By mapping all synonyms to a single token. In this case, using
+** the above example, this means that the tokenizer returns the
** same token for inputs "first" and "1st". Say that token is in
** fact "first", so that when the user inserts the document "I won
** 1st place" entries are added to the index for tokens "i", "won",
@@ -13397,6 +13624,26 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
#endif
/*
+** The harmless(X) macro indicates that expression X is usually false
+** but can be true without causing any problems, but we don't know of
+** any way to cause X to be true.
+**
+** In debugging and testing builds, this macro will abort if X is ever
+** true. In this way, developers are alerted to a possible test case
+** that causes X to be true. If a harmless macro ever fails, that is
+** an opportunity to change the macro into a testcase() and add a new
+** test case to the test suite.
+**
+** For normal production builds, harmless(X) is a no-op, since it does
+** not matter whether expression X is true or false.
+*/
+#ifdef SQLITE_DEBUG
+# define harmless(X) assert(!(X));
+#else
+# define harmless(X)
+#endif
+
+/*
** Some conditionals are optimizations only. In other words, if the
** conditionals are replaced with a constant 1 (true) or 0 (false) then
** the correct answer is still obtained, though perhaps not as quickly.
@@ -13673,90 +13920,92 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_GROUPS 92
#define TK_OTHERS 93
#define TK_TIES 94
-#define TK_REINDEX 95
-#define TK_RENAME 96
-#define TK_CTIME_KW 97
-#define TK_ANY 98
-#define TK_BITAND 99
-#define TK_BITOR 100
-#define TK_LSHIFT 101
-#define TK_RSHIFT 102
-#define TK_PLUS 103
-#define TK_MINUS 104
-#define TK_STAR 105
-#define TK_SLASH 106
-#define TK_REM 107
-#define TK_CONCAT 108
-#define TK_COLLATE 109
-#define TK_BITNOT 110
-#define TK_ON 111
-#define TK_INDEXED 112
-#define TK_STRING 113
-#define TK_JOIN_KW 114
-#define TK_CONSTRAINT 115
-#define TK_DEFAULT 116
-#define TK_NULL 117
-#define TK_PRIMARY 118
-#define TK_UNIQUE 119
-#define TK_CHECK 120
-#define TK_REFERENCES 121
-#define TK_AUTOINCR 122
-#define TK_INSERT 123
-#define TK_DELETE 124
-#define TK_UPDATE 125
-#define TK_SET 126
-#define TK_DEFERRABLE 127
-#define TK_FOREIGN 128
-#define TK_DROP 129
-#define TK_UNION 130
-#define TK_ALL 131
-#define TK_EXCEPT 132
-#define TK_INTERSECT 133
-#define TK_SELECT 134
-#define TK_VALUES 135
-#define TK_DISTINCT 136
-#define TK_DOT 137
-#define TK_FROM 138
-#define TK_JOIN 139
-#define TK_USING 140
-#define TK_ORDER 141
-#define TK_GROUP 142
-#define TK_HAVING 143
-#define TK_LIMIT 144
-#define TK_WHERE 145
-#define TK_INTO 146
-#define TK_NOTHING 147
-#define TK_FLOAT 148
-#define TK_BLOB 149
-#define TK_INTEGER 150
-#define TK_VARIABLE 151
-#define TK_CASE 152
-#define TK_WHEN 153
-#define TK_THEN 154
-#define TK_ELSE 155
-#define TK_INDEX 156
-#define TK_ALTER 157
-#define TK_ADD 158
-#define TK_WINDOW 159
-#define TK_OVER 160
-#define TK_FILTER 161
-#define TK_COLUMN 162
-#define TK_AGG_FUNCTION 163
-#define TK_AGG_COLUMN 164
-#define TK_TRUEFALSE 165
-#define TK_ISNOT 166
-#define TK_FUNCTION 167
-#define TK_UMINUS 168
-#define TK_UPLUS 169
-#define TK_TRUTH 170
-#define TK_REGISTER 171
-#define TK_VECTOR 172
-#define TK_SELECT_COLUMN 173
-#define TK_IF_NULL_ROW 174
-#define TK_ASTERISK 175
-#define TK_SPAN 176
-#define TK_SPACE 177
-#define TK_ILLEGAL 178
+#define TK_GENERATED 95
+#define TK_ALWAYS 96
+#define TK_REINDEX 97
+#define TK_RENAME 98
+#define TK_CTIME_KW 99
+#define TK_ANY 100
+#define TK_BITAND 101
+#define TK_BITOR 102
+#define TK_LSHIFT 103
+#define TK_RSHIFT 104
+#define TK_PLUS 105
+#define TK_MINUS 106
+#define TK_STAR 107
+#define TK_SLASH 108
+#define TK_REM 109
+#define TK_CONCAT 110
+#define TK_COLLATE 111
+#define TK_BITNOT 112
+#define TK_ON 113
+#define TK_INDEXED 114
+#define TK_STRING 115
+#define TK_JOIN_KW 116
+#define TK_CONSTRAINT 117
+#define TK_DEFAULT 118
+#define TK_NULL 119
+#define TK_PRIMARY 120
+#define TK_UNIQUE 121
+#define TK_CHECK 122
+#define TK_REFERENCES 123
+#define TK_AUTOINCR 124
+#define TK_INSERT 125
+#define TK_DELETE 126
+#define TK_UPDATE 127
+#define TK_SET 128
+#define TK_DEFERRABLE 129
+#define TK_FOREIGN 130
+#define TK_DROP 131
+#define TK_UNION 132
+#define TK_ALL 133
+#define TK_EXCEPT 134
+#define TK_INTERSECT 135
+#define TK_SELECT 136
+#define TK_VALUES 137
+#define TK_DISTINCT 138
+#define TK_DOT 139
+#define TK_FROM 140
+#define TK_JOIN 141
+#define TK_USING 142
+#define TK_ORDER 143
+#define TK_GROUP 144
+#define TK_HAVING 145
+#define TK_LIMIT 146
+#define TK_WHERE 147
+#define TK_INTO 148
+#define TK_NOTHING 149
+#define TK_FLOAT 150
+#define TK_BLOB 151
+#define TK_INTEGER 152
+#define TK_VARIABLE 153
+#define TK_CASE 154
+#define TK_WHEN 155
+#define TK_THEN 156
+#define TK_ELSE 157
+#define TK_INDEX 158
+#define TK_ALTER 159
+#define TK_ADD 160
+#define TK_WINDOW 161
+#define TK_OVER 162
+#define TK_FILTER 163
+#define TK_COLUMN 164
+#define TK_AGG_FUNCTION 165
+#define TK_AGG_COLUMN 166
+#define TK_TRUEFALSE 167
+#define TK_ISNOT 168
+#define TK_FUNCTION 169
+#define TK_UMINUS 170
+#define TK_UPLUS 171
+#define TK_TRUTH 172
+#define TK_REGISTER 173
+#define TK_VECTOR 174
+#define TK_SELECT_COLUMN 175
+#define TK_IF_NULL_ROW 176
+#define TK_ASTERISK 177
+#define TK_SPAN 178
+#define TK_SPACE 179
+#define TK_ILLEGAL 180
/************** End of parse.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
@@ -14354,6 +14603,7 @@ typedef struct With With;
** A bit in a Bitmask
*/
#define MASKBIT(n) (((Bitmask)1)<<(n))
+#define MASKBIT64(n) (((u64)1)<<(n))
#define MASKBIT32(n) (((unsigned int)1)<<(n))
#define ALLBITS ((Bitmask)-1)
@@ -14680,6 +14930,8 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags);
SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags);
SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*);
+SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor*);
+SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor*);
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*);
#endif
@@ -14688,7 +14940,7 @@ SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*);
SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*);
-SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
+SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(sqlite3*,Btree*,int*aRoot,int nRoot,int,int*);
SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);
SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor*);
@@ -14709,7 +14961,7 @@ SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor*);
#ifndef SQLITE_OMIT_BTREECOUNT
-SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *);
+SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3*, BtCursor*, i64*);
#endif
#ifdef SQLITE_TEST
@@ -14966,30 +15218,30 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_SeekLE 23 /* jump, synopsis: key=r[P3@P4] */
#define OP_SeekGE 24 /* jump, synopsis: key=r[P3@P4] */
#define OP_SeekGT 25 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IfNoHope 26 /* jump, synopsis: key=r[P3@P4] */
-#define OP_NoConflict 27 /* jump, synopsis: key=r[P3@P4] */
-#define OP_NotFound 28 /* jump, synopsis: key=r[P3@P4] */
-#define OP_Found 29 /* jump, synopsis: key=r[P3@P4] */
-#define OP_SeekRowid 30 /* jump, synopsis: intkey=r[P3] */
-#define OP_NotExists 31 /* jump, synopsis: intkey=r[P3] */
-#define OP_Last 32 /* jump */
-#define OP_IfSmaller 33 /* jump */
-#define OP_SorterSort 34 /* jump */
-#define OP_Sort 35 /* jump */
-#define OP_Rewind 36 /* jump */
-#define OP_IdxLE 37 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxGT 38 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxLT 39 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxGE 40 /* jump, synopsis: key=r[P3@P4] */
-#define OP_RowSetRead 41 /* jump, synopsis: r[P3]=rowset(P1) */
-#define OP_RowSetTest 42 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
+#define OP_IfNotOpen 26 /* jump, synopsis: if( !csr[P1] ) goto P2 */
+#define OP_IfNoHope 27 /* jump, synopsis: key=r[P3@P4] */
+#define OP_NoConflict 28 /* jump, synopsis: key=r[P3@P4] */
+#define OP_NotFound 29 /* jump, synopsis: key=r[P3@P4] */
+#define OP_Found 30 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekRowid 31 /* jump, synopsis: intkey=r[P3] */
+#define OP_NotExists 32 /* jump, synopsis: intkey=r[P3] */
+#define OP_Last 33 /* jump */
+#define OP_IfSmaller 34 /* jump */
+#define OP_SorterSort 35 /* jump */
+#define OP_Sort 36 /* jump */
+#define OP_Rewind 37 /* jump */
+#define OP_IdxLE 38 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGT 39 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxLT 40 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGE 41 /* jump, synopsis: key=r[P3@P4] */
+#define OP_RowSetRead 42 /* jump, synopsis: r[P3]=rowset(P1) */
#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
-#define OP_Program 45 /* jump */
-#define OP_FkIfZero 46 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
-#define OP_IfPos 47 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
-#define OP_IfNotZero 48 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
-#define OP_DecrJumpZero 49 /* jump, synopsis: if (--r[P1])==0 goto P2 */
+#define OP_RowSetTest 45 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
+#define OP_Program 46 /* jump */
+#define OP_FkIfZero 47 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
+#define OP_IfPos 48 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+#define OP_IfNotZero 49 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
#define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
#define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
#define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
@@ -14999,83 +15251,83 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
#define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
#define OP_ElseNotEq 58 /* jump, same as TK_ESCAPE */
-#define OP_IncrVacuum 59 /* jump */
-#define OP_VNext 60 /* jump */
-#define OP_Init 61 /* jump, synopsis: Start at P2 */
-#define OP_PureFunc0 62
-#define OP_Function0 63 /* synopsis: r[P3]=func(r[P2@P5]) */
-#define OP_PureFunc 64
-#define OP_Function 65 /* synopsis: r[P3]=func(r[P2@P5]) */
-#define OP_Return 66
-#define OP_EndCoroutine 67
-#define OP_HaltIfNull 68 /* synopsis: if r[P3]=null halt */
-#define OP_Halt 69
-#define OP_Integer 70 /* synopsis: r[P2]=P1 */
-#define OP_Int64 71 /* synopsis: r[P2]=P4 */
-#define OP_String 72 /* synopsis: r[P2]='P4' (len=P1) */
-#define OP_Null 73 /* synopsis: r[P2..P3]=NULL */
-#define OP_SoftNull 74 /* synopsis: r[P1]=NULL */
-#define OP_Blob 75 /* synopsis: r[P2]=P4 (len=P1) */
-#define OP_Variable 76 /* synopsis: r[P2]=parameter(P1,P4) */
-#define OP_Move 77 /* synopsis: r[P2@P3]=r[P1@P3] */
-#define OP_Copy 78 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
-#define OP_SCopy 79 /* synopsis: r[P2]=r[P1] */
-#define OP_IntCopy 80 /* synopsis: r[P2]=r[P1] */
-#define OP_ResultRow 81 /* synopsis: output=r[P1@P2] */
-#define OP_CollSeq 82
-#define OP_AddImm 83 /* synopsis: r[P1]=r[P1]+P2 */
-#define OP_RealAffinity 84
-#define OP_Cast 85 /* synopsis: affinity(r[P1]) */
-#define OP_Permutation 86
-#define OP_Compare 87 /* synopsis: r[P1@P3] <-> r[P2@P3] */
-#define OP_IsTrue 88 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
-#define OP_Offset 89 /* synopsis: r[P3] = sqlite_offset(P1) */
-#define OP_Column 90 /* synopsis: r[P3]=PX */
-#define OP_Affinity 91 /* synopsis: affinity(r[P1@P2]) */
-#define OP_MakeRecord 92 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
-#define OP_Count 93 /* synopsis: r[P2]=count() */
-#define OP_ReadCookie 94
-#define OP_SetCookie 95
-#define OP_ReopenIdx 96 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenRead 97 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenWrite 98 /* synopsis: root=P2 iDb=P3 */
-#define OP_BitAnd 99 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
-#define OP_BitOr 100 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
-#define OP_ShiftLeft 101 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
-#define OP_ShiftRight 102 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
-#define OP_Add 103 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
-#define OP_Subtract 104 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
-#define OP_Multiply 105 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
-#define OP_Divide 106 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
-#define OP_Remainder 107 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
-#define OP_Concat 108 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
-#define OP_OpenDup 109
-#define OP_BitNot 110 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
-#define OP_OpenAutoindex 111 /* synopsis: nColumn=P2 */
-#define OP_OpenEphemeral 112 /* synopsis: nColumn=P2 */
-#define OP_String8 113 /* same as TK_STRING, synopsis: r[P2]='P4' */
-#define OP_SorterOpen 114
-#define OP_SequenceTest 115 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
-#define OP_OpenPseudo 116 /* synopsis: P3 columns in r[P2] */
-#define OP_Close 117
-#define OP_ColumnsUsed 118
-#define OP_SeekHit 119 /* synopsis: seekHit=P2 */
-#define OP_Sequence 120 /* synopsis: r[P2]=cursor[P1].ctr++ */
-#define OP_NewRowid 121 /* synopsis: r[P2]=rowid */
-#define OP_Insert 122 /* synopsis: intkey=r[P3] data=r[P2] */
-#define OP_Delete 123
-#define OP_ResetCount 124
-#define OP_SorterCompare 125 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
-#define OP_SorterData 126 /* synopsis: r[P2]=data */
-#define OP_RowData 127 /* synopsis: r[P2]=data */
-#define OP_Rowid 128 /* synopsis: r[P2]=rowid */
-#define OP_NullRow 129
-#define OP_SeekEnd 130
-#define OP_SorterInsert 131 /* synopsis: key=r[P2] */
-#define OP_IdxInsert 132 /* synopsis: key=r[P2] */
-#define OP_IdxDelete 133 /* synopsis: key=r[P2@P3] */
-#define OP_DeferredSeek 134 /* synopsis: Move P3 to P1.rowid if needed */
-#define OP_IdxRowid 135 /* synopsis: r[P2]=rowid */
+#define OP_DecrJumpZero 59 /* jump, synopsis: if (--r[P1])==0 goto P2 */
+#define OP_IncrVacuum 60 /* jump */
+#define OP_VNext 61 /* jump */
+#define OP_Init 62 /* jump, synopsis: Start at P2 */
+#define OP_PureFunc 63 /* synopsis: r[P3]=func(r[P2@P5]) */
+#define OP_Function 64 /* synopsis: r[P3]=func(r[P2@P5]) */
+#define OP_Return 65
+#define OP_EndCoroutine 66
+#define OP_HaltIfNull 67 /* synopsis: if r[P3]=null halt */
+#define OP_Halt 68
+#define OP_Integer 69 /* synopsis: r[P2]=P1 */
+#define OP_Int64 70 /* synopsis: r[P2]=P4 */
+#define OP_String 71 /* synopsis: r[P2]='P4' (len=P1) */
+#define OP_Null 72 /* synopsis: r[P2..P3]=NULL */
+#define OP_SoftNull 73 /* synopsis: r[P1]=NULL */
+#define OP_Blob 74 /* synopsis: r[P2]=P4 (len=P1) */
+#define OP_Variable 75 /* synopsis: r[P2]=parameter(P1,P4) */
+#define OP_Move 76 /* synopsis: r[P2@P3]=r[P1@P3] */
+#define OP_Copy 77 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
+#define OP_SCopy 78 /* synopsis: r[P2]=r[P1] */
+#define OP_IntCopy 79 /* synopsis: r[P2]=r[P1] */
+#define OP_ResultRow 80 /* synopsis: output=r[P1@P2] */
+#define OP_CollSeq 81
+#define OP_AddImm 82 /* synopsis: r[P1]=r[P1]+P2 */
+#define OP_RealAffinity 83
+#define OP_Cast 84 /* synopsis: affinity(r[P1]) */
+#define OP_Permutation 85
+#define OP_Compare 86 /* synopsis: r[P1@P3] <-> r[P2@P3] */
+#define OP_IsTrue 87 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
+#define OP_Offset 88 /* synopsis: r[P3] = sqlite_offset(P1) */
+#define OP_Column 89 /* synopsis: r[P3]=PX */
+#define OP_Affinity 90 /* synopsis: affinity(r[P1@P2]) */
+#define OP_MakeRecord 91 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
+#define OP_Count 92 /* synopsis: r[P2]=count() */
+#define OP_ReadCookie 93
+#define OP_SetCookie 94
+#define OP_ReopenIdx 95 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenRead 96 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenWrite 97 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenDup 98
+#define OP_OpenAutoindex 99 /* synopsis: nColumn=P2 */
+#define OP_OpenEphemeral 100 /* synopsis: nColumn=P2 */
+#define OP_BitAnd 101 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr 102 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft 103 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
+#define OP_ShiftRight 104 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
+#define OP_Add 105 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract 106 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply 107 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide 108 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder 109 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat 110 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
+#define OP_SorterOpen 111
+#define OP_BitNot 112 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
+#define OP_SequenceTest 113 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
+#define OP_OpenPseudo 114 /* synopsis: P3 columns in r[P2] */
+#define OP_String8 115 /* same as TK_STRING, synopsis: r[P2]='P4' */
+#define OP_Close 116
+#define OP_ColumnsUsed 117
+#define OP_SeekHit 118 /* synopsis: seekHit=P2 */
+#define OP_Sequence 119 /* synopsis: r[P2]=cursor[P1].ctr++ */
+#define OP_NewRowid 120 /* synopsis: r[P2]=rowid */
+#define OP_Insert 121 /* synopsis: intkey=r[P3] data=r[P2] */
+#define OP_Delete 122
+#define OP_ResetCount 123
+#define OP_SorterCompare 124 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
+#define OP_SorterData 125 /* synopsis: r[P2]=data */
+#define OP_RowData 126 /* synopsis: r[P2]=data */
+#define OP_Rowid 127 /* synopsis: r[P2]=rowid */
+#define OP_NullRow 128
+#define OP_SeekEnd 129
+#define OP_SorterInsert 130 /* synopsis: key=r[P2] */
+#define OP_IdxInsert 131 /* synopsis: key=r[P2] */
+#define OP_IdxDelete 132 /* synopsis: key=r[P2@P3] */
+#define OP_DeferredSeek 133 /* synopsis: Move P3 to P1.rowid if needed */
+#define OP_IdxRowid 134 /* synopsis: r[P2]=rowid */
+#define OP_FinishSeek 135
#define OP_Destroy 136
#define OP_Clear 137
#define OP_ResetSorter 138
@@ -15088,9 +15340,9 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_DropTrigger 145
#define OP_IntegrityCk 146
#define OP_RowSetAdd 147 /* synopsis: rowset(P1)=r[P2] */
-#define OP_Real 148 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
-#define OP_Param 149
-#define OP_FkCounter 150 /* synopsis: fkctr[P1]+=P2 */
+#define OP_Param 148
+#define OP_FkCounter 149 /* synopsis: fkctr[P1]+=P2 */
+#define OP_Real 150 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
#define OP_MemMax 151 /* synopsis: r[P1]=max(r[P1],r[P2]) */
#define OP_OffsetLimit 152 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
#define OP_AggInverse 153 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
@@ -15099,20 +15351,23 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_AggValue 156 /* synopsis: r[P3]=value N=P2 */
#define OP_AggFinal 157 /* synopsis: accum=r[P1] N=P2 */
#define OP_Expire 158
-#define OP_TableLock 159 /* synopsis: iDb=P1 root=P2 write=P3 */
-#define OP_VBegin 160
-#define OP_VCreate 161
-#define OP_VDestroy 162
-#define OP_VOpen 163
-#define OP_VColumn 164 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VRename 165
-#define OP_Pagecount 166
-#define OP_MaxPgcnt 167
-#define OP_Trace 168
-#define OP_CursorHint 169
-#define OP_Noop 170
-#define OP_Explain 171
-#define OP_Abortable 172
+#define OP_CursorLock 159
+#define OP_CursorUnlock 160
+#define OP_TableLock 161 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 162
+#define OP_VCreate 163
+#define OP_VDestroy 164
+#define OP_VOpen 165
+#define OP_VColumn 166 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VRename 167
+#define OP_Pagecount 168
+#define OP_MaxPgcnt 169
+#define OP_Trace 170
+#define OP_CursorHint 171
+#define OP_ReleaseReg 172 /* synopsis: release r[P1@P2] mask P3 */
+#define OP_Noop 173
+#define OP_Explain 174
+#define OP_Abortable 175
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
@@ -15128,25 +15383,26 @@ typedef struct VdbeOpList VdbeOpList;
/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x10,\
/* 8 */ 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03,\
/* 16 */ 0x01, 0x01, 0x03, 0x12, 0x03, 0x01, 0x09, 0x09,\
-/* 24 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\
-/* 32 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
-/* 40 */ 0x01, 0x23, 0x0b, 0x26, 0x26, 0x01, 0x01, 0x03,\
+/* 24 */ 0x09, 0x09, 0x01, 0x09, 0x09, 0x09, 0x09, 0x09,\
+/* 32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
+/* 40 */ 0x01, 0x01, 0x23, 0x26, 0x26, 0x0b, 0x01, 0x01,\
/* 48 */ 0x03, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
-/* 56 */ 0x0b, 0x0b, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,\
-/* 64 */ 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10,\
-/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,\
-/* 80 */ 0x10, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\
-/* 88 */ 0x12, 0x20, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\
-/* 96 */ 0x00, 0x00, 0x00, 0x26, 0x26, 0x26, 0x26, 0x26,\
-/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12, 0x00,\
-/* 112 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 128 */ 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10,\
+/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00,\
+/* 64 */ 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10,\
+/* 72 */ 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,\
+/* 80 */ 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x12,\
+/* 88 */ 0x20, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
+/* 96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x26, 0x26,\
+/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00,\
+/* 112 */ 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,\
+/* 120 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
+/* 128 */ 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10, 0x00,\
/* 136 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
-/* 144 */ 0x00, 0x00, 0x00, 0x06, 0x10, 0x10, 0x00, 0x04,\
+/* 144 */ 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x10, 0x04,\
/* 152 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\
-/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00,}
+/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 168 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+}
/* The sqlite3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode. The smaller the maximum
@@ -15154,7 +15410,7 @@ typedef struct VdbeOpList VdbeOpList;
** generated this include file strives to group all JUMP opcodes
** together near the beginning of the list.
*/
-#define SQLITE_MX_JUMP_OPCODE 61 /* Maximum JUMP opcode */
+#define SQLITE_MX_JUMP_OPCODE 62 /* Maximum JUMP opcode */
/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
@@ -15170,6 +15426,7 @@ typedef struct VdbeOpList VdbeOpList;
** for a description of what each of these routines does.
*/
SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse*);
+SQLITE_PRIVATE Parse *sqlite3VdbeParser(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
@@ -15180,6 +15437,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
+SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall(Parse*,int,int,int,int,const FuncDef*,int);
SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe*,int);
#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N);
@@ -15221,6 +15479,11 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters(Parse*,int addr, int n, u32 mask, int);
+#else
+# define sqlite3VdbeReleaseRegisters(P,A,N,M,F)
+#endif
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type);
SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
@@ -15269,9 +15532,8 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
-#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
-#endif
+SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe*);
SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
@@ -15585,7 +15847,7 @@ SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*);
SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
#endif
SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
-SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int);
+SQLITE_PRIVATE const char *sqlite3PagerFilename(const Pager*, int);
SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager*);
SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager*);
@@ -16305,15 +16567,47 @@ struct Schema {
** is shared by multiple database connections. Therefore, while parsing
** schema information, the Lookaside.bEnabled flag is cleared so that
** lookaside allocations are not used to construct the schema objects.
+**
+** New lookaside allocations are only allowed if bDisable==0. When
+** bDisable is greater than zero, sz is set to zero which effectively
+** disables lookaside without adding a new test for the bDisable flag
+** in a performance-critical path. sz should be set by to szTrue whenever
+** bDisable changes back to zero.
+**
+** Lookaside buffers are initially held on the pInit list. As they are
+** used and freed, they are added back to the pFree list. New allocations
+** come off of pFree first, then pInit as a fallback. This dual-list
+** allows use to compute a high-water mark - the maximum number of allocations
+** outstanding at any point in the past - by subtracting the number of
+** allocations on the pInit list from the total number of allocations.
+**
+** Enhancement on 2019-12-12: Two-size-lookaside
+** The default lookaside configuration is 100 slots of 1200 bytes each.
+** The larger slot sizes are important for performance, but they waste
+** a lot of space, as most lookaside allocations are less than 128 bytes.
+** The two-size-lookaside enhancement breaks up the lookaside allocation
+** into two pools: One of 128-byte slots and the other of the default size
+** (1200-byte) slots. Allocations are filled from the small-pool first,
+** failing over to the full-size pool if that does not work. Thus more
+** lookaside slots are available while also using less memory.
+** This enhancement can be omitted by compiling with
+** SQLITE_OMIT_TWOSIZE_LOOKASIDE.
*/
struct Lookaside {
u32 bDisable; /* Only operate the lookaside when zero */
u16 sz; /* Size of each buffer in bytes */
+ u16 szTrue; /* True value of sz, even if disabled */
u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
u32 nSlot; /* Number of lookaside slots allocated */
u32 anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
LookasideSlot *pInit; /* List of buffers not previously used */
LookasideSlot *pFree; /* List of available buffers */
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ LookasideSlot *pSmallInit; /* List of small buffers not prediously used */
+ LookasideSlot *pSmallFree; /* List of available small buffers */
+ void *pMiddle; /* First byte past end of full-size buffers and
+ ** the first byte of LOOKASIDE_SMALL buffers */
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
void *pStart; /* First byte of available memory space */
void *pEnd; /* First byte past end of available space */
};
@@ -16321,6 +16615,17 @@ struct LookasideSlot {
LookasideSlot *pNext; /* Next buffer in the list of free buffers */
};
+#define DisableLookaside db->lookaside.bDisable++;db->lookaside.sz=0
+#define EnableLookaside db->lookaside.bDisable--;\
+ db->lookaside.sz=db->lookaside.bDisable?0:db->lookaside.szTrue
+
+/* Size of the smaller allocations in two-size lookside */
+#ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+# define LOOKASIDE_SMALL 0
+#else
+# define LOOKASIDE_SMALL 128
+#endif
+
/*
** A hash table for built-in function definitions. (Application-defined
** functions use a regular table table from hash.h.)
@@ -16530,6 +16835,13 @@ struct sqlite3 {
#define ENC(db) ((db)->enc)
/*
+** A u64 constant where the lower 32 bits are all zeros. Only the
+** upper 32 bits are included in the argument. Necessary because some
+** C-compilers still do not accept LL integer literals.
+*/
+#define HI(X) ((u64)(X)<<32)
+
+/*
** Possible values for the sqlite3.flags.
**
** Value constraints (enforced via assert()):
@@ -16544,9 +16856,8 @@ struct sqlite3 {
#define SQLITE_CkptFullFSync 0x00000010 /* Use full fsync for checkpoint */
#define SQLITE_CacheSpill 0x00000020 /* OK to spill pager cache */
#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */
-#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */
- /* DELETE, or UPDATE and return */
- /* the count using a callback. */
+#define SQLITE_TrustedSchema 0x00000080 /* Allow unsafe functions and
+ ** vtabs in the schema definition */
#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
/* result set is empty */
#define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */
@@ -16572,9 +16883,11 @@ struct sqlite3 {
#define SQLITE_DqsDDL 0x20000000 /* dbl-quoted strings allowed in DDL*/
#define SQLITE_DqsDML 0x40000000 /* dbl-quoted strings allowed in DML*/
#define SQLITE_EnableView 0x80000000 /* Enable the use of views */
+#define SQLITE_CountRows HI(0x00001) /* Count rows changed by INSERT, */
+ /* DELETE, or UPDATE and return */
+ /* the count using a callback. */
/* Flags used only if debugging */
-#define HI(X) ((u64)(X)<<32)
#ifdef SQLITE_DEBUG
#define SQLITE_SqlTrace HI(0x0100000) /* Debug print SQL as it executes */
#define SQLITE_VdbeListing HI(0x0200000) /* Debug listings of VDBE progs */
@@ -16592,6 +16905,7 @@ struct sqlite3 {
#define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */
#define DBFLAG_VacuumInto 0x0008 /* Currently running VACUUM INTO */
#define DBFLAG_SchemaKnownOk 0x0010 /* Schema is known to be valid */
+#define DBFLAG_InternalFunc 0x0020 /* Allow use of internal functions */
/*
** Bits of the sqlite3.dbOptFlags field that are used by the
@@ -16699,6 +17013,7 @@ struct FuncDestructor {
** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
+** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS
** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
*/
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
@@ -16715,12 +17030,22 @@ struct FuncDestructor {
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
** single query - might change over time */
-#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
+#define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */
#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */
#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */
#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
#define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */
#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */
+#define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */
+#define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */
+
+/* Identifier numbers for each in-line function */
+#define INLINEFUNC_coalesce 0
+#define INLINEFUNC_implies_nonnull_row 1
+#define INLINEFUNC_expr_implies_expr 2
+#define INLINEFUNC_expr_compare 3
+#define INLINEFUNC_affinity 4
+#define INLINEFUNC_unlikely 99 /* Default case */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -16736,6 +17061,22 @@ struct FuncDestructor {
** VFUNCTION(zName, nArg, iArg, bNC, xFunc)
** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag.
**
+** SFUNCTION(zName, nArg, iArg, bNC, xFunc)
+** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
+** adds the SQLITE_DIRECTONLY flag.
+**
+** INLINE_FUNC(zName, nArg, iFuncId, mFlags)
+** zName is the name of a function that is implemented by in-line
+** byte code rather than by the usual callbacks. The iFuncId
+** parameter determines the function id. The mFlags parameter is
+** optional SQLITE_FUNC_ flags for this function.
+**
+** TEST_FUNC(zName, nArg, iFuncId, mFlags)
+** zName is the name of a test-only function implemented by in-line
+** byte code rather than by the usual callbacks. The iFuncId
+** parameter determines the function id. The mFlags parameter is
+** optional SQLITE_FUNC_ flags for this function.
+**
** DFUNCTION(zName, nArg, iArg, bNC, xFunc)
** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
** adds the SQLITE_FUNC_SLOCHNG flag. Used for date & time functions
@@ -16775,6 +17116,16 @@ struct FuncDestructor {
#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
+#define SFUNCTION(zName, nArg, iArg, bNC, xFunc) \
+ {nArg, SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
+#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
+ {nArg, SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
+ SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
+#define TEST_FUNC(zName, nArg, iArg, mFlags) \
+ {nArg, SQLITE_UTF8|SQLITE_FUNC_INTERNAL|SQLITE_FUNC_TEST| \
+ SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
+ SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
0, 0, xFunc, 0, 0, 0, #zName, {0} }
@@ -16790,12 +17141,6 @@ struct FuncDestructor {
#define LIKEFUNC(zName, nArg, arg, flags) \
{nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
(void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} }
-#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue) \
- {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \
- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,0,#zName, {0}}
-#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \
- {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}}
#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}}
@@ -16841,26 +17186,45 @@ struct Module {
};
/*
-** information about each column of an SQL table is held in an instance
-** of this structure.
+** Information about each column of an SQL table is held in an instance
+** of the Column structure, in the Table.aCol[] array.
+**
+** Definitions:
+**
+** "table column index" This is the index of the column in the
+** Table.aCol[] array, and also the index of
+** the column in the original CREATE TABLE stmt.
+**
+** "storage column index" This is the index of the column in the
+** record BLOB generated by the OP_MakeRecord
+** opcode. The storage column index is less than
+** or equal to the table column index. It is
+** equal if and only if there are no VIRTUAL
+** columns to the left.
*/
struct Column {
char *zName; /* Name of this column, \000, then the type */
- Expr *pDflt; /* Default value of this column */
+ Expr *pDflt; /* Default value or GENERATED ALWAYS AS value */
char *zColl; /* Collating sequence. If NULL, use the default */
u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
char affinity; /* One of the SQLITE_AFF_... values */
u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */
- u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */
+ u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
};
/* Allowed values for Column.colFlags:
*/
-#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
-#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
-#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */
-#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */
+#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
+#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
+#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */
+#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */
#define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */
+#define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */
+#define COLFLAG_STORED 0x0040 /* GENERATED ALWAYS AS ... STORED */
+#define COLFLAG_NOTAVAIL 0x0080 /* STORED column not yet calculated */
+#define COLFLAG_BUSY 0x0100 /* Blocks recursion on GENERATED columns */
+#define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */
+#define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */
/*
** A "Collating Sequence" is defined by an instance of the following
@@ -16978,10 +17342,17 @@ struct VTable {
sqlite3_vtab *pVtab; /* Pointer to vtab instance */
int nRef; /* Number of pointers to this structure */
u8 bConstraint; /* True if constraints are supported */
+ u8 eVtabRisk; /* Riskiness of allowing hacker access */
int iSavepoint; /* Depth of the SAVEPOINT stack */
VTable *pNext; /* Next in linked list (see above) */
};
+/* Allowed values for VTable.eVtabRisk
+*/
+#define SQLITE_VTABRISK_Low 0
+#define SQLITE_VTABRISK_Normal 1
+#define SQLITE_VTABRISK_High 2
+
/*
** The schema for each SQL table and view is represented in memory
** by an instance of the following structure.
@@ -17000,6 +17371,7 @@ struct Table {
u32 tabFlags; /* Mask of TF_* values */
i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
i16 nCol; /* Number of columns in this table */
+ i16 nNVCol; /* Number of columns that are not VIRTUAL */
LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
LogEst szTabRow; /* Estimated size of each table row in bytes */
#ifdef SQLITE_ENABLE_COSTMULT
@@ -17026,20 +17398,28 @@ struct Table {
** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING
** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden,
** the TF_OOOHidden attribute would apply in this case. Such tables require
-** special handling during INSERT processing.
+** special handling during INSERT processing. The "OOO" means "Out Of Order".
+**
+** Constraints:
+**
+** TF_HasVirtual == COLFLAG_Virtual
+** TF_HasStored == COLFLAG_Stored
*/
#define TF_Readonly 0x0001 /* Read-only system table */
#define TF_Ephemeral 0x0002 /* An ephemeral table */
#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */
#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */
#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */
-#define TF_WithoutRowid 0x0020 /* No rowid. PRIMARY KEY is the key */
-#define TF_NoVisibleRowid 0x0040 /* No user-visible "rowid" column */
-#define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */
+#define TF_HasVirtual 0x0020 /* Has one or more VIRTUAL columns */
+#define TF_HasStored 0x0040 /* Has one or more STORED columns */
+#define TF_HasGenerated 0x0060 /* Combo: HasVirtual + HasStored */
+#define TF_WithoutRowid 0x0080 /* No rowid. PRIMARY KEY is the key */
#define TF_StatsUsed 0x0100 /* Query planner decisions affected by
** Index.aiRowLogEst[] values */
-#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */
-#define TF_Shadow 0x0400 /* True for a shadow table */
+#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 */
/*
** Test to see whether or not a table is a virtual table. This is
@@ -17290,6 +17670,7 @@ struct Index {
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
+ unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
#ifdef SQLITE_ENABLE_STAT4
int nSample; /* Number of elements in aSample[] */
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
@@ -17481,6 +17862,10 @@ typedef int ynVar;
struct Expr {
u8 op; /* Operation performed by this node */
char affExpr; /* affinity, or RAISE type */
+ u8 op2; /* TK_REGISTER/TK_TRUTH: original value of Expr.op
+ ** TK_COLUMN: the value of p5 for OP_Column
+ ** TK_AGG_FUNCTION: nesting depth
+ ** TK_FUNCTION: NC_SelfRef flag if needs OP_PureFunc */
u32 flags; /* Various flags. EP_* See below */
union {
char *zToken; /* Token value. Zero terminated and dequoted */
@@ -17519,9 +17904,6 @@ struct Expr {
** TK_SELECT_COLUMN: column of the result vector */
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
- u8 op2; /* TK_REGISTER/TK_TRUTH: original value of Expr.op
- ** TK_COLUMN: the value of p5 for OP_Column
- ** TK_AGG_FUNCTION: nesting depth */
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
union {
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
@@ -17550,7 +17932,7 @@ struct Expr {
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */
- /* 0x000200 Available for reuse */
+#define EP_Commuted 0x000200 /* Comparison operator has been commuted */
#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Skip 0x001000 /* Operator does not contribute to affinity */
@@ -17571,7 +17953,7 @@ struct Expr {
#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
-#define EP_Indirect 0x40000000 /* Contained within a TRIGGER or a VIEW */
+#define EP_FromDDL 0x40000000 /* Originates from sqlite_master */
/*
** The EP_Propagate mask is a set of properties that automatically propagate
@@ -17635,23 +18017,28 @@ struct Expr {
** also be used as the argument to a function, in which case the a.zName
** field is not used.
**
-** By default the Expr.zSpan field holds a human-readable description of
-** the expression that is used in the generation of error messages and
-** column labels. In this case, Expr.zSpan is typically the text of a
-** column expression as it exists in a SELECT statement. However, if
-** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
-** of the result column in the form: DATABASE.TABLE.COLUMN. This later
-** form is used for name resolution with nested FROM clauses.
+** In order to try to keep memory usage down, the Expr.a.zEName field
+** is used for multiple purposes:
+**
+** eEName Usage
+** ---------- -------------------------
+** ENAME_NAME (1) the AS of result set column
+** (2) COLUMN= of an UPDATE
+**
+** ENAME_TAB DB.TABLE.NAME used to resolve names
+** of subqueries
+**
+** ENAME_SPAN Text of the original result set
+** expression.
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The parse tree for this expression */
- char *zName; /* Token associated with this expression */
- char *zSpan; /* Original text of the expression */
+ 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 bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
unsigned reusable :1; /* Constant expression is reusable */
unsigned bSorterRef :1; /* Defer evaluation until after sorting */
unsigned bNulls: 1; /* True if explicit "NULLS FIRST/LAST" */
@@ -17666,6 +18053,13 @@ struct ExprList {
};
/*
+** Allowed values for Expr.a.eEName
+*/
+#define ENAME_NAME 0 /* The AS clause of a result set */
+#define ENAME_SPAN 1 /* Complete text of the result set expression */
+#define ENAME_TAB 2 /* "DB.TABLE.NAME" for the result set */
+
+/*
** An instance of this structure can hold a simple list of identifiers,
** such as the list "a,b,c" in the following statements:
**
@@ -17728,6 +18122,7 @@ struct SrcList {
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_master */
} fg;
int iCursor; /* The VDBE cursor number used to access this table */
Expr *pOn; /* The ON clause of a join */
@@ -17831,21 +18226,24 @@ struct NameContext {
** NC_HasWin == EP_Win
**
*/
-#define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */
-#define NC_PartIdx 0x0002 /* True if resolving a partial index WHERE */
-#define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */
-#define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */
-#define NC_HasAgg 0x0010 /* One or more aggregate functions seen */
-#define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */
-#define NC_VarSelect 0x0040 /* A correlated subquery has been seen */
-#define NC_UEList 0x0080 /* True if uNC.pEList is used */
-#define NC_UAggInfo 0x0100 /* True if uNC.pAggInfo is used */
-#define NC_UUpsert 0x0200 /* True if uNC.pUpsert is used */
-#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */
-#define NC_Complex 0x2000 /* True if a function or subquery seen */
-#define NC_AllowWin 0x4000 /* Window functions are allowed here */
-#define NC_HasWin 0x8000 /* One or more window functions seen */
-#define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */
+#define NC_AllowAgg 0x00001 /* Aggregate functions are allowed here */
+#define NC_PartIdx 0x00002 /* True if resolving a partial index WHERE */
+#define NC_IsCheck 0x00004 /* True if resolving a CHECK constraint */
+#define NC_GenCol 0x00008 /* True for a GENERATED ALWAYS AS clause */
+#define NC_HasAgg 0x00010 /* One or more aggregate functions seen */
+#define NC_IdxExpr 0x00020 /* True if resolving columns of CREATE INDEX */
+#define NC_SelfRef 0x0002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
+#define NC_VarSelect 0x00040 /* A correlated subquery has been seen */
+#define NC_UEList 0x00080 /* True if uNC.pEList is used */
+#define NC_UAggInfo 0x00100 /* True if uNC.pAggInfo is used */
+#define NC_UUpsert 0x00200 /* True if uNC.pUpsert is used */
+#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_master */
/*
** An instance of the following object describes a single ON CONFLICT
@@ -17895,13 +18293,13 @@ struct Upsert {
** sequences for the ORDER BY clause.
*/
struct Select {
- ExprList *pEList; /* The fields of the result */
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
LogEst nSelectRow; /* Estimated number of result rows */
u32 selFlags; /* Various SF_* values */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
u32 selId; /* Unique identifier number for this SELECT */
int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
+ ExprList *pEList; /* The fields of the result */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
ExprList *pGroupBy; /* The GROUP BY clause */
@@ -17926,26 +18324,27 @@ struct Select {
** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
** SF_FixedLimit == WHERE_USE_LIMIT
*/
-#define SF_Distinct 0x00001 /* Output should be DISTINCT */
-#define SF_All 0x00002 /* Includes the ALL keyword */
-#define SF_Resolved 0x00004 /* Identifiers have been resolved */
-#define SF_Aggregate 0x00008 /* Contains agg functions or a GROUP BY */
-#define SF_HasAgg 0x00010 /* Contains aggregate functions */
-#define SF_UsesEphemeral 0x00020 /* Uses the OpenEphemeral opcode */
-#define SF_Expanded 0x00040 /* sqlite3SelectExpand() called on this */
-#define SF_HasTypeInfo 0x00080 /* FROM subqueries have Table metadata */
-#define SF_Compound 0x00100 /* Part of a compound query */
-#define SF_Values 0x00200 /* Synthesized from VALUES clause */
-#define SF_MultiValue 0x00400 /* Single VALUES term with multiple rows */
-#define SF_NestedFrom 0x00800 /* Part of a parenthesized FROM clause */
-#define SF_MinMaxAgg 0x01000 /* Aggregate containing min() or max() */
-#define SF_Recursive 0x02000 /* The recursive part of a recursive CTE */
-#define SF_FixedLimit 0x04000 /* nSelectRow set by a constant LIMIT */
-#define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */
-#define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */
-#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
-#define SF_ComplexResult 0x40000 /* Result contains subquery or function */
-#define SF_WhereBegin 0x80000 /* Really a WhereBegin() call. Debug Only */
+#define SF_Distinct 0x0000001 /* Output should be DISTINCT */
+#define SF_All 0x0000002 /* Includes the ALL keyword */
+#define SF_Resolved 0x0000004 /* Identifiers have been resolved */
+#define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */
+#define SF_HasAgg 0x0000010 /* Contains aggregate functions */
+#define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */
+#define SF_Expanded 0x0000040 /* sqlite3SelectExpand() called on this */
+#define SF_HasTypeInfo 0x0000080 /* FROM subqueries have Table metadata */
+#define SF_Compound 0x0000100 /* Part of a compound query */
+#define SF_Values 0x0000200 /* Synthesized from VALUES clause */
+#define SF_MultiValue 0x0000400 /* Single VALUES term with multiple rows */
+#define SF_NestedFrom 0x0000800 /* Part of a parenthesized FROM clause */
+#define SF_MinMaxAgg 0x0001000 /* Aggregate containing min() or max() */
+#define SF_Recursive 0x0002000 /* The recursive part of a recursive CTE */
+#define SF_FixedLimit 0x0004000 /* nSelectRow set by a constant LIMIT */
+#define SF_MaybeConvert 0x0008000 /* Need convertCompoundSelectToSubquery() */
+#define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */
+#define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */
+#define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
+#define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
+#define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
#define SF_View 0x0200000 /* SELECT statement is a view */
/*
@@ -18226,8 +18625,8 @@ struct Parse {
#define PARSE_MODE_NORMAL 0
#define PARSE_MODE_DECLARE_VTAB 1
-#define PARSE_MODE_RENAME_COLUMN 2
-#define PARSE_MODE_RENAME_TABLE 3
+#define PARSE_MODE_RENAME 2
+#define PARSE_MODE_UNMAP 3
/*
** Sizes and pointers of various parts of the Parse object.
@@ -18249,7 +18648,7 @@ struct Parse {
#if defined(SQLITE_OMIT_ALTERTABLE)
#define IN_RENAME_OBJECT 0
#else
- #define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME_COLUMN)
+ #define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME)
#endif
#if defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE)
@@ -18400,7 +18799,7 @@ typedef struct DbFixer DbFixer;
struct DbFixer {
Parse *pParse; /* The parsing context. Error messages written here */
Schema *pSchema; /* Fix items to this schema */
- int bVarOnly; /* Check for variable references only */
+ u8 bTemp; /* True for TEMP schema entries */
const char *zDb; /* Make sure all objects are contained in this database */
const char *zType; /* Type of the container - used for error messages */
const Token *pName; /* Name of the container - used for error messages */
@@ -18505,7 +18904,6 @@ struct Sqlite3Config {
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
#endif
int bLocaltimeFault; /* True to fail localtime() calls */
- int bInternalFunctions; /* Internal SQL functions are visible */
int iOnceResetThreshold; /* When to reset OP_Once counters */
u32 szSorterRef; /* Min size in bytes to use sorter-refs */
unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */
@@ -18538,7 +18936,7 @@ struct Walker {
int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */
void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */
int walkerDepth; /* Number of subqueries */
- u8 eCode; /* A small processing code */
+ u16 eCode; /* A small processing code */
union { /* Extra data for callback */
NameContext *pNC; /* Naming context */
int n; /* A counter */
@@ -18554,6 +18952,7 @@ struct Walker {
struct WindowRewrite *pRewrite; /* Window rewrite context */
struct WhereConst *pConst; /* WHERE clause constants */
struct RenameCtx *pRename; /* RENAME COLUMN context */
+ struct Table *pTab; /* Table of generated column */
} u;
};
@@ -18667,7 +19066,7 @@ SQLITE_PRIVATE Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*,
SQLITE_PRIVATE void sqlite3WindowAttach(Parse*, Expr*, Window*);
SQLITE_PRIVATE void sqlite3WindowLink(Select *pSel, Window *pWin);
SQLITE_PRIVATE int sqlite3WindowCompare(Parse*, Window*, Window*, int);
-SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Window*);
+SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Select*);
SQLITE_PRIVATE void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
SQLITE_PRIVATE int sqlite3WindowRewrite(Parse*, Select*);
SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
@@ -18933,6 +19332,7 @@ SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*);
SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr*);
SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
+SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*);
SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
@@ -18961,7 +19361,14 @@ SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*
SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*);
-SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index*, i16);
+SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index*, i16);
+#ifdef SQLITE_OMIT_GENERATED_COLUMNS
+# define sqlite3TableColumnToStorage(T,X) (X) /* No-op pass-through */
+# define sqlite3StorageColumnToTable(T,X) (X) /* No-op pass-through */
+#else
+SQLITE_PRIVATE i16 sqlite3TableColumnToStorage(Table*, i16);
+SQLITE_PRIVATE i16 sqlite3StorageColumnToTable(Table*, i16);
+#endif
SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
#if SQLITE_ENABLE_HIDDEN_COLUMNS
SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*);
@@ -18974,6 +19381,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
+SQLITE_PRIVATE void sqlite3AddGenerated(Parse*,Expr*,Token*);
SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
sqlite3_vfs**,char**,char **);
@@ -19031,6 +19439,9 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse);
# define sqlite3AutoincrementEnd(X)
#endif
SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+SQLITE_PRIVATE void sqlite3ComputeGeneratedColumns(Parse*, int, Table*);
+#endif
SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
@@ -19053,6 +19464,7 @@ SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,u32,Expr*);
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
+SQLITE_PRIVATE void sqlite3SelectReset(Parse*, Select*);
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
@@ -19075,17 +19487,20 @@ SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo*, int*);
#define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */
#define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */
#define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */
+SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo*);
SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Column*, int);
+#endif
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCodeAtInit(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int);
-SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */
#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
@@ -19127,6 +19542,7 @@ SQLITE_PRIVATE void sqlite3EndTransaction(Parse*,int);
SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*);
SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *);
SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
+SQLITE_PRIVATE u32 sqlite3IsTrueOrFalse(const char*);
SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*);
SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*);
@@ -19222,6 +19638,7 @@ SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Tab
#endif
SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*);
+SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr*,int);
SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int);
#ifndef SQLITE_OMIT_AUTHORIZATION
@@ -19382,7 +19799,12 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
-SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
+SQLITE_PRIVATE int sqlite3MatchEName(
+ const struct ExprList_item*,
+ const char*,
+ const char*,
+ const char*
+);
SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
SQLITE_PRIVATE int sqlite3ResolveExprListNames(NameContext*, ExprList*);
SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
@@ -19522,7 +19944,7 @@ SQLITE_PRIVATE Module *sqlite3VtabCreateModule(
#endif
SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db);
#ifndef SQLITE_OMIT_VIRTUALTABLE
-SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
+SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
#else
# define sqlite3ShadowTableName(A,B) 0
#endif
@@ -19547,6 +19969,7 @@ SQLITE_PRIVATE char *sqlite3Normalize(Vdbe*, const char*);
#endif
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
+SQLITE_PRIVATE CollSeq *sqlite3ExprCompareCollSeq(Parse*,Expr*);
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*);
SQLITE_PRIVATE const char *sqlite3JournalModename(int);
@@ -19853,7 +20276,6 @@ SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = {
** non-ASCII UTF character. Hence the test for whether or not a character is
** part of an identifier is 0x46.
*/
-#ifdef SQLITE_ASCII
SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */
@@ -19891,7 +20313,6 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */
};
-#endif
/* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards
** compatibility for legacy applications, the URI filename capability is
@@ -19956,9 +20377,18 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
** changed as start-time using sqlite3_config(SQLITE_CONFIG_LOOKASIDE)
** or at run-time for an individual database connection using
** sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE);
+**
+** With the two-size-lookaside enhancement, less lookaside is required.
+** The default configuration of 1200,40 actually provides 30 1200-byte slots
+** and 93 128-byte slots, which is more lookaside than is available
+** using the older 1200,100 configuration without two-size-lookaside.
*/
#ifndef SQLITE_DEFAULT_LOOKASIDE
-# define SQLITE_DEFAULT_LOOKASIDE 1200,100
+# ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+# define SQLITE_DEFAULT_LOOKASIDE 1200,100 /* 120KB of memory */
+# else
+# define SQLITE_DEFAULT_LOOKASIDE 1200,40 /* 48KB of memory */
+# endif
#endif
@@ -20024,7 +20454,6 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xTestCallback */
#endif
0, /* bLocaltimeFault */
- 0, /* bInternalFunctions */
0x7ffffffe, /* iOnceResetThreshold */
SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */
0, /* iPrngSeed */
@@ -20389,7 +20818,8 @@ struct sqlite3_value {
** True if Mem X is a NULL-nochng type.
*/
#define MemNullNochng(X) \
- ((X)->flags==(MEM_Null|MEM_Zero) && (X)->n==0 && (X)->u.nZero==0)
+ (((X)->flags&MEM_TypeMask)==(MEM_Null|MEM_Zero) \
+ && (X)->n==0 && (X)->u.nZero==0)
/*
** Return true if a memory cell is not marked as invalid. This macro
@@ -20585,6 +21015,7 @@ struct PreUpdate {
SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...);
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
void sqliteVdbePopStack(Vdbe*,int);
+SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor*);
SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor**, int*);
SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*);
SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
@@ -20631,7 +21062,7 @@ SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull);
SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
-SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8);
+SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem*,u8,u8);
SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
@@ -20697,7 +21128,7 @@ SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*);
-SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
+SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr);
#endif
#ifndef SQLITE_OMIT_UTF16
SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8);
@@ -20889,6 +21320,10 @@ static u32 countLookasideSlots(LookasideSlot *p){
SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
u32 nInit = countLookasideSlots(db->lookaside.pInit);
u32 nFree = countLookasideSlots(db->lookaside.pFree);
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ nInit += countLookasideSlots(db->lookaside.pSmallInit);
+ nFree += countLookasideSlots(db->lookaside.pSmallFree);
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
return db->lookaside.nSlot - (nInit+nFree);
}
@@ -20921,6 +21356,15 @@ SQLITE_API int sqlite3_db_status(
db->lookaside.pInit = db->lookaside.pFree;
db->lookaside.pFree = 0;
}
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ p = db->lookaside.pSmallFree;
+ if( p ){
+ while( p->pNext ) p = p->pNext;
+ p->pNext = db->lookaside.pSmallInit;
+ db->lookaside.pSmallInit = db->lookaside.pSmallFree;
+ db->lookaside.pSmallFree = 0;
+ }
+#endif
}
break;
}
@@ -21772,7 +22216,7 @@ static int parseModifier(
r = p->s*1000.0 + 210866760000000.0;
if( r>=0.0 && r<464269060800000.0 ){
clearYMD_HMS_TZ(p);
- p->iJD = (sqlite3_int64)r;
+ p->iJD = (sqlite3_int64)(r + 0.5);
p->validJD = 1;
p->rawS = 0;
rc = 0;
@@ -22551,7 +22995,7 @@ SQLITE_PRIVATE int sqlite3OsOpen(
** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
** reaching the VFS. */
- rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
+ rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut);
assert( rc==SQLITE_OK || pFile->pMethods==0 );
return rc;
}
@@ -26069,7 +26513,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
******************************************************************************
**
** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 class CPUs.
+** counters for x86 and x86_64 class CPUs.
*/
#ifndef SQLITE_HWTIME_H
#define SQLITE_HWTIME_H
@@ -26080,8 +26524,9 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
** processor and returns that value. This can be used for high-res
** profiling.
*/
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
+#if !defined(__STRICT_ANSI__) && \
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
#if defined(__GNUC__)
@@ -26102,7 +26547,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
#endif
-#elif (defined(__GNUC__) && defined(__x86_64__))
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long val;
@@ -26110,7 +26555,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
return val;
}
-#elif (defined(__GNUC__) && defined(__ppc__))
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long long retval;
@@ -26127,14 +26572,13 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
#else
- #error Need implementation of sqlite3Hwtime() for your platform.
-
/*
- ** To compile without implementing sqlite3Hwtime() for your platform,
- ** you can remove the above #error and use the following
- ** stub function. You will lose timing support for many
- ** of the debugging and testing utilities, but it should at
- ** least compile and run.
+ ** asm() is needed for hardware timing support. Without asm(),
+ ** disable the sqlite3Hwtime() routine.
+ **
+ ** sqlite3Hwtime() is only used for some obscure debugging
+ ** and analysis configurations, not in any deliverable, so this
+ ** should not be a great loss.
*/
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
@@ -26719,18 +27163,26 @@ SQLITE_API int sqlite3_release_memory(int n){
}
/*
+** Default value of the hard heap limit. 0 means "no limit".
+*/
+#ifndef SQLITE_MAX_MEMORY
+# define SQLITE_MAX_MEMORY 0
+#endif
+
+/*
** State information local to the memory allocation subsystem.
*/
static SQLITE_WSD struct Mem0Global {
sqlite3_mutex *mutex; /* Mutex to serialize access */
sqlite3_int64 alarmThreshold; /* The soft heap limit */
+ sqlite3_int64 hardLimit; /* The hard upper bound on memory */
/*
** True if heap is nearly "full" where "full" is defined by the
** sqlite3_soft_heap_limit() setting.
*/
int nearlyFull;
-} mem0 = { 0, 0, 0 };
+} mem0 = { 0, SQLITE_MAX_MEMORY, SQLITE_MAX_MEMORY, 0 };
#define mem0 GLOBAL(struct Mem0Global, mem0)
@@ -26760,8 +27212,15 @@ SQLITE_API int sqlite3_memory_alarm(
#endif
/*
-** Set the soft heap-size limit for the library. Passing a zero or
-** negative value indicates no limit.
+** Set the soft heap-size limit for the library. An argument of
+** zero disables the limit. A negative argument is a no-op used to
+** obtain the return value.
+**
+** The return value is the value of the heap limit just before this
+** interface was called.
+**
+** If the hard heap limit is enabled, then the soft heap limit cannot
+** be disabled nor raised above the hard heap limit.
*/
SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
sqlite3_int64 priorLimit;
@@ -26777,6 +27236,9 @@ SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
sqlite3_mutex_leave(mem0.mutex);
return priorLimit;
}
+ if( mem0.hardLimit>0 && (n>mem0.hardLimit || n==0) ){
+ n = mem0.hardLimit;
+ }
mem0.alarmThreshold = n;
nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
mem0.nearlyFull = (n>0 && n<=nUsed);
@@ -26791,6 +27253,37 @@ SQLITE_API void sqlite3_soft_heap_limit(int n){
}
/*
+** Set the hard heap-size limit for the library. An argument of zero
+** disables the hard heap limit. A negative argument is a no-op used
+** to obtain the return value without affecting the hard heap limit.
+**
+** The return value is the value of the hard heap limit just prior to
+** calling this interface.
+**
+** Setting the hard heap limit will also activate the soft heap limit
+** and constrain the soft heap limit to be no more than the hard heap
+** limit.
+*/
+SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 n){
+ sqlite3_int64 priorLimit;
+#ifndef SQLITE_OMIT_AUTOINIT
+ int rc = sqlite3_initialize();
+ if( rc ) return -1;
+#endif
+ sqlite3_mutex_enter(mem0.mutex);
+ priorLimit = mem0.hardLimit;
+ if( n>=0 ){
+ mem0.hardLimit = n;
+ if( n<mem0.alarmThreshold || mem0.alarmThreshold==0 ){
+ mem0.alarmThreshold = n;
+ }
+ }
+ sqlite3_mutex_leave(mem0.mutex);
+ return priorLimit;
+}
+
+
+/*
** Initialize the memory allocation subsystem.
*/
SQLITE_PRIVATE int sqlite3MallocInit(void){
@@ -26876,19 +27369,19 @@ static void mallocWithAlarm(int n, void **pp){
** following xRoundup() call. */
nFull = sqlite3GlobalConfig.m.xRoundup(n);
-#ifdef SQLITE_MAX_MEMORY
- if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nFull>SQLITE_MAX_MEMORY ){
- *pp = 0;
- return;
- }
-#endif
-
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
if( mem0.alarmThreshold>0 ){
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
if( nUsed >= mem0.alarmThreshold - nFull ){
mem0.nearlyFull = 1;
sqlite3MallocAlarm(nFull);
+ if( mem0.hardLimit ){
+ nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
+ if( nUsed >= mem0.hardLimit - nFull ){
+ *pp = 0;
+ return;
+ }
+ }
}else{
mem0.nearlyFull = 0;
}
@@ -26969,10 +27462,17 @@ SQLITE_PRIVATE int sqlite3MallocSize(void *p){
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
return sqlite3GlobalConfig.m.xSize(p);
}
+static int lookasideMallocSize(sqlite3 *db, void *p){
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ return p<db->lookaside.pMiddle ? db->lookaside.szTrue : LOOKASIDE_SMALL;
+#else
+ return db->lookaside.szTrue;
+#endif
+}
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
assert( p!=0 );
- if( db==0 || !isLookaside(db,p) ){
#ifdef SQLITE_DEBUG
+ if( db==0 || !isLookaside(db,p) ){
if( db==0 ){
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
@@ -26980,12 +27480,23 @@ SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
}
+ }
#endif
- return sqlite3GlobalConfig.m.xSize(p);
- }else{
- assert( sqlite3_mutex_held(db->mutex) );
- return db->lookaside.sz;
+ if( db ){
+ if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
+ assert( sqlite3_mutex_held(db->mutex) );
+ return LOOKASIDE_SMALL;
+ }
+#endif
+ if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
+ assert( sqlite3_mutex_held(db->mutex) );
+ return db->lookaside.szTrue;
+ }
+ }
}
+ return sqlite3GlobalConfig.m.xSize(p);
}
SQLITE_API sqlite3_uint64 sqlite3_msize(void *p){
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
@@ -27032,15 +27543,27 @@ SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){
measureAllocationSize(db, p);
return;
}
- if( isLookaside(db, p) ){
- LookasideSlot *pBuf = (LookasideSlot*)p;
+ if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
+ LookasideSlot *pBuf = (LookasideSlot*)p;
#ifdef SQLITE_DEBUG
- /* Trash all content in the buffer being freed */
- memset(p, 0xaa, db->lookaside.sz);
+ memset(p, 0xaa, LOOKASIDE_SMALL); /* Trash freed content */
#endif
- pBuf->pNext = db->lookaside.pFree;
- db->lookaside.pFree = pBuf;
- return;
+ pBuf->pNext = db->lookaside.pSmallFree;
+ db->lookaside.pSmallFree = pBuf;
+ return;
+ }
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
+ if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
+ LookasideSlot *pBuf = (LookasideSlot*)p;
+#ifdef SQLITE_DEBUG
+ memset(p, 0xaa, db->lookaside.szTrue); /* Trash freed content */
+#endif
+ pBuf->pNext = db->lookaside.pFree;
+ db->lookaside.pFree = pBuf;
+ return;
+ }
}
}
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
@@ -27196,23 +27719,37 @@ SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){
assert( db!=0 );
assert( sqlite3_mutex_held(db->mutex) );
assert( db->pnBytesFreed==0 );
- if( db->lookaside.bDisable==0 ){
- assert( db->mallocFailed==0 );
- if( n>db->lookaside.sz ){
- db->lookaside.anStat[1]++;
- }else if( (pBuf = db->lookaside.pFree)!=0 ){
- db->lookaside.pFree = pBuf->pNext;
+ if( n>db->lookaside.sz ){
+ if( !db->lookaside.bDisable ){
+ db->lookaside.anStat[1]++;
+ }else if( db->mallocFailed ){
+ return 0;
+ }
+ return dbMallocRawFinish(db, n);
+ }
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ if( n<=LOOKASIDE_SMALL ){
+ if( (pBuf = db->lookaside.pSmallFree)!=0 ){
+ db->lookaside.pSmallFree = pBuf->pNext;
db->lookaside.anStat[0]++;
return (void*)pBuf;
- }else if( (pBuf = db->lookaside.pInit)!=0 ){
- db->lookaside.pInit = pBuf->pNext;
+ }else if( (pBuf = db->lookaside.pSmallInit)!=0 ){
+ db->lookaside.pSmallInit = pBuf->pNext;
db->lookaside.anStat[0]++;
return (void*)pBuf;
- }else{
- db->lookaside.anStat[2]++;
}
- }else if( db->mallocFailed ){
- return 0;
+ }
+#endif
+ if( (pBuf = db->lookaside.pFree)!=0 ){
+ db->lookaside.pFree = pBuf->pNext;
+ db->lookaside.anStat[0]++;
+ return (void*)pBuf;
+ }else if( (pBuf = db->lookaside.pInit)!=0 ){
+ db->lookaside.pInit = pBuf->pNext;
+ db->lookaside.anStat[0]++;
+ return (void*)pBuf;
+ }else{
+ db->lookaside.anStat[2]++;
}
#else
assert( db!=0 );
@@ -27236,7 +27773,16 @@ SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
assert( db!=0 );
if( p==0 ) return sqlite3DbMallocRawNN(db, n);
assert( sqlite3_mutex_held(db->mutex) );
- if( isLookaside(db,p) && n<=db->lookaside.sz ) return p;
+ if( ((uptr)p)<(uptr)db->lookaside.pEnd ){
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ if( ((uptr)p)>=(uptr)db->lookaside.pMiddle ){
+ if( n<=LOOKASIDE_SMALL ) return p;
+ }else
+#endif
+ if( ((uptr)p)>=(uptr)db->lookaside.pStart ){
+ if( n<=db->lookaside.szTrue ) return p;
+ }
+ }
return dbReallocFinish(db, p, n);
}
static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
@@ -27247,7 +27793,7 @@ static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
if( isLookaside(db, p) ){
pNew = sqlite3DbMallocRawNN(db, n);
if( pNew ){
- memcpy(pNew, p, db->lookaside.sz);
+ memcpy(pNew, p, lookasideMallocSize(db, p));
sqlite3DbFree(db, p);
}
}else{
@@ -27346,7 +27892,7 @@ SQLITE_PRIVATE void sqlite3OomFault(sqlite3 *db){
if( db->nVdbeExec>0 ){
db->u1.isInterrupted = 1;
}
- db->lookaside.bDisable++;
+ DisableLookaside;
if( db->pParse ){
db->pParse->rc = SQLITE_NOMEM_BKPT;
}
@@ -27365,7 +27911,7 @@ SQLITE_PRIVATE void sqlite3OomClear(sqlite3 *db){
db->mallocFailed = 0;
db->u1.isInterrupted = 0;
assert( db->lookaside.bDisable>0 );
- db->lookaside.bDisable--;
+ EnableLookaside;
}
}
@@ -28773,7 +29319,7 @@ static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_start(ap, zFormat);
sqlite3_str_vappendf(&acc, zFormat, ap);
va_end(ap);
- assert( acc.nChar>0 );
+ assert( acc.nChar>0 || acc.accError );
sqlite3_str_append(&acc, "\n", 1);
}
sqlite3StrAccumFinish(&acc);
@@ -28813,7 +29359,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m
char cSep = '(';
int j;
for(j=0; j<pCte->pCols->nExpr; j++){
- sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zName);
+ sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zEName);
cSep = ',';
}
sqlite3_str_appendf(&x, ")");
@@ -28838,7 +29384,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
StrAccum x;
char zLine[100];
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
- sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor);
+ sqlite3_str_appendf(&x, "{%d:*}", pItem->iCursor);
if( pItem->zDatabase ){
sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
}else if( pItem->zName ){
@@ -28854,6 +29400,9 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
if( pItem->fg.jointype & JT_LEFT ){
sqlite3_str_appendf(&x, " LEFT-JOIN");
}
+ if( pItem->fg.fromDDL ){
+ sqlite3_str_appendf(&x, " DDL");
+ }
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
if( pItem->pSelect ){
@@ -29110,14 +29659,17 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
return;
}
if( pExpr->flags || pExpr->affExpr ){
+ StrAccum x;
+ sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0);
+ sqlite3_str_appendf(&x, " fg.af=%x.%c",
+ pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n');
if( ExprHasProperty(pExpr, EP_FromJoin) ){
- sqlite3_snprintf(sizeof(zFlgs),zFlgs," fg.af=%x.%c iRJT=%d",
- pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n',
- pExpr->iRightJoinTable);
- }else{
- sqlite3_snprintf(sizeof(zFlgs),zFlgs," fg.af=%x.%c",
- pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n');
+ sqlite3_str_appendf(&x, " iRJT=%d", pExpr->iRightJoinTable);
+ }
+ if( ExprHasProperty(pExpr, EP_FromDDL) ){
+ sqlite3_str_appendf(&x, " DDL");
}
+ sqlite3StrAccumFinish(&x);
}else{
zFlgs[0] = 0;
}
@@ -29130,10 +29682,18 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
case TK_COLUMN: {
if( pExpr->iTable<0 ){
/* This only happens when coding check constraints */
- sqlite3TreeViewLine(pView, "COLUMN(%d)%s", pExpr->iColumn, zFlgs);
+ char zOp2[16];
+ if( pExpr->op2 ){
+ sqlite3_snprintf(sizeof(zOp2),zOp2," op2=0x%02x",pExpr->op2);
+ }else{
+ zOp2[0] = 0;
+ }
+ sqlite3TreeViewLine(pView, "COLUMN(%d)%s%s",
+ pExpr->iColumn, zFlgs, zOp2);
}else{
- sqlite3TreeViewLine(pView, "{%d:%d}%s",
- pExpr->iTable, pExpr->iColumn, zFlgs);
+ sqlite3TreeViewLine(pView, "{%d:%d} pTab=%p%s",
+ pExpr->iTable, pExpr->iColumn,
+ pExpr->y.pTab, zFlgs);
}
if( ExprHasProperty(pExpr, EP_FixedCol) ){
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
@@ -29265,7 +29825,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
}else{
pFarg = pExpr->x.pList;
#ifndef SQLITE_OMIT_WINDOWFUNC
- pWin = pExpr->y.pWin;
+ pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0;
#else
pWin = 0;
#endif
@@ -29273,6 +29833,17 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
if( pExpr->op==TK_AGG_FUNCTION ){
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s",
pExpr->op2, pExpr->u.zToken, zFlgs);
+ }else if( pExpr->op2!=0 ){
+ const char *zOp2;
+ char zBuf[8];
+ sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",pExpr->op2);
+ zOp2 = zBuf;
+ if( pExpr->op2==NC_IsCheck ) zOp2 = "NC_IsCheck";
+ if( pExpr->op2==NC_IdxExpr ) zOp2 = "NC_IdxExpr";
+ if( pExpr->op2==NC_PartIdx ) zOp2 = "NC_PartIdx";
+ if( pExpr->op2==NC_GenCol ) zOp2 = "NC_GenCol";
+ sqlite3TreeViewLine(pView, "FUNCTION %Q%s op2=%s",
+ pExpr->u.zToken, zFlgs, zOp2);
}else{
sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs);
}
@@ -29368,7 +29939,9 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
break;
}
case TK_VECTOR: {
- sqlite3TreeViewBareExprList(pView, pExpr->x.pList, "VECTOR");
+ char *z = sqlite3_mprintf("VECTOR%s",zFlgs);
+ sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
+ sqlite3_free(z);
break;
}
case TK_SELECT_COLUMN: {
@@ -29414,8 +29987,9 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList(
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; i<pList->nExpr; i++){
int j = pList->a[i].u.x.iOrderByCol;
- char *zName = pList->a[i].zName;
+ char *zName = pList->a[i].zEName;
int moreToFollow = i<pList->nExpr - 1;
+ if( pList->a[i].eEName!=ENAME_NAME ) zName = 0;
if( j || zName ){
sqlite3TreeViewPush(pView, moreToFollow);
moreToFollow = 0;
@@ -30082,9 +30656,11 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desired
#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
{
- char zBuf[100];
- sqlite3VdbeMemPrettyPrint(pMem, zBuf);
- fprintf(stderr, "INPUT: %s\n", zBuf);
+ StrAccum acc;
+ char zBuf[1000];
+ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
+ sqlite3VdbeMemPrettyPrint(pMem, &acc);
+ fprintf(stderr, "INPUT: %s\n", sqlite3StrAccumFinish(&acc));
}
#endif
@@ -30192,9 +30768,11 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desired
translate_out:
#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
{
- char zBuf[100];
- sqlite3VdbeMemPrettyPrint(pMem, zBuf);
- fprintf(stderr, "OUTPUT: %s\n", zBuf);
+ StrAccum acc;
+ char zBuf[1000];
+ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
+ sqlite3VdbeMemPrettyPrint(pMem, &acc);
+ fprintf(stderr, "OUTPUT: %s\n", sqlite3StrAccumFinish(&acc));
}
#endif
return SQLITE_OK;
@@ -30419,7 +30997,9 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
*/
/* #include "sqliteInt.h" */
/* #include <stdarg.h> */
+#ifndef SQLITE_OMIT_FLOATING_POINT
#include <math.h>
+#endif
/*
** Routine needed to support the testcase() macro.
@@ -30594,6 +31174,7 @@ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
sqlite3DbFree(db, pParse->zErrMsg);
pParse->zErrMsg = zMsg;
pParse->rc = SQLITE_ERROR;
+ pParse->pWith = 0;
}
}
@@ -30784,10 +31365,13 @@ static LONGDOUBLE_TYPE sqlite3Pow10(int E){
** returns FALSE but it still converts the prefix and writes the result
** into *pResult.
*/
+#if defined(_MSC_VER)
+#pragma warning(disable : 4756)
+#endif
SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
#ifndef SQLITE_OMIT_FLOATING_POINT
int incr;
- const char *zEnd = z + length;
+ const char *zEnd;
/* sign * significand * (10 ^ (esign * exponent)) */
int sign = 1; /* sign of significand */
i64 s = 0; /* significand */
@@ -30801,12 +31385,15 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
*pResult = 0.0; /* Default return value, in case of an error */
+ if( length==0 ) return 0;
if( enc==SQLITE_UTF8 ){
incr = 1;
+ zEnd = z + length;
}else{
int i;
incr = 2;
+ length &= ~1;
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
testcase( enc==SQLITE_UTF16LE );
testcase( enc==SQLITE_UTF16BE );
@@ -30971,6 +31558,9 @@ do_atof_calc:
return !sqlite3Atoi64(z, pResult, length, enc);
#endif /* SQLITE_OMIT_FLOATING_POINT */
}
+#if defined(_MSC_VER)
+#pragma warning(default : 4756)
+#endif
/*
** Compare the 19-character string zNum against the text representation
@@ -32341,30 +32931,30 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 23 */ "SeekLE" OpHelp("key=r[P3@P4]"),
/* 24 */ "SeekGE" OpHelp("key=r[P3@P4]"),
/* 25 */ "SeekGT" OpHelp("key=r[P3@P4]"),
- /* 26 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
- /* 27 */ "NoConflict" OpHelp("key=r[P3@P4]"),
- /* 28 */ "NotFound" OpHelp("key=r[P3@P4]"),
- /* 29 */ "Found" OpHelp("key=r[P3@P4]"),
- /* 30 */ "SeekRowid" OpHelp("intkey=r[P3]"),
- /* 31 */ "NotExists" OpHelp("intkey=r[P3]"),
- /* 32 */ "Last" OpHelp(""),
- /* 33 */ "IfSmaller" OpHelp(""),
- /* 34 */ "SorterSort" OpHelp(""),
- /* 35 */ "Sort" OpHelp(""),
- /* 36 */ "Rewind" OpHelp(""),
- /* 37 */ "IdxLE" OpHelp("key=r[P3@P4]"),
- /* 38 */ "IdxGT" OpHelp("key=r[P3@P4]"),
- /* 39 */ "IdxLT" OpHelp("key=r[P3@P4]"),
- /* 40 */ "IdxGE" OpHelp("key=r[P3@P4]"),
- /* 41 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
- /* 42 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
+ /* 26 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"),
+ /* 27 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
+ /* 28 */ "NoConflict" OpHelp("key=r[P3@P4]"),
+ /* 29 */ "NotFound" OpHelp("key=r[P3@P4]"),
+ /* 30 */ "Found" OpHelp("key=r[P3@P4]"),
+ /* 31 */ "SeekRowid" OpHelp("intkey=r[P3]"),
+ /* 32 */ "NotExists" OpHelp("intkey=r[P3]"),
+ /* 33 */ "Last" OpHelp(""),
+ /* 34 */ "IfSmaller" OpHelp(""),
+ /* 35 */ "SorterSort" OpHelp(""),
+ /* 36 */ "Sort" OpHelp(""),
+ /* 37 */ "Rewind" OpHelp(""),
+ /* 38 */ "IdxLE" OpHelp("key=r[P3@P4]"),
+ /* 39 */ "IdxGT" OpHelp("key=r[P3@P4]"),
+ /* 40 */ "IdxLT" OpHelp("key=r[P3@P4]"),
+ /* 41 */ "IdxGE" OpHelp("key=r[P3@P4]"),
+ /* 42 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
/* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
/* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
- /* 45 */ "Program" OpHelp(""),
- /* 46 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
- /* 47 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
- /* 48 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
- /* 49 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
+ /* 45 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
+ /* 46 */ "Program" OpHelp(""),
+ /* 47 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
+ /* 48 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+ /* 49 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
/* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
/* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
/* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
@@ -32374,83 +32964,83 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
/* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
/* 58 */ "ElseNotEq" OpHelp(""),
- /* 59 */ "IncrVacuum" OpHelp(""),
- /* 60 */ "VNext" OpHelp(""),
- /* 61 */ "Init" OpHelp("Start at P2"),
- /* 62 */ "PureFunc0" OpHelp(""),
- /* 63 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"),
- /* 64 */ "PureFunc" OpHelp(""),
- /* 65 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"),
- /* 66 */ "Return" OpHelp(""),
- /* 67 */ "EndCoroutine" OpHelp(""),
- /* 68 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
- /* 69 */ "Halt" OpHelp(""),
- /* 70 */ "Integer" OpHelp("r[P2]=P1"),
- /* 71 */ "Int64" OpHelp("r[P2]=P4"),
- /* 72 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
- /* 73 */ "Null" OpHelp("r[P2..P3]=NULL"),
- /* 74 */ "SoftNull" OpHelp("r[P1]=NULL"),
- /* 75 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
- /* 76 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
- /* 77 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
- /* 78 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
- /* 79 */ "SCopy" OpHelp("r[P2]=r[P1]"),
- /* 80 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
- /* 81 */ "ResultRow" OpHelp("output=r[P1@P2]"),
- /* 82 */ "CollSeq" OpHelp(""),
- /* 83 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
- /* 84 */ "RealAffinity" OpHelp(""),
- /* 85 */ "Cast" OpHelp("affinity(r[P1])"),
- /* 86 */ "Permutation" OpHelp(""),
- /* 87 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
- /* 88 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
- /* 89 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
- /* 90 */ "Column" OpHelp("r[P3]=PX"),
- /* 91 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
- /* 92 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
- /* 93 */ "Count" OpHelp("r[P2]=count()"),
- /* 94 */ "ReadCookie" OpHelp(""),
- /* 95 */ "SetCookie" OpHelp(""),
- /* 96 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
- /* 97 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
- /* 98 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
- /* 99 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
- /* 100 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
- /* 101 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
- /* 102 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
- /* 103 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
- /* 104 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
- /* 105 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
- /* 106 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
- /* 107 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
- /* 108 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
- /* 109 */ "OpenDup" OpHelp(""),
- /* 110 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
- /* 111 */ "OpenAutoindex" OpHelp("nColumn=P2"),
- /* 112 */ "OpenEphemeral" OpHelp("nColumn=P2"),
- /* 113 */ "String8" OpHelp("r[P2]='P4'"),
- /* 114 */ "SorterOpen" OpHelp(""),
- /* 115 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
- /* 116 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
- /* 117 */ "Close" OpHelp(""),
- /* 118 */ "ColumnsUsed" OpHelp(""),
- /* 119 */ "SeekHit" OpHelp("seekHit=P2"),
- /* 120 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
- /* 121 */ "NewRowid" OpHelp("r[P2]=rowid"),
- /* 122 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
- /* 123 */ "Delete" OpHelp(""),
- /* 124 */ "ResetCount" OpHelp(""),
- /* 125 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
- /* 126 */ "SorterData" OpHelp("r[P2]=data"),
- /* 127 */ "RowData" OpHelp("r[P2]=data"),
- /* 128 */ "Rowid" OpHelp("r[P2]=rowid"),
- /* 129 */ "NullRow" OpHelp(""),
- /* 130 */ "SeekEnd" OpHelp(""),
- /* 131 */ "SorterInsert" OpHelp("key=r[P2]"),
- /* 132 */ "IdxInsert" OpHelp("key=r[P2]"),
- /* 133 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
- /* 134 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
- /* 135 */ "IdxRowid" OpHelp("r[P2]=rowid"),
+ /* 59 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
+ /* 60 */ "IncrVacuum" OpHelp(""),
+ /* 61 */ "VNext" OpHelp(""),
+ /* 62 */ "Init" OpHelp("Start at P2"),
+ /* 63 */ "PureFunc" OpHelp("r[P3]=func(r[P2@P5])"),
+ /* 64 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"),
+ /* 65 */ "Return" OpHelp(""),
+ /* 66 */ "EndCoroutine" OpHelp(""),
+ /* 67 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
+ /* 68 */ "Halt" OpHelp(""),
+ /* 69 */ "Integer" OpHelp("r[P2]=P1"),
+ /* 70 */ "Int64" OpHelp("r[P2]=P4"),
+ /* 71 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
+ /* 72 */ "Null" OpHelp("r[P2..P3]=NULL"),
+ /* 73 */ "SoftNull" OpHelp("r[P1]=NULL"),
+ /* 74 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
+ /* 75 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
+ /* 76 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
+ /* 77 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
+ /* 78 */ "SCopy" OpHelp("r[P2]=r[P1]"),
+ /* 79 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
+ /* 80 */ "ResultRow" OpHelp("output=r[P1@P2]"),
+ /* 81 */ "CollSeq" OpHelp(""),
+ /* 82 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
+ /* 83 */ "RealAffinity" OpHelp(""),
+ /* 84 */ "Cast" OpHelp("affinity(r[P1])"),
+ /* 85 */ "Permutation" OpHelp(""),
+ /* 86 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
+ /* 87 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
+ /* 88 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
+ /* 89 */ "Column" OpHelp("r[P3]=PX"),
+ /* 90 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
+ /* 91 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
+ /* 92 */ "Count" OpHelp("r[P2]=count()"),
+ /* 93 */ "ReadCookie" OpHelp(""),
+ /* 94 */ "SetCookie" OpHelp(""),
+ /* 95 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
+ /* 96 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 97 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
+ /* 98 */ "OpenDup" OpHelp(""),
+ /* 99 */ "OpenAutoindex" OpHelp("nColumn=P2"),
+ /* 100 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 101 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
+ /* 102 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
+ /* 103 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
+ /* 104 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
+ /* 105 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
+ /* 106 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
+ /* 107 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
+ /* 108 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
+ /* 109 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
+ /* 110 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
+ /* 111 */ "SorterOpen" OpHelp(""),
+ /* 112 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
+ /* 113 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
+ /* 114 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
+ /* 115 */ "String8" OpHelp("r[P2]='P4'"),
+ /* 116 */ "Close" OpHelp(""),
+ /* 117 */ "ColumnsUsed" OpHelp(""),
+ /* 118 */ "SeekHit" OpHelp("seekHit=P2"),
+ /* 119 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
+ /* 120 */ "NewRowid" OpHelp("r[P2]=rowid"),
+ /* 121 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
+ /* 122 */ "Delete" OpHelp(""),
+ /* 123 */ "ResetCount" OpHelp(""),
+ /* 124 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
+ /* 125 */ "SorterData" OpHelp("r[P2]=data"),
+ /* 126 */ "RowData" OpHelp("r[P2]=data"),
+ /* 127 */ "Rowid" OpHelp("r[P2]=rowid"),
+ /* 128 */ "NullRow" OpHelp(""),
+ /* 129 */ "SeekEnd" OpHelp(""),
+ /* 130 */ "SorterInsert" OpHelp("key=r[P2]"),
+ /* 131 */ "IdxInsert" OpHelp("key=r[P2]"),
+ /* 132 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
+ /* 133 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
+ /* 134 */ "IdxRowid" OpHelp("r[P2]=rowid"),
+ /* 135 */ "FinishSeek" OpHelp(""),
/* 136 */ "Destroy" OpHelp(""),
/* 137 */ "Clear" OpHelp(""),
/* 138 */ "ResetSorter" OpHelp(""),
@@ -32463,9 +33053,9 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 145 */ "DropTrigger" OpHelp(""),
/* 146 */ "IntegrityCk" OpHelp(""),
/* 147 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
- /* 148 */ "Real" OpHelp("r[P2]=P4"),
- /* 149 */ "Param" OpHelp(""),
- /* 150 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 148 */ "Param" OpHelp(""),
+ /* 149 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 150 */ "Real" OpHelp("r[P2]=P4"),
/* 151 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
/* 152 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
/* 153 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
@@ -32474,20 +33064,23 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 156 */ "AggValue" OpHelp("r[P3]=value N=P2"),
/* 157 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
/* 158 */ "Expire" OpHelp(""),
- /* 159 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
- /* 160 */ "VBegin" OpHelp(""),
- /* 161 */ "VCreate" OpHelp(""),
- /* 162 */ "VDestroy" OpHelp(""),
- /* 163 */ "VOpen" OpHelp(""),
- /* 164 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 165 */ "VRename" OpHelp(""),
- /* 166 */ "Pagecount" OpHelp(""),
- /* 167 */ "MaxPgcnt" OpHelp(""),
- /* 168 */ "Trace" OpHelp(""),
- /* 169 */ "CursorHint" OpHelp(""),
- /* 170 */ "Noop" OpHelp(""),
- /* 171 */ "Explain" OpHelp(""),
- /* 172 */ "Abortable" OpHelp(""),
+ /* 159 */ "CursorLock" OpHelp(""),
+ /* 160 */ "CursorUnlock" OpHelp(""),
+ /* 161 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 162 */ "VBegin" OpHelp(""),
+ /* 163 */ "VCreate" OpHelp(""),
+ /* 164 */ "VDestroy" OpHelp(""),
+ /* 165 */ "VOpen" OpHelp(""),
+ /* 166 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 167 */ "VRename" OpHelp(""),
+ /* 168 */ "Pagecount" OpHelp(""),
+ /* 169 */ "MaxPgcnt" OpHelp(""),
+ /* 170 */ "Trace" OpHelp(""),
+ /* 171 */ "CursorHint" OpHelp(""),
+ /* 172 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
+ /* 173 */ "Noop" OpHelp(""),
+ /* 174 */ "Explain" OpHelp(""),
+ /* 175 */ "Abortable" OpHelp(""),
};
return azName[i];
}
@@ -32851,7 +33444,7 @@ static pid_t randomnessPid = 0;
******************************************************************************
**
** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 class CPUs.
+** counters for x86 and x86_64 class CPUs.
*/
#ifndef SQLITE_HWTIME_H
#define SQLITE_HWTIME_H
@@ -32862,8 +33455,9 @@ static pid_t randomnessPid = 0;
** processor and returns that value. This can be used for high-res
** profiling.
*/
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
+#if !defined(__STRICT_ANSI__) && \
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
#if defined(__GNUC__)
@@ -32884,7 +33478,7 @@ static pid_t randomnessPid = 0;
#endif
-#elif (defined(__GNUC__) && defined(__x86_64__))
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long val;
@@ -32892,7 +33486,7 @@ static pid_t randomnessPid = 0;
return val;
}
-#elif (defined(__GNUC__) && defined(__ppc__))
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long long retval;
@@ -32909,14 +33503,13 @@ static pid_t randomnessPid = 0;
#else
- #error Need implementation of sqlite3Hwtime() for your platform.
-
/*
- ** To compile without implementing sqlite3Hwtime() for your platform,
- ** you can remove the above #error and use the following
- ** stub function. You will lose timing support for many
- ** of the debugging and testing utilities, but it should at
- ** least compile and run.
+ ** asm() is needed for hardware timing support. Without asm(),
+ ** disable the sqlite3Hwtime() routine.
+ **
+ ** sqlite3Hwtime() is only used for some obscure debugging
+ ** and analysis configurations, not in any deliverable, so this
+ ** should not be a great loss.
*/
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
@@ -36380,7 +36973,7 @@ static int openDirectory(const char *zFilename, int *pFd){
if( zDirname[0]!='/' ) zDirname[0] = '.';
zDirname[1] = 0;
}
- fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
+ fd = robust_open(zDirname, O_RDONLY|O_BINARY|O_NOFOLLOW, 0);
if( fd>=0 ){
OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
}
@@ -37271,10 +37864,12 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
if( pInode->bProcessLock==0 ){
if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
- pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT,(sStat.st_mode&0777));
+ pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT|O_NOFOLLOW,
+ (sStat.st_mode&0777));
}
if( pShmNode->hShm<0 ){
- pShmNode->hShm = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
+ pShmNode->hShm = robust_open(zShm, O_RDONLY|O_NOFOLLOW,
+ (sStat.st_mode&0777));
if( pShmNode->hShm<0 ){
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm);
goto shm_open_err;
@@ -38624,7 +39219,7 @@ static int unixOpen(
unixFile *p = (unixFile *)pFile;
int fd = -1; /* File descriptor returned by open() */
int openFlags = 0; /* Flags to pass to open() */
- int eType = flags&0xFFFFFF00; /* Type of file to open */
+ int eType = flags&0x0FFF00; /* Type of file to open */
int noLock; /* True to omit locking primitives */
int rc = SQLITE_OK; /* Function Return Code */
int ctrlFlags = 0; /* UNIXFILE_* flags */
@@ -38734,7 +39329,7 @@ static int unixOpen(
if( isReadWrite ) openFlags |= O_RDWR;
if( isCreate ) openFlags |= O_CREAT;
if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
- openFlags |= (O_LARGEFILE|O_BINARY);
+ openFlags |= (O_LARGEFILE|O_BINARY|O_NOFOLLOW);
if( fd<0 ){
mode_t openMode; /* Permissions to create file with */
@@ -38952,7 +39547,8 @@ static int unixAccess(
if( flags==SQLITE_ACCESS_EXISTS ){
struct stat buf;
- *pResOut = (0==osStat(zPath, &buf) && buf.st_size>0);
+ *pResOut = 0==osStat(zPath, &buf) &&
+ (!S_ISREG(buf.st_mode) || buf.st_size>0);
}else{
*pResOut = osAccess(zPath, W_OK|R_OK)==0;
}
@@ -39006,7 +39602,7 @@ static int unixFullPathname(
#else
int rc = SQLITE_OK;
int nByte;
- int nLink = 1; /* Number of symbolic links followed so far */
+ int nLink = 0; /* Number of symbolic links followed so far */
const char *zIn = zPath; /* Input path for each iteration of loop */
char *zDel = 0;
@@ -39035,10 +39631,11 @@ static int unixFullPathname(
}
if( bLink ){
+ nLink++;
if( zDel==0 ){
zDel = sqlite3_malloc(nOut);
if( zDel==0 ) rc = SQLITE_NOMEM_BKPT;
- }else if( ++nLink>SQLITE_MAX_SYMLINKS ){
+ }else if( nLink>=SQLITE_MAX_SYMLINKS ){
rc = SQLITE_CANTOPEN_BKPT;
}
@@ -39074,6 +39671,7 @@ static int unixFullPathname(
}while( rc==SQLITE_OK );
sqlite3_free(zDel);
+ if( rc==SQLITE_OK && nLink ) rc = SQLITE_OK_SYMLINK;
return rc;
#endif /* HAVE_READLINK && HAVE_LSTAT */
}
@@ -39559,7 +40157,7 @@ static int proxyCreateUnixFile(
int fd = -1;
unixFile *pNew;
int rc = SQLITE_OK;
- int openFlags = O_RDWR | O_CREAT;
+ int openFlags = O_RDWR | O_CREAT | O_NOFOLLOW;
sqlite3_vfs dummyVfs;
int terrno = 0;
UnixUnusedFd *pUnused = NULL;
@@ -39589,7 +40187,7 @@ static int proxyCreateUnixFile(
}
}
if( fd<0 ){
- openFlags = O_RDONLY;
+ openFlags = O_RDONLY | O_NOFOLLOW;
fd = robust_open(path, openFlags, 0);
terrno = errno;
}
@@ -39715,7 +40313,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
goto end_breaklock;
}
/* write it out to the temporary break file */
- fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL), 0);
+ fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW), 0);
if( fd<0 ){
sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
goto end_breaklock;
@@ -40673,7 +41271,7 @@ SQLITE_API int sqlite3_os_end(void){
******************************************************************************
**
** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 class CPUs.
+** counters for x86 and x86_64 class CPUs.
*/
#ifndef SQLITE_HWTIME_H
#define SQLITE_HWTIME_H
@@ -40684,8 +41282,9 @@ SQLITE_API int sqlite3_os_end(void){
** processor and returns that value. This can be used for high-res
** profiling.
*/
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
+#if !defined(__STRICT_ANSI__) && \
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
#if defined(__GNUC__)
@@ -40706,7 +41305,7 @@ SQLITE_API int sqlite3_os_end(void){
#endif
-#elif (defined(__GNUC__) && defined(__x86_64__))
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long val;
@@ -40714,7 +41313,7 @@ SQLITE_API int sqlite3_os_end(void){
return val;
}
-#elif (defined(__GNUC__) && defined(__ppc__))
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long long retval;
@@ -40731,14 +41330,13 @@ SQLITE_API int sqlite3_os_end(void){
#else
- #error Need implementation of sqlite3Hwtime() for your platform.
-
/*
- ** To compile without implementing sqlite3Hwtime() for your platform,
- ** you can remove the above #error and use the following
- ** stub function. You will lose timing support for many
- ** of the debugging and testing utilities, but it should at
- ** least compile and run.
+ ** asm() is needed for hardware timing support. Without asm(),
+ ** disable the sqlite3Hwtime() routine.
+ **
+ ** sqlite3Hwtime() is only used for some obscure debugging
+ ** and analysis configurations, not in any deliverable, so this
+ ** should not be a great loss.
*/
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
@@ -49306,13 +49904,15 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
}
#else
pPg = pcache1Alloc(pCache->szAlloc);
- p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
#endif
if( benignMalloc ){ sqlite3EndBenignMalloc(); }
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
pcache1EnterMutex(pCache->pGroup);
#endif
if( pPg==0 ) return 0;
+#ifndef SQLITE_PCACHE_SEPARATE_HEADER
+ p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
+#endif
p->page.pBuf = pPg;
p->page.pExtra = &p[1];
p->isBulkLocal = 0;
@@ -51967,6 +52567,7 @@ static int pagerUnlockDb(Pager *pPager, int eLock){
}
IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
}
+ pPager->changeCountDone = pPager->tempFile; /* ticket fb3b3024ea238d5c */
return rc;
}
@@ -52154,6 +52755,7 @@ static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
len = 0;
}
zMaster[len] = '\0';
+ zMaster[len+1] = '\0';
return SQLITE_OK;
}
@@ -52687,7 +53289,6 @@ static void pager_unlock(Pager *pPager){
** code is cleared and the cache reset in the block below.
*/
assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
- pPager->changeCountDone = 0;
pPager->eState = PAGER_OPEN;
}
@@ -52951,7 +53552,6 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
&& (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
){
rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
- pPager->changeCountDone = 0;
}
pPager->eState = PAGER_READER;
pPager->setMaster = 0;
@@ -53390,15 +53990,16 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){
rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
if( rc!=SQLITE_OK ) goto delmaster_out;
nMasterPtr = pVfs->mxPathname+1;
- zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 1);
+ zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 2);
if( !zMasterJournal ){
rc = SQLITE_NOMEM_BKPT;
goto delmaster_out;
}
- zMasterPtr = &zMasterJournal[nMasterJournal+1];
+ zMasterPtr = &zMasterJournal[nMasterJournal+2];
rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0);
if( rc!=SQLITE_OK ) goto delmaster_out;
zMasterJournal[nMasterJournal] = 0;
+ zMasterJournal[nMasterJournal+1] = 0;
zJournal = zMasterJournal;
while( (zJournal-zMasterJournal)<nMasterJournal ){
@@ -55555,7 +56156,8 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */
u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */
const char *zUri = 0; /* URI args to copy */
- int nUri = 0; /* Number of bytes of URI args at *zUri */
+ int nUriByte = 1; /* Number of bytes of URI args at *zUri */
+ int nUri = 0; /* Number of URI parameters */
/* Figure out how much space is required for each journal file-handle
** (there are two of them, the main journal and the sub-journal). */
@@ -55589,14 +56191,24 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
}
zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_OK_SYMLINK ){
+ if( vfsFlags & SQLITE_OPEN_NOFOLLOW ){
+ rc = SQLITE_CANTOPEN_SYMLINK;
+ }else{
+ rc = SQLITE_OK;
+ }
+ }
+ }
nPathname = sqlite3Strlen30(zPathname);
z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
while( *z ){
- z += sqlite3Strlen30(z)+1;
- z += sqlite3Strlen30(z)+1;
+ z += strlen(z)+1;
+ z += strlen(z)+1;
+ nUri++;
}
- nUri = (int)(&z[1] - zUri);
- assert( nUri>=0 );
+ nUriByte = (int)(&z[1] - zUri);
+ assert( nUriByte>=1 );
if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
/* This branch is taken when the journal path required by
** the database being opened will be more than pVfs->mxPathname
@@ -55621,50 +56233,103 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
** Database file handle (pVfs->szOsFile bytes)
** Sub-journal file handle (journalFileSize bytes)
** Main journal file handle (journalFileSize bytes)
+ ** \0\0\0\0 database prefix (4 bytes)
** Database file name (nPathname+1 bytes)
- ** Journal file name (nPathname+8+1 bytes)
+ ** URI query parameters (nUriByte bytes)
+ ** Journal filename (nPathname+8+1 bytes)
+ ** WAL filename (nPathname+4+1 bytes)
+ ** \0\0\0 terminator (3 bytes)
+ **
+ ** Some 3rd-party software, over which we have no control, depends on
+ ** the specific order of the filenames and the \0 separators between them
+ ** so that it can (for example) find the database filename given the WAL
+ ** filename without using the sqlite3_filename_database() API. This is a
+ ** misuse of SQLite and a bug in the 3rd-party software, but the 3rd-party
+ ** software is in widespread use, so we try to avoid changing the filename
+ ** order and formatting if possible. In particular, the details of the
+ ** filename format expected by 3rd-party software should be as follows:
+ **
+ ** - Main Database Path
+ ** - \0
+ ** - Multiple URI components consisting of:
+ ** - Key
+ ** - \0
+ ** - Value
+ ** - \0
+ ** - \0
+ ** - Journal Path
+ ** - \0
+ ** - WAL Path (zWALName)
+ ** - \0
*/
pPtr = (u8 *)sqlite3MallocZero(
- ROUND8(sizeof(*pPager)) + /* Pager structure */
- ROUND8(pcacheSize) + /* PCache object */
- ROUND8(pVfs->szOsFile) + /* The main db file */
- journalFileSize * 2 + /* The two journal files */
- nPathname + 1 + nUri + /* zFilename */
- nPathname + 8 + 2 /* zJournal */
+ ROUND8(sizeof(*pPager)) + /* Pager structure */
+ ROUND8(pcacheSize) + /* PCache object */
+ ROUND8(pVfs->szOsFile) + /* The main db file */
+ journalFileSize * 2 + /* The two journal files */
+ 4 + /* Database prefix */
+ nPathname + 1 + /* database filename */
+ nUriByte + /* query parameters */
+ nPathname + 8 + 1 + /* Journal filename */
#ifndef SQLITE_OMIT_WAL
- + nPathname + 4 + 2 /* zWal */
+ nPathname + 4 + 1 + /* WAL filename */
#endif
+ 3 /* Terminator */
);
assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
if( !pPtr ){
sqlite3DbFree(0, zPathname);
return SQLITE_NOMEM_BKPT;
}
- pPager = (Pager*)(pPtr);
- pPager->pPCache = (PCache*)(pPtr += ROUND8(sizeof(*pPager)));
- pPager->fd = (sqlite3_file*)(pPtr += ROUND8(pcacheSize));
- pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile));
- pPager->jfd = (sqlite3_file*)(pPtr += journalFileSize);
- pPager->zFilename = (char*)(pPtr += journalFileSize);
+ pPager = (Pager*)pPtr; pPtr += ROUND8(sizeof(*pPager));
+ pPager->pPCache = (PCache*)pPtr; pPtr += ROUND8(pcacheSize);
+ pPager->fd = (sqlite3_file*)pPtr; pPtr += ROUND8(pVfs->szOsFile);
+ pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
+ pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
- /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
- if( zPathname ){
- assert( nPathname>0 );
- pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri);
- memcpy(pPager->zFilename, zPathname, nPathname);
- if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
- memcpy(pPager->zJournal, zPathname, nPathname);
- memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2);
- sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
+ /* Fill in the Pager.zFilename and pPager.zQueryParam fields */
+ pPtr += 4; /* Skip zero prefix */
+ pPager->zFilename = (char*)pPtr;
+ if( nPathname>0 ){
+ memcpy(pPtr, zPathname, nPathname); pPtr += nPathname + 1;
+ if( zUri ){
+ memcpy(pPtr, zUri, nUriByte); pPtr += nUriByte;
+ }else{
+ pPtr++;
+ }
+ }
+
+
+ /* Fill in Pager.zJournal */
+ if( nPathname>0 ){
+ pPager->zJournal = (char*)pPtr;
+ memcpy(pPtr, zPathname, nPathname); pPtr += nPathname;
+ memcpy(pPtr, "-journal",8); pPtr += 8 + 1;
+#ifdef SQLITE_ENABLE_8_3_NAMES
+ sqlite3FileSuffix3(zFilename,pPager->zJournal);
+ pPtr = (u8*)(pPager->zJournal + sqlite3Strlen30(pPager->zJournal)+1);
+#endif
+ }else{
+ pPager->zJournal = 0;
+ }
+
#ifndef SQLITE_OMIT_WAL
- pPager->zWal = &pPager->zJournal[nPathname+8+1];
- memcpy(pPager->zWal, zPathname, nPathname);
- memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1);
- sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
+ /* Fill in Pager.zWal */
+ if( nPathname>0 ){
+ pPager->zWal = (char*)pPtr;
+ memcpy(pPtr, zPathname, nPathname); pPtr += nPathname;
+ memcpy(pPtr, "-wal", 4); pPtr += 4 + 1;
+#ifdef SQLITE_ENABLE_8_3_NAMES
+ sqlite3FileSuffix3(zFilename, pPager->zWal);
+ pPtr = (u8*)(pPager->zWal + sqlite3Strlen30(pPager->zWal)+1);
#endif
- sqlite3DbFree(0, zPathname);
+ }else{
+ pPager->zWal = 0;
}
+#endif
+
+ if( nPathname ) sqlite3DbFree(0, zPathname);
pPager->pVfs = pVfs;
pPager->vfsFlags = vfsFlags;
@@ -55713,9 +56378,9 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
}
#endif
}
- pPager->noLock = sqlite3_uri_boolean(zFilename, "nolock", 0);
+ pPager->noLock = sqlite3_uri_boolean(pPager->zFilename, "nolock", 0);
if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0
- || sqlite3_uri_boolean(zFilename, "immutable", 0) ){
+ || sqlite3_uri_boolean(pPager->zFilename, "immutable", 0) ){
vfsFlags |= SQLITE_OPEN_READONLY;
goto act_like_temp_file;
}
@@ -57406,6 +58071,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
** But if (due to a coding error elsewhere in the system) it does get
** called, just return the same error code without doing anything. */
if( NEVER(pPager->errCode) ) return pPager->errCode;
+ pPager->iDataVersion++;
assert( pPager->eState==PAGER_WRITER_LOCKED
|| pPager->eState==PAGER_WRITER_FINISHED
@@ -57434,7 +58100,6 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
}
PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
- pPager->iDataVersion++;
rc = pager_end_transaction(pPager, pPager->setMaster, 1);
return pager_error(pPager, rc);
}
@@ -57778,9 +58443,13 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
** behavior. But when the Btree needs to know the filename for matching to
** shared cache, it uses nullIfMemDb==0 so that in-memory databases can
** participate in shared-cache.
+**
+** The return value to this routine is always safe to use with
+** sqlite3_uri_parameter() and sqlite3_filename_database() and friends.
*/
-SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
- return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
+SQLITE_PRIVATE const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){
+ static const char zFake[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ return (nullIfMemDb && pPager->memDb) ? &zFake[4] : pPager->zFilename;
}
/*
@@ -58435,6 +59104,8 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
return rc;
}
+
+
#ifdef SQLITE_ENABLE_SNAPSHOT
/*
** If this is a WAL database, obtain a snapshot handle for the snapshot
@@ -60355,7 +61026,19 @@ static int walCheckpoint(
** not decreasing it. So assuming either that either the "old" or
** "new" version of the value is read, and not some arbitrary value
** that would never be written by a real client, things are still
- ** safe. */
+ ** safe.
+ **
+ ** Astute readers have pointed out that the assumption stated in the
+ ** last sentence of the previous paragraph is not guaranteed to be
+ ** true for all conforming systems. However, the assumption is true
+ ** for all compilers and architectures in common use today (circa
+ ** 2019-11-27) and the alternatives are both slow and complex, and
+ ** so we will continue to go with the current design for now. If this
+ ** bothers you, or if you really are running on a system where aligned
+ ** 32-bit reads and writes are not atomic, then you can simply avoid
+ ** the use of WAL mode, or only use WAL mode together with
+ ** PRAGMA locking_mode=EXCLUSIVE and all will be well.
+ */
u32 y = pInfo->aReadMark[i];
if( mxSafeFrame>y ){
assert( y<=pWal->hdr.mxFrame );
@@ -60433,6 +61116,10 @@ static int walCheckpoint(
}
}
if( rc==SQLITE_OK ){
+ rc = sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0);
+ if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
+ }
+ if( rc==SQLITE_OK ){
pInfo->nBackfill = mxSafeFrame;
}
}
@@ -62942,6 +63629,7 @@ struct BtCursor {
#define BTCF_AtLast 0x08 /* Cursor is pointing ot the last entry */
#define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */
#define BTCF_Multiple 0x20 /* Maybe another cursor on the same btree */
+#define BTCF_Pinned 0x40 /* Cursor is busy and cannot be moved */
/*
** Potential values for BtCursor.eState.
@@ -63085,6 +63773,7 @@ struct IntegrityCk {
int v1, v2; /* Values for up to two %d fields in zPfx */
StrAccum errMsg; /* Accumulate the error message text here */
u32 *heap; /* Min-heap used for analyzing cell coverage */
+ sqlite3 *db; /* Database connection running the check */
};
/*
@@ -64106,6 +64795,9 @@ static int saveCursorPosition(BtCursor *pCur){
assert( 0==pCur->pKey );
assert( cursorHoldsMutex(pCur) );
+ if( pCur->curFlags & BTCF_Pinned ){
+ return SQLITE_CONSTRAINT_PINNED;
+ }
if( pCur->eState==CURSOR_SKIPNEXT ){
pCur->eState = CURSOR_VALID;
}else{
@@ -64853,7 +65545,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
int sz2 = 0;
int sz = get2byte(&data[iFree+2]);
int top = get2byte(&data[hdr+5]);
- if( top>=iFree ){
+ if( NEVER(top>=iFree) ){
return SQLITE_CORRUPT_PAGE(pPage);
}
if( iFree2 ){
@@ -64862,7 +65554,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
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 ){
+ }else if( NEVER(iFree+sz>usableSize) ){
return SQLITE_CORRUPT_PAGE(pPage);
}
@@ -65054,8 +65746,10 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){
u8 *pSpace = pageFindSlot(pPage, nByte, &rc);
if( pSpace ){
+ int g2;
assert( pSpace+nByte<=data+pPage->pBt->usableSize );
- if( (*pIdx = (int)(pSpace-data))<=gap ){
+ *pIdx = g2 = (int)(pSpace-data);
+ if( NEVER(g2<=gap) ){
return SQLITE_CORRUPT_PAGE(pPage);
}else{
return SQLITE_OK;
@@ -65133,12 +65827,12 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
}else{
while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){
if( iFreeBlk<iPtr+4 ){
- if( iFreeBlk==0 ) break;
+ if( iFreeBlk==0 ) break; /* TH3: corrupt082.100 */
return SQLITE_CORRUPT_PAGE(pPage);
}
iPtr = iFreeBlk;
}
- if( iFreeBlk>pPage->pBt->usableSize-4 ){
+ if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */
return SQLITE_CORRUPT_PAGE(pPage);
}
assert( iFreeBlk>iPtr || iFreeBlk==0 );
@@ -65153,7 +65847,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
nFrag = iFreeBlk - iEnd;
if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage);
iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]);
- if( iEnd > pPage->pBt->usableSize ){
+ if( NEVER(iEnd > pPage->pBt->usableSize) ){
return SQLITE_CORRUPT_PAGE(pPage);
}
iSize = iEnd - iStart;
@@ -65181,7 +65875,8 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
/* The new freeblock is at the beginning of the cell content area,
** so just extend the cell content area rather than create another
** freelist entry */
- if( iStart<x || iPtr!=hdr+1 ) return SQLITE_CORRUPT_PAGE(pPage);
+ if( iStart<x ) return SQLITE_CORRUPT_PAGE(pPage);
+ if( NEVER(iPtr!=hdr+1) ) return SQLITE_CORRUPT_PAGE(pPage);
put2byte(&data[hdr+1], iFreeBlk);
put2byte(&data[hdr+5], iEnd);
}else{
@@ -65301,7 +65996,7 @@ static int btreeComputeFreeSpace(MemPage *pPage){
nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */
if( pc>0 ){
u32 next, size;
- if( pc<iCellFirst ){
+ if( pc<top ){
/* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will
** always be at least one cell before the first freeblock.
*/
@@ -65538,12 +66233,12 @@ static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){
** error, return ((unsigned int)-1).
*/
static Pgno btreePagecount(BtShared *pBt){
+ assert( (pBt->nPage & 0x80000000)==0 || CORRUPT_DB );
return pBt->nPage;
}
SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){
assert( sqlite3BtreeHoldsMutex(p) );
- assert( ((p->pBt->nPage)&0x80000000)==0 );
- return btreePagecount(p->pBt);
+ return btreePagecount(p->pBt) & 0x7fffffff;
}
/*
@@ -65810,9 +66505,13 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
rc = sqlite3OsFullPathname(pVfs, zFilename,
nFullPathname, zFullPathname);
if( rc ){
- sqlite3_free(zFullPathname);
- sqlite3_free(p);
- return rc;
+ if( rc==SQLITE_OK_SYMLINK ){
+ rc = SQLITE_OK;
+ }else{
+ sqlite3_free(zFullPathname);
+ sqlite3_free(p);
+ return rc;
+ }
}
}
#if SQLITE_THREADSAFE
@@ -67772,8 +68471,9 @@ static int btreeCursor(
/* The following assert statements verify that if this is a sharable
** b-tree database, the connection is holding the required table locks,
** and that no other connection has any open cursor that conflicts with
- ** this lock. */
- assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1)) );
+ ** this lock. The iTable<1 term disables the check for corrupt schemas. */
+ assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1))
+ || iTable<1 );
assert( wrFlag==0 || !hasReadConflicts(p, iTable) );
/* Assert that the caller has opened the required transaction. */
@@ -67786,9 +68486,13 @@ static int btreeCursor(
allocateTempSpace(pBt);
if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT;
}
- if( iTable==1 && btreePagecount(pBt)==0 ){
- assert( wrFlag==0 );
- iTable = 0;
+ if( iTable<=1 ){
+ if( iTable<1 ){
+ return SQLITE_CORRUPT_BKPT;
+ }else if( btreePagecount(pBt)==0 ){
+ assert( wrFlag==0 );
+ iTable = 0;
+ }
}
/* Now that no other errors can occur, finish filling in the BtCursor
@@ -67813,6 +68517,19 @@ static int btreeCursor(
pCur->eState = CURSOR_INVALID;
return SQLITE_OK;
}
+static int btreeCursorWithLock(
+ Btree *p, /* The btree */
+ int iTable, /* Root page of table to open */
+ int wrFlag, /* 1 to write. 0 read-only */
+ struct KeyInfo *pKeyInfo, /* First arg to comparison function */
+ BtCursor *pCur /* Space for new cursor */
+){
+ int rc;
+ sqlite3BtreeEnter(p);
+ rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
+ sqlite3BtreeLeave(p);
+ return rc;
+}
SQLITE_PRIVATE int sqlite3BtreeCursor(
Btree *p, /* The btree */
int iTable, /* Root page of table to open */
@@ -67820,15 +68537,11 @@ SQLITE_PRIVATE int sqlite3BtreeCursor(
struct KeyInfo *pKeyInfo, /* First arg to xCompare() */
BtCursor *pCur /* Write new cursor here */
){
- int rc;
- if( iTable<1 ){
- rc = SQLITE_CORRUPT_BKPT;
+ if( p->sharable ){
+ return btreeCursorWithLock(p, iTable, wrFlag, pKeyInfo, pCur);
}else{
- sqlite3BtreeEnter(p);
- rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
- sqlite3BtreeLeave(p);
+ return btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
}
- return rc;
}
/*
@@ -67951,6 +68664,18 @@ SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor *pCur){
return pCur->info.nKey;
}
+/*
+** Pin or unpin a cursor.
+*/
+SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor *pCur){
+ assert( (pCur->curFlags & BTCF_Pinned)==0 );
+ pCur->curFlags |= BTCF_Pinned;
+}
+SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor *pCur){
+ assert( (pCur->curFlags & BTCF_Pinned)!=0 );
+ pCur->curFlags &= ~BTCF_Pinned;
+}
+
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
/*
** Return the offset into the database file for the start of the
@@ -69107,8 +69832,11 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
** to be invalid here. This can only occur if a second cursor modifies
** the page while cursor pCur is holding a reference to it. Which can
** only happen if the database is corrupt in such a way as to link the
- ** page into more than one b-tree structure. */
- testcase( idx>pPage->nCell );
+ ** page into more than one b-tree structure.
+ **
+ ** Update 2019-12-23: appears to long longer be possible after the
+ ** addition of anotherValidCursor() condition on balance_deeper(). */
+ harmless( idx>pPage->nCell );
if( idx>=pPage->nCell ){
if( !pPage->leaf ){
@@ -70307,7 +71035,7 @@ static int rebuildPage(
assert( i<iEnd );
j = get2byte(&aData[hdr+5]);
- if( j>(u32)usableSize ){ j = 0; }
+ if( NEVER(j>(u32)usableSize) ){ j = 0; }
memcpy(&pTmp[j], &aData[j], usableSize - j);
for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
@@ -70333,7 +71061,7 @@ static int rebuildPage(
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) );
+ testcase( sz!=pPg->xCellSize(pPg,pCell) )
i++;
if( i>=iEnd ) break;
if( pCArray->ixNx[k]<=i ){
@@ -71698,6 +72426,30 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
}
/*
+** Return SQLITE_CORRUPT if any cursor other than pCur is currently valid
+** on the same B-tree as pCur.
+**
+** This can if a database is corrupt with two or more SQL tables
+** pointing to the same b-tree. If an insert occurs on one SQL table
+** and causes a BEFORE TRIGGER to do a secondary insert on the other SQL
+** table linked to the same b-tree. If the secondary insert causes a
+** rebalance, that can change content out from under the cursor on the
+** first SQL table, violating invariants on the first insert.
+*/
+static int anotherValidCursor(BtCursor *pCur){
+ BtCursor *pOther;
+ for(pOther=pCur->pBt->pCursor; pOther; pOther=pOther->pNext){
+ if( pOther!=pCur
+ && pOther->eState==CURSOR_VALID
+ && pOther->pPage==pCur->pPage
+ ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ }
+ return SQLITE_OK;
+}
+
+/*
** The page that pCur currently points to has just been modified in
** some way. This function figures out if this modification means the
** tree needs to be balanced, and if so calls the appropriate balancing
@@ -71724,7 +72476,7 @@ static int balance(BtCursor *pCur){
if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
break;
}else if( (iPage = pCur->iPage)==0 ){
- if( pPage->nOverflow ){
+ if( pPage->nOverflow && (rc = anotherValidCursor(pCur))==SQLITE_OK ){
/* The root page of the b-tree is overfull. In this case call the
** balance_deeper() function to create a new child for the root-page
** and copy the current contents of the root-page to it. The
@@ -72020,7 +72772,6 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
if( flags & BTREE_SAVEPOSITION ){
assert( pCur->curFlags & BTCF_ValidNKey );
assert( pX->nKey==pCur->info.nKey );
- assert( pCur->info.nSize!=0 );
assert( loc==0 );
}
#endif
@@ -72095,7 +72846,9 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
}
}
- assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
+ assert( pCur->eState==CURSOR_VALID
+ || (pCur->eState==CURSOR_INVALID && loc)
+ || CORRUPT_DB );
pPage = pCur->pPage;
assert( pPage->intKey || pX->nKey>=0 );
@@ -72866,7 +73619,7 @@ SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
** Otherwise, if an error is encountered (i.e. an IO error or database
** corruption) an SQLite error code is returned.
*/
-SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
+SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3 *db, BtCursor *pCur, i64 *pnEntry){
i64 nEntry = 0; /* Value to return in *pnEntry */
int rc; /* Return code */
@@ -72879,7 +73632,7 @@ SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
/* Unless an error occurs, the following loop runs one iteration for each
** page in the B-Tree structure (not including overflow pages).
*/
- while( rc==SQLITE_OK ){
+ while( rc==SQLITE_OK && !db->u1.isInterrupted ){
int iIdx; /* Index of child node in parent */
MemPage *pPage; /* Current page of the b-tree */
@@ -73005,6 +73758,7 @@ static int checkRef(IntegrityCk *pCheck, Pgno iPage){
checkAppendMsg(pCheck, "2nd reference to page %d", iPage);
return 1;
}
+ if( pCheck->db->u1.isInterrupted ) return 1;
setPageReferenced(pCheck, iPage);
return 0;
}
@@ -73448,6 +74202,7 @@ end_of_check:
** returned. If a memory allocation error occurs, NULL is returned.
*/
SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
+ sqlite3 *db, /* Database connection that is running the check */
Btree *p, /* The btree to be checked */
int *aRoot, /* An array of root pages numbers for individual trees */
int nRoot, /* Number of entries in aRoot[] */
@@ -73465,6 +74220,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) );
assert( nRef>=0 );
+ sCheck.db = db;
sCheck.pBt = pBt;
sCheck.pPager = pBt->pPager;
sCheck.nPage = btreePagecount(sCheck.pBt);
@@ -75131,15 +75887,11 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){
sqlite3_context ctx;
- Mem t;
assert( pFunc!=0 );
assert( pFunc->xValue!=0 );
assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef );
assert( pAccum->db==0 || sqlite3_mutex_held(pAccum->db->mutex) );
memset(&ctx, 0, sizeof(ctx));
- memset(&t, 0, sizeof(t));
- t.flags = MEM_Null;
- t.db = pAccum->db;
sqlite3VdbeMemSetNull(pOut);
ctx.pOut = pOut;
ctx.pMem = pAccum;
@@ -75265,8 +76017,7 @@ SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){
return pMem->u.i;
}else if( flags & MEM_Real ){
return doubleToInt64(pMem->u.r);
- }else if( flags & (MEM_Str|MEM_Blob) ){
- assert( pMem->z || pMem->n==0 );
+ }else if( (flags & (MEM_Str|MEM_Blob))!=0 && pMem->z!=0 ){
return memIntValue(pMem);
}else{
return 0;
@@ -75423,8 +76174,8 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
** affinity even if that results in loss of data. This routine is
** used (for example) to implement the SQL "cast()" operator.
*/
-SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
- if( pMem->flags & MEM_Null ) return;
+SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
+ if( pMem->flags & MEM_Null ) return SQLITE_OK;
switch( aff ){
case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
if( (pMem->flags & MEM_Blob)==0 ){
@@ -75455,9 +76206,10 @@ SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal|MEM_Blob|MEM_Zero);
- break;
+ return sqlite3VdbeChangeEncoding(pMem, encoding);
}
}
+ return SQLITE_OK;
}
/*
@@ -75623,23 +76375,30 @@ SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){
** its link to a shallow copy and by marking any current shallow
** copies of this cell as invalid.
**
-** This is used for testing and debugging only - to make sure shallow
-** copies are not misused.
+** This is used for testing and debugging only - to help ensure that shallow
+** copies (created by OP_SCopy) are not misused.
*/
SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
int i;
Mem *pX;
- for(i=0, pX=pVdbe->aMem; i<pVdbe->nMem; i++, pX++){
+ for(i=1, pX=pVdbe->aMem+1; i<pVdbe->nMem; i++, pX++){
if( pX->pScopyFrom==pMem ){
+ u16 mFlags;
+ if( pVdbe->db->flags & SQLITE_VdbeTrace ){
+ sqlite3DebugPrintf("Invalidate R[%d] due to change in R[%d]\n",
+ (int)(pX - pVdbe->aMem), (int)(pMem - pVdbe->aMem));
+ }
/* If pX is marked as a shallow copy of pMem, then verify that
** no significant changes have been made to pX since the OP_SCopy.
** A significant change would indicated a missed call to this
** function for pX. Minor changes, such as adding or removing a
** dual type, are allowed, as long as the underlying value is the
** same. */
- u16 mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
+ mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
assert( (mFlags&(MEM_Int|MEM_IntReal))==0 || pMem->u.i==pX->u.i );
- assert( (mFlags&MEM_Real)==0 || pMem->u.r==pX->u.r );
+ /* assert( (mFlags&MEM_Real)==0 || pMem->u.r==pX->u.r ); */
+ /* ^^ */
+ /* Cannot reliably compare doubles for equality */
assert( (mFlags&MEM_Str)==0 || (pMem->n==pX->n && pMem->z==pX->z) );
assert( (mFlags&MEM_Blob)==0 || sqlite3BlobCompare(pMem,pX)==0 );
@@ -75653,7 +76412,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
}
#endif /* SQLITE_DEBUG */
-
/*
** Make an shallow copy of pFrom into pTo. Prior contents of
** pTo are freed. The pFrom->z field is not duplicated. If
@@ -75799,10 +76557,19 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
pMem->n = nByte;
pMem->flags = flags;
- pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
+ if( enc ){
+ pMem->enc = enc;
+#ifdef SQLITE_ENABLE_SESSION
+ }else if( pMem->db==0 ){
+ pMem->enc = SQLITE_UTF8;
+#endif
+ }else{
+ assert( pMem->db!=0 );
+ pMem->enc = ENC(pMem->db);
+ }
#ifndef SQLITE_OMIT_UTF16
- if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
+ if( enc>SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
return SQLITE_NOMEM_BKPT;
}
#endif
@@ -76219,7 +76986,11 @@ static int valueFromExpr(
if( pVal->flags & MEM_Real ){
pVal->u.r = -pVal->u.r;
}else if( pVal->u.i==SMALLEST_INT64 ){
+#ifndef SQLITE_OMIT_FLOATING_POINT
pVal->u.r = -(double)SMALLEST_INT64;
+#else
+ pVal->u.r = LARGEST_INT64;
+#endif
MemSetTypeFlag(pVal, MEM_Real);
}else{
pVal->u.i = -pVal->u.i;
@@ -76578,6 +77349,10 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
/* #include "sqliteInt.h" */
/* #include "vdbeInt.h" */
+/* Forward references */
+static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef);
+static void vdbeFreeOpArray(sqlite3 *, Op *, int);
+
/*
** Create a new virtual database engine.
*/
@@ -76606,6 +77381,13 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){
}
/*
+** Return the Parse object that owns a Vdbe object.
+*/
+SQLITE_PRIVATE Parse *sqlite3VdbeParser(Vdbe *p){
+ return p->pParse;
+}
+
+/*
** Change the error string stored in Vdbe.zErrMsg
*/
SQLITE_PRIVATE void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){
@@ -76685,7 +77467,7 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
zTmp = pA->zSql;
pA->zSql = pB->zSql;
pB->zSql = zTmp;
-#if 0
+#ifdef SQLITE_ENABLE_NORMALIZE
zTmp = pA->zNormSql;
pA->zNormSql = pB->zNormSql;
pB->zNormSql = zTmp;
@@ -76746,9 +77528,16 @@ static int growOpArray(Vdbe *v, int nOp){
#ifdef SQLITE_DEBUG
/* This routine is just a convenient place to set a breakpoint that will
** fire after each opcode is inserted and displayed using
-** "PRAGMA vdbe_addoptrace=on".
+** "PRAGMA vdbe_addoptrace=on". Parameters "pc" (program counter) and
+** pOp are available to make the breakpoint conditional.
+**
+** Other useful labels for breakpoints include:
+** test_trace_breakpoint(pc,pOp)
+** sqlite3CorruptError(lineno)
+** sqlite3MisuseError(lineno)
+** sqlite3CantopenError(lineno)
*/
-static void test_addop_breakpoint(void){
+static void test_addop_breakpoint(int pc, Op *pOp){
static int n = 0;
n++;
}
@@ -76801,7 +77590,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
#ifdef SQLITE_DEBUG
if( p->db->flags & SQLITE_VdbeAddopTrace ){
sqlite3VdbePrintOp(0, i, &p->aOp[i]);
- test_addop_breakpoint();
+ test_addop_breakpoint(i, &p->aOp[i]);
}
#endif
#ifdef VDBE_PROFILE
@@ -76885,6 +77674,49 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4(
}
/*
+** Add an OP_Function or OP_PureFunc opcode.
+**
+** The eCallCtx argument is information (typically taken from Expr.op2)
+** that describes the calling context of the function. 0 means a general
+** function call. NC_IsCheck means called by a check constraint,
+** NC_IdxExpr means called as part of an index expression. NC_PartIdx
+** means in the WHERE clause of a partial index. NC_GenCol means called
+** while computing a generated column value. 0 is the usual case.
+*/
+SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall(
+ Parse *pParse, /* Parsing context */
+ int p1, /* Constant argument mask */
+ int p2, /* First argument register */
+ int p3, /* Register into which results are written */
+ int nArg, /* Number of argument */
+ const FuncDef *pFunc, /* The function to be invoked */
+ int eCallCtx /* Calling context */
+){
+ Vdbe *v = pParse->pVdbe;
+ int nByte;
+ int addr;
+ sqlite3_context *pCtx;
+ assert( v );
+ nByte = sizeof(*pCtx) + (nArg-1)*sizeof(sqlite3_value*);
+ pCtx = sqlite3DbMallocRawNN(pParse->db, nByte);
+ if( pCtx==0 ){
+ assert( pParse->db->mallocFailed );
+ freeEphemeralFunction(pParse->db, (FuncDef*)pFunc);
+ return 0;
+ }
+ pCtx->pOut = 0;
+ pCtx->pFunc = (FuncDef*)pFunc;
+ pCtx->pVdbe = 0;
+ pCtx->isError = 0;
+ pCtx->argc = nArg;
+ pCtx->iOp = sqlite3VdbeCurrentAddr(v);
+ addr = sqlite3VdbeAddOp4(v, eCallCtx ? OP_PureFunc : OP_Function,
+ p1, p2, p3, (char*)pCtx, P4_FUNCCTX);
+ sqlite3VdbeChangeP5(v, eCallCtx & NC_SelfRef);
+ return addr;
+}
+
+/*
** Add an opcode that includes the p4 value with a P4_INT64 or
** P4_REAL type.
*/
@@ -77176,6 +78008,7 @@ static Op *opIterNext(VdbeOpIter *p){
** * OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
** * OP_Destroy
** * OP_VUpdate
+** * OP_VCreate
** * OP_VRename
** * OP_FkCounter with P2==0 (immediate foreign key constraint)
** * OP_CreateBtree/BTREE_INTKEY and OP_InitCoroutine
@@ -77203,6 +78036,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
int opcode = pOp->opcode;
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
|| opcode==OP_VDestroy
+ || opcode==OP_VCreate
|| (opcode==OP_ParseSchema && pOp->p4.z==0)
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
&& ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
@@ -77576,8 +78410,6 @@ static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
}
}
-static void vdbeFreeOpArray(sqlite3 *, Op *, int);
-
/*
** Delete a P4 value if necessary.
*/
@@ -77587,7 +78419,7 @@ static SQLITE_NOINLINE void freeP4Mem(sqlite3 *db, Mem *p){
}
static SQLITE_NOINLINE void freeP4FuncCtx(sqlite3 *db, sqlite3_context *p){
freeEphemeralFunction(db, p->pFunc);
- sqlite3DbFreeNN(db, p);
+ sqlite3DbFreeNN(db, p);
}
static void freeP4(sqlite3 *db, int p4type, void *p4){
assert( db );
@@ -77662,6 +78494,13 @@ SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
}
/*
+** Return true if the given Vdbe has any SubPrograms.
+*/
+SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe *pVdbe){
+ return pVdbe->pProgram!=0;
+}
+
+/*
** Change the opcode at addr into OP_Noop
*/
SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
@@ -77688,6 +78527,41 @@ SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
}
}
+#ifdef SQLITE_DEBUG
+/*
+** Generate an OP_ReleaseReg opcode to indicate that a range of
+** registers, except any identified by mask, are no longer in use.
+*/
+SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters(
+ Parse *pParse, /* Parsing context */
+ int iFirst, /* Index of first register to be released */
+ int N, /* Number of registers to release */
+ u32 mask, /* Mask of registers to NOT release */
+ int bUndefine /* If true, mark registers as undefined */
+){
+ if( N==0 ) return;
+ assert( pParse->pVdbe );
+ assert( iFirst>=1 );
+ assert( iFirst+N-1<=pParse->nMem );
+ if( N<=31 && mask!=0 ){
+ while( N>0 && (mask&1)!=0 ){
+ mask >>= 1;
+ iFirst++;
+ N--;
+ }
+ while( N>0 && N<=32 && (mask & MASKBIT32(N-1))!=0 ){
+ mask &= ~MASKBIT32(N-1);
+ N--;
+ }
+ }
+ if( N>0 ){
+ sqlite3VdbeAddOp3(pParse->pVdbe, OP_ReleaseReg, iFirst, N, *(int*)&mask);
+ if( bUndefine ) sqlite3VdbeChangeP5(pParse->pVdbe, 1);
+ }
+}
+#endif /* SQLITE_DEBUG */
+
+
/*
** Change the value of the P4 operand for a specific instruction.
** This routine is useful when a large program is loaded from a
@@ -77805,7 +78679,8 @@ SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){
*/
static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){
assert( p->nOp>0 || p->aOp==0 );
- assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );
+ assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed
+ || p->pParse->nErr>0 );
if( p->nOp ){
assert( p->aOp );
sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment);
@@ -78086,13 +78961,11 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
break;
}
-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
case P4_FUNCCTX: {
FuncDef *pDef = pOp->p4.pCtx->pFunc;
sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
break;
}
-#endif
case P4_INT64: {
sqlite3_str_appendf(&x, "%lld", *pOp->p4.pI64);
break;
@@ -78786,8 +79659,26 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
resolveP2Values(p, &nArg);
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
- if( pParse->explain && nMem<10 ){
- nMem = 10;
+ if( pParse->explain ){
+ static const char * const azColName[] = {
+ "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
+ "id", "parent", "notused", "detail"
+ };
+ int iFirst, mx, i;
+ if( nMem<10 ) nMem = 10;
+ if( pParse->explain==2 ){
+ sqlite3VdbeSetNumCols(p, 4);
+ iFirst = 8;
+ mx = 12;
+ }else{
+ sqlite3VdbeSetNumCols(p, 8);
+ iFirst = 0;
+ mx = 8;
+ }
+ for(i=iFirst; i<mx; i++){
+ sqlite3VdbeSetColName(p, i-iFirst, COLNAME_NAME,
+ azColName[i], SQLITE_STATIC);
+ }
}
p->expired = 0;
@@ -79137,7 +80028,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
/* Select a master journal file name */
nMainFile = sqlite3Strlen30(zMainFile);
- zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XXz", zMainFile);
+ zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XXz%c%c", zMainFile, 0, 0);
if( zMaster==0 ) return SQLITE_NOMEM_BKPT;
do {
u32 iRandom;
@@ -79876,7 +80767,7 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
** carried out. Seek the cursor now. If an error occurs, return
** the appropriate error code.
*/
-static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){
+SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor *p){
int res, rc;
#ifdef SQLITE_TEST
extern int sqlite3_search_count;
@@ -79948,7 +80839,7 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){
*piCol = iMap - 1;
return SQLITE_OK;
}
- return handleDeferredMoveto(p);
+ return sqlite3VdbeFinishMoveto(p);
}
if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
return handleMovedCursor(p);
@@ -81488,13 +82379,25 @@ SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
** features such as 'now'.
*/
SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context *pCtx){
+ const VdbeOp *pOp;
#ifdef SQLITE_ENABLE_STAT4
if( pCtx->pVdbe==0 ) return 1;
#endif
- if( pCtx->pVdbe->aOp[pCtx->iOp].opcode==OP_PureFunc ){
- sqlite3_result_error(pCtx,
- "non-deterministic function in index expression or CHECK constraint",
- -1);
+ pOp = pCtx->pVdbe->aOp + pCtx->iOp;
+ if( pOp->opcode==OP_PureFunc ){
+ const char *zContext;
+ char *zMsg;
+ if( pOp->p5 & NC_IsCheck ){
+ zContext = "a CHECK constraint";
+ }else if( pOp->p5 & NC_GenCol ){
+ zContext = "a generated column";
+ }else{
+ zContext = "an index";
+ }
+ zMsg = sqlite3_mprintf("non-deterministic use of %s() in %s",
+ pCtx->pFunc->zName, zContext);
+ sqlite3_result_error(pCtx, zMsg, -1);
+ sqlite3_free(zMsg);
return 0;
}
return 1;
@@ -83441,7 +84344,7 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
goto preupdate_old_out;
}
if( p->pPk ){
- iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
+ iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
}
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
@@ -83531,7 +84434,7 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
goto preupdate_new_out;
}
if( p->pPk && p->op!=SQLITE_UPDATE ){
- iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
+ iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
}
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
@@ -83979,6 +84882,26 @@ SQLITE_API int sqlite3_found_count = 0;
# define UPDATE_MAX_BLOBSIZE(P)
#endif
+#ifdef SQLITE_DEBUG
+/* This routine provides a convenient place to set a breakpoint during
+** tracing with PRAGMA vdbe_trace=on. The breakpoint fires right after
+** each opcode is printed. Variables "pc" (program counter) and pOp are
+** available to add conditionals to the breakpoint. GDB example:
+**
+** break test_trace_breakpoint if pc=22
+**
+** Other useful labels for breakpoints include:
+** test_addop_breakpoint(pc,pOp)
+** sqlite3CorruptError(lineno)
+** sqlite3MisuseError(lineno)
+** sqlite3CantopenError(lineno)
+*/
+static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){
+ static int n = 0;
+ n++;
+}
+#endif
+
/*
** Invoke the VDBE coverage callback, if that callback is defined. This
** feature is used for test suite validation only and does not appear an
@@ -84323,12 +85246,9 @@ static u16 numericType(Mem *pMem){
** Write a nice string representation of the contents of cell pMem
** into buffer zBuf, length nBuf.
*/
-SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
- char *zCsr = zBuf;
+SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr){
int f = pMem->flags;
-
static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"};
-
if( f&MEM_Blob ){
int i;
char c;
@@ -84344,57 +85264,40 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
}else{
c = 's';
}
- *(zCsr++) = c;
- *(zCsr++) = 'x';
- sqlite3_snprintf(100, zCsr, "%d[", pMem->n);
- zCsr += sqlite3Strlen30(zCsr);
+ sqlite3_str_appendf(pStr, "%cx[", c);
for(i=0; i<25 && i<pMem->n; i++){
- sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF));
- zCsr += sqlite3Strlen30(zCsr);
+ sqlite3_str_appendf(pStr, "%02X", ((int)pMem->z[i] & 0xFF));
}
- *zCsr++ = '|';
+ sqlite3_str_appendf(pStr, "|");
for(i=0; i<25 && i<pMem->n; i++){
char z = pMem->z[i];
- if( z<32 || z>126 ) *zCsr++ = '.';
- else *zCsr++ = z;
+ sqlite3_str_appendchar(pStr, 1, (z<32||z>126)?'.':z);
}
- *(zCsr++) = ']';
+ sqlite3_str_appendf(pStr,"]");
if( f & MEM_Zero ){
- sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero);
- zCsr += sqlite3Strlen30(zCsr);
+ sqlite3_str_appendf(pStr, "+%dz",pMem->u.nZero);
}
- *zCsr = '\0';
}else if( f & MEM_Str ){
- int j, k;
- zBuf[0] = ' ';
+ int j;
+ u8 c;
if( f & MEM_Dyn ){
- zBuf[1] = 'z';
+ c = 'z';
assert( (f & (MEM_Static|MEM_Ephem))==0 );
}else if( f & MEM_Static ){
- zBuf[1] = 't';
+ c = 't';
assert( (f & (MEM_Dyn|MEM_Ephem))==0 );
}else if( f & MEM_Ephem ){
- zBuf[1] = 'e';
+ c = 'e';
assert( (f & (MEM_Static|MEM_Dyn))==0 );
}else{
- zBuf[1] = 's';
+ c = 's';
}
- k = 2;
- sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n);
- k += sqlite3Strlen30(&zBuf[k]);
- zBuf[k++] = '[';
+ sqlite3_str_appendf(pStr, " %c%d[", c, pMem->n);
for(j=0; j<25 && j<pMem->n; j++){
- u8 c = pMem->z[j];
- if( c>=0x20 && c<0x7f ){
- zBuf[k++] = c;
- }else{
- zBuf[k++] = '.';
- }
+ c = pMem->z[j];
+ sqlite3_str_appendchar(pStr, 1, (c>=0x20&&c<=0x7f) ? c : '.');
}
- zBuf[k++] = ']';
- sqlite3_snprintf(100,&zBuf[k], encnames[pMem->enc]);
- k += sqlite3Strlen30(&zBuf[k]);
- zBuf[k++] = 0;
+ sqlite3_str_appendf(pStr, "]%s", encnames[pMem->enc]);
}
}
#endif
@@ -84421,21 +85324,38 @@ static void memTracePrint(Mem *p){
}else if( sqlite3VdbeMemIsRowSet(p) ){
printf(" (rowset)");
}else{
- char zBuf[200];
- sqlite3VdbeMemPrettyPrint(p, zBuf);
- printf(" %s", zBuf);
+ StrAccum acc;
+ char zBuf[1000];
+ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
+ sqlite3VdbeMemPrettyPrint(p, &acc);
+ printf(" %s", sqlite3StrAccumFinish(&acc));
}
if( p->flags & MEM_Subtype ) printf(" subtype=0x%02x", p->eSubtype);
}
static void registerTrace(int iReg, Mem *p){
- printf("REG[%d] = ", iReg);
+ printf("R[%d] = ", iReg);
memTracePrint(p);
+ if( p->pScopyFrom ){
+ printf(" <== R[%d]", (int)(p->pScopyFrom - &p[-iReg]));
+ }
printf("\n");
sqlite3VdbeCheckMemInvariants(p);
}
#endif
#ifdef SQLITE_DEBUG
+/*
+** Show the values of all registers in the virtual machine. Used for
+** interactive debugging.
+*/
+SQLITE_PRIVATE void sqlite3VdbeRegisterDump(Vdbe *v){
+ int i;
+ for(i=1; i<v->nMem; i++) registerTrace(i, v->aMem+i);
+}
+#endif /* SQLITE_DEBUG */
+
+
+#ifdef SQLITE_DEBUG
# define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M)
#else
# define REGISTER_TRACE(R,M)
@@ -84463,7 +85383,7 @@ static void registerTrace(int iReg, Mem *p){
******************************************************************************
**
** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 class CPUs.
+** counters for x86 and x86_64 class CPUs.
*/
#ifndef SQLITE_HWTIME_H
#define SQLITE_HWTIME_H
@@ -84474,8 +85394,9 @@ static void registerTrace(int iReg, Mem *p){
** processor and returns that value. This can be used for high-res
** profiling.
*/
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
+#if !defined(__STRICT_ANSI__) && \
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
#if defined(__GNUC__)
@@ -84496,7 +85417,7 @@ static void registerTrace(int iReg, Mem *p){
#endif
-#elif (defined(__GNUC__) && defined(__x86_64__))
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long val;
@@ -84504,7 +85425,7 @@ static void registerTrace(int iReg, Mem *p){
return val;
}
-#elif (defined(__GNUC__) && defined(__ppc__))
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long long retval;
@@ -84521,14 +85442,13 @@ static void registerTrace(int iReg, Mem *p){
#else
- #error Need implementation of sqlite3Hwtime() for your platform.
-
/*
- ** To compile without implementing sqlite3Hwtime() for your platform,
- ** you can remove the above #error and use the following
- ** stub function. You will lose timing support for many
- ** of the debugging and testing utilities, but it should at
- ** least compile and run.
+ ** asm() is needed for hardware timing support. Without asm(),
+ ** disable the sqlite3Hwtime() routine.
+ **
+ ** sqlite3Hwtime() is only used for some obscure debugging
+ ** and analysis configurations, not in any deliverable, so this
+ ** should not be a great loss.
*/
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
@@ -84689,6 +85609,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeTrace ){
sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp);
+ test_trace_breakpoint((int)(pOp - aOp),pOp,p);
}
#endif
@@ -84796,6 +85717,20 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
** to the current line should be indented for EXPLAIN output.
*/
case OP_Goto: { /* jump */
+
+#ifdef SQLITE_DEBUG
+ /* In debuggging mode, when the p5 flags is set on an OP_Goto, that
+ ** means we should really jump back to the preceeding OP_ReleaseReg
+ ** instruction. */
+ if( pOp->p5 ){
+ assert( pOp->p2 < (int)(pOp - aOp) );
+ assert( pOp->p2 > 1 );
+ pOp = &aOp[pOp->p2 - 2];
+ assert( pOp[1].opcode==OP_ReleaseReg );
+ goto check_for_interrupt;
+ }
+#endif
+
jump_to_p2_and_check_for_interrupt:
pOp = &aOp[pOp->p2 - 1];
@@ -85272,8 +86207,13 @@ case OP_Move: {
memAboutToChange(p, pOut);
sqlite3VdbeMemMove(pOut, pIn1);
#ifdef SQLITE_DEBUG
- if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<pOut ){
- pOut->pScopyFrom += pOp->p2 - p1;
+ pIn1->pScopyFrom = 0;
+ { int i;
+ for(i=1; i<p->nMem; i++){
+ if( aMem[i].pScopyFrom==pIn1 ){
+ aMem[i].pScopyFrom = pOut;
+ }
+ }
}
#endif
Deephemeralize(pOut);
@@ -85414,6 +86354,14 @@ case OP_ResultRow: {
|| (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
sqlite3VdbeMemNulTerminate(&pMem[i]);
REGISTER_TRACE(pOp->p1+i, &pMem[i]);
+#ifdef SQLITE_DEBUG
+ /* The registers in the result will not be used again when the
+ ** prepared statement restarts. This is because sqlite3_column()
+ ** APIs might have caused type conversions of made other changes to
+ ** the register values. Therefore, we can go ahead and break any
+ ** OP_SCopy dependencies. */
+ pMem[i].pScopyFrom = 0;
+#endif
}
if( db->mallocFailed ) goto no_mem;
@@ -85421,6 +86369,7 @@ case OP_ResultRow: {
db->xTrace(SQLITE_TRACE_ROW, db->pTraceArg, p, 0);
}
+
/* Return SQLITE_ROW
*/
p->pc = (int)(pOp - aOp) + 1;
@@ -85817,9 +86766,11 @@ case OP_Cast: { /* in1 */
pIn1 = &aMem[pOp->p1];
memAboutToChange(p, pIn1);
rc = ExpandBlob(pIn1);
- sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
- UPDATE_MAX_BLOBSIZE(pIn1);
if( rc ) goto abort_due_to_error;
+ rc = sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
+ if( rc ) goto abort_due_to_error;
+ UPDATE_MAX_BLOBSIZE(pIn1);
+ REGISTER_TRACE(pOp->p1, pIn1);
break;
}
#endif /* SQLITE_OMIT_CAST */
@@ -85978,12 +86929,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
if( (flags1 | flags3)&MEM_Str ){
if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
applyNumericAffinity(pIn1,0);
- assert( flags3==pIn3->flags );
- /* testcase( flags3!=pIn3->flags );
- ** this used to be possible with pIn1==pIn3, but not since
- ** the column cache was removed. The following assignment
- ** is essentially a no-op. But, it provides defense-in-depth
- ** in case our analysis is incorrect, so it is left in. */
+ testcase( flags3!=pIn3->flags );
flags3 = pIn3->flags;
}
if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
@@ -86006,7 +86952,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
sqlite3VdbeMemStringify(pIn1, encoding, 1);
testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
- assert( pIn1!=pIn3 );
+ if( pIn1==pIn3 ) flags3 = flags1 | MEM_Str;
}
if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
testcase( pIn3->flags & MEM_Int );
@@ -86041,10 +86987,10 @@ compare_op:
}
/* Undo any changes made by applyAffinity() to the input registers. */
- assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
- pIn1->flags = flags1;
assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
pIn3->flags = flags3;
+ assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
+ pIn1->flags = flags1;
if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &aMem[pOp->p2];
@@ -86080,16 +87026,31 @@ compare_op:
/* Opcode: ElseNotEq * P2 * * *
**
-** This opcode must immediately follow an OP_Lt or OP_Gt comparison operator.
-** If result of an OP_Eq comparison on the same two operands
-** would have be NULL or false (0), then then jump to P2.
-** If the result of an OP_Eq comparison on the two previous operands
-** would have been true (1), then fall through.
+** This opcode must follow an OP_Lt or OP_Gt comparison operator. There
+** can be zero or more OP_ReleaseReg opcodes intervening, but no other
+** opcodes are allowed to occur between this instruction and the previous
+** OP_Lt or OP_Gt. 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 */
- assert( pOp>aOp );
- assert( pOp[-1].opcode==OP_Lt || pOp[-1].opcode==OP_Gt );
- assert( pOp[-1].p5 & SQLITE_STOREP2 );
+
+#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;
@@ -86500,7 +87461,9 @@ case OP_Column: {
u32 t; /* A type code from the record header */
Mem *pReg; /* PseudoTable input register */
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
p2 = pOp->p2;
/* If the cursor cache is stale (meaning it is not currently point at
@@ -86512,7 +87475,6 @@ case OP_Column: {
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pC!=0 );
assert( p2<pC->nField );
aOffset = pC->aOffset;
@@ -86723,10 +87685,11 @@ case OP_Column: {
**
** Although sqlite3VdbeSerialGet() may read at most 8 bytes from the
** buffer passed to it, debugging function VdbeMemPrettyPrint() may
- ** read up to 16. So 16 bytes of bogus content is supplied.
+ ** read more. Use the global constant sqlite3CtypeMap[] as the array,
+ ** as that array is 256 bytes long (plenty for VdbeMemPrettyPrint())
+ ** and it begins with a bunch of zeros.
*/
- static u8 aZero[16]; /* This is the bogus content */
- sqlite3VdbeSerialGet(aZero, t, pDest);
+ sqlite3VdbeSerialGet((u8*)sqlite3CtypeMap, t, pDest);
}else{
rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
@@ -86769,7 +87732,7 @@ case OP_Affinity: {
pIn1 = &aMem[pOp->p1];
while( 1 /*exit-by-break*/ ){
assert( pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)] );
- assert( memIsValid(pIn1) );
+ assert( zAffinity[0]==SQLITE_AFF_NONE || memIsValid(pIn1) );
applyAffinity(pIn1, zAffinity[0], encoding);
if( zAffinity[0]==SQLITE_AFF_REAL && (pIn1->flags & MEM_Int)!=0 ){
/* When applying REAL affinity, if the result is still an MEM_Int
@@ -87094,11 +88057,11 @@ case OP_Count: { /* out2 */
pCrsr = p->apCsr[pOp->p1]->uc.pCursor;
assert( pCrsr );
nEntry = 0; /* Not needed. Only used to silence a warning. */
- rc = sqlite3BtreeCount(pCrsr, &nEntry);
+ rc = sqlite3BtreeCount(db, pCrsr, &nEntry);
if( rc ) goto abort_due_to_error;
pOut = out2Prerelease(p, pOp);
pOut->u.i = nEntry;
- break;
+ goto check_for_interrupt;
}
#endif
@@ -87215,8 +88178,12 @@ case OP_Savepoint: {
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
}
- db->isTransactionSavepoint = 0;
rc = p->rc;
+ if( rc ){
+ db->autoCommit = 0;
+ }else{
+ db->isTransactionSavepoint = 0;
+ }
}else{
int isSchemaChange;
iSavepoint = db->nSavepoint - iSavepoint - 1;
@@ -87244,6 +88211,7 @@ case OP_Savepoint: {
db->mDbFlags |= DBFLAG_SchemaChange;
}
}
+ if( rc ) goto abort_due_to_error;
/* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
** savepoints nested inside of the savepoint being operated on. */
@@ -87326,7 +88294,6 @@ case OP_AutoCommit: {
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
}
- assert( db->nStatement==0 );
sqlite3CloseSavepoints(db);
if( p->rc==SQLITE_OK ){
rc = SQLITE_DONE;
@@ -87407,7 +88374,8 @@ case OP_Transaction: {
goto abort_due_to_error;
}
- if( pOp->p2 && p->usesStmtJournal
+ if( p->usesStmtJournal
+ && pOp->p2
&& (db->autoCommit==0 || db->nVdbeRead>1)
){
assert( sqlite3BtreeIsInTrans(pBt) );
@@ -87739,6 +88707,7 @@ case OP_OpenDup: {
VdbeCursor *pCx; /* The new cursor */
pOrig = p->apCsr[pOp->p2];
+ assert( pOrig );
assert( pOrig->pBtx!=0 ); /* Only ephemeral cursors can be duplicated */
pCx = allocateCursor(p, pOp->p1, pOrig->nField, -1, CURTYPE_BTREE);
@@ -87802,15 +88771,13 @@ case OP_OpenEphemeral: {
assert( pOp->p1>=0 );
assert( pOp->p2>=0 );
pCx = p->apCsr[pOp->p1];
- if( pCx ){
+ if( pCx && pCx->pBtx ){
/* If the ephermeral table is already open, erase all existing content
** so that the table is empty again, rather than creating a new table. */
assert( pCx->isEphemeral );
pCx->seqCount = 0;
pCx->cacheStatus = CACHE_STALE;
- if( pCx->pBtx ){
- rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0);
- }
+ rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0);
}else{
pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE);
if( pCx==0 ) goto no_mem;
@@ -88242,7 +89209,7 @@ seek_not_found:
** Synopsis: seekHit=P2
**
** Set the seekHit flag on cursor P1 to the value in P2.
-** The seekHit flag is used by the IfNoHope opcode.
+* The seekHit flag is used by the IfNoHope opcode.
**
** P1 must be a valid b-tree cursor. P2 must be a boolean value,
** either 0 or 1.
@@ -88257,6 +89224,20 @@ case OP_SeekHit: {
break;
}
+/* Opcode: IfNotOpen P1 P2 * * *
+** Synopsis: if( !csr[P1] ) goto P2
+**
+** If cursor P1 is not open, jump to instruction P2. Otherwise, fall through.
+*/
+case OP_IfNotOpen: { /* jump */
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ VdbeBranchTaken(p->apCsr[pOp->p1]==0, 2);
+ if( !p->apCsr[pOp->p1] ){
+ goto jump_to_p2_and_check_for_interrupt;
+ }
+ break;
+}
+
/* Opcode: Found P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
@@ -88745,6 +89726,7 @@ case OP_Insert: {
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->eCurType==CURTYPE_BTREE );
+ assert( pC->deferredMoveto==0 );
assert( pC->uc.pCursor!=0 );
assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
@@ -88862,7 +89844,11 @@ case OP_Delete: {
sqlite3VdbeIncrWriteCounter(p, pC);
#ifdef SQLITE_DEBUG
- if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){
+ if( pOp->p4type==P4_TABLE
+ && HasRowid(pOp->p4.pTab)
+ && pOp->p5==0
+ && sqlite3BtreeCursorIsValidNN(pC->uc.pCursor)
+ ){
/* If p5 is zero, the seek operation that positioned the cursor prior to
** OP_Delete will have also set the pC->movetoTarget field to the rowid of
** the row that is being deleted */
@@ -89618,6 +90604,24 @@ case OP_IdxRowid: { /* out2 */
break;
}
+/* Opcode: FinishSeek P1 * * * *
+**
+** If cursor P1 was previously moved via OP_DeferredSeek, complete that
+** seek operation now, without further delay. If the cursor seek has
+** already occurred, this instruction is a no-op.
+*/
+case OP_FinishSeek: {
+ VdbeCursor *pC; /* The P1 index cursor */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ pC = p->apCsr[pOp->p1];
+ if( pC->deferredMoveto ){
+ rc = sqlite3VdbeFinishMoveto(pC);
+ if( rc ) goto abort_due_to_error;
+ }
+ break;
+}
+
/* Opcode: IdxGE P1 P2 P3 P4 P5
** Synopsis: key=r[P3@P4]
**
@@ -90054,7 +91058,7 @@ case OP_IntegrityCk: {
pIn1 = &aMem[pOp->p1];
assert( pOp->p5<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p5) );
- z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, &aRoot[1], nRoot,
+ z = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1], nRoot,
(int)pnErr->u.i+1, &nErr);
sqlite3VdbeMemSetNull(pIn1);
if( nErr==0 ){
@@ -90067,7 +91071,7 @@ case OP_IntegrityCk: {
}
UPDATE_MAX_BLOBSIZE(pIn1);
sqlite3VdbeChangeEncoding(pIn1, encoding);
- break;
+ goto check_for_interrupt;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
@@ -90924,6 +91928,36 @@ case OP_Expire: {
break;
}
+/* Opcode: CursorLock P1 * * * *
+**
+** Lock the btree to which cursor P1 is pointing so that the btree cannot be
+** written by an other cursor.
+*/
+case OP_CursorLock: {
+ VdbeCursor *pC;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( pC->eCurType==CURTYPE_BTREE );
+ sqlite3BtreeCursorPin(pC->uc.pCursor);
+ break;
+}
+
+/* Opcode: CursorUnlock P1 * * * *
+**
+** Unlock the btree to which cursor P1 is pointing so that it can be
+** written by other cursors.
+*/
+case OP_CursorUnlock: {
+ VdbeCursor *pC;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( pC->eCurType==CURTYPE_BTREE );
+ sqlite3BtreeCursorUnpin(pC->uc.pCursor);
+ break;
+}
+
#ifndef SQLITE_OMIT_SHARED_CACHE
/* Opcode: TableLock P1 P2 P3 P4 *
** Synopsis: iDb=P1 root=P2 write=P3
@@ -91168,7 +92202,7 @@ case OP_VColumn: {
assert( pModule->xColumn );
memset(&sContext, 0, sizeof(sContext));
sContext.pOut = pDest;
- testcase( (pOp->p5 & OPFLAG_NOCHNG)==0 && pOp->p5!=0 );
+ assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 );
if( pOp->p5 & OPFLAG_NOCHNG ){
sqlite3VdbeMemSetNull(pDest);
pDest->flags = MEM_Null|MEM_Zero;
@@ -91393,13 +92427,15 @@ case OP_MaxPgcnt: { /* out2 */
}
#endif
-/* Opcode: Function0 P1 P2 P3 P4 P5
+/* Opcode: Function P1 P2 P3 P4 *
** Synopsis: r[P3]=func(r[P2@P5])
**
-** Invoke a user function (P4 is a pointer to a FuncDef object that
-** defines the function) with P5 arguments taken from register P2 and
-** successors. The result of the function is stored in register P3.
-** Register P3 must not be one of the function inputs.
+** Invoke a user function (P4 is a pointer to an sqlite3_context object that
+** contains a pointer to the function to be run) with arguments taken
+** from register P2 and successors. The number of arguments is in
+** the sqlite3_context object that P4 points to.
+** The result of the function is stored
+** in register P3. Register P3 must not be one of the function inputs.
**
** P1 is a 32-bit bitmask indicating whether or not each argument to the
** function was determined to be constant at compile time. If the first
@@ -91408,14 +92444,16 @@ case OP_MaxPgcnt: { /* out2 */
** sqlite3_set_auxdata() API may be safely retained until the next
** invocation of this opcode.
**
-** See also: Function, AggStep, AggFinal
+** See also: AggStep, AggFinal, PureFunc
*/
-/* Opcode: Function P1 P2 P3 P4 P5
+/* Opcode: PureFunc P1 P2 P3 P4 *
** Synopsis: r[P3]=func(r[P2@P5])
**
** Invoke a user function (P4 is a pointer to an sqlite3_context object that
-** contains a pointer to the function to be run) with P5 arguments taken
-** from register P2 and successors. The result of the function is stored
+** contains a pointer to the function to be run) with arguments taken
+** from register P2 and successors. The number of arguments is in
+** the sqlite3_context object that P4 points to.
+** The result of the function is stored
** in register P3. Register P3 must not be one of the function inputs.
**
** P1 is a 32-bit bitmask indicating whether or not each argument to the
@@ -91425,40 +92463,16 @@ case OP_MaxPgcnt: { /* out2 */
** sqlite3_set_auxdata() API may be safely retained until the next
** invocation of this opcode.
**
-** SQL functions are initially coded as OP_Function0 with P4 pointing
-** to a FuncDef object. But on first evaluation, the P4 operand is
-** automatically converted into an sqlite3_context object and the operation
-** changed to this OP_Function opcode. In this way, the initialization of
-** the sqlite3_context object occurs only once, rather than once for each
-** evaluation of the function.
+** This opcode works exactly like OP_Function. The only difference is in
+** its name. This opcode is used in places where the function must be
+** purely non-deterministic. Some built-in date/time functions can be
+** either determinitic of non-deterministic, depending on their arguments.
+** When those function are used in a non-deterministic way, they will check
+** to see if they were called using OP_PureFunc instead of OP_Function, and
+** if they were, they throw an error.
**
-** See also: Function0, AggStep, AggFinal
+** See also: AggStep, AggFinal, Function
*/
-case OP_PureFunc0: /* group */
-case OP_Function0: { /* group */
- int n;
- sqlite3_context *pCtx;
-
- assert( pOp->p4type==P4_FUNCDEF );
- n = pOp->p5;
- assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
- assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
- assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
- pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
- if( pCtx==0 ) goto no_mem;
- pCtx->pOut = 0;
- pCtx->pFunc = pOp->p4.pFunc;
- pCtx->iOp = (int)(pOp - aOp);
- pCtx->pVdbe = p;
- pCtx->isError = 0;
- pCtx->argc = n;
- pOp->p4type = P4_FUNCCTX;
- pOp->p4.pCtx = pCtx;
- assert( OP_PureFunc == OP_PureFunc0+2 );
- assert( OP_Function == OP_Function0+2 );
- pOp->opcode += 2;
- /* Fall through into OP_Function */
-}
case OP_PureFunc: /* group */
case OP_Function: { /* group */
int i;
@@ -91473,9 +92487,11 @@ case OP_Function: { /* group */
** reinitializes the relavant parts of the sqlite3_context object */
pOut = &aMem[pOp->p3];
if( pCtx->pOut != pOut ){
+ pCtx->pVdbe = p;
pCtx->pOut = pOut;
for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
}
+ assert( pCtx->pVdbe==p );
memAboutToChange(p, pOut);
#ifdef SQLITE_DEBUG
@@ -91647,6 +92663,55 @@ case OP_Abortable: {
}
#endif
+#ifdef SQLITE_DEBUG
+/* Opcode: ReleaseReg P1 P2 P3 * P5
+** Synopsis: release r[P1@P2] mask P3
+**
+** Release registers from service. Any content that was in the
+** the registers is unreliable after this opcode completes.
+**
+** The registers released will be the P2 registers starting at P1,
+** except if bit ii of P3 set, then do not release register P1+ii.
+** In other words, P3 is a mask of registers to preserve.
+**
+** Releasing a register clears the Mem.pScopyFrom pointer. That means
+** that if the content of the released register was set using OP_SCopy,
+** a change to the value of the source register for the OP_SCopy will no longer
+** generate an assertion fault in sqlite3VdbeMemAboutToChange().
+**
+** If P5 is set, then all released registers have their type set
+** to MEM_Undefined so that any subsequent attempt to read the released
+** register (before it is reinitialized) will generate an assertion fault.
+**
+** P5 ought to be set on every call to this opcode.
+** However, there are places in the code generator will release registers
+** before their are used, under the (valid) assumption that the registers
+** will not be reallocated for some other purpose before they are used and
+** hence are safe to release.
+**
+** This opcode is only available in testing and debugging builds. It is
+** not generated for release builds. The purpose of this opcode is to help
+** validate the generated bytecode. This opcode does not actually contribute
+** to computing an answer.
+*/
+case OP_ReleaseReg: {
+ Mem *pMem;
+ int i;
+ u32 constMask;
+ assert( pOp->p1>0 );
+ assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );
+ pMem = &aMem[pOp->p1];
+ constMask = pOp->p3;
+ for(i=0; i<pOp->p2; i++, pMem++){
+ if( i>=32 || (constMask & MASKBIT32(i))==0 ){
+ pMem->pScopyFrom = 0;
+ if( i<32 && pOp->p5 ) MemSetTypeFlag(pMem, MEM_Undefined);
+ }
+ }
+ break;
+}
+#endif
+
/* Opcode: Noop * * * * *
**
** Do nothing. This instruction is often useful as a jump
@@ -91698,6 +92763,12 @@ default: { /* This is really OP_Noop, OP_Explain */
if( opProperty & OPFLG_OUT3 ){
registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]);
}
+ if( opProperty==0xff ){
+ /* Never happens. This code exists to avoid a harmless linkage
+ ** warning aboud sqlite3VdbeRegisterDump() being defined but not
+ ** used. */
+ sqlite3VdbeRegisterDump(p);
+ }
}
#endif /* SQLITE_DEBUG */
#endif /* NDEBUG */
@@ -93684,20 +94755,16 @@ static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){
*/
static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){
int i;
- SorterRecord **aSlot;
SorterRecord *p;
int rc;
+ SorterRecord *aSlot[64];
rc = vdbeSortAllocUnpacked(pTask);
if( rc!=SQLITE_OK ) return rc;
p = pList->pList;
pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter);
-
- aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
- if( !aSlot ){
- return SQLITE_NOMEM_BKPT;
- }
+ memset(aSlot, 0, sizeof(aSlot));
while( p ){
SorterRecord *pNext;
@@ -93722,13 +94789,12 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){
}
p = 0;
- for(i=0; i<64; i++){
+ for(i=0; i<ArraySize(aSlot); i++){
if( aSlot[i]==0 ) continue;
p = p ? vdbeSorterMerge(pTask, p, aSlot[i]) : aSlot[i];
}
pList->pList = p;
- sqlite3_free(aSlot);
assert( pTask->pUnpacked->errCode==SQLITE_OK
|| pTask->pUnpacked->errCode==SQLITE_NOMEM
);
@@ -95561,8 +96627,8 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
rc = pWalker->xExprCallback(pWalker, pExpr);
if( rc ) return rc & WRC_Abort;
if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
+ assert( pExpr->x.pList==0 || pExpr->pRight==0 );
if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
- assert( pExpr->x.pList==0 || pExpr->pRight==0 );
if( pExpr->pRight ){
assert( !ExprHasProperty(pExpr, EP_WinFunc) );
pExpr = pExpr->pRight;
@@ -95831,13 +96897,16 @@ static int nameInUsingClause(IdList *pUsing, const char *zCol){
** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will
** match anything.
*/
-SQLITE_PRIVATE int sqlite3MatchSpanName(
- const char *zSpan,
+SQLITE_PRIVATE int sqlite3MatchEName(
+ const struct ExprList_item *pItem,
const char *zCol,
const char *zTab,
const char *zDb
){
int n;
+ const char *zSpan;
+ if( NEVER(pItem->eEName!=ENAME_TAB) ) return 0;
+ zSpan = pItem->zEName;
for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
return 0;
@@ -95966,7 +97035,7 @@ static int lookupName(
int hit = 0;
pEList = pItem->pSelect->pEList;
for(j=0; j<pEList->nExpr; j++){
- if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
+ if( sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){
cnt++;
cntTab = 2;
pMatch = pItem;
@@ -96113,7 +97182,7 @@ static int lookupName(
if( cnt==0
&& cntTab==1
&& pMatch
- && (pNC->ncFlags & NC_IdxExpr)==0
+ && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
&& sqlite3IsRowid(zCol)
&& VisibleRowid(pMatch->pTab)
){
@@ -96147,8 +97216,10 @@ static int lookupName(
pEList = pNC->uNC.pEList;
assert( pEList!=0 );
for(j=0; j<pEList->nExpr; j++){
- char *zAs = pEList->a[j].zName;
- if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+ char *zAs = pEList->a[j].zEName;
+ if( pEList->a[j].eEName==ENAME_NAME
+ && sqlite3_stricmp(zAs, zCol)==0
+ ){
Expr *pOrig;
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
assert( pExpr->x.pList==0 );
@@ -96158,7 +97229,9 @@ static int lookupName(
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
return WRC_Abort;
}
- if( (pNC->ncFlags&NC_AllowWin)==0 && ExprHasProperty(pOrig, EP_Win) ){
+ if( ExprHasProperty(pOrig, EP_Win)
+ && ((pNC->ncFlags&NC_AllowWin)==0 || pNC!=pTopNC )
+ ){
sqlite3ErrorMsg(pParse, "misuse of aliased window function %s",zAs);
return WRC_Abort;
}
@@ -96250,18 +97323,35 @@ static int lookupName(
/* If a column from a table in pSrcList is referenced, then record
** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes
- ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the
- ** column number is greater than the number of bits in the bitmask
- ** then set the high-order bit of the bitmask.
+ ** bit 0 to be set. Column 1 sets bit 1. And so forth. Bit 63 is
+ ** set if the 63rd or any subsequent column is used.
+ **
+ ** The colUsed mask is an optimization used to help determine if an
+ ** index is a covering index. The correct answer is still obtained
+ ** if the mask contains extra set bits. However, it is important to
+ ** avoid setting bits beyond the maximum column number of the table.
+ ** (See ticket [b92e5e8ec2cdbaa1]).
+ **
+ ** If a generated column is referenced, set bits for every column
+ ** of the table.
*/
if( pExpr->iColumn>=0 && pMatch!=0 ){
int n = pExpr->iColumn;
- testcase( n==BMS-1 );
- if( n>=BMS ){
- n = BMS-1;
- }
+ Table *pExTab = pExpr->y.pTab;
+ assert( pExTab!=0 );
assert( pMatch->iCursor==pExpr->iTable );
- pMatch->colUsed |= ((Bitmask)1)<<n;
+ if( (pExTab->tabFlags & TF_HasGenerated)!=0
+ && (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0
+ ){
+ testcase( pExTab->nCol==BMS-1 );
+ testcase( pExTab->nCol==BMS );
+ pMatch->colUsed = pExTab->nCol>=BMS ? ALLBITS : MASKBIT(pExTab->nCol)-1;
+ }else{
+ testcase( n==BMS-1 );
+ testcase( n==BMS );
+ if( n>=BMS ) n = BMS-1;
+ pMatch->colUsed |= ((Bitmask)1)<<n;
+ }
}
/* Clean up and return
@@ -96300,15 +97390,23 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr
Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
if( p ){
struct SrcList_item *pItem = &pSrc->a[iSrc];
- p->y.pTab = pItem->pTab;
+ Table *pTab = p->y.pTab = pItem->pTab;
p->iTable = pItem->iCursor;
if( p->y.pTab->iPKey==iCol ){
p->iColumn = -1;
}else{
p->iColumn = (ynVar)iCol;
- testcase( iCol==BMS );
- testcase( iCol==BMS-1 );
- pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
+ if( (pTab->tabFlags & TF_HasGenerated)!=0
+ && (pTab->aCol[iCol].colFlags & COLFLAG_GENERATED)!=0
+ ){
+ testcase( pTab->nCol==63 );
+ testcase( pTab->nCol==64 );
+ pItem->colUsed = pTab->nCol>=64 ? ALLBITS : MASKBIT(pTab->nCol)-1;
+ }else{
+ testcase( iCol==BMS );
+ testcase( iCol==BMS-1 );
+ pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
+ }
}
}
return p;
@@ -96317,23 +97415,39 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr
/*
** Report an error that an expression is not valid for some set of
** pNC->ncFlags values determined by validMask.
-*/
-static void notValid(
- Parse *pParse, /* Leave error message here */
- NameContext *pNC, /* The name context */
- const char *zMsg, /* Type of error */
- int validMask /* Set of contexts for which prohibited */
-){
- assert( (validMask&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr))==0 );
- if( (pNC->ncFlags & validMask)!=0 ){
- const char *zIn = "partial index WHERE clauses";
- if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions";
+**
+** static void notValid(
+** Parse *pParse, // Leave error message here
+** NameContext *pNC, // The name context
+** const char *zMsg, // Type of error
+** int validMask, // Set of contexts for which prohibited
+** Expr *pExpr // Invalidate this expression on error
+** ){...}
+**
+** As an optimization, since the conditional is almost always false
+** (because errors are rare), the conditional is moved outside of the
+** function call using a macro.
+*/
+static void notValidImpl(
+ Parse *pParse, /* Leave error message here */
+ NameContext *pNC, /* The name context */
+ const char *zMsg, /* Type of error */
+ Expr *pExpr /* Invalidate this expression on error */
+){
+ const char *zIn = "partial index WHERE clauses";
+ if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions";
#ifndef SQLITE_OMIT_CHECK
- else if( pNC->ncFlags & NC_IsCheck ) zIn = "CHECK constraints";
+ else if( pNC->ncFlags & NC_IsCheck ) zIn = "CHECK constraints";
#endif
- sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn);
- }
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ else if( pNC->ncFlags & NC_GenCol ) zIn = "generated columns";
+#endif
+ sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn);
+ if( pExpr ) pExpr->op = TK_NULL;
}
+#define sqlite3ResolveNotValid(P,N,M,X,E) \
+ assert( ((X)&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol))==0 ); \
+ if( ((N)->ncFlags & (X))!=0 ) notValidImpl(P,N,M,E);
/*
** Expression p should encode a floating point value between 1.0 and 0.0.
@@ -96422,7 +97536,10 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
zColumn = pExpr->u.zToken;
}else{
Expr *pLeft = pExpr->pLeft;
- notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
+ testcase( pNC->ncFlags & NC_IdxExpr );
+ testcase( pNC->ncFlags & NC_GenCol );
+ sqlite3ResolveNotValid(pParse, pNC, "the \".\" operator",
+ NC_IdxExpr|NC_GenCol, 0);
pRight = pExpr->pRight;
if( pRight->op==TK_ID ){
zDb = 0;
@@ -96511,33 +97628,39 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
/* For the purposes of the EP_ConstFunc flag, date and time
** functions and other functions that change slowly are considered
- ** constant because they are constant for the duration of one query */
+ ** constant because they are constant for the duration of one query.
+ ** This allows them to be factored out of inner loops. */
ExprSetProperty(pExpr,EP_ConstFunc);
}
if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){
- /* Date/time functions that use 'now', and other functions like
+ /* Clearly non-deterministic functions like random(), but also
+ ** date/time functions that use 'now', and other functions like
** sqlite_version() that might change over time cannot be used
- ** in an index. */
- notValid(pParse, pNC, "non-deterministic functions",
- NC_IdxExpr|NC_PartIdx);
+ ** in an index or generated column. Curiously, they can be used
+ ** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all
+ ** all this. */
+ sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions",
+ NC_IdxExpr|NC_PartIdx|NC_GenCol, 0);
+ }else{
+ assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */
+ pExpr->op2 = pNC->ncFlags & NC_SelfRef;
+ if( pNC->ncFlags & NC_FromDDL ) ExprSetProperty(pExpr, EP_FromDDL);
}
if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0
&& pParse->nested==0
- && sqlite3Config.bInternalFunctions==0
+ && (pParse->db->mDbFlags & DBFLAG_InternalFunc)==0
){
/* Internal-use-only functions are disallowed unless the
- ** SQL is being compiled using sqlite3NestedParse() */
+ ** SQL is being compiled using sqlite3NestedParse() or
+ ** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be
+ ** used to activate internal functionsn for testing purposes */
no_such_func = 1;
pDef = 0;
}else
- if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0
- && ExprHasProperty(pExpr, EP_Indirect)
+ if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0
&& !IN_RENAME_OBJECT
){
- /* Functions tagged with SQLITE_DIRECTONLY may not be used
- ** inside of triggers and views */
- sqlite3ErrorMsg(pParse, "%s() prohibited in triggers and views",
- pDef->zName);
+ sqlite3ExprFunctionUsable(pParse, pExpr, pDef);
}
}
@@ -96618,7 +97741,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
Select *pSel = pNC->pWinSelect;
assert( pWin==pExpr->y.pWin );
if( IN_RENAME_OBJECT==0 ){
- sqlite3WindowUpdate(pParse, pSel->pWinDefn, pWin, pDef);
+ sqlite3WindowUpdate(pParse, pSel ? pSel->pWinDefn : 0, pWin, pDef);
}
sqlite3WalkExprList(pWalker, pWin->pPartition);
sqlite3WalkExprList(pWalker, pWin->pOrderBy);
@@ -96663,7 +97786,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_IN );
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
int nRef = pNC->nRef;
- notValid(pParse, pNC, "subqueries", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
+ testcase( pNC->ncFlags & NC_IsCheck );
+ testcase( pNC->ncFlags & NC_PartIdx );
+ testcase( pNC->ncFlags & NC_IdxExpr );
+ testcase( pNC->ncFlags & NC_GenCol );
+ sqlite3ResolveNotValid(pParse, pNC, "subqueries",
+ NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr);
sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
assert( pNC->nRef>=nRef );
if( nRef!=pNC->nRef ){
@@ -96674,7 +97802,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
break;
}
case TK_VARIABLE: {
- notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
+ testcase( pNC->ncFlags & NC_IsCheck );
+ testcase( pNC->ncFlags & NC_PartIdx );
+ testcase( pNC->ncFlags & NC_IdxExpr );
+ testcase( pNC->ncFlags & NC_GenCol );
+ sqlite3ResolveNotValid(pParse, pNC, "parameters",
+ NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr);
break;
}
case TK_IS:
@@ -96756,8 +97889,9 @@ static int resolveAsName(
if( pE->op==TK_ID ){
char *zCol = pE->u.zToken;
for(i=0; i<pEList->nExpr; i++){
- char *zAs = pEList->a[i].zName;
- if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+ if( pEList->a[i].eEName==ENAME_NAME
+ && sqlite3_stricmp(pEList->a[i].zEName, zCol)==0
+ ){
return i+1;
}
}
@@ -97483,10 +98617,13 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames(
** Resolve names in expressions that can only reference a single table
** or which cannot reference any tables at all. Examples:
**
-** (1) CHECK constraints
-** (2) WHERE clauses on partial indices
-** (3) Expressions in indexes on expressions
-** (4) Expression arguments to VACUUM INTO.
+** "type" flag
+** ------------
+** (1) CHECK constraints NC_IsCheck
+** (2) WHERE clauses on partial indices NC_PartIdx
+** (3) Expressions in indexes on expressions NC_IdxExpr
+** (4) Expression arguments to VACUUM INTO. 0
+** (5) GENERATED ALWAYS as expressions NC_GenCol
**
** In all cases except (4), the Expr.iTable value for Expr.op==TK_COLUMN
** nodes of the expression is set to -1 and the Expr.iColumn value is
@@ -97495,18 +98632,19 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames(
** Any errors cause an error message to be set in pParse.
*/
SQLITE_PRIVATE int sqlite3ResolveSelfReference(
- Parse *pParse, /* Parsing context */
- Table *pTab, /* The table being referenced, or NULL */
- int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr, or 0 */
- Expr *pExpr, /* Expression to resolve. May be NULL. */
- ExprList *pList /* Expression list to resolve. May be NULL. */
+ Parse *pParse, /* Parsing context */
+ Table *pTab, /* The table being referenced, or NULL */
+ int type, /* NC_IsCheck, NC_PartIdx, NC_IdxExpr, NC_GenCol, or 0 */
+ Expr *pExpr, /* Expression to resolve. May be NULL. */
+ ExprList *pList /* Expression list to resolve. May be NULL. */
){
SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
NameContext sNC; /* Name context for pParse->pNewTable */
int rc;
assert( type==0 || pTab!=0 );
- assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr || pTab==0 );
+ assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr
+ || type==NC_GenCol || pTab==0 );
memset(&sNC, 0, sizeof(sNC));
memset(&sSrc, 0, sizeof(sSrc));
if( pTab ){
@@ -97514,6 +98652,11 @@ SQLITE_PRIVATE int sqlite3ResolveSelfReference(
sSrc.a[0].zName = pTab->zName;
sSrc.a[0].pTab = pTab;
sSrc.a[0].iCursor = -1;
+ if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){
+ /* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP
+ ** schema elements */
+ type |= NC_FromDDL;
+ }
}
sNC.pParse = pParse;
sNC.pSrcList = &sSrc;
@@ -97597,6 +98740,9 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
);
}
+ if( op==TK_VECTOR ){
+ return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr);
+ }
return pExpr->affExpr;
}
@@ -97699,6 +98845,10 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
p = p->pLeft;
continue;
}
+ if( op==TK_VECTOR ){
+ p = p->x.pList->a[0].pExpr;
+ continue;
+ }
if( op==TK_COLLATE ){
pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
break;
@@ -97710,12 +98860,12 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
Expr *pNext = p->pRight;
/* The Expr.x union is never used at the same time as Expr.pRight */
assert( p->x.pList==0 || p->pRight==0 );
- /* p->flags holds EP_Collate and p->pLeft->flags does not. And
- ** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at
- ** least one EP_Collate. Thus the following two ALWAYS. */
- if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){
+ if( p->x.pList!=0
+ && !db->mallocFailed
+ && ALWAYS(!ExprHasProperty(p, EP_xIsSelect))
+ ){
int i;
- for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){
+ for(i=0; i<p->x.pList->nExpr; i++){
if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){
pNext = p->x.pList->a[i].pExpr;
break;
@@ -97863,6 +99013,22 @@ SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(
return pColl;
}
+/* Expresssion p is a comparison operator. Return a collation sequence
+** appropriate for the comparison operator.
+**
+** This is normally just a wrapper around sqlite3BinaryCompareCollSeq().
+** However, if the OP_Commuted flag is set, then the order of the operands
+** is reversed in the sqlite3BinaryCompareCollSeq() call so that the
+** correct collating sequence is found.
+*/
+SQLITE_PRIVATE CollSeq *sqlite3ExprCompareCollSeq(Parse *pParse, Expr *p){
+ if( ExprHasProperty(p, EP_Commuted) ){
+ return sqlite3BinaryCompareCollSeq(pParse, p->pRight, p->pLeft);
+ }else{
+ return sqlite3BinaryCompareCollSeq(pParse, p->pLeft, p->pRight);
+ }
+}
+
/*
** Generate code for a comparison operator.
*/
@@ -97873,13 +99039,19 @@ static int codeCompare(
int opcode, /* The comparison opcode */
int in1, int in2, /* Register holding operands */
int dest, /* Jump here if true. */
- int jumpIfNull /* If true, jump if either operand is NULL */
+ int jumpIfNull, /* If true, jump if either operand is NULL */
+ int isCommuted /* The comparison has been commuted */
){
int p5;
int addr;
CollSeq *p4;
- p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
+ if( pParse->nErr ) return 0;
+ if( isCommuted ){
+ p4 = sqlite3BinaryCompareCollSeq(pParse, pRight, pLeft);
+ }else{
+ p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
+ }
p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
(void*)p4, P4_COLLSEQ);
@@ -98090,7 +99262,9 @@ static void codeVectorCompare(
int regRight = 0;
u8 opx = op;
int addrDone = sqlite3VdbeMakeLabel(pParse);
+ int isCommuted = ExprHasProperty(pExpr,EP_Commuted);
+ if( pParse->nErr ) return;
if( nLeft!=sqlite3ExprVectorSize(pRight) ){
sqlite3ErrorMsg(pParse, "row value misused");
return;
@@ -98119,7 +99293,7 @@ static void codeVectorCompare(
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);
+ 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);
@@ -98429,9 +99603,11 @@ SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){
return pRight;
}else if( pRight==0 ){
return pLeft;
- }else if( ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight) ){
- sqlite3ExprUnmapAndDelete(pParse, pLeft);
- sqlite3ExprUnmapAndDelete(pParse, pRight);
+ }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);
@@ -98468,6 +99644,40 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(
}
/*
+** Check to see if a function is usable according to current access
+** rules:
+**
+** SQLITE_FUNC_DIRECT - Only usable from top-level SQL
+**
+** SQLITE_FUNC_UNSAFE - Usable if TRUSTED_SCHEMA or from
+** top-level SQL
+**
+** If the function is not usable, create an error.
+*/
+SQLITE_PRIVATE void sqlite3ExprFunctionUsable(
+ Parse *pParse, /* Parsing and code generating context */
+ Expr *pExpr, /* The function invocation */
+ FuncDef *pDef /* The function being invoked */
+){
+ assert( !IN_RENAME_OBJECT );
+ assert( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 );
+ if( ExprHasProperty(pExpr, EP_FromDDL) ){
+ if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0
+ || (pParse->db->flags & SQLITE_TrustedSchema)==0
+ ){
+ /* Functions prohibited in triggers and views if:
+ ** (1) tagged with SQLITE_DIRECTONLY
+ ** (2) not tagged with SQLITE_INNOCUOUS (which means it
+ ** is tagged with SQLITE_FUNC_UNSAFE) and
+ ** SQLITE_DBCONFIG_TRUSTED_SCHEMA is off (meaning
+ ** that the schema is possibly tainted).
+ */
+ sqlite3ErrorMsg(pParse, "unsafe use of %s()", pDef->zName);
+ }
+ }
+}
+
+/*
** Assign a variable number to an expression that encodes a wildcard
** in the original SQL statement.
**
@@ -98934,12 +100144,11 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags)
pNewExpr->pLeft = pPriorSelectCol;
}
}
- pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
- pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
+ pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
pItem->sortFlags = pOldItem->sortFlags;
+ pItem->eEName = pOldItem->eEName;
pItem->done = 0;
pItem->bNulls = pOldItem->bNulls;
- pItem->bSpanIsTab = pOldItem->bSpanIsTab;
pItem->bSorterRef = pOldItem->bSorterRef;
pItem->u = pOldItem->u;
}
@@ -99106,9 +100315,9 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(
pList = pNew;
}
pItem = &pList->a[pList->nExpr++];
- assert( offsetof(struct ExprList_item,zName)==sizeof(pItem->pExpr) );
+ assert( offsetof(struct ExprList_item,zEName)==sizeof(pItem->pExpr) );
assert( offsetof(struct ExprList_item,pExpr)==0 );
- memset(&pItem->zName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zName));
+ memset(&pItem->zEName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zEName));
pItem->pExpr = pExpr;
return pList;
@@ -99165,7 +100374,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(
pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
if( pList ){
assert( pList->nExpr==iFirst+i+1 );
- pList->a[pList->nExpr-1].zName = pColumns->a[i].zName;
+ pList->a[pList->nExpr-1].zEName = pColumns->a[i].zName;
pColumns->a[i].zName = 0;
}
}
@@ -99225,7 +100434,7 @@ SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder, int
}
/*
-** Set the ExprList.a[].zName element of the most recently added item
+** Set the ExprList.a[].zEName element of the most recently added item
** on the expression list.
**
** pList might be NULL following an OOM error. But pName should never be
@@ -99243,11 +100452,12 @@ SQLITE_PRIVATE void sqlite3ExprListSetName(
struct ExprList_item *pItem;
assert( pList->nExpr>0 );
pItem = &pList->a[pList->nExpr-1];
- assert( pItem->zName==0 );
- pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
- if( dequote ) sqlite3Dequote(pItem->zName);
+ assert( pItem->zEName==0 );
+ assert( pItem->eEName==ENAME_NAME );
+ pItem->zEName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
+ if( dequote ) sqlite3Dequote(pItem->zEName);
if( IN_RENAME_OBJECT ){
- sqlite3RenameTokenMap(pParse, (void*)pItem->zName, pName);
+ sqlite3RenameTokenMap(pParse, (void*)pItem->zEName, pName);
}
}
}
@@ -99271,8 +100481,10 @@ SQLITE_PRIVATE void sqlite3ExprListSetSpan(
if( pList ){
struct ExprList_item *pItem = &pList->a[pList->nExpr-1];
assert( pList->nExpr>0 );
- sqlite3DbFree(db, pItem->zSpan);
- pItem->zSpan = sqlite3DbSpanDup(db, zStart, zEnd);
+ if( pItem->zEName==0 ){
+ pItem->zEName = sqlite3DbSpanDup(db, zStart, zEnd);
+ pItem->eEName = ENAME_SPAN;
+ }
}
}
@@ -99302,8 +100514,7 @@ static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){
assert( pList->nExpr>0 );
do{
sqlite3ExprDelete(db, pItem->pExpr);
- sqlite3DbFree(db, pItem->zName);
- sqlite3DbFree(db, pItem->zSpan);
+ sqlite3DbFree(db, pItem->zEName);
pItem++;
}while( --i>0 );
sqlite3DbFreeNN(db, pList);
@@ -99342,18 +100553,33 @@ SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){
}
/*
+** Check the input string to see if it is "true" or "false" (in any case).
+**
+** If the string is.... Return
+** "true" EP_IsTrue
+** "false" EP_IsFalse
+** anything else 0
+*/
+SQLITE_PRIVATE u32 sqlite3IsTrueOrFalse(const char *zIn){
+ if( sqlite3StrICmp(zIn, "true")==0 ) return EP_IsTrue;
+ if( sqlite3StrICmp(zIn, "false")==0 ) return EP_IsFalse;
+ return 0;
+}
+
+
+/*
** If the input expression is an ID with the name "true" or "false"
** then convert it into an TK_TRUEFALSE term. Return non-zero if
** the conversion happened, and zero if the expression is unaltered.
*/
SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr *pExpr){
+ u32 v;
assert( pExpr->op==TK_ID || pExpr->op==TK_STRING );
if( !ExprHasProperty(pExpr, EP_Quoted)
- && (sqlite3StrICmp(pExpr->u.zToken, "true")==0
- || sqlite3StrICmp(pExpr->u.zToken, "false")==0)
+ && (v = sqlite3IsTrueOrFalse(pExpr->u.zToken))!=0
){
pExpr->op = TK_TRUEFALSE;
- ExprSetProperty(pExpr, pExpr->u.zToken[4]==0 ? EP_IsTrue : EP_IsFalse);
+ ExprSetProperty(pExpr, v);
return 1;
}
return 0;
@@ -99415,10 +100641,11 @@ SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){
** In all cases, the callbacks set Walker.eCode=0 and abort if the expression
** is found to not be a constant.
**
-** The sqlite3ExprIsConstantOrFunction() is used for evaluating expressions
-** in a CREATE TABLE statement. The Walker.eCode value is 5 when parsing
-** an existing schema and 4 when processing a new statement. A bound
-** parameter raises an error for new statements, but is silently converted
+** The sqlite3ExprIsConstantOrFunction() is used for evaluating DEFAULT
+** expressions in a CREATE TABLE statement. The Walker.eCode value is 5
+** when parsing an existing schema out of the sqlite_master table and 4
+** when processing a new CREATE TABLE statement. A bound parameter raises
+** an error for new statements, but is silently converted
** to NULL for existing schemas. This allows sqlite_master tables that
** contain a bound parameter because they were generated by older versions
** of SQLite to be parsed by newer versions of SQLite without raising a
@@ -99439,7 +100666,10 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
** and either pWalker->eCode==4 or 5 or the function has the
** SQLITE_FUNC_CONST flag. */
case TK_FUNCTION:
- if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc) ){
+ if( (pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc))
+ && !ExprHasProperty(pExpr, EP_WinFunc)
+ ){
+ if( pWalker->eCode==5 ) ExprSetProperty(pExpr, EP_FromDDL);
return WRC_Continue;
}else{
pWalker->eCode = 0;
@@ -99603,9 +100833,21 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprLi
}
/*
-** Walk an expression tree. Return non-zero if the expression is constant
-** or a function call with constant arguments. Return and 0 if there
-** are any variables.
+** Walk an expression tree for the DEFAULT field of a column definition
+** in a CREATE TABLE statement. Return non-zero if the expression is
+** acceptable for use as a DEFAULT. That is to say, return non-zero if
+** the expression is constant or a function call with constant arguments.
+** Return and 0 if there are any variables.
+**
+** isInit is true when parsing from sqlite_master. isInit is false when
+** processing a new CREATE TABLE statement. When isInit is true, parameters
+** (such as ? or $abc) in the expression are converted into NULL. When
+** isInit is false, parameters raise an error. Parameters should not be
+** allowed in a CREATE TABLE statement, but some legacy versions of SQLite
+** allowed it, so we need to support it when reading sqlite_master for
+** backwards compatibility.
+**
+** If isInit is true, set EP_FromDDL on every TK_FUNCTION node.
**
** For the purposes of this function, a double-quoted string (ex: "abc")
** is considered a variable but a single-quoted string (ex: 'abc') is
@@ -99702,7 +100944,9 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){
case TK_COLUMN:
return ExprHasProperty(p, EP_CanBeNull) ||
p->y.pTab==0 || /* Reference to column of index on expression */
- (p->iColumn>=0 && p->y.pTab->aCol[p->iColumn].notNull==0);
+ (p->iColumn>=0
+ && ALWAYS(p->y.pTab->aCol!=0) /* Defense against OOM problems */
+ && p->y.pTab->aCol[p->iColumn].notNull==0);
default:
return 1;
}
@@ -100179,8 +101423,10 @@ static char *exprINAffinity(Parse *pParse, Expr *pExpr){
** "sub-select returns N columns - expected M"
*/
SQLITE_PRIVATE void sqlite3SubselectError(Parse *pParse, int nActual, int nExpect){
- const char *zFmt = "sub-select returns %d columns - expected %d";
- sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect);
+ if( pParse->nErr==0 ){
+ const char *zFmt = "sub-select returns %d columns - expected %d";
+ sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect);
+ }
}
#endif
@@ -100681,19 +101927,25 @@ static void sqlite3ExprCodeIN(
if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){
sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull);
}
+ sqlite3ReleaseTempReg(pParse, regToFree);
if( ii<pList->nExpr-1 || destIfNull!=destIfFalse ){
- sqlite3VdbeAddOp4(v, OP_Eq, rLhs, labelOk, r2,
+ int op = rLhs!=r2 ? OP_Eq : OP_NotNull;
+ sqlite3VdbeAddOp4(v, op, rLhs, labelOk, r2,
(void*)pColl, P4_COLLSEQ);
- VdbeCoverageIf(v, ii<pList->nExpr-1);
- VdbeCoverageIf(v, ii==pList->nExpr-1);
+ VdbeCoverageIf(v, ii<pList->nExpr-1 && op==OP_Eq);
+ VdbeCoverageIf(v, ii==pList->nExpr-1 && op==OP_Eq);
+ VdbeCoverageIf(v, ii<pList->nExpr-1 && op==OP_NotNull);
+ VdbeCoverageIf(v, ii==pList->nExpr-1 && op==OP_NotNull);
sqlite3VdbeChangeP5(v, zAff[0]);
}else{
+ int op = rLhs!=r2 ? OP_Ne : OP_IsNull;
assert( destIfNull==destIfFalse );
- sqlite3VdbeAddOp4(v, OP_Ne, rLhs, destIfFalse, r2,
- (void*)pColl, P4_COLLSEQ); VdbeCoverage(v);
+ sqlite3VdbeAddOp4(v, op, rLhs, destIfFalse, r2,
+ (void*)pColl, P4_COLLSEQ);
+ VdbeCoverageIf(v, op==OP_Ne);
+ VdbeCoverageIf(v, op==OP_IsNull);
sqlite3VdbeChangeP5(v, zAff[0] | SQLITE_JUMPIFNULL);
}
- sqlite3ReleaseTempReg(pParse, regToFree);
}
if( regCkNull ){
sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v);
@@ -100713,6 +101965,7 @@ static void sqlite3ExprCodeIN(
}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) ){
@@ -100894,16 +102147,45 @@ SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(
}
}
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+/*
+** Generate code that will compute the value of generated column pCol
+** and store the result in register regOut
+*/
+SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(
+ Parse *pParse,
+ Column *pCol,
+ int regOut
+){
+ int iAddr;
+ Vdbe *v = pParse->pVdbe;
+ assert( v!=0 );
+ assert( pParse->iSelfTab!=0 );
+ if( pParse->iSelfTab>0 ){
+ iAddr = sqlite3VdbeAddOp3(v, OP_IfNullRow, pParse->iSelfTab-1, 0, regOut);
+ }else{
+ iAddr = 0;
+ }
+ sqlite3ExprCode(pParse, pCol->pDflt, regOut);
+ if( pCol->affinity>=SQLITE_AFF_TEXT ){
+ sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1);
+ }
+ if( iAddr ) sqlite3VdbeJumpHere(v, iAddr);
+}
+#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
+
/*
** Generate code to extract the value of the iCol-th column of a table.
*/
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
- Vdbe *v, /* The VDBE under construction */
+ Vdbe *v, /* Parsing context */
Table *pTab, /* The table containing the value */
int iTabCur, /* The table cursor. Or the PK cursor for WITHOUT ROWID */
int iCol, /* Index of the column to extract */
int regOut /* Extract the value into this register */
){
+ Column *pCol;
+ assert( v!=0 );
if( pTab==0 ){
sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut);
return;
@@ -100911,14 +102193,36 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
if( iCol<0 || iCol==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
}else{
- int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
- int x = iCol;
- if( !HasRowid(pTab) && !IsVirtual(pTab) ){
- x = sqlite3ColumnOfIndex(sqlite3PrimaryKeyIndex(pTab), iCol);
+ int op;
+ int x;
+ if( IsVirtual(pTab) ){
+ op = OP_VColumn;
+ x = iCol;
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ }else if( (pCol = &pTab->aCol[iCol])->colFlags & COLFLAG_VIRTUAL ){
+ Parse *pParse = sqlite3VdbeParser(v);
+ if( pCol->colFlags & COLFLAG_BUSY ){
+ sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pCol->zName);
+ }else{
+ int savedSelfTab = pParse->iSelfTab;
+ pCol->colFlags |= COLFLAG_BUSY;
+ pParse->iSelfTab = iTabCur+1;
+ sqlite3ExprCodeGeneratedColumn(pParse, pCol, regOut);
+ pParse->iSelfTab = savedSelfTab;
+ pCol->colFlags &= ~COLFLAG_BUSY;
+ }
+ return;
+#endif
+ }else if( !HasRowid(pTab) ){
+ testcase( iCol!=sqlite3TableColumnToStorage(pTab, iCol) );
+ x = sqlite3TableColumnToIndex(sqlite3PrimaryKeyIndex(pTab), iCol);
+ op = OP_Column;
+ }else{
+ x = sqlite3TableColumnToStorage(pTab,iCol);
+ testcase( x!=iCol );
+ op = OP_Column;
}
sqlite3VdbeAddOp3(v, op, iTabCur, x, regOut);
- }
- if( iCol>=0 ){
sqlite3ColumnDefault(v, pTab, iCol, regOut);
}
}
@@ -100938,11 +102242,11 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(
int iReg, /* Store results here */
u8 p5 /* P5 value for OP_Column + FLAGS */
){
- Vdbe *v = pParse->pVdbe;
- assert( v!=0 );
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
+ assert( pParse->pVdbe!=0 );
+ sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg);
if( p5 ){
- sqlite3VdbeChangeP5(v, p5);
+ VdbeOp *pOp = sqlite3VdbeGetOp(pParse->pVdbe,-1);
+ if( pOp->opcode==OP_Column ) pOp->p5 = p5;
}
return iReg;
}
@@ -100952,7 +102256,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(
** over to iTo..iTo+nReg-1.
*/
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
- assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
}
@@ -101004,6 +102307,109 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){
return iResult;
}
+/*
+** Generate code to implement special SQL functions that are implemented
+** in-line rather than by using the usual callbacks.
+*/
+static int exprCodeInlineFunction(
+ Parse *pParse, /* Parsing context */
+ ExprList *pFarg, /* List of function arguments */
+ int iFuncId, /* Function ID. One of the INTFUNC_... values */
+ int target /* Store function result in this register */
+){
+ int nFarg;
+ Vdbe *v = pParse->pVdbe;
+ assert( v!=0 );
+ assert( pFarg!=0 );
+ nFarg = pFarg->nExpr;
+ assert( nFarg>0 ); /* All in-line functions have at least one argument */
+ switch( iFuncId ){
+ case INLINEFUNC_coalesce: {
+ /* Attempt a direct implementation of the built-in COALESCE() and
+ ** IFNULL() functions. This avoids unnecessary evaluation of
+ ** arguments past the first non-NULL argument.
+ */
+ int endCoalesce = sqlite3VdbeMakeLabel(pParse);
+ int i;
+ assert( nFarg>=2 );
+ sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
+ for(i=1; i<nFarg; i++){
+ sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
+ VdbeCoverage(v);
+ sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
+ }
+ if( sqlite3VdbeGetOp(v, -1)->opcode==OP_Copy ){
+ sqlite3VdbeChangeP5(v, 1); /* Tag trailing OP_Copy as not mergable */
+ }
+ sqlite3VdbeResolveLabel(v, endCoalesce);
+ break;
+ }
+
+ default: {
+ /* The UNLIKELY() function is a no-op. The result is the value
+ ** of the first argument.
+ */
+ assert( nFarg==1 || nFarg==2 );
+ target = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
+ break;
+ }
+
+ /***********************************************************************
+ ** Test-only SQL functions that are only usable if enabled
+ ** via SQLITE_TESTCTRL_INTERNAL_FUNCTIONS
+ */
+ case INLINEFUNC_expr_compare: {
+ /* Compare two expressions using sqlite3ExprCompare() */
+ assert( nFarg==2 );
+ sqlite3VdbeAddOp2(v, OP_Integer,
+ sqlite3ExprCompare(0,pFarg->a[0].pExpr, pFarg->a[1].pExpr,-1),
+ target);
+ break;
+ }
+
+ case INLINEFUNC_expr_implies_expr: {
+ /* Compare two expressions using sqlite3ExprImpliesExpr() */
+ assert( nFarg==2 );
+ sqlite3VdbeAddOp2(v, OP_Integer,
+ sqlite3ExprImpliesExpr(pParse,pFarg->a[0].pExpr, pFarg->a[1].pExpr,-1),
+ target);
+ break;
+ }
+
+ case INLINEFUNC_implies_nonnull_row: {
+ /* REsult of sqlite3ExprImpliesNonNullRow() */
+ Expr *pA1;
+ assert( nFarg==2 );
+ pA1 = pFarg->a[1].pExpr;
+ if( pA1->op==TK_COLUMN ){
+ sqlite3VdbeAddOp2(v, OP_Integer,
+ sqlite3ExprImpliesNonNullRow(pFarg->a[0].pExpr,pA1->iTable),
+ target);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Null, 0, target);
+ }
+ break;
+ }
+
+#ifdef SQLITE_DEBUG
+ case INLINEFUNC_affinity: {
+ /* The AFFINITY() function evaluates to a string that describes
+ ** the type affinity of the argument. This is used for testing of
+ ** the SQLite type logic.
+ */
+ const char *azAff[] = { "blob", "text", "numeric", "integer", "real" };
+ char aff;
+ assert( nFarg==1 );
+ aff = sqlite3ExprAffinity(pFarg->a[0].pExpr);
+ sqlite3VdbeLoadString(v, target,
+ (aff<=SQLITE_AFF_NONE) ? "none" : azAff[aff-SQLITE_AFF_BLOB]);
+ break;
+ }
+#endif
+ }
+ return target;
+}
+
/*
** Generate code into the current Vdbe to evaluate the given
@@ -101054,6 +102460,7 @@ expr_code_doover:
}
case TK_COLUMN: {
int iTab = pExpr->iTable;
+ int iReg;
if( ExprHasProperty(pExpr, EP_FixedCol) ){
/* This COLUMN expression is really a constant due to WHERE clause
** constraints, and that constant is coded by the pExpr->pLeft
@@ -101061,8 +102468,8 @@ expr_code_doover:
** datatype by applying the Affinity of the table column to the
** constant.
*/
- int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
int aff;
+ iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
if( pExpr->y.pTab ){
aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
}else{
@@ -101083,19 +102490,46 @@ expr_code_doover:
}
if( iTab<0 ){
if( pParse->iSelfTab<0 ){
- /* Generating CHECK constraints or inserting into partial index */
- assert( pExpr->y.pTab!=0 );
- assert( pExpr->iColumn>=XN_ROWID );
- assert( pExpr->iColumn<pExpr->y.pTab->nCol );
- if( pExpr->iColumn>=0
- && pExpr->y.pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
- ){
- sqlite3VdbeAddOp2(v, OP_SCopy, pExpr->iColumn - pParse->iSelfTab,
- target);
+ /* Other columns in the same row for CHECK constraints or
+ ** generated columns or for inserting into partial index.
+ ** The row is unpacked into registers beginning at
+ ** 0-(pParse->iSelfTab). The rowid (if any) is in a register
+ ** immediately prior to the first column.
+ */
+ Column *pCol;
+ Table *pTab = pExpr->y.pTab;
+ int iSrc;
+ int iCol = pExpr->iColumn;
+ assert( pTab!=0 );
+ assert( iCol>=XN_ROWID );
+ assert( iCol<pTab->nCol );
+ if( iCol<0 ){
+ return -1-pParse->iSelfTab;
+ }
+ pCol = pTab->aCol + iCol;
+ testcase( iCol!=sqlite3TableColumnToStorage(pTab,iCol) );
+ iSrc = sqlite3TableColumnToStorage(pTab, iCol) - pParse->iSelfTab;
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ if( pCol->colFlags & COLFLAG_GENERATED ){
+ if( pCol->colFlags & COLFLAG_BUSY ){
+ sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"",
+ pCol->zName);
+ return 0;
+ }
+ pCol->colFlags |= COLFLAG_BUSY;
+ if( pCol->colFlags & COLFLAG_NOTAVAIL ){
+ sqlite3ExprCodeGeneratedColumn(pParse, pCol, iSrc);
+ }
+ pCol->colFlags &= ~(COLFLAG_BUSY|COLFLAG_NOTAVAIL);
+ return iSrc;
+ }else
+#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
+ if( pCol->affinity==SQLITE_AFF_REAL ){
+ sqlite3VdbeAddOp2(v, OP_SCopy, iSrc, target);
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
return target;
}else{
- return pExpr->iColumn - pParse->iSelfTab;
+ return iSrc;
}
}else{
/* Coding an expression that is part of an index where column names
@@ -101103,9 +102537,13 @@ expr_code_doover:
iTab = pParse->iSelfTab - 1;
}
}
- return sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
+ iReg = sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
pExpr->iColumn, iTab, target,
pExpr->op2);
+ if( pExpr->y.pTab==0 && pExpr->affExpr==SQLITE_AFF_REAL ){
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
+ }
+ return iReg;
}
case TK_INTEGER: {
codeInteger(pParse, pExpr, 0, target);
@@ -101127,7 +102565,12 @@ expr_code_doover:
sqlite3VdbeLoadString(v, target, pExpr->u.zToken);
return target;
}
- case TK_NULL: {
+ default: {
+ /* Make NULL the default case so that if a bug causes an illegal
+ ** Expr node to be passed into this function, it will be handled
+ ** sanely and not crash. But keep the assert() to bring the problem
+ ** to the attention of the developers. */
+ assert( op==TK_NULL );
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
return target;
}
@@ -101154,7 +102597,7 @@ expr_code_doover:
sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
if( pExpr->u.zToken[1]!=0 ){
const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn);
- assert( pExpr->u.zToken[0]=='?' || strcmp(pExpr->u.zToken, z)==0 );
+ assert( pExpr->u.zToken[0]=='?' || (z && !strcmp(pExpr->u.zToken, z)) );
pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */
sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC);
}
@@ -101194,7 +102637,8 @@ expr_code_doover:
r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pLeft, pExpr->pRight, op,
- r1, r2, inReg, SQLITE_STOREP2 | p5);
+ 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);
@@ -101346,48 +102790,15 @@ expr_code_doover:
sqlite3ErrorMsg(pParse, "unknown function: %s()", zId);
break;
}
-
- /* Attempt a direct implementation of the built-in COALESCE() and
- ** IFNULL() functions. This avoids unnecessary evaluation of
- ** arguments past the first non-NULL argument.
- */
- if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){
- int endCoalesce = sqlite3VdbeMakeLabel(pParse);
- assert( nFarg>=2 );
- sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
- for(i=1; i<nFarg; i++){
- sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
- VdbeCoverage(v);
- sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
- }
- sqlite3VdbeResolveLabel(v, endCoalesce);
- break;
- }
-
- /* The UNLIKELY() function is a no-op. The result is the value
- ** of the first argument.
- */
- if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
- assert( nFarg>=1 );
- return sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
+ if( pDef->funcFlags & SQLITE_FUNC_INLINE ){
+ assert( (pDef->funcFlags & SQLITE_FUNC_UNSAFE)==0 );
+ assert( (pDef->funcFlags & SQLITE_FUNC_DIRECT)==0 );
+ return exprCodeInlineFunction(pParse, pFarg,
+ SQLITE_PTR_TO_INT(pDef->pUserData), target);
+ }else if( pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE) ){
+ sqlite3ExprFunctionUsable(pParse, pExpr, pDef);
}
-#ifdef SQLITE_DEBUG
- /* The AFFINITY() function evaluates to a string that describes
- ** the type affinity of the argument. This is used for testing of
- ** the SQLite type logic.
- */
- if( pDef->funcFlags & SQLITE_FUNC_AFFINITY ){
- const char *azAff[] = { "blob", "text", "numeric", "integer", "real" };
- char aff;
- assert( nFarg==1 );
- aff = sqlite3ExprAffinity(pFarg->a[0].pExpr);
- sqlite3VdbeLoadString(v, target,
- (aff<=SQLITE_AFF_NONE) ? "none" : azAff[aff-SQLITE_AFF_BLOB]);
- return target;
- }
-#endif
-
for(i=0; i<nFarg; i++){
if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
testcase( i==31 );
@@ -101463,12 +102874,15 @@ expr_code_doover:
}else
#endif
{
- sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0,
- constMask, r1, target, (char*)pDef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, (u8)nFarg);
+ sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg,
+ pDef, pExpr->op2);
}
- if( nFarg && constMask==0 ){
- sqlite3ReleaseTempRange(pParse, r1, nFarg);
+ if( nFarg ){
+ if( constMask==0 ){
+ sqlite3ReleaseTempRange(pParse, r1, nFarg);
+ }else{
+ sqlite3VdbeReleaseRegisters(pParse, r1, nFarg, constMask, 1);
+ }
}
return target;
}
@@ -101562,17 +102976,19 @@ expr_code_doover:
** p1==2 -> old.b p1==5 -> new.b
*/
Table *pTab = pExpr->y.pTab;
- int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
+ int iCol = pExpr->iColumn;
+ int p1 = pExpr->iTable * (pTab->nCol+1) + 1
+ + sqlite3TableColumnToStorage(pTab, iCol);
assert( pExpr->iTable==0 || pExpr->iTable==1 );
- assert( pExpr->iColumn>=-1 && pExpr->iColumn<pTab->nCol );
- assert( pTab->iPKey<0 || pExpr->iColumn!=pTab->iPKey );
+ assert( iCol>=-1 && iCol<pTab->nCol );
+ assert( pTab->iPKey<0 || iCol!=pTab->iPKey );
assert( p1>=0 && p1<(pTab->nCol*2+2) );
sqlite3VdbeAddOp2(v, OP_Param, p1, target);
VdbeComment((v, "r[%d]=%s.%s", target,
(pExpr->iTable ? "new" : "old"),
- (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[pExpr->iColumn].zName)
+ (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[iCol].zName)
));
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -101581,9 +102997,7 @@ expr_code_doover:
**
** EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to
** floating point when extracting it from the record. */
- if( pExpr->iColumn>=0
- && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
- ){
+ if( iCol>=0 && pTab->aCol[iCol].affinity==SQLITE_AFF_REAL ){
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
}
#endif
@@ -101638,7 +103052,7 @@ expr_code_doover:
** or if there is no matching Ei, the ELSE term Y, or if there is
** no ELSE term, NULL.
*/
- default: assert( op==TK_CASE ); {
+ case TK_CASE: {
int endLabel; /* GOTO label for end of CASE stmt */
int nextCase; /* GOTO label for next WHEN clause */
int nExpr; /* 2x number of WHEN terms */
@@ -101816,14 +103230,16 @@ SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
int inReg;
assert( target>0 && target<=pParse->nMem );
- if( pExpr && pExpr->op==TK_REGISTER ){
- sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target);
- }else{
- inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
- assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
- if( inReg!=target && pParse->pVdbe ){
- sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target);
+ inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
+ assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
+ if( inReg!=target && pParse->pVdbe ){
+ u8 op;
+ if( ExprHasProperty(pExpr,EP_Subquery) ){
+ op = OP_Copy;
+ }else{
+ op = OP_SCopy;
}
+ sqlite3VdbeAddOp2(pParse->pVdbe, op, inReg, target);
}
}
@@ -101854,30 +103270,6 @@ SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int ta
}
/*
-** Generate code that evaluates the given expression and puts the result
-** in register target.
-**
-** Also make a copy of the expression results into another "cache" register
-** and modify the expression so that the next time it is evaluated,
-** the result is a copy of the cache register.
-**
-** This routine is used for expressions that are used multiple
-** times. They are evaluated once and the results of the expression
-** are reused.
-*/
-SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
- Vdbe *v = pParse->pVdbe;
- int iMem;
-
- assert( target>0 );
- assert( pExpr->op!=TK_REGISTER );
- sqlite3ExprCode(pParse, pExpr, target);
- iMem = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Copy, target, iMem);
- exprToRegister(pExpr, iMem);
-}
-
-/*
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
**
@@ -101940,6 +103332,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList(
&& (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy
&& pOp->p1+pOp->p3+1==inReg
&& pOp->p2+pOp->p3+1==target+i
+ && pOp->p5==0 /* The do-not-merge flag must be clear */
){
pOp->p3++;
}else{
@@ -102114,7 +103507,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
- r1, r2, dest, jumpIfNull);
+ r1, r2, dest, jumpIfNull, ExprHasProperty(pExpr,EP_Commuted));
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
@@ -102289,7 +103682,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
- r1, r2, dest, jumpIfNull);
+ r1, r2, dest, jumpIfNull,ExprHasProperty(pExpr,EP_Commuted));
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
@@ -102475,7 +103868,8 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTa
return 2;
}
}
- if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
+ if( (pA->flags & (EP_Distinct|EP_Commuted))
+ != (pB->flags & (EP_Distinct|EP_Commuted)) ) return 2;
if( (combinedFlags & EP_TokenOnly)==0 ){
if( combinedFlags & EP_xIsSelect ) return 2;
if( (combinedFlags & EP_FixedCol)==0
@@ -102487,18 +103881,33 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTa
&& (combinedFlags & EP_Reduced)==0
){
if( pA->iColumn!=pB->iColumn ) return 2;
- if( pA->op2!=pB->op2 ) return 2;
- if( pA->op!=TK_IN
- && pA->iTable!=pB->iTable
- && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
+ if( pA->op2!=pB->op2 ){
+ if( pA->op==TK_TRUTH ) return 2;
+ if( pA->op==TK_FUNCTION && iTab<0 ){
+ /* Ex: CREATE TABLE t1(a CHECK( a<julianday('now') ));
+ ** INSERT INTO t1(a) VALUES(julianday('now')+10);
+ ** Without this test, sqlite3ExprCodeAtInit() will run on the
+ ** the julianday() of INSERT first, and remember that expression.
+ ** Then sqlite3ExprCodeInit() will see the julianday() in the CHECK
+ ** constraint as redundant, reusing the one from the INSERT, even
+ ** though the julianday() in INSERT lacks the critical NC_IsCheck
+ ** flag. See ticket [830277d9db6c3ba1] (2019-10-30)
+ */
+ return 2;
+ }
+ }
+ if( pA->op!=TK_IN && pA->iTable!=pB->iTable && pA->iTable!=iTab ){
+ return 2;
+ }
}
}
return 0;
}
/*
-** Compare two ExprList objects. Return 0 if they are identical and
-** non-zero if they differ in any way.
+** Compare two ExprList objects. Return 0 if they are identical, 1
+** if they are certainly different, or 2 if it is not possible to
+** determine if they are identical or not.
**
** If any subelement of pB has Expr.iTable==(-1) then it is allowed
** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
@@ -102517,10 +103926,11 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
if( pA==0 || pB==0 ) return 1;
if( pA->nExpr!=pB->nExpr ) return 1;
for(i=0; i<pA->nExpr; i++){
+ int res;
Expr *pExprA = pA->a[i].pExpr;
Expr *pExprB = pB->a[i].pExpr;
if( pA->a[i].sortFlags!=pB->a[i].sortFlags ) return 1;
- if( sqlite3ExprCompare(0, pExprA, pExprB, iTab) ) return 1;
+ if( (res = sqlite3ExprCompare(0, pExprA, pExprB, iTab)) ) return res;
}
return 0;
}
@@ -102657,7 +104067,7 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, i
}
/*
-** This is the Expr node callback for sqlite3ExprImpliesNotNullRow().
+** This is the Expr node callback for sqlite3ExprImpliesNonNullRow().
** If the expression node requires that the table at pWalker->iCur
** have one or more non-NULL column, then set pWalker->eCode to 1 and abort.
**
@@ -102675,6 +104085,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
case TK_NOTNULL:
case TK_IS:
case TK_OR:
+ case TK_VECTOR:
case TK_CASE:
case TK_IN:
case TK_FUNCTION:
@@ -102684,6 +104095,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_NOTNULL );
testcase( pExpr->op==TK_IS );
testcase( pExpr->op==TK_OR );
+ testcase( pExpr->op==TK_VECTOR );
testcase( pExpr->op==TK_CASE );
testcase( pExpr->op==TK_IN );
testcase( pExpr->op==TK_FUNCTION );
@@ -102697,15 +104109,20 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
return WRC_Prune;
case TK_AND:
- if( sqlite3ExprImpliesNonNullRow(pExpr->pLeft, pWalker->u.iCur)
- && sqlite3ExprImpliesNonNullRow(pExpr->pRight, pWalker->u.iCur)
- ){
- pWalker->eCode = 1;
+ if( pWalker->eCode==0 ){
+ sqlite3WalkExpr(pWalker, pExpr->pLeft);
+ if( pWalker->eCode ){
+ pWalker->eCode = 0;
+ sqlite3WalkExpr(pWalker, pExpr->pRight);
+ }
}
return WRC_Prune;
case TK_BETWEEN:
- sqlite3WalkExpr(pWalker, pExpr->pLeft);
+ if( sqlite3WalkExpr(pWalker, pExpr->pLeft)==WRC_Abort ){
+ assert( pWalker->eCode );
+ return WRC_Abort;
+ }
return WRC_Prune;
/* Virtual tables are allowed to use constraints like x=NULL. So
@@ -102759,14 +104176,13 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){
Walker w;
p = sqlite3ExprSkipCollateAndLikely(p);
- while( p ){
- if( p->op==TK_NOTNULL ){
- p = p->pLeft;
- }else if( p->op==TK_AND ){
+ if( p==0 ) return 0;
+ if( p->op==TK_NOTNULL ){
+ p = p->pLeft;
+ }else{
+ while( p->op==TK_AND ){
if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab) ) return 1;
p = p->pRight;
- }else{
- break;
}
}
w.xExprCallback = impliesNotNullRow;
@@ -102798,7 +104214,7 @@ struct IdxCover {
static int exprIdxCover(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_COLUMN
&& pExpr->iTable==pWalker->u.pIdxCover->iCur
- && sqlite3ColumnOfIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0
+ && sqlite3TableColumnToIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0
){
pWalker->eCode = 1;
return WRC_Abort;
@@ -102849,12 +104265,13 @@ struct SrcCount {
** Count the number of references to columns.
*/
static int exprSrcCount(Walker *pWalker, Expr *pExpr){
- /* The NEVER() on the second term is because sqlite3FunctionUsesThisSrc()
- ** is always called before sqlite3ExprAnalyzeAggregates() and so the
- ** TK_COLUMNs have not yet been converted into TK_AGG_COLUMN. If
- ** sqlite3FunctionUsesThisSrc() is used differently in the future, the
- ** NEVER() will need to be removed. */
- if( pExpr->op==TK_COLUMN || NEVER(pExpr->op==TK_AGG_COLUMN) ){
+ /* There was once a NEVER() on the second term on the grounds that
+ ** sqlite3FunctionUsesThisSrc() was always called before
+ ** sqlite3ExprAnalyzeAggregates() and so the TK_COLUMNs have not yet
+ ** been converted into TK_AGG_COLUMN. But this is no longer true due
+ ** to window functions - sqlite3WindowRewrite() may now indirectly call
+ ** FunctionUsesThisSrc() when creating a new sub-select. */
+ if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){
int i;
struct SrcCount *p = pWalker->u.pSrcCount;
SrcList *pSrc = p->pSrc;
@@ -102892,6 +104309,11 @@ SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
cnt.nThis = 0;
cnt.nOther = 0;
sqlite3WalkExprList(&w, pExpr->x.pList);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
+ sqlite3WalkExpr(&w, pExpr->y.pWin->pFilter);
+ }
+#endif
return cnt.nThis>0 || cnt.nOther==0;
}
@@ -103120,8 +104542,11 @@ SQLITE_PRIVATE int sqlite3GetTempReg(Parse *pParse){
** purpose.
*/
SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
- if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
- pParse->aTempReg[pParse->nTempReg++] = iReg;
+ if( iReg ){
+ sqlite3VdbeReleaseRegisters(pParse, iReg, 1, 0, 0);
+ if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
+ pParse->aTempReg[pParse->nTempReg++] = iReg;
+ }
}
}
@@ -103147,6 +104572,7 @@ SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
sqlite3ReleaseTempReg(pParse, iReg);
return;
}
+ sqlite3VdbeReleaseRegisters(pParse, iReg, nReg, 0, 0);
if( nReg>pParse->nRangeReg ){
pParse->nRangeReg = nReg;
pParse->iRangeReg = iReg;
@@ -103224,9 +104650,8 @@ SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse *pParse, int iFirst, int iLast){
static int isAlterableTable(Parse *pParse, Table *pTab){
if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
#ifndef SQLITE_OMIT_VIRTUALTABLE
- || ( (pTab->tabFlags & TF_Shadow)
- && (pParse->db->flags & SQLITE_Defensive)
- && pParse->db->nVdbeExec==0
+ || ( (pTab->tabFlags & TF_Shadow)!=0
+ && sqlite3ReadOnlyShadowTables(pParse->db)
)
#endif
){
@@ -103491,14 +104916,6 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
}
#endif
- /* If the default value for the new column was specified with a
- ** literal NULL, then set pDflt to 0. This simplifies checking
- ** for an SQL NULL default below.
- */
- assert( pDflt==0 || pDflt->op==TK_SPAN );
- if( pDflt && pDflt->pLeft->op==TK_NULL ){
- pDflt = 0;
- }
/* Check that the new column is not specified as PRIMARY KEY or UNIQUE.
** If there is a NOT NULL constraint, then the default value for the
@@ -103512,36 +104929,50 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column");
return;
}
- if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
- sqlite3ErrorMsg(pParse,
- "Cannot add a REFERENCES column with non-NULL default value");
- return;
- }
- if( pCol->notNull && !pDflt ){
- sqlite3ErrorMsg(pParse,
- "Cannot add a NOT NULL column with default value NULL");
- return;
- }
-
- /* Ensure the default expression is something that sqlite3ValueFromExpr()
- ** can handle (i.e. not CURRENT_TIME etc.)
- */
- if( pDflt ){
- sqlite3_value *pVal = 0;
- int rc;
- rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);
- assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
- if( rc!=SQLITE_OK ){
- assert( db->mallocFailed == 1 );
+ if( (pCol->colFlags & COLFLAG_GENERATED)==0 ){
+ /* If the default value for the new column was specified with a
+ ** literal NULL, then set pDflt to 0. This simplifies checking
+ ** for an SQL NULL default below.
+ */
+ assert( pDflt==0 || pDflt->op==TK_SPAN );
+ if( pDflt && pDflt->pLeft->op==TK_NULL ){
+ pDflt = 0;
+ }
+ if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
+ sqlite3ErrorMsg(pParse,
+ "Cannot add a REFERENCES column with non-NULL default value");
return;
}
- if( !pVal ){
- sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
+ if( pCol->notNull && !pDflt ){
+ sqlite3ErrorMsg(pParse,
+ "Cannot add a NOT NULL column with default value NULL");
return;
}
- sqlite3ValueFree(pVal);
+
+ /* Ensure the default expression is something that sqlite3ValueFromExpr()
+ ** can handle (i.e. not CURRENT_TIME etc.)
+ */
+ if( pDflt ){
+ sqlite3_value *pVal = 0;
+ int rc;
+ rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);
+ assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
+ if( rc!=SQLITE_OK ){
+ assert( db->mallocFailed == 1 );
+ return;
+ }
+ if( !pVal ){
+ sqlite3ErrorMsg(pParse,"Cannot add a column with non-constant default");
+ return;
+ }
+ sqlite3ValueFree(pVal);
+ }
+ }else if( pCol->colFlags & COLFLAG_STORED ){
+ sqlite3ErrorMsg(pParse, "cannot add a STORED column");
+ return;
}
+
/* Modify the CREATE TABLE statement. */
zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
if( zCol ){
@@ -103885,12 +105316,14 @@ SQLITE_PRIVATE void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pTo
RenameToken *pNew;
assert( pPtr || pParse->db->mallocFailed );
renameTokenCheckAll(pParse, pPtr);
- pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));
- if( pNew ){
- pNew->p = pPtr;
- pNew->t = *pToken;
- pNew->pNext = pParse->pRename;
- pParse->pRename = pNew;
+ if( pParse->eParseMode!=PARSE_MODE_UNMAP ){
+ pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));
+ if( pNew ){
+ pNew->p = pPtr;
+ pNew->t = *pToken;
+ pNew->pNext = pParse->pRename;
+ pParse->pRename = pNew;
+ }
}
return pPtr;
@@ -103922,17 +105355,38 @@ static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){
}
/*
+** Iterate through the Select objects that are part of WITH clauses attached
+** to select statement pSelect.
+*/
+static void renameWalkWith(Walker *pWalker, Select *pSelect){
+ With *pWith = pSelect->pWith;
+ if( pWith ){
+ int i;
+ for(i=0; i<pWith->nCte; i++){
+ Select *p = pWith->a[i].pSelect;
+ NameContext sNC;
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pWalker->pParse;
+ sqlite3SelectPrep(sNC.pParse, p, &sNC);
+ sqlite3WalkSelect(pWalker, p);
+ sqlite3RenameExprlistUnmap(pWalker->pParse, pWith->a[i].pCols);
+ }
+ }
+}
+
+/*
** Walker callback used by sqlite3RenameExprUnmap().
*/
static int renameUnmapSelectCb(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
int i;
- if( p->selFlags & SF_View ) return WRC_Prune;
+ 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].zName ){
- sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zName);
+ if( pList->a[i].zEName && pList->a[i].eEName==ENAME_NAME ){
+ sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName);
}
}
}
@@ -103940,8 +105394,11 @@ static int renameUnmapSelectCb(Walker *pWalker, Select *p){
SrcList *pSrc = p->pSrc;
for(i=0; i<pSrc->nSrc; i++){
sqlite3RenameTokenRemap(pParse, 0, (void*)pSrc->a[i].zName);
+ if( sqlite3WalkExpr(pWalker, pSrc->a[i].pOn) ) return WRC_Abort;
}
}
+
+ renameWalkWith(pWalker, p);
return WRC_Continue;
}
@@ -103949,12 +105406,15 @@ static int renameUnmapSelectCb(Walker *pWalker, Select *p){
** Remove all nodes that are part of expression pExpr from the rename list.
*/
SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){
+ u8 eMode = pParse->eParseMode;
Walker sWalker;
memset(&sWalker, 0, sizeof(Walker));
sWalker.pParse = pParse;
sWalker.xExprCallback = renameUnmapExprCb;
sWalker.xSelectCallback = renameUnmapSelectCb;
+ pParse->eParseMode = PARSE_MODE_UNMAP;
sqlite3WalkExpr(&sWalker, pExpr);
+ pParse->eParseMode = eMode;
}
/*
@@ -103970,7 +105430,9 @@ SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse *pParse, ExprList *pEList){
sWalker.xExprCallback = renameUnmapExprCb;
sqlite3WalkExprList(&sWalker, pEList);
for(i=0; i<pEList->nExpr; i++){
- sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zName);
+ if( ALWAYS(pEList->a[i].eEName==ENAME_NAME) ){
+ sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zEName);
+ }
}
}
}
@@ -104009,24 +105471,6 @@ static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
}
/*
-** Iterate through the Select objects that are part of WITH clauses attached
-** to select statement pSelect.
-*/
-static void renameWalkWith(Walker *pWalker, Select *pSelect){
- if( pSelect->pWith ){
- int i;
- for(i=0; i<pSelect->pWith->nCte; i++){
- Select *p = pSelect->pWith->a[i].pSelect;
- NameContext sNC;
- memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pWalker->pParse;
- sqlite3SelectPrep(sNC.pParse, p, &sNC);
- sqlite3WalkSelect(pWalker, p);
- }
- }
-}
-
-/*
** This is a Walker select callback. It does nothing. It is only required
** because without a dummy callback, sqlite3WalkExpr() and similar do not
** descend into sub-select statements.
@@ -104126,8 +105570,11 @@ static void renameColumnElistNames(
if( pEList ){
int i;
for(i=0; i<pEList->nExpr; i++){
- char *zName = pEList->a[i].zName;
- if( 0==sqlite3_stricmp(zName, zOld) ){
+ char *zName = pEList->a[i].zEName;
+ if( ALWAYS(pEList->a[i].eEName==ENAME_NAME)
+ && ALWAYS(zName!=0)
+ && 0==sqlite3_stricmp(zName, zOld)
+ ){
renameTokenFind(pParse, pCtx, (void*)zName);
}
}
@@ -104163,7 +105610,6 @@ static void renameColumnIdlistNames(
static int renameParseSql(
Parse *p, /* Memory to use for Parse object */
const char *zDb, /* Name of schema SQL belongs to */
- int bTable, /* 1 -> RENAME TABLE, 0 -> RENAME COLUMN */
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL to parse */
int bTemp /* True if SQL is from temp schema */
@@ -104177,7 +105623,7 @@ static int renameParseSql(
** occurs and the parse does not result in a new table, index or
** trigger object, the database must be corrupt. */
memset(p, 0, sizeof(Parse));
- p->eParseMode = (bTable ? PARSE_MODE_RENAME_TABLE : PARSE_MODE_RENAME_COLUMN);
+ p->eParseMode = PARSE_MODE_RENAME;
p->db = db;
p->nQueryLoop = 1;
rc = sqlite3RunParser(p, zSql, &zErr);
@@ -104484,7 +105930,7 @@ static void renameColumnFunc(
#ifndef SQLITE_OMIT_AUTHORIZATION
db->xAuth = 0;
#endif
- rc = renameParseSql(&sParse, zDb, 0, db, zSql, bTemp);
+ rc = renameParseSql(&sParse, zDb, db, zSql, bTemp);
/* Find tokens that need to be replaced. */
memset(&sWalker, 0, sizeof(Walker));
@@ -104527,6 +105973,11 @@ static void renameColumnFunc(
sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
}
}
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ for(i=0; i<sParse.pNewTable->nCol; i++){
+ sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
+ }
+#endif
for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
for(i=0; i<pFKey->nCol; i++){
@@ -104683,7 +106134,7 @@ static void renameTableFunc(
sWalker.xSelectCallback = renameTableSelectCb;
sWalker.u.pRename = &sCtx;
- rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
+ rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
if( rc==SQLITE_OK ){
int isLegacy = (db->flags & SQLITE_LegacyAlter);
@@ -104700,8 +106151,11 @@ static void renameTableFunc(
assert( pSelect->selFlags & SF_View );
pSelect->selFlags &= ~SF_View;
sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
- if( sParse.nErr ) rc = sParse.rc;
- sqlite3WalkSelect(&sWalker, pTab->pSelect);
+ if( sParse.nErr ){
+ rc = sParse.rc;
+ }else{
+ sqlite3WalkSelect(&sWalker, pTab->pSelect);
+ }
}
}else{
/* Modify any FK definitions to point to the new table. */
@@ -104822,7 +106276,7 @@ static void renameTableTest(
if( zDb && zInput ){
int rc;
Parse sParse;
- rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
+ rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
if( rc==SQLITE_OK ){
if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
NameContext sNC;
@@ -105788,18 +107242,17 @@ static const FuncDef statGetFuncdef = {
{0}
};
-static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
- assert( regOut!=regStat4 && regOut!=regStat4+1 );
+static void callStatGet(Parse *pParse, int regStat4, int iParam, int regOut){
#ifdef SQLITE_ENABLE_STAT4
- sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1);
+ sqlite3VdbeAddOp2(pParse->pVdbe, OP_Integer, iParam, regStat4+1);
#elif SQLITE_DEBUG
assert( iParam==STAT_GET_STAT1 );
#else
UNUSED_PARAMETER( iParam );
#endif
- sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4, regOut,
- (char*)&statGetFuncdef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, 1 + IsStat4);
+ assert( regOut!=regStat4 && regOut!=regStat4+1 );
+ sqlite3VdbeAddFunctionCall(pParse, 0, regStat4, regOut, 1+IsStat4,
+ &statGetFuncdef, 0);
}
/*
@@ -105967,9 +107420,8 @@ static void analyzeOneTable(
#endif
sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2);
- sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4+1, regStat4,
- (char*)&statInitFuncdef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, 2+IsStat4);
+ sqlite3VdbeAddFunctionCall(pParse, 0, regStat4+1, regStat4, 2+IsStat4,
+ &statInitFuncdef, 0);
/* Implementation of the following:
**
@@ -106054,7 +107506,7 @@ static void analyzeOneTable(
int j, k, regKey;
regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
for(j=0; j<pPk->nKeyCol; j++){
- k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
+ k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
assert( k>=0 && k<pIdx->nColumn );
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
@@ -106064,13 +107516,12 @@ static void analyzeOneTable(
}
#endif
assert( regChng==(regStat4+1) );
- sqlite3VdbeAddOp4(v, OP_Function0, 1, regStat4, regTemp,
- (char*)&statPushFuncdef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, 2+IsStat4);
+ sqlite3VdbeAddFunctionCall(pParse, 1, regStat4, regTemp, 2+IsStat4,
+ &statPushFuncdef, 0);
sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
/* Add the entry to the stat1 table. */
- callStatGet(v, regStat4, STAT_GET_STAT1, regStat1);
+ callStatGet(pParse, regStat4, STAT_GET_STAT1, regStat1);
assert( "BBB"[0]==SQLITE_AFF_TEXT );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
@@ -106096,12 +107547,12 @@ static void analyzeOneTable(
pParse->nMem = MAX(pParse->nMem, regCol+nCol);
addrNext = sqlite3VdbeCurrentAddr(v);
- callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid);
+ callStatGet(pParse, regStat4, STAT_GET_ROWID, regSampleRowid);
addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
VdbeCoverage(v);
- callStatGet(v, regStat4, STAT_GET_NEQ, regEq);
- callStatGet(v, regStat4, STAT_GET_NLT, regLt);
- callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
+ callStatGet(pParse, regStat4, STAT_GET_NEQ, regEq);
+ callStatGet(pParse, regStat4, STAT_GET_NLT, regLt);
+ callStatGet(pParse, regStat4, STAT_GET_NDLT, regDLt);
sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
VdbeCoverage(v);
for(i=0; i<nCol; i++){
@@ -106726,9 +108177,9 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
/* Load the statistics from the sqlite_stat4 table. */
#ifdef SQLITE_ENABLE_STAT4
if( rc==SQLITE_OK ){
- db->lookaside.bDisable++;
+ DisableLookaside;
rc = loadStat4(db, sInfo.zDatabase);
- db->lookaside.bDisable--;
+ EnableLookaside;
}
for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
@@ -107151,11 +108602,8 @@ static void codeAttach(
assert( v || db->mallocFailed );
if( v ){
- sqlite3VdbeAddOp4(v, OP_Function0, 0, regArgs+3-pFunc->nArg, regArgs+3,
- (char *)pFunc, P4_FUNCDEF);
- assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg );
- sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg));
-
+ sqlite3VdbeAddFunctionCall(pParse, 0, regArgs+3-pFunc->nArg, regArgs+3,
+ pFunc->nArg, pFunc, 0);
/* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
** statement only). For DETACH, set it to false (expire all existing
** statements).
@@ -107230,7 +108678,7 @@ SQLITE_PRIVATE void sqlite3FixInit(
pFix->pSchema = db->aDb[iDb].pSchema;
pFix->zType = zType;
pFix->pName = pName;
- pFix->bVarOnly = (iDb==1);
+ pFix->bTemp = (iDb==1);
}
/*
@@ -107258,7 +108706,7 @@ SQLITE_PRIVATE int sqlite3FixSrcList(
if( NEVER(pList==0) ) return 0;
zDb = pFix->zDb;
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
- if( pFix->bVarOnly==0 ){
+ if( pFix->bTemp==0 ){
if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
sqlite3ErrorMsg(pFix->pParse,
"%s %T cannot reference objects in database %s",
@@ -107268,6 +108716,7 @@ SQLITE_PRIVATE int sqlite3FixSrcList(
sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
pItem->zDatabase = 0;
pItem->pSchema = pFix->pSchema;
+ pItem->fg.fromDDL = 1;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
@@ -107323,7 +108772,7 @@ SQLITE_PRIVATE int sqlite3FixExpr(
Expr *pExpr /* The expression to be fixed to one database */
){
while( pExpr ){
- ExprSetProperty(pExpr, EP_Indirect);
+ if( !pFix->bTemp ) ExprSetProperty(pExpr, EP_FromDDL);
if( pExpr->op==TK_VARIABLE ){
if( pFix->pParse->db->init.busy ){
pExpr->op = TK_NULL;
@@ -108498,22 +109947,6 @@ SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3 *db){
}
/*
- ** Return TRUE if shadow tables should be read-only in the current
- ** context.
- */
-int sqlite3ReadOnlyShadowTables(sqlite3 *db){
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( (db->flags & SQLITE_Defensive)!=0
- && db->pVtabCtx==0
- && db->nVdbeExec==0
- ){
- return 1;
- }
-#endif
- return 0;
-}
-
-/*
** This routine is used to check if the UTF-8 string zName is a legal
** unqualified name for a new schema object (table, index, view or
** trigger). All names are legal except those that begin with the string
@@ -108546,13 +109979,14 @@ SQLITE_PRIVATE int sqlite3CheckObjectName(
}
}
}else{
- if( (pParse->nested==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7))
- || (sqlite3ReadOnlyShadowTables(db) && sqlite3ShadowTableName(db, zName))
+ if( (pParse->nested==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7))
+ || (sqlite3ReadOnlyShadowTables(db) && sqlite3ShadowTableName(db, zName))
){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s",
zName);
return SQLITE_ERROR;
}
+
}
return SQLITE_OK;
}
@@ -108567,10 +110001,12 @@ SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table *pTab){
}
/*
-** Return the column of index pIdx that corresponds to table
-** column iCol. Return -1 if not found.
+** Convert an table column number into a index column number. That is,
+** for the column iCol in the table (as defined by the CREATE TABLE statement)
+** find the (first) offset of that column in index pIdx. Or return -1
+** if column iCol is not used in index pIdx.
*/
-SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index *pIdx, i16 iCol){
+SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index *pIdx, i16 iCol){
int i;
for(i=0; i<pIdx->nColumn; i++){
if( iCol==pIdx->aiColumn[i] ) return i;
@@ -108578,6 +110014,84 @@ SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index *pIdx, i16 iCol){
return -1;
}
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+/* Convert a storage column number into a table column number.
+**
+** The storage column number (0,1,2,....) is the index of the value
+** as it appears in the record on disk. The true column number
+** is the index (0,1,2,...) of the column in the CREATE TABLE statement.
+**
+** The storage column number is less than the table column number if
+** and only there are VIRTUAL columns to the left.
+**
+** If SQLITE_OMIT_GENERATED_COLUMNS, this routine is a no-op macro.
+*/
+SQLITE_PRIVATE i16 sqlite3StorageColumnToTable(Table *pTab, i16 iCol){
+ if( pTab->tabFlags & TF_HasVirtual ){
+ int i;
+ for(i=0; i<=iCol; i++){
+ if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) iCol++;
+ }
+ }
+ return iCol;
+}
+#endif
+
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+/* Convert a table column number into a storage column number.
+**
+** The storage column number (0,1,2,....) is the index of the value
+** as it appears in the record on disk. Or, if the input column is
+** the N-th virtual column (zero-based) then the storage number is
+** the number of non-virtual columns in the table plus N.
+**
+** The true column number is the index (0,1,2,...) of the column in
+** the CREATE TABLE statement.
+**
+** If the input column is a VIRTUAL column, then it should not appear
+** in storage. But the value sometimes is cached in registers that
+** follow the range of registers used to construct storage. This
+** avoids computing the same VIRTUAL column multiple times, and provides
+** values for use by OP_Param opcodes in triggers. Hence, if the
+** input column is a VIRTUAL table, put it after all the other columns.
+**
+** In the following, N means "normal column", S means STORED, and
+** V means VIRTUAL. Suppose the CREATE TABLE has columns like this:
+**
+** CREATE TABLE ex(N,S,V,N,S,V,N,S,V);
+** -- 0 1 2 3 4 5 6 7 8
+**
+** Then the mapping from this function is as follows:
+**
+** INPUTS: 0 1 2 3 4 5 6 7 8
+** OUTPUTS: 0 1 6 2 3 7 4 5 8
+**
+** So, in other words, this routine shifts all the virtual columns to
+** the end.
+**
+** If SQLITE_OMIT_GENERATED_COLUMNS then there are no virtual columns and
+** this routine is a no-op macro. If the pTab does not have any virtual
+** columns, then this routine is no-op that always return iCol. If iCol
+** is negative (indicating the ROWID column) then this routine return iCol.
+*/
+SQLITE_PRIVATE i16 sqlite3TableColumnToStorage(Table *pTab, i16 iCol){
+ int i;
+ i16 n;
+ assert( iCol<pTab->nCol );
+ if( (pTab->tabFlags & TF_HasVirtual)==0 || iCol<0 ) return iCol;
+ for(i=0, n=0; i<iCol; i++){
+ if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) n++;
+ }
+ if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ){
+ /* iCol is a virtual column itself */
+ return pTab->nNVCol + i - n;
+ }else{
+ /* iCol is a normal or stored column */
+ return n;
+ }
+}
+#endif
+
/*
** Begin constructing a new table representation in memory. This is
** the first of several action routines that get called in response
@@ -108868,6 +110382,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
pCol->colFlags |= COLFLAG_HASTYPE;
}
p->nCol++;
+ p->nNVCol++;
pParse->constraintName.n = 0;
}
@@ -109012,10 +110527,17 @@ SQLITE_PRIVATE void sqlite3AddDefaultValue(
sqlite3 *db = pParse->db;
p = pParse->pNewTable;
if( p!=0 ){
+ int isInit = db->init.busy && db->init.iDb!=1;
pCol = &(p->aCol[p->nCol-1]);
- if( !sqlite3ExprIsConstantOrFunction(pExpr, db->init.busy) ){
+ if( !sqlite3ExprIsConstantOrFunction(pExpr, isInit) ){
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
pCol->zName);
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ }else if( pCol->colFlags & COLFLAG_GENERATED ){
+ testcase( pCol->colFlags & COLFLAG_VIRTUAL );
+ testcase( pCol->colFlags & COLFLAG_STORED );
+ sqlite3ErrorMsg(pParse, "cannot use DEFAULT on a generated column");
+#endif
}else{
/* A copy of pExpr is used instead of the original, as pExpr contains
** tokens that point to volatile memory.
@@ -109062,6 +110584,21 @@ static void sqlite3StringToId(Expr *p){
}
/*
+** Tag the given column as being part of the PRIMARY KEY
+*/
+static void makeColumnPartOfPrimaryKey(Parse *pParse, Column *pCol){
+ pCol->colFlags |= COLFLAG_PRIMKEY;
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ if( pCol->colFlags & COLFLAG_GENERATED ){
+ testcase( pCol->colFlags & COLFLAG_VIRTUAL );
+ testcase( pCol->colFlags & COLFLAG_STORED );
+ sqlite3ErrorMsg(pParse,
+ "generated columns cannot be part of the PRIMARY KEY");
+ }
+#endif
+}
+
+/*
** Designate the PRIMARY KEY for the table. pList is a list of names
** of columns that form the primary key. If pList is NULL, then the
** most recently added column of the table is the primary key.
@@ -109100,7 +110637,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
if( pList==0 ){
iCol = pTab->nCol - 1;
pCol = &pTab->aCol[iCol];
- pCol->colFlags |= COLFLAG_PRIMKEY;
+ makeColumnPartOfPrimaryKey(pParse, pCol);
nTerm = 1;
}else{
nTerm = pList->nExpr;
@@ -109113,7 +110650,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
for(iCol=0; iCol<pTab->nCol; iCol++){
if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){
pCol = &pTab->aCol[iCol];
- pCol->colFlags |= COLFLAG_PRIMKEY;
+ makeColumnPartOfPrimaryKey(pParse, pCol);
break;
}
}
@@ -109134,6 +110671,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
assert( autoInc==0 || autoInc==1 );
pTab->tabFlags |= autoInc*TF_Autoincrement;
if( pList ) pParse->iPkSortOrder = pList->a[0].sortFlags;
+ (void)sqlite3HasExplicitNulls(pParse, pList);
}else if( autoInc ){
#ifndef SQLITE_OMIT_AUTOINCREMENT
sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
@@ -109210,41 +110748,58 @@ SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){
}
}
-/*
-** This function returns the collation sequence for database native text
-** encoding identified by the string zName, length nName.
-**
-** If the requested collation sequence is not available, or not available
-** in the database native encoding, the collation factory is invoked to
-** request it. If the collation factory does not supply such a sequence,
-** and the sequence is available in another text encoding, then that is
-** returned instead.
-**
-** If no versions of the requested collations sequence are available, or
-** another error occurs, NULL is returned and an error message written into
-** pParse.
-**
-** This routine is a wrapper around sqlite3FindCollSeq(). This routine
-** invokes the collation factory if the named collation cannot be found
-** and generates an error message.
-**
-** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq()
+/* Change the most recently parsed column to be a GENERATED ALWAYS AS
+** column.
*/
-SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
- sqlite3 *db = pParse->db;
- u8 enc = ENC(db);
- u8 initbusy = db->init.busy;
- CollSeq *pColl;
-
- pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
- if( !initbusy && (!pColl || !pColl->xCmp) ){
- pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
+SQLITE_PRIVATE void sqlite3AddGenerated(Parse *pParse, Expr *pExpr, Token *pType){
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ u8 eType = COLFLAG_VIRTUAL;
+ Table *pTab = pParse->pNewTable;
+ Column *pCol;
+ if( pTab==0 ){
+ /* generated column in an CREATE TABLE IF NOT EXISTS that already exists */
+ goto generated_done;
+ }
+ pCol = &(pTab->aCol[pTab->nCol-1]);
+ if( IN_DECLARE_VTAB ){
+ sqlite3ErrorMsg(pParse, "virtual tables cannot use computed columns");
+ goto generated_done;
+ }
+ if( pCol->pDflt ) goto generated_error;
+ if( pType ){
+ if( pType->n==7 && sqlite3StrNICmp("virtual",pType->z,7)==0 ){
+ /* no-op */
+ }else if( pType->n==6 && sqlite3StrNICmp("stored",pType->z,6)==0 ){
+ eType = COLFLAG_STORED;
+ }else{
+ goto generated_error;
+ }
+ }
+ if( eType==COLFLAG_VIRTUAL ) pTab->nNVCol--;
+ pCol->colFlags |= eType;
+ assert( TF_HasVirtual==COLFLAG_VIRTUAL );
+ assert( TF_HasStored==COLFLAG_STORED );
+ pTab->tabFlags |= eType;
+ if( pCol->colFlags & COLFLAG_PRIMKEY ){
+ makeColumnPartOfPrimaryKey(pParse, pCol); /* For the error message */
}
+ pCol->pDflt = pExpr;
+ pExpr = 0;
+ goto generated_done;
- return pColl;
+generated_error:
+ sqlite3ErrorMsg(pParse, "error in generated column \"%s\"",
+ pCol->zName);
+generated_done:
+ sqlite3ExprDelete(pParse->db, pExpr);
+#else
+ /* Throw and error for the GENERATED ALWAYS AS clause if the
+ ** SQLITE_OMIT_GENERATED_COLUMNS compile-time option is used. */
+ sqlite3ErrorMsg(pParse, "generated columns not supported");
+ sqlite3ExprDelete(pParse->db, pExpr);
+#endif
}
-
/*
** Generate code that will increment the schema cookie.
**
@@ -109502,15 +111057,24 @@ static int isDupColumn(Index *pIdx, int nKey, Index *pPk, int iCol){
** high-order bit of colNotIdxed is always 1. All unindexed columns
** of the table have a 1.
**
+** 2019-10-24: For the purpose of this computation, virtual columns are
+** not considered to be covered by the index, even if they are in the
+** index, because we do not trust the logic in whereIndexExprTrans() to be
+** able to find all instances of a reference to the indexed table column
+** and convert them into references to the index. Hence we always want
+** the actual table at hand in order to recompute the virtual column, if
+** necessary.
+**
** The colNotIdxed mask is AND-ed with the SrcList.a[].colUsed mask
** to determine if the index is covering index.
*/
static void recomputeColumnsNotIndexed(Index *pIdx){
Bitmask m = 0;
int j;
+ Table *pTab = pIdx->pTable;
for(j=pIdx->nColumn-1; j>=0; j--){
int x = pIdx->aiColumn[j];
- if( x>=0 ){
+ if( x>=0 && (pTab->aCol[x].colFlags & COLFLAG_VIRTUAL)==0 ){
testcase( x==BMS-1 );
testcase( x==BMS-2 );
if( x<BMS-1 ) m |= MASKBIT(x);
@@ -109561,6 +111125,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
pTab->aCol[i].notNull = OE_Abort;
}
}
+ pTab->tabFlags |= TF_HasNotNull;
}
/* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
@@ -109668,11 +111233,14 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
*/
nExtra = 0;
for(i=0; i<pTab->nCol; i++){
- if( !hasColumn(pPk->aiColumn, nPk, i) ) nExtra++;
+ if( !hasColumn(pPk->aiColumn, nPk, i)
+ && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) nExtra++;
}
if( resizeIndexObject(db, pPk, nPk+nExtra) ) return;
for(i=0, j=nPk; i<pTab->nCol; i++){
- if( !hasColumn(pPk->aiColumn, j, i) ){
+ if( !hasColumn(pPk->aiColumn, j, i)
+ && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0
+ ){
assert( j<pPk->nColumn );
pPk->aiColumn[j] = i;
pPk->azColl[j] = sqlite3StrBINARY;
@@ -109680,7 +111248,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
}
}
assert( pPk->nColumn==j );
- assert( pTab->nCol<=j );
+ assert( pTab->nNVCol<=j );
recomputeColumnsNotIndexed(pPk);
}
@@ -109692,7 +111260,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
** zName is temporarily modified while this routine is running, but is
** restored to its original value prior to this routine returning.
*/
-int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
+SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
char *zTail; /* Pointer to the last "_" in zName */
Table *pTab; /* Table that zName is a shadow of */
Module *pMod; /* Module for the virtual table */
@@ -109787,12 +111355,11 @@ SQLITE_PRIVATE void sqlite3EndTable(
}
if( (p->tabFlags & TF_HasPrimaryKey)==0 ){
sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName);
- }else{
- p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid;
- convertToWithoutRowidTable(pParse, p);
+ return;
}
+ p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid;
+ convertToWithoutRowidTable(pParse, p);
}
-
iDb = sqlite3SchemaToIndex(db, p->pSchema);
#ifndef SQLITE_OMIT_CHECK
@@ -109800,8 +111367,45 @@ SQLITE_PRIVATE void sqlite3EndTable(
*/
if( p->pCheck ){
sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
+ if( pParse->nErr ){
+ /* If errors are seen, delete the CHECK constraints now, else they might
+ ** actually be used if PRAGMA writable_schema=ON is set. */
+ sqlite3ExprListDelete(db, p->pCheck);
+ p->pCheck = 0;
+ }
}
#endif /* !defined(SQLITE_OMIT_CHECK) */
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ if( p->tabFlags & TF_HasGenerated ){
+ int ii, nNG = 0;
+ testcase( p->tabFlags & TF_HasVirtual );
+ testcase( p->tabFlags & TF_HasStored );
+ for(ii=0; ii<p->nCol; ii++){
+ u32 colFlags = p->aCol[ii].colFlags;
+ if( (colFlags & COLFLAG_GENERATED)!=0 ){
+ Expr *pX = p->aCol[ii].pDflt;
+ testcase( colFlags & COLFLAG_VIRTUAL );
+ testcase( colFlags & COLFLAG_STORED );
+ if( sqlite3ResolveSelfReference(pParse, p, NC_GenCol, pX, 0) ){
+ /* If there are errors in resolving the expression, change the
+ ** expression to a NULL. This prevents code generators that operate
+ ** on the expression from inserting extra parts into the expression
+ ** tree that have been allocated from lookaside memory, which is
+ ** illegal in a schema and will lead to errors or heap corruption
+ ** when the database connection closes. */
+ sqlite3ExprDelete(db, pX);
+ p->aCol[ii].pDflt = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
+ }
+ }else{
+ nNG++;
+ }
+ }
+ if( nNG==0 ){
+ sqlite3ErrorMsg(pParse, "must have at least one non-generated column");
+ return;
+ }
+ }
+#endif
/* Estimate the average row size for the table and for all implied indices */
estimateTableWidth(p);
@@ -109878,7 +111482,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect, SQLITE_AFF_BLOB);
if( pSelTab==0 ) return;
assert( p->aCol==0 );
- p->nCol = pSelTab->nCol;
+ p->nCol = p->nNVCol = pSelTab->nCol;
p->aCol = pSelTab->aCol;
pSelTab->nCol = 0;
pSelTab->aCol = 0;
@@ -109951,7 +111555,6 @@ SQLITE_PRIVATE void sqlite3EndTable(
sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName));
}
-
/* Add the table to the in-memory representation of the database.
*/
if( db->init.busy ){
@@ -110136,7 +111739,7 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
n = pParse->nTab;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
pTable->nCol = -1;
- db->lookaside.bDisable++;
+ DisableLookaside;
#ifndef SQLITE_OMIT_AUTHORIZATION
xAuth = db->xAuth;
db->xAuth = 0;
@@ -110146,7 +111749,10 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
#endif
pParse->nTab = n;
- if( pTable->pCheck ){
+ if( pSelTab==0 ){
+ pTable->nCol = 0;
+ nErr++;
+ }else if( pTable->pCheck ){
/* CREATE VIEW name(arglist) AS ...
** The names of the columns in the table are taken from
** arglist which is stored in pTable->pCheck. The pCheck field
@@ -110162,7 +111768,7 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel,
SQLITE_AFF_NONE);
}
- }else if( pSelTab ){
+ }else{
/* CREATE VIEW name AS... without an argument list. Construct
** the column names from the SELECT statement that defines the view.
*/
@@ -110172,13 +111778,11 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
pSelTab->nCol = 0;
pSelTab->aCol = 0;
assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
- }else{
- pTable->nCol = 0;
- nErr++;
}
+ pTable->nNVCol = pTable->nCol;
sqlite3DeleteTable(db, pSelTab);
sqlite3SelectDelete(db, pSel);
- db->lookaside.bDisable--;
+ EnableLookaside;
#ifndef SQLITE_OMIT_ALTERTABLE
pParse->eParseMode = eParseMode;
#endif
@@ -110436,6 +112040,37 @@ SQLITE_PRIVATE void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, in
}
/*
+** Return TRUE if shadow tables should be read-only in the current
+** context.
+*/
+SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db){
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( (db->flags & SQLITE_Defensive)!=0
+ && db->pVtabCtx==0
+ && db->nVdbeExec==0
+ ){
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/*
+** Return true if it is not allowed to drop the given table
+*/
+static int tableMayNotBeDropped(sqlite3 *db, Table *pTab){
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
+ if( sqlite3StrNICmp(pTab->zName+7, "stat", 4)==0 ) return 0;
+ if( sqlite3StrNICmp(pTab->zName+7, "parameters", 10)==0 ) return 0;
+ return 1;
+ }
+ if( (pTab->tabFlags & TF_Shadow)!=0 && sqlite3ReadOnlyShadowTables(db) ){
+ return 1;
+ }
+ return 0;
+}
+
+/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
*/
@@ -110504,9 +112139,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
}
}
#endif
- if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
- && sqlite3StrNICmp(pTab->zName+7, "stat", 4)!=0
- && sqlite3StrNICmp(pTab->zName+7, "parameters", 10)!=0 ){
+ if( tableMayNotBeDropped(db, pTab) ){
sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
goto exit_drop_table;
}
@@ -110598,7 +112231,7 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
if( pToCol ){
for(i=0; i<pToCol->nExpr; i++){
- nByte += sqlite3Strlen30(pToCol->a[i].zName) + 1;
+ nByte += sqlite3Strlen30(pToCol->a[i].zEName) + 1;
}
}
pFKey = sqlite3DbMallocZero(db, nByte );
@@ -110623,7 +112256,7 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
for(i=0; i<nCol; i++){
int j;
for(j=0; j<p->nCol; j++){
- if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){
+ if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zEName)==0 ){
pFKey->aCol[i].iFrom = j;
break;
}
@@ -110631,22 +112264,22 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
if( j>=p->nCol ){
sqlite3ErrorMsg(pParse,
"unknown column \"%s\" in foreign key definition",
- pFromCol->a[i].zName);
+ pFromCol->a[i].zEName);
goto fk_end;
}
if( IN_RENAME_OBJECT ){
- sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zName);
+ sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zEName);
}
}
}
if( pToCol ){
for(i=0; i<nCol; i++){
- int n = sqlite3Strlen30(pToCol->a[i].zName);
+ int n = sqlite3Strlen30(pToCol->a[i].zEName);
pFKey->aCol[i].zCol = z;
if( IN_RENAME_OBJECT ){
- sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zName);
+ sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zEName);
}
- memcpy(z, pToCol->a[i].zName, n);
+ memcpy(z, pToCol->a[i].zEName, n);
z[n] = 0;
z += n+1;
}
@@ -111177,8 +112810,13 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
assert( j<=0x7fff );
if( j<0 ){
j = pTab->iPKey;
- }else if( pTab->aCol[j].notNull==0 ){
- pIndex->uniqNotNull = 0;
+ }else{
+ if( pTab->aCol[j].notNull==0 ){
+ pIndex->uniqNotNull = 0;
+ }
+ if( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ){
+ pIndex->bHasVCol = 1;
+ }
}
pIndex->aiColumn[i] = (i16)j;
}
@@ -111233,13 +112871,13 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
/* If this index contains every column of its table, then mark
** it as a covering index */
assert( HasRowid(pTab)
- || pTab->iPKey<0 || sqlite3ColumnOfIndex(pIndex, pTab->iPKey)>=0 );
+ || pTab->iPKey<0 || sqlite3TableColumnToIndex(pIndex, pTab->iPKey)>=0 );
recomputeColumnsNotIndexed(pIndex);
if( pTblName!=0 && pIndex->nColumn>=pTab->nCol ){
pIndex->isCovering = 1;
for(j=0; j<pTab->nCol; j++){
if( j==pTab->iPKey ) continue;
- if( sqlite3ColumnOfIndex(pIndex,j)>=0 ) continue;
+ if( sqlite3TableColumnToIndex(pIndex,j)>=0 ) continue;
pIndex->isCovering = 0;
break;
}
@@ -111414,26 +113052,9 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
sqlite3VdbeJumpHere(v, pIndex->tnum);
}
}
-
- /* When adding an index to the list of indices for a table, make
- ** sure all indices labeled OE_Replace come after all those labeled
- ** OE_Ignore. This is necessary for the correct constraint check
- ** processing (in sqlite3GenerateConstraintChecks()) as part of
- ** UPDATE and INSERT statements.
- */
if( db->init.busy || pTblName==0 ){
- if( onError!=OE_Replace || pTab->pIndex==0
- || pTab->pIndex->onError==OE_Replace){
- pIndex->pNext = pTab->pIndex;
- pTab->pIndex = pIndex;
- }else{
- Index *pOther = pTab->pIndex;
- while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
- pOther = pOther->pNext;
- }
- pIndex->pNext = pOther->pNext;
- pOther->pNext = pIndex;
- }
+ pIndex->pNext = pTab->pIndex;
+ pTab->pIndex = pIndex;
pIndex = 0;
}
else if( IN_RENAME_OBJECT ){
@@ -111445,6 +113066,21 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
/* Clean up before exiting */
exit_create_index:
if( pIndex ) sqlite3FreeIndex(db, pIndex);
+ if( pTab ){ /* Ensure all REPLACE indexes are at the end of the list */
+ Index **ppFrom = &pTab->pIndex;
+ Index *pThis;
+ for(ppFrom=&pTab->pIndex; (pThis = *ppFrom)!=0; ppFrom=&pThis->pNext){
+ Index *pNext;
+ if( pThis->onError!=OE_Replace ) continue;
+ while( (pNext = pThis->pNext)!=0 && pNext->onError!=OE_Replace ){
+ *ppFrom = pNext;
+ pThis->pNext = pNext->pNext;
+ pNext->pNext = pThis;
+ ppFrom = &pNext->pNext;
+ }
+ break;
+ }
+ }
sqlite3ExprDelete(db, pPIWhere);
sqlite3ExprListDelete(db, pList);
sqlite3SrcListDelete(db, pTblName);
@@ -112580,51 +114216,6 @@ static int synthCollSeq(sqlite3 *db, CollSeq *pColl){
}
/*
-** This function is responsible for invoking the collation factory callback
-** or substituting a collation sequence of a different encoding when the
-** requested collation sequence is not available in the desired encoding.
-**
-** If it is not NULL, then pColl must point to the database native encoding
-** collation sequence with name zName, length nName.
-**
-** The return value is either the collation sequence to be used in database
-** db for collation type name zName, length nName, or NULL, if no collation
-** sequence can be found. If no collation is found, leave an error message.
-**
-** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
-*/
-SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
- Parse *pParse, /* Parsing context */
- u8 enc, /* The desired encoding for the collating sequence */
- CollSeq *pColl, /* Collating sequence with native encoding, or NULL */
- const char *zName /* Collating sequence name */
-){
- CollSeq *p;
- sqlite3 *db = pParse->db;
-
- p = pColl;
- if( !p ){
- p = sqlite3FindCollSeq(db, enc, zName, 0);
- }
- if( !p || !p->xCmp ){
- /* No collation sequence of this type for this encoding is registered.
- ** Call the collation factory to see if it can supply us with one.
- */
- callCollNeeded(db, enc, zName);
- p = sqlite3FindCollSeq(db, enc, zName, 0);
- }
- if( p && !p->xCmp && synthCollSeq(db, p) ){
- p = 0;
- }
- assert( !p || p->xCmp );
- if( p==0 ){
- sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
- pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ;
- }
- return p;
-}
-
-/*
** This routine is called on a collation sequence before it is used to
** check that it is defined. An undefined collation sequence exists when
** a database is loaded that contains references to collation sequences
@@ -112716,10 +114307,10 @@ static CollSeq *findCollSeqEntry(
** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq()
*/
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(
- sqlite3 *db,
- u8 enc,
- const char *zName,
- int create
+ sqlite3 *db, /* Database connection to search */
+ u8 enc, /* Desired text encoding */
+ const char *zName, /* Name of the collating sequence. Might be NULL */
+ int create /* True to create CollSeq if doesn't already exist */
){
CollSeq *pColl;
if( zName ){
@@ -112733,6 +114324,85 @@ SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(
return pColl;
}
+/*
+** This function is responsible for invoking the collation factory callback
+** or substituting a collation sequence of a different encoding when the
+** requested collation sequence is not available in the desired encoding.
+**
+** If it is not NULL, then pColl must point to the database native encoding
+** collation sequence with name zName, length nName.
+**
+** The return value is either the collation sequence to be used in database
+** db for collation type name zName, length nName, or NULL, if no collation
+** sequence can be found. If no collation is found, leave an error message.
+**
+** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
+*/
+SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
+ Parse *pParse, /* Parsing context */
+ u8 enc, /* The desired encoding for the collating sequence */
+ CollSeq *pColl, /* Collating sequence with native encoding, or NULL */
+ const char *zName /* Collating sequence name */
+){
+ CollSeq *p;
+ sqlite3 *db = pParse->db;
+
+ p = pColl;
+ if( !p ){
+ p = sqlite3FindCollSeq(db, enc, zName, 0);
+ }
+ if( !p || !p->xCmp ){
+ /* No collation sequence of this type for this encoding is registered.
+ ** Call the collation factory to see if it can supply us with one.
+ */
+ callCollNeeded(db, enc, zName);
+ p = sqlite3FindCollSeq(db, enc, zName, 0);
+ }
+ if( p && !p->xCmp && synthCollSeq(db, p) ){
+ p = 0;
+ }
+ assert( !p || p->xCmp );
+ if( p==0 ){
+ sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
+ pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ;
+ }
+ return p;
+}
+
+/*
+** This function returns the collation sequence for database native text
+** encoding identified by the string zName.
+**
+** If the requested collation sequence is not available, or not available
+** in the database native encoding, the collation factory is invoked to
+** request it. If the collation factory does not supply such a sequence,
+** and the sequence is available in another text encoding, then that is
+** returned instead.
+**
+** If no versions of the requested collations sequence are available, or
+** another error occurs, NULL is returned and an error message written into
+** pParse.
+**
+** This routine is a wrapper around sqlite3FindCollSeq(). This routine
+** invokes the collation factory if the named collation cannot be found
+** and generates an error message.
+**
+** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq()
+*/
+SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
+ sqlite3 *db = pParse->db;
+ u8 enc = ENC(db);
+ u8 initbusy = db->init.busy;
+ CollSeq *pColl;
+
+ pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
+ if( !initbusy && (!pColl || !pColl->xCmp) ){
+ pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
+ }
+
+ return pColl;
+}
+
/* During the search for the best function definition, this procedure
** is called to test how well the function passed as the first argument
** matches the request for a function with nArg arguments in a system
@@ -112768,12 +114438,13 @@ static int matchQuality(
u8 enc /* Desired text encoding */
){
int match;
-
- /* nArg of -2 is a special case */
- if( nArg==(-2) ) return (p->xSFunc==0) ? 0 : FUNC_PERFECT_MATCH;
+ assert( p->nArg>=-1 );
/* Wrong number of arguments means "no match" */
- if( p->nArg!=nArg && p->nArg>=0 ) return 0;
+ if( p->nArg!=nArg ){
+ if( nArg==(-2) ) return (p->xSFunc==0) ? 0 : FUNC_PERFECT_MATCH;
+ if( p->nArg>=0 ) return 0;
+ }
/* Give a better score to a function with a specific number of arguments
** than to function that accepts any number of arguments. */
@@ -113075,11 +114746,7 @@ static int tabIsReadOnly(Parse *pParse, Table *pTab){
return sqlite3WritableSchema(db)==0 && pParse->nested==0;
}
assert( pTab->tabFlags & TF_Shadow );
- return (db->flags & SQLITE_Defensive)!=0
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- && db->pVtabCtx==0
-#endif
- && db->nVdbeExec==0;
+ return sqlite3ReadOnlyShadowTables(db);
}
/*
@@ -113742,7 +115409,8 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
testcase( mask!=0xffffffff && iCol==31 );
testcase( mask!=0xffffffff && iCol==32 );
if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
+ int kk = sqlite3TableColumnToStorage(pTab, iCol);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+kk+1);
}
}
@@ -113922,6 +115590,8 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
SQLITE_JUMPIFNULL);
pParse->iSelfTab = 0;
+ pPrior = 0; /* Ticket a9efb42811fa41ee 2019-11-02;
+ ** pPartIdxWhere may have corrupted regPrior registers */
}else{
*piPartIdxLabel = 0;
}
@@ -113988,7 +115658,9 @@ SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){
/* #include "sqliteInt.h" */
/* #include <stdlib.h> */
/* #include <assert.h> */
+#ifndef SQLITE_OMIT_FLOATING_POINT
/* #include <math.h> */
+#endif
/* #include "vdbeInt.h" */
/*
@@ -115834,6 +117506,9 @@ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocas
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
nExpr = pExpr->x.pList->nExpr;
pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0);
+#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
+ if( pDef==0 ) return 0;
+#endif
if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){
return 0;
}
@@ -115879,12 +117554,20 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
** For peak efficiency, put the most frequently used function last.
*/
static FuncDef aBuiltinFunc[] = {
+/***** Functions only available with SQLITE_TESTCTRL_INTERNAL_FUNCTIONS *****/
+ TEST_FUNC(implies_nonnull_row, 2, INLINEFUNC_implies_nonnull_row, 0),
+ TEST_FUNC(expr_compare, 2, INLINEFUNC_expr_compare, 0),
+ TEST_FUNC(expr_implies_expr, 2, INLINEFUNC_expr_implies_expr, 0),
+#ifdef SQLITE_DEBUG
+ TEST_FUNC(affinity, 1, INLINEFUNC_affinity, 0),
+#endif
+/***** Regular functions *****/
#ifdef SQLITE_SOUNDEX
FUNCTION(soundex, 1, 0, 0, soundexFunc ),
#endif
#ifndef SQLITE_OMIT_LOAD_EXTENSION
- VFUNCTION(load_extension, 1, 0, 0, loadExt ),
- VFUNCTION(load_extension, 2, 0, 0, loadExt ),
+ SFUNCTION(load_extension, 1, 0, 0, loadExt ),
+ SFUNCTION(load_extension, 2, 0, 0, loadExt ),
#endif
#if SQLITE_USER_AUTHENTICATION
FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ),
@@ -115893,12 +117576,9 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
- FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
- FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
- FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
-#ifdef SQLITE_DEBUG
- FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY),
-#endif
+ INLINE_FUNC(unlikely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
+ INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
+ INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET|
SQLITE_FUNC_TYPEOF),
@@ -115931,7 +117611,7 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
FUNCTION(upper, 1, 0, 0, upperFunc ),
FUNCTION(lower, 1, 0, 0, lowerFunc ),
FUNCTION(hex, 1, 0, 0, hexFunc ),
- FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
+ INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, SQLITE_FUNC_COALESCE),
VFUNCTION(random, 0, 0, 0, randomFunc ),
VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
@@ -115971,7 +117651,7 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
#endif
FUNCTION(coalesce, 1, 0, 0, 0 ),
FUNCTION(coalesce, 0, 0, 0, 0 ),
- FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
+ INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, SQLITE_FUNC_COALESCE),
};
#ifndef SQLITE_OMIT_ALTERTABLE
sqlite3AlterFunctions();
@@ -116350,7 +118030,7 @@ static void fkLookupParent(
VdbeCoverage(v);
}
for(i=0; i<pFKey->nCol; i++){
- int iReg = aiCol[i] + regData + 1;
+ int iReg = sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[i]) + regData + 1;
sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); VdbeCoverage(v);
}
@@ -116366,7 +118046,8 @@ static void fkLookupParent(
** is no matching parent key. Before using MustBeInt, make a copy of
** the value. Otherwise, the value inserted into the child key column
** will have INTEGER affinity applied to it, which may not be correct. */
- sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp);
+ sqlite3VdbeAddOp2(v, OP_SCopy,
+ sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[0])+1+regData, regTemp);
iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0);
VdbeCoverage(v);
@@ -116393,7 +118074,9 @@ static void fkLookupParent(
sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
for(i=0; i<nCol; i++){
- sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i);
+ sqlite3VdbeAddOp2(v, OP_Copy,
+ sqlite3TableColumnToStorage(pFKey->pFrom, aiCol[i])+1+regData,
+ regTemp+i);
}
/* If the parent table is the same as the child table, and we are about
@@ -116409,8 +118092,11 @@ static void fkLookupParent(
if( pTab==pFKey->pFrom && nIncr==1 ){
int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1;
for(i=0; i<nCol; i++){
- int iChild = aiCol[i]+1+regData;
- int iParent = pIdx->aiColumn[i]+1+regData;
+ int iChild = sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[i])
+ +1+regData;
+ int iParent = 1+regData;
+ iParent += sqlite3TableColumnToStorage(pIdx->pTable,
+ pIdx->aiColumn[i]);
assert( pIdx->aiColumn[i]>=0 );
assert( aiCol[i]!=pTab->iPKey );
if( pIdx->aiColumn[i]==pTab->iPKey ){
@@ -116478,7 +118164,7 @@ static Expr *exprTableRegister(
if( pExpr ){
if( iCol>=0 && iCol!=pTab->iPKey ){
pCol = &pTab->aCol[iCol];
- pExpr->iTable = regBase + iCol + 1;
+ pExpr->iTable = regBase + sqlite3TableColumnToStorage(pTab,iCol) + 1;
pExpr->affExpr = pCol->affinity;
zColl = pCol->zColl;
if( zColl==0 ) zColl = db->pDfltColl->zName;
@@ -116927,7 +118613,9 @@ SQLITE_PRIVATE void sqlite3FkCheck(
Vdbe *v = sqlite3GetVdbe(pParse);
int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1;
for(i=0; i<pFKey->nCol; i++){
- int iReg = pFKey->aCol[i].iFrom + regOld + 1;
+ int iFromCol, iReg;
+ iFromCol = pFKey->aCol[i].iFrom;
+ iReg = sqlite3TableColumnToStorage(pFKey->pFrom,iFromCol) + regOld+1;
sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); VdbeCoverage(v);
}
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1);
@@ -117262,7 +118950,15 @@ static Trigger *fkActionTrigger(
sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
sqlite3ExprAlloc(db, TK_ID, &tToCol, 0));
}else if( action==OE_SetDflt ){
- Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt;
+ Column *pCol = pFKey->pFrom->aCol + iFromCol;
+ Expr *pDflt;
+ if( pCol->colFlags & COLFLAG_GENERATED ){
+ testcase( pCol->colFlags & COLFLAG_VIRTUAL );
+ testcase( pCol->colFlags & COLFLAG_STORED );
+ pDflt = 0;
+ }else{
+ pDflt = pCol->pDflt;
+ }
if( pDflt ){
pNew = sqlite3ExprDup(db, pDflt, 0);
}else{
@@ -117300,7 +118996,7 @@ static Trigger *fkActionTrigger(
}
/* Disable lookaside memory allocation */
- db->lookaside.bDisable++;
+ DisableLookaside;
pTrigger = (Trigger *)sqlite3DbMallocZero(db,
sizeof(Trigger) + /* struct Trigger */
@@ -117322,7 +119018,7 @@ static Trigger *fkActionTrigger(
}
/* Re-enable the lookaside buffer, if it was disabled earlier. */
- db->lookaside.bDisable--;
+ EnableLookaside;
sqlite3ExprDelete(db, pWhere);
sqlite3ExprDelete(db, pWhen);
@@ -117473,7 +119169,7 @@ SQLITE_PRIVATE void sqlite3OpenTable(
sqlite3TableLock(pParse, iDb, pTab->tnum,
(opcode==OP_OpenWrite)?1:0, pTab->zName);
if( HasRowid(pTab) ){
- sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol);
+ sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nNVCol);
VdbeComment((v, "%s", pTab->zName));
}else{
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
@@ -117565,7 +119261,7 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){
** 'E' REAL
*/
SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
- int i;
+ int i, j;
char *zColAff = pTab->zColAff;
if( zColAff==0 ){
sqlite3 *db = sqlite3VdbeDb(v);
@@ -117575,13 +119271,15 @@ SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
return;
}
- for(i=0; i<pTab->nCol; i++){
+ for(i=j=0; i<pTab->nCol; i++){
assert( pTab->aCol[i].affinity!=0 );
- zColAff[i] = pTab->aCol[i].affinity;
+ if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
+ zColAff[j++] = pTab->aCol[i].affinity;
+ }
}
do{
- zColAff[i--] = 0;
- }while( i>=0 && zColAff[i]<=SQLITE_AFF_BLOB );
+ zColAff[j--] = 0;
+ }while( j>=0 && zColAff[j]<=SQLITE_AFF_BLOB );
pTab->zColAff = zColAff;
}
assert( zColAff!=0 );
@@ -117635,6 +119333,119 @@ static int readsTable(Parse *p, int iDb, Table *pTab){
return 0;
}
+/* This walker callback will compute the union of colFlags flags for all
+** referenced columns in a CHECK constraint or generated column expression.
+*/
+static int exprColumnFlagUnion(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 ){
+ assert( pExpr->iColumn < pWalker->u.pTab->nCol );
+ pWalker->eCode |= pWalker->u.pTab->aCol[pExpr->iColumn].colFlags;
+ }
+ return WRC_Continue;
+}
+
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+/*
+** All regular columns for table pTab have been puts into registers
+** starting with iRegStore. The registers that correspond to STORED
+** or VIRTUAL columns have not yet been initialized. This routine goes
+** back and computes the values for those columns based on the previously
+** computed normal columns.
+*/
+SQLITE_PRIVATE void sqlite3ComputeGeneratedColumns(
+ Parse *pParse, /* Parsing context */
+ int iRegStore, /* Register holding the first column */
+ Table *pTab /* The table */
+){
+ int i;
+ Walker w;
+ Column *pRedo;
+ int eProgress;
+ VdbeOp *pOp;
+
+ assert( pTab->tabFlags & TF_HasGenerated );
+ testcase( pTab->tabFlags & TF_HasVirtual );
+ testcase( pTab->tabFlags & TF_HasStored );
+
+ /* Before computing generated columns, first go through and make sure
+ ** that appropriate affinity has been applied to the regular columns
+ */
+ sqlite3TableAffinity(pParse->pVdbe, pTab, iRegStore);
+ if( (pTab->tabFlags & TF_HasStored)!=0
+ && (pOp = sqlite3VdbeGetOp(pParse->pVdbe,-1))->opcode==OP_Affinity
+ ){
+ /* Change the OP_Affinity argument to '@' (NONE) for all stored
+ ** columns. '@' is the no-op affinity and those columns have not
+ ** yet been computed. */
+ int ii, jj;
+ char *zP4 = pOp->p4.z;
+ assert( zP4!=0 );
+ assert( pOp->p4type==P4_DYNAMIC );
+ for(ii=jj=0; zP4[jj]; ii++){
+ if( pTab->aCol[ii].colFlags & COLFLAG_VIRTUAL ){
+ continue;
+ }
+ if( pTab->aCol[ii].colFlags & COLFLAG_STORED ){
+ zP4[jj] = SQLITE_AFF_NONE;
+ }
+ jj++;
+ }
+ }
+
+ /* Because there can be multiple generated columns that refer to one another,
+ ** this is a two-pass algorithm. On the first pass, mark all generated
+ ** columns as "not available".
+ */
+ for(i=0; i<pTab->nCol; i++){
+ if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
+ testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL );
+ testcase( pTab->aCol[i].colFlags & COLFLAG_STORED );
+ pTab->aCol[i].colFlags |= COLFLAG_NOTAVAIL;
+ }
+ }
+
+ w.u.pTab = pTab;
+ w.xExprCallback = exprColumnFlagUnion;
+ w.xSelectCallback = 0;
+ w.xSelectCallback2 = 0;
+
+ /* On the second pass, compute the value of each NOT-AVAILABLE column.
+ ** Companion code in the TK_COLUMN case of sqlite3ExprCodeTarget() will
+ ** compute dependencies and mark remove the COLSPAN_NOTAVAIL mark, as
+ ** they are needed.
+ */
+ pParse->iSelfTab = -iRegStore;
+ do{
+ eProgress = 0;
+ pRedo = 0;
+ for(i=0; i<pTab->nCol; i++){
+ Column *pCol = pTab->aCol + i;
+ if( (pCol->colFlags & COLFLAG_NOTAVAIL)!=0 ){
+ int x;
+ pCol->colFlags |= COLFLAG_BUSY;
+ w.eCode = 0;
+ sqlite3WalkExpr(&w, pCol->pDflt);
+ pCol->colFlags &= ~COLFLAG_BUSY;
+ if( w.eCode & COLFLAG_NOTAVAIL ){
+ pRedo = pCol;
+ continue;
+ }
+ eProgress = 1;
+ assert( pCol->colFlags & COLFLAG_GENERATED );
+ x = sqlite3TableColumnToStorage(pTab, i) + iRegStore;
+ sqlite3ExprCodeGeneratedColumn(pParse, pCol, x);
+ pCol->colFlags &= ~COLFLAG_NOTAVAIL;
+ }
+ }
+ }while( pRedo && eProgress );
+ if( pRedo ){
+ sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pRedo->zName);
+ }
+ pParse->iSelfTab = 0;
+}
+#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
+
+
#ifndef SQLITE_OMIT_AUTOINCREMENT
/*
** Locate or create an AutoincInfo structure associated with table pTab
@@ -117942,7 +119753,7 @@ SQLITE_PRIVATE void sqlite3Insert(
Parse *pParse, /* Parser context */
SrcList *pTabList, /* Name of table into which we are inserting */
Select *pSelect, /* A SELECT statement to use as the data source */
- IdList *pColumn, /* Column names corresponding to IDLIST. */
+ IdList *pColumn, /* Column names corresponding to IDLIST, or NULL. */
int onError, /* How to handle constraint errors */
Upsert *pUpsert /* ON CONFLICT clauses for upsert, or NULL */
){
@@ -117967,6 +119778,7 @@ SQLITE_PRIVATE void sqlite3Insert(
u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */
u8 bIdListInOrder; /* True if IDLIST is in table order */
ExprList *pList = 0; /* List of VALUES() to be inserted */
+ int iRegStore; /* Register in which to store next column */
/* Register allocations */
int regFromSelect = 0;/* Base register for data coming from SELECT */
@@ -118074,8 +119886,8 @@ SQLITE_PRIVATE void sqlite3Insert(
*/
regAutoinc = autoIncBegin(pParse, iDb, pTab);
- /* Allocate registers for holding the rowid of the new row,
- ** the content of the new row, and the assembled row record.
+ /* Allocate a block registers to hold the rowid and the values
+ ** for all columns of the new row.
*/
regRowid = regIns = pParse->nMem+1;
pParse->nMem += pTab->nCol + 1;
@@ -118094,9 +119906,17 @@ SQLITE_PRIVATE void sqlite3Insert(
** the index into IDLIST of the primary key column. ipkColumn is
** the index of the primary key as it appears in IDLIST, not as
** is appears in the original table. (The index of the INTEGER
- ** PRIMARY KEY in the original table is pTab->iPKey.)
+ ** PRIMARY KEY in the original table is pTab->iPKey.) After this
+ ** loop, if ipkColumn==(-1), that means that integer primary key
+ ** is unspecified, and hence the table is either WITHOUT ROWID or
+ ** it will automatically generated an integer primary key.
+ **
+ ** bIdListInOrder is true if the columns in IDLIST are in storage
+ ** order. This enables an optimization that avoids shuffling the
+ ** columns into storage order. False negatives are harmless,
+ ** but false positives will cause database corruption.
*/
- bIdListInOrder = (pTab->tabFlags & TF_OOOHidden)==0;
+ bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0;
if( pColumn ){
for(i=0; i<pColumn->nId; i++){
pColumn->a[i].idx = -1;
@@ -118109,6 +119929,14 @@ SQLITE_PRIVATE void sqlite3Insert(
if( j==pTab->iPKey ){
ipkColumn = i; assert( !withoutRowid );
}
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
+ sqlite3ErrorMsg(pParse,
+ "cannot INSERT into generated column \"%s\"",
+ pTab->aCol[j].zName);
+ goto insert_cleanup;
+ }
+#endif
break;
}
}
@@ -118218,13 +120046,26 @@ SQLITE_PRIVATE void sqlite3Insert(
*/
if( pColumn==0 && nColumn>0 ){
ipkColumn = pTab->iPKey;
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ if( ipkColumn>=0 && (pTab->tabFlags & TF_HasGenerated)!=0 ){
+ testcase( pTab->tabFlags & TF_HasVirtual );
+ testcase( pTab->tabFlags & TF_HasStored );
+ for(i=ipkColumn-1; i>=0; i--){
+ if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
+ testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL );
+ testcase( pTab->aCol[i].colFlags & COLFLAG_STORED );
+ ipkColumn--;
+ }
+ }
+ }
+#endif
}
/* Make sure the number of columns in the source data matches the number
** of columns to be inserted into the table.
*/
for(i=0; i<pTab->nCol; i++){
- nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0);
+ if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
}
if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
sqlite3ErrorMsg(pParse,
@@ -118270,6 +120111,10 @@ SQLITE_PRIVATE void sqlite3Insert(
pTab->zName);
goto insert_cleanup;
}
+ if( pTab->pSelect ){
+ sqlite3ErrorMsg(pParse, "cannot UPSERT a view");
+ goto insert_cleanup;
+ }
if( sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget) ){
goto insert_cleanup;
}
@@ -118307,10 +120152,91 @@ SQLITE_PRIVATE void sqlite3Insert(
** goto C
** D: ...
*/
+ sqlite3VdbeReleaseRegisters(pParse, regData, pTab->nCol, 0, 0);
addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
VdbeCoverage(v);
+ if( ipkColumn>=0 ){
+ /* tag-20191021-001: If the INTEGER PRIMARY KEY is being generated by the
+ ** SELECT, go ahead and copy the value into the rowid slot now, so that
+ ** the value does not get overwritten by a NULL at tag-20191021-002. */
+ sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid);
+ }
+ }
+
+ /* Compute data for ordinary columns of the new entry. Values
+ ** are written in storage order into registers starting with regData.
+ ** Only ordinary columns are computed in this loop. The rowid
+ ** (if there is one) is computed later and generated columns are
+ ** computed after the rowid since they might depend on the value
+ ** of the rowid.
+ */
+ nHidden = 0;
+ iRegStore = regData; assert( regData==regRowid+1 );
+ for(i=0; i<pTab->nCol; i++, iRegStore++){
+ int k;
+ u32 colFlags;
+ assert( i>=nHidden );
+ if( i==pTab->iPKey ){
+ /* tag-20191021-002: References to the INTEGER PRIMARY KEY are filled
+ ** using the rowid. So put a NULL in the IPK slot of the record to avoid
+ ** using excess space. The file format definition requires this extra
+ ** NULL - we cannot optimize further by skipping the column completely */
+ sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore);
+ continue;
+ }
+ if( ((colFlags = pTab->aCol[i].colFlags) & COLFLAG_NOINSERT)!=0 ){
+ nHidden++;
+ if( (colFlags & COLFLAG_VIRTUAL)!=0 ){
+ /* Virtual columns do not participate in OP_MakeRecord. So back up
+ ** iRegStore by one slot to compensate for the iRegStore++ in the
+ ** outer for() loop */
+ iRegStore--;
+ continue;
+ }else if( (colFlags & COLFLAG_STORED)!=0 ){
+ /* Stored columns are computed later. But if there are BEFORE
+ ** triggers, the slots used for stored columns will be OP_Copy-ed
+ ** to a second block of registers, so the register needs to be
+ ** initialized to NULL to avoid an uninitialized register read */
+ if( tmask & TRIGGER_BEFORE ){
+ sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore);
+ }
+ continue;
+ }else if( pColumn==0 ){
+ /* Hidden columns that are not explicitly named in the INSERT
+ ** get there default value */
+ sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
+ continue;
+ }
+ }
+ if( pColumn ){
+ for(j=0; j<pColumn->nId && pColumn->a[j].idx!=i; j++){}
+ if( j>=pColumn->nId ){
+ /* A column not named in the insert column list gets its
+ ** default value */
+ sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
+ continue;
+ }
+ k = j;
+ }else if( nColumn==0 ){
+ /* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */
+ sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
+ continue;
+ }else{
+ k = i - nHidden;
+ }
+
+ if( useTempTable ){
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, k, iRegStore);
+ }else if( pSelect ){
+ if( regFromSelect!=regData ){
+ sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+k, iRegStore);
+ }
+ }else{
+ sqlite3ExprCode(pParse, pList->a[k].pExpr, iRegStore);
+ }
}
+
/* Run the BEFORE and INSTEAD OF triggers, if there are any
*/
endOfLoop = sqlite3VdbeMakeLabel(pParse);
@@ -118345,25 +120271,21 @@ SQLITE_PRIVATE void sqlite3Insert(
*/
assert( !IsVirtual(pTab) );
- /* Create the new column data
- */
- for(i=j=0; i<pTab->nCol; i++){
- if( pColumn ){
- for(j=0; j<pColumn->nId; j++){
- if( pColumn->a[j].idx==i ) break;
- }
- }
- if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId)
- || (pColumn==0 && IsOrdinaryHiddenColumn(&pTab->aCol[i])) ){
- sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1);
- }else if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1);
- }else{
- assert( pSelect==0 ); /* Otherwise useTempTable is true */
- sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1);
- }
- if( pColumn==0 && !IsOrdinaryHiddenColumn(&pTab->aCol[i]) ) j++;
+ /* Copy the new data already generated. */
+ assert( pTab->nNVCol>0 );
+ sqlite3VdbeAddOp3(v, OP_Copy, regRowid+1, regCols+1, pTab->nNVCol-1);
+
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ /* Compute the new value for generated columns after all other
+ ** columns have already been computed. This must be done after
+ ** computing the ROWID in case one of the generated columns
+ ** refers to the ROWID. */
+ if( pTab->tabFlags & TF_HasGenerated ){
+ testcase( pTab->tabFlags & TF_HasVirtual );
+ testcase( pTab->tabFlags & TF_HasStored );
+ sqlite3ComputeGeneratedColumns(pParse, regCols+1, pTab);
}
+#endif
/* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,
** do not attempt any conversions before assembling the record.
@@ -118381,19 +120303,17 @@ SQLITE_PRIVATE void sqlite3Insert(
sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1);
}
- /* Compute the content of the next row to insert into a range of
- ** registers beginning at regIns.
- */
if( !isView ){
if( IsVirtual(pTab) ){
/* The row that the VUpdate opcode will delete: none */
sqlite3VdbeAddOp2(v, OP_Null, 0, regIns);
}
if( ipkColumn>=0 ){
+ /* Compute the new rowid */
if( useTempTable ){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regRowid);
}else if( pSelect ){
- sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid);
+ /* Rowid already initialized at tag-20191021-001 */
}else{
Expr *pIpk = pList->a[ipkColumn].pExpr;
if( pIpk->op==TK_NULL && !IsVirtual(pTab) ){
@@ -118426,45 +120346,15 @@ SQLITE_PRIVATE void sqlite3Insert(
}
autoIncStep(pParse, regAutoinc, regRowid);
- /* Compute data for all columns of the new entry, beginning
- ** with the first column.
- */
- nHidden = 0;
- for(i=0; i<pTab->nCol; i++){
- int iRegStore = regRowid+1+i;
- if( i==pTab->iPKey ){
- /* The value of the INTEGER PRIMARY KEY column is always a NULL.
- ** Whenever this column is read, the rowid will be substituted
- ** in its place. Hence, fill this column with a NULL to avoid
- ** taking up data space with information that will never be used.
- ** As there may be shallow copies of this value, make it a soft-NULL */
- sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore);
- continue;
- }
- if( pColumn==0 ){
- if( IsHiddenColumn(&pTab->aCol[i]) ){
- j = -1;
- nHidden++;
- }else{
- j = i - nHidden;
- }
- }else{
- for(j=0; j<pColumn->nId; j++){
- if( pColumn->a[j].idx==i ) break;
- }
- }
- if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){
- sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
- }else if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore);
- }else if( pSelect ){
- if( regFromSelect!=regData ){
- sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);
- }
- }else{
- sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore);
- }
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ /* Compute the new value for generated columns after all other
+ ** columns have already been computed. This must be done after
+ ** computing the ROWID in case one of the generated columns
+ ** is derived from the INTEGER PRIMARY KEY. */
+ if( pTab->tabFlags & TF_HasGenerated ){
+ sqlite3ComputeGeneratedColumns(pParse, regRowid+1, pTab);
}
+#endif
/* Generate code to check constraints and generate index keys and
** do the insertion.
@@ -118494,9 +120384,7 @@ SQLITE_PRIVATE void sqlite3Insert(
** cursor that is disturbed. And these instructions both clear the
** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT
** functionality. */
- bUseSeek = (isReplace==0 || (pTrigger==0 &&
- ((db->flags & SQLITE_ForeignKeys)==0 || sqlite3FkReferences(pTab)==0)
- ));
+ bUseSeek = (isReplace==0 || !sqlite3VdbeHasSubProgram(v));
sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
regIns, aRegIdx, 0, appendFlag, bUseSeek
);
@@ -118525,6 +120413,15 @@ SQLITE_PRIVATE void sqlite3Insert(
sqlite3VdbeAddOp1(v, OP_Close, srcTab);
}else if( pSelect ){
sqlite3VdbeGoto(v, addrCont);
+#ifdef SQLITE_DEBUG
+ /* If we are jumping back to an OP_Yield that is preceded by an
+ ** OP_ReleaseReg, set the p5 flag on the OP_Goto so that the
+ ** OP_ReleaseReg will be included in the loop. */
+ if( sqlite3VdbeGetOp(v, addrCont-1)->opcode==OP_ReleaseReg ){
+ assert( sqlite3VdbeGetOp(v, addrCont)->opcode==OP_Yield );
+ sqlite3VdbeChangeP5(v, 1);
+ }
+#endif
sqlite3VdbeJumpHere(v, addrInsTop);
}
@@ -118747,7 +120644,6 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
int ix; /* Index loop counter */
int nCol; /* Number of columns */
int onError; /* Conflict resolution strategy */
- int addr1; /* Address of jump instruction */
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
Index *pUpIdx = 0; /* Index to which to apply the upsert */
@@ -118757,6 +120653,13 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
int upsertJump = 0; /* Address of Goto that jumps into upsert subroutine */
int ipkTop = 0; /* Top of the IPK uniqueness check */
int ipkBottom = 0; /* OP_Goto at the end of the IPK uniqueness check */
+ /* Variables associated with retesting uniqueness constraints after
+ ** replace triggers fire have run */
+ int regTrigCnt; /* Register used to count replace trigger invocations */
+ int addrRecheck = 0; /* Jump here to recheck all uniqueness constraints */
+ int lblRecheckOk = 0; /* Each recheck jumps to this label if it passes */
+ Trigger *pTrigger; /* List of DELETE triggers on the table pTab */
+ int nReplaceTrig = 0; /* Number of replace triggers coded */
isUpdate = regOldData!=0;
db = pParse->db;
@@ -118783,63 +120686,103 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
/* Test all NOT NULL constraints.
*/
- for(i=0; i<nCol; i++){
- if( i==pTab->iPKey ){
- continue; /* ROWID is never NULL */
- }
- if( aiChng && aiChng[i]<0 ){
- /* Don't bother checking for NOT NULL on columns that do not change */
- continue;
- }
- onError = pTab->aCol[i].notNull;
- if( onError==OE_None ) continue; /* This column is allowed to be NULL */
- if( overrideError!=OE_Default ){
- onError = overrideError;
- }else if( onError==OE_Default ){
- onError = OE_Abort;
- }
- if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
- onError = OE_Abort;
- }
- assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
- || onError==OE_Ignore || onError==OE_Replace );
- addr1 = 0;
- switch( onError ){
- case OE_Replace: {
- assert( onError==OE_Replace );
- addr1 = sqlite3VdbeMakeLabel(pParse);
- sqlite3VdbeAddOp2(v, OP_NotNull, regNewData+1+i, addr1);
- VdbeCoverage(v);
- sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
- sqlite3VdbeAddOp2(v, OP_NotNull, regNewData+1+i, addr1);
- VdbeCoverage(v);
- onError = OE_Abort;
- /* Fall through into the OE_Abort case to generate code that runs
- ** if both the input and the default value are NULL */
- }
- case OE_Abort:
- sqlite3MayAbort(pParse);
- /* Fall through */
- case OE_Rollback:
- case OE_Fail: {
- char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
- pTab->aCol[i].zName);
- sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError,
- regNewData+1+i);
- sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
- sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
- VdbeCoverage(v);
- if( addr1 ) sqlite3VdbeResolveLabel(v, addr1);
- break;
- }
- default: {
- assert( onError==OE_Ignore );
- sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest);
- VdbeCoverage(v);
- break;
+ if( pTab->tabFlags & TF_HasNotNull ){
+ int b2ndPass = 0; /* True if currently running 2nd pass */
+ int nSeenReplace = 0; /* Number of ON CONFLICT REPLACE operations */
+ int nGenerated = 0; /* Number of generated columns with NOT NULL */
+ while(1){ /* Make 2 passes over columns. Exit loop via "break" */
+ for(i=0; i<nCol; i++){
+ int iReg; /* Register holding column value */
+ Column *pCol = &pTab->aCol[i]; /* The column to check for NOT NULL */
+ int isGenerated; /* non-zero if column is generated */
+ onError = pCol->notNull;
+ if( onError==OE_None ) continue; /* No NOT NULL on this column */
+ if( i==pTab->iPKey ){
+ continue; /* ROWID is never NULL */
+ }
+ isGenerated = pCol->colFlags & COLFLAG_GENERATED;
+ if( isGenerated && !b2ndPass ){
+ nGenerated++;
+ continue; /* Generated columns processed on 2nd pass */
+ }
+ if( aiChng && aiChng[i]<0 && !isGenerated ){
+ /* Do not check NOT NULL on columns that do not change */
+ continue;
+ }
+ if( overrideError!=OE_Default ){
+ onError = overrideError;
+ }else if( onError==OE_Default ){
+ onError = OE_Abort;
+ }
+ if( onError==OE_Replace ){
+ if( b2ndPass /* REPLACE becomes ABORT on the 2nd pass */
+ || pCol->pDflt==0 /* REPLACE is ABORT if no DEFAULT value */
+ ){
+ testcase( pCol->colFlags & COLFLAG_VIRTUAL );
+ testcase( pCol->colFlags & COLFLAG_STORED );
+ testcase( pCol->colFlags & COLFLAG_GENERATED );
+ onError = OE_Abort;
+ }else{
+ assert( !isGenerated );
+ }
+ }else if( b2ndPass && !isGenerated ){
+ continue;
+ }
+ assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
+ || onError==OE_Ignore || onError==OE_Replace );
+ testcase( i!=sqlite3TableColumnToStorage(pTab, i) );
+ iReg = sqlite3TableColumnToStorage(pTab, i) + regNewData + 1;
+ switch( onError ){
+ case OE_Replace: {
+ int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, iReg);
+ VdbeCoverage(v);
+ assert( (pCol->colFlags & COLFLAG_GENERATED)==0 );
+ nSeenReplace++;
+ sqlite3ExprCode(pParse, pCol->pDflt, iReg);
+ sqlite3VdbeJumpHere(v, addr1);
+ break;
+ }
+ case OE_Abort:
+ sqlite3MayAbort(pParse);
+ /* Fall through */
+ case OE_Rollback:
+ case OE_Fail: {
+ char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
+ pCol->zName);
+ sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL,
+ onError, iReg);
+ sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
+ sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
+ VdbeCoverage(v);
+ break;
+ }
+ default: {
+ assert( onError==OE_Ignore );
+ sqlite3VdbeAddOp2(v, OP_IsNull, iReg, ignoreDest);
+ VdbeCoverage(v);
+ break;
+ }
+ } /* end switch(onError) */
+ } /* end loop i over columns */
+ if( nGenerated==0 && nSeenReplace==0 ){
+ /* If there are no generated columns with NOT NULL constraints
+ ** and no NOT NULL ON CONFLICT REPLACE constraints, then a single
+ ** pass is sufficient */
+ break;
+ }
+ if( b2ndPass ) break; /* Never need more than 2 passes */
+ b2ndPass = 1;
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ if( nSeenReplace>0 && (pTab->tabFlags & TF_HasGenerated)!=0 ){
+ /* If any NOT NULL ON CONFLICT REPLACE constraints fired on the
+ ** first pass, recomputed values for all generated columns, as
+ ** those values might depend on columns affected by the REPLACE.
+ */
+ sqlite3ComputeGeneratedColumns(pParse, regNewData+1, pTab);
}
- }
- }
+#endif
+ } /* end of 2-pass loop */
+ } /* end if( has-not-null-constraints ) */
/* Test all CHECK constraints
*/
@@ -118864,7 +120807,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
if( onError==OE_Ignore ){
sqlite3VdbeGoto(v, ignoreDest);
}else{
- char *zName = pCheck->a[i].zName;
+ char *zName = pCheck->a[i].zEName;
if( zName==0 ) zName = pTab->zName;
if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-26383-51744 */
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
@@ -118921,6 +120864,50 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
}
+ /* Determine if it is possible that triggers (either explicitly coded
+ ** triggers or FK resolution actions) might run as a result of deletes
+ ** that happen when OE_Replace conflict resolution occurs. (Call these
+ ** "replace triggers".) If any replace triggers run, we will need to
+ ** recheck all of the uniqueness constraints after they have all run.
+ ** But on the recheck, the resolution is OE_Abort instead of OE_Replace.
+ **
+ ** If replace triggers are a possibility, then
+ **
+ ** (1) Allocate register regTrigCnt and initialize it to zero.
+ ** That register will count the number of replace triggers that
+ ** fire. Constraint recheck only occurs if the number is positive.
+ ** (2) Initialize pTrigger to the list of all DELETE triggers on pTab.
+ ** (3) Initialize addrRecheck and lblRecheckOk
+ **
+ ** The uniqueness rechecking code will create a series of tests to run
+ ** in a second pass. The addrRecheck and lblRecheckOk variables are
+ ** used to link together these tests which are separated from each other
+ ** in the generate bytecode.
+ */
+ if( (db->flags & (SQLITE_RecTriggers|SQLITE_ForeignKeys))==0 ){
+ /* There are not DELETE triggers nor FK constraints. No constraint
+ ** rechecks are needed. */
+ pTrigger = 0;
+ regTrigCnt = 0;
+ }else{
+ if( db->flags&SQLITE_RecTriggers ){
+ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
+ regTrigCnt = pTrigger!=0 || sqlite3FkRequired(pParse, pTab, 0, 0);
+ }else{
+ pTrigger = 0;
+ regTrigCnt = sqlite3FkRequired(pParse, pTab, 0, 0);
+ }
+ if( regTrigCnt ){
+ /* Replace triggers might exist. Allocate the counter and
+ ** initialize it to zero. */
+ regTrigCnt = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regTrigCnt);
+ VdbeComment((v, "trigger count"));
+ lblRecheckOk = sqlite3VdbeMakeLabel(pParse);
+ addrRecheck = lblRecheckOk;
+ }
+ }
+
/* If rowid is changing, make sure the new rowid does not previously
** exist in the table.
*/
@@ -119010,14 +120997,12 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
** to run without a statement journal if there are no indexes on the
** table.
*/
- Trigger *pTrigger = 0;
- if( db->flags&SQLITE_RecTriggers ){
- pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
- }
- if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
+ if( regTrigCnt ){
sqlite3MultiWrite(pParse);
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
regNewData, 1, 0, OE_Replace, 1, -1);
+ sqlite3VdbeAddOp2(v, OP_AddImm, regTrigCnt, 1); /* incr trigger cnt */
+ nReplaceTrig++;
}else{
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
assert( HasRowid(pTab) );
@@ -119067,6 +121052,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
int regR; /* Range of registers holding conflicting PK */
int iThisCur; /* Cursor for this UNIQUE index */
int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */
+ int addrConflictCk; /* First opcode in the conflict check logic */
if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */
if( pUpIdx==pIdx ){
@@ -119106,14 +121092,15 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i);
pParse->iSelfTab = 0;
VdbeComment((v, "%s column %d", pIdx->zName, i));
+ }else if( iField==XN_ROWID || iField==pTab->iPKey ){
+ x = regNewData;
+ sqlite3VdbeAddOp2(v, OP_IntCopy, x, regIdx+i);
+ VdbeComment((v, "rowid"));
}else{
- if( iField==XN_ROWID || iField==pTab->iPKey ){
- x = regNewData;
- }else{
- x = iField + regNewData + 1;
- }
- sqlite3VdbeAddOp2(v, iField<0 ? OP_IntCopy : OP_SCopy, x, regIdx+i);
- VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName));
+ testcase( sqlite3TableColumnToStorage(pTab, iField)!=iField );
+ x = sqlite3TableColumnToStorage(pTab, iField) + regNewData + 1;
+ sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i);
+ VdbeComment((v, "%s", pTab->aCol[iField].zName));
}
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
@@ -119123,6 +121110,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
sqlite3SetMakeRecordP5(v, pIdx->pTable);
}
#endif
+ sqlite3VdbeReleaseRegisters(pParse, regIdx, pIdx->nColumn, 0, 0);
/* In an UPDATE operation, if this index is the PRIMARY KEY index
** of a WITHOUT ROWID table and there has been no change the
@@ -119180,8 +121168,9 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
/* Check to see if the new index entry will be unique */
sqlite3VdbeVerifyAbortable(v, onError);
- sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
- regIdx, pIdx->nKeyCol); VdbeCoverage(v);
+ addrConflictCk =
+ sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
+ regIdx, pIdx->nKeyCol); VdbeCoverage(v);
/* Generate code to handle collisions */
regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField);
@@ -119202,7 +121191,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
if( pIdx!=pPk ){
for(i=0; i<pPk->nKeyCol; i++){
assert( pPk->aiColumn[i]>=0 );
- x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
+ x = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
VdbeComment((v, "%s.%s", pTab->zName,
pTab->aCol[pPk->aiColumn[i]].zName));
@@ -119228,6 +121217,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
addrJump = addrUniqueOk;
op = OP_Eq;
}
+ x = sqlite3TableColumnToStorage(pTab, x);
sqlite3VdbeAddOp4(v, op,
regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ
);
@@ -119264,17 +121254,71 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
break;
}
default: {
- Trigger *pTrigger = 0;
+ int nConflictCk; /* Number of opcodes in conflict check logic */
+
assert( onError==OE_Replace );
- if( db->flags&SQLITE_RecTriggers ){
- pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
- }
- if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
+ nConflictCk = sqlite3VdbeCurrentAddr(v) - addrConflictCk;
+ assert( nConflictCk>0 );
+ testcase( nConflictCk>1 );
+ if( regTrigCnt ){
sqlite3MultiWrite(pParse);
+ nReplaceTrig++;
+ }
+ if( pTrigger && isUpdate ){
+ sqlite3VdbeAddOp1(v, OP_CursorLock, iDataCur);
}
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
regR, nPkField, 0, OE_Replace,
(pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
+ if( pTrigger && isUpdate ){
+ sqlite3VdbeAddOp1(v, OP_CursorUnlock, iDataCur);
+ }
+ if( regTrigCnt ){
+ int addrBypass; /* Jump destination to bypass recheck logic */
+
+ sqlite3VdbeAddOp2(v, OP_AddImm, regTrigCnt, 1); /* incr trigger cnt */
+ addrBypass = sqlite3VdbeAddOp0(v, OP_Goto); /* Bypass recheck */
+ VdbeComment((v, "bypass recheck"));
+
+ /* Here we insert code that will be invoked after all constraint
+ ** checks have run, if and only if one or more replace triggers
+ ** fired. */
+ sqlite3VdbeResolveLabel(v, lblRecheckOk);
+ lblRecheckOk = sqlite3VdbeMakeLabel(pParse);
+ if( pIdx->pPartIdxWhere ){
+ /* Bypass the recheck if this partial index is not defined
+ ** for the current row */
+ sqlite3VdbeAddOp2(v, OP_IsNull, regIdx-1, lblRecheckOk);
+ VdbeCoverage(v);
+ }
+ /* Copy the constraint check code from above, except change
+ ** the constraint-ok jump destination to be the address of
+ ** the next retest block */
+ while( nConflictCk>0 ){
+ VdbeOp x; /* Conflict check opcode to copy */
+ /* The sqlite3VdbeAddOp4() call might reallocate the opcode array.
+ ** Hence, make a complete copy of the opcode, rather than using
+ ** a pointer to the opcode. */
+ x = *sqlite3VdbeGetOp(v, addrConflictCk);
+ if( x.opcode!=OP_IdxRowid ){
+ int p2; /* New P2 value for copied conflict check opcode */
+ if( sqlite3OpcodeProperty[x.opcode]&OPFLG_JUMP ){
+ p2 = lblRecheckOk;
+ }else{
+ p2 = x.p2;
+ }
+ sqlite3VdbeAddOp4(v, x.opcode, x.p1, p2, x.p3, x.p4.z, x.p4type);
+ sqlite3VdbeChangeP5(v, x.p5);
+ VdbeCoverageIf(v, p2!=x.p2);
+ }
+ nConflictCk--;
+ addrConflictCk++;
+ }
+ /* If the retest fails, issue an abort */
+ sqlite3UniqueConstraint(pParse, OE_Abort, pIdx);
+
+ sqlite3VdbeJumpHere(v, addrBypass); /* Terminate the recheck bypass */
+ }
seenReplace = 1;
break;
}
@@ -119295,10 +121339,30 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
sqlite3VdbeJumpHere(v, ipkBottom);
}
+ /* Recheck all uniqueness constraints after replace triggers have run */
+ testcase( regTrigCnt!=0 && nReplaceTrig==0 );
+ assert( regTrigCnt!=0 || nReplaceTrig==0 );
+ if( nReplaceTrig ){
+ sqlite3VdbeAddOp2(v, OP_IfNot, regTrigCnt, lblRecheckOk);VdbeCoverage(v);
+ if( !pPk ){
+ if( isUpdate ){
+ sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRecheck, regOldData);
+ sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
+ VdbeCoverage(v);
+ }
+ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRecheck, regNewData);
+ VdbeCoverage(v);
+ sqlite3RowidConstraint(pParse, OE_Abort, pTab);
+ }else{
+ sqlite3VdbeGoto(v, addrRecheck);
+ }
+ sqlite3VdbeResolveLabel(v, lblRecheckOk);
+ }
+
/* Generate the table record */
if( HasRowid(pTab) ){
int regRec = aRegIdx[ix];
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regNewData+1, pTab->nCol, regRec);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regNewData+1, pTab->nNVCol, regRec);
sqlite3SetMakeRecordP5(v, pTab);
if( !bAffinityDone ){
sqlite3TableAffinity(v, pTab, 0);
@@ -119365,6 +121429,10 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
+ /* All REPLACE indexes are at the end of the list */
+ assert( pIdx->onError!=OE_Replace
+ || pIdx->pNext==0
+ || pIdx->pNext->onError==OE_Replace );
if( aRegIdx[i]==0 ) continue;
if( pIdx->pPartIdxWhere ){
sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
@@ -119515,7 +121583,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
int i;
assert( pDest && pSrc );
assert( pDest->pTable!=pSrc->pTable );
- if( pDest->nKeyCol!=pSrc->nKeyCol ){
+ if( pDest->nKeyCol!=pSrc->nKeyCol || pDest->nColumn!=pSrc->nColumn ){
return 0; /* Different number of columns */
}
if( pDest->onError!=pSrc->onError ){
@@ -119693,6 +121761,39 @@ static int xferOptimization(
return 0; /* Neither table may have __hidden__ columns */
}
#endif
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ /* Even if tables t1 and t2 have identical schemas, if they contain
+ ** generated columns, then this statement is semantically incorrect:
+ **
+ ** INSERT INTO t2 SELECT * FROM t1;
+ **
+ ** The reason is that generated column values are returned by the
+ ** the SELECT statement on the right but the INSERT statement on the
+ ** left wants them to be omitted.
+ **
+ ** Nevertheless, this is a useful notational shorthand to tell SQLite
+ ** to do a bulk transfer all of the content from t1 over to t2.
+ **
+ ** We could, in theory, disable this (except for internal use by the
+ ** VACUUM command where it is actually needed). But why do that? It
+ ** seems harmless enough, and provides a useful service.
+ */
+ if( (pDestCol->colFlags & COLFLAG_GENERATED) !=
+ (pSrcCol->colFlags & COLFLAG_GENERATED) ){
+ return 0; /* Both columns have the same generated-column type */
+ }
+ /* But the transfer is only allowed if both the source and destination
+ ** tables have the exact same expressions for generated columns.
+ ** This requirement could be relaxed for VIRTUAL columns, I suppose.
+ */
+ if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){
+ if( sqlite3ExprCompare(0, pSrcCol->pDflt, pDestCol->pDflt, -1)!=0 ){
+ testcase( pDestCol->colFlags & COLFLAG_VIRTUAL );
+ testcase( pDestCol->colFlags & COLFLAG_STORED );
+ return 0; /* Different generator expressions */
+ }
+ }
+#endif
if( pDestCol->affinity!=pSrcCol->affinity ){
return 0; /* Affinity must be the same on all columns */
}
@@ -119703,7 +121804,7 @@ static int xferOptimization(
return 0; /* tab2 must be NOT NULL if tab1 is */
}
/* Default values for second and subsequent columns need to match. */
- if( i>0 ){
+ if( (pDestCol->colFlags & COLFLAG_GENERATED)==0 && i>0 ){
assert( pDestCol->pDflt==0 || pDestCol->pDflt->op==TK_SPAN );
assert( pSrcCol->pDflt==0 || pSrcCol->pDflt->op==TK_SPAN );
if( (pDestCol->pDflt==0)!=(pSrcCol->pDflt==0)
@@ -120388,6 +122489,12 @@ struct sqlite3_api_routines {
int (*value_frombind)(sqlite3_value*);
/* Version 3.30.0 and later */
int (*drop_modules)(sqlite3*,const char**);
+ /* Version 3.31.0 and later */
+ sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64);
+ const char *(*uri_key)(const char*,int);
+ const char *(*filename_database)(const char*);
+ const char *(*filename_journal)(const char*);
+ const char *(*filename_wal)(const char*);
};
/*
@@ -120678,10 +122785,16 @@ typedef int (*sqlite3_loadext_entry)(
/* Version 3.26.0 and later */
#define sqlite3_normalized_sql sqlite3_api->normalized_sql
/* Version 3.28.0 and later */
-#define sqlite3_stmt_isexplain sqlite3_api->isexplain
-#define sqlite3_value_frombind sqlite3_api->frombind
+#define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain
+#define sqlite3_value_frombind sqlite3_api->value_frombind
/* Version 3.30.0 and later */
#define sqlite3_drop_modules sqlite3_api->drop_modules
+/* Version 3.31.0 and later */
+#define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64
+#define sqlite3_uri_key sqlite3_api->uri_key
+#define sqlite3_filename_database sqlite3_api->filename_database
+#define sqlite3_filename_journal sqlite3_api->filename_journal
+#define sqlite3_filename_wal sqlite3_api->filename_wal
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -121154,6 +123267,12 @@ static const sqlite3_api_routines sqlite3Apis = {
#else
0,
#endif
+ /* Version 3.31.0 and later */
+ sqlite3_hard_heap_limit64,
+ sqlite3_uri_key,
+ sqlite3_filename_database,
+ sqlite3_filename_journal,
+ sqlite3_filename_wal,
};
/*
@@ -121576,34 +123695,35 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){
#define PragTyp_FOREIGN_KEY_CHECK 13
#define PragTyp_FOREIGN_KEY_LIST 14
#define PragTyp_FUNCTION_LIST 15
-#define PragTyp_INCREMENTAL_VACUUM 16
-#define PragTyp_INDEX_INFO 17
-#define PragTyp_INDEX_LIST 18
-#define PragTyp_INTEGRITY_CHECK 19
-#define PragTyp_JOURNAL_MODE 20
-#define PragTyp_JOURNAL_SIZE_LIMIT 21
-#define PragTyp_LOCK_PROXY_FILE 22
-#define PragTyp_LOCKING_MODE 23
-#define PragTyp_PAGE_COUNT 24
-#define PragTyp_MMAP_SIZE 25
-#define PragTyp_MODULE_LIST 26
-#define PragTyp_OPTIMIZE 27
-#define PragTyp_PAGE_SIZE 28
-#define PragTyp_PRAGMA_LIST 29
-#define PragTyp_SECURE_DELETE 30
-#define PragTyp_SHRINK_MEMORY 31
-#define PragTyp_SOFT_HEAP_LIMIT 32
-#define PragTyp_SYNCHRONOUS 33
-#define PragTyp_TABLE_INFO 34
-#define PragTyp_TEMP_STORE 35
-#define PragTyp_TEMP_STORE_DIRECTORY 36
-#define PragTyp_THREADS 37
-#define PragTyp_WAL_AUTOCHECKPOINT 38
-#define PragTyp_WAL_CHECKPOINT 39
-#define PragTyp_ACTIVATE_EXTENSIONS 40
-#define PragTyp_KEY 41
-#define PragTyp_LOCK_STATUS 42
-#define PragTyp_STATS 43
+#define PragTyp_HARD_HEAP_LIMIT 16
+#define PragTyp_INCREMENTAL_VACUUM 17
+#define PragTyp_INDEX_INFO 18
+#define PragTyp_INDEX_LIST 19
+#define PragTyp_INTEGRITY_CHECK 20
+#define PragTyp_JOURNAL_MODE 21
+#define PragTyp_JOURNAL_SIZE_LIMIT 22
+#define PragTyp_LOCK_PROXY_FILE 23
+#define PragTyp_LOCKING_MODE 24
+#define PragTyp_PAGE_COUNT 25
+#define PragTyp_MMAP_SIZE 26
+#define PragTyp_MODULE_LIST 27
+#define PragTyp_OPTIMIZE 28
+#define PragTyp_PAGE_SIZE 29
+#define PragTyp_PRAGMA_LIST 30
+#define PragTyp_SECURE_DELETE 31
+#define PragTyp_SHRINK_MEMORY 32
+#define PragTyp_SOFT_HEAP_LIMIT 33
+#define PragTyp_SYNCHRONOUS 34
+#define PragTyp_TABLE_INFO 35
+#define PragTyp_TEMP_STORE 36
+#define PragTyp_TEMP_STORE_DIRECTORY 37
+#define PragTyp_THREADS 38
+#define PragTyp_WAL_AUTOCHECKPOINT 39
+#define PragTyp_WAL_CHECKPOINT 40
+#define PragTyp_ACTIVATE_EXTENSIONS 41
+#define PragTyp_KEY 42
+#define PragTyp_LOCK_STATUS 43
+#define PragTyp_STATS 44
/* Property flags associated with various pragma. */
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
@@ -121642,35 +123762,39 @@ static const char *const pragCName[] = {
/* 18 */ "desc",
/* 19 */ "coll",
/* 20 */ "key",
- /* 21 */ "tbl", /* Used by: stats */
- /* 22 */ "idx",
- /* 23 */ "wdth",
- /* 24 */ "hght",
- /* 25 */ "flgs",
- /* 26 */ "seq", /* Used by: index_list */
- /* 27 */ "name",
- /* 28 */ "unique",
- /* 29 */ "origin",
- /* 30 */ "partial",
- /* 31 */ "table", /* Used by: foreign_key_check */
- /* 32 */ "rowid",
- /* 33 */ "parent",
- /* 34 */ "fkid",
+ /* 21 */ "name", /* Used by: function_list */
+ /* 22 */ "builtin",
+ /* 23 */ "type",
+ /* 24 */ "enc",
+ /* 25 */ "narg",
+ /* 26 */ "flags",
+ /* 27 */ "tbl", /* Used by: stats */
+ /* 28 */ "idx",
+ /* 29 */ "wdth",
+ /* 30 */ "hght",
+ /* 31 */ "flgs",
+ /* 32 */ "seq", /* Used by: index_list */
+ /* 33 */ "name",
+ /* 34 */ "unique",
+ /* 35 */ "origin",
+ /* 36 */ "partial",
+ /* 37 */ "table", /* Used by: foreign_key_check */
+ /* 38 */ "rowid",
+ /* 39 */ "parent",
+ /* 40 */ "fkid",
/* index_info reuses 15 */
- /* 35 */ "seq", /* Used by: database_list */
- /* 36 */ "name",
- /* 37 */ "file",
- /* 38 */ "busy", /* Used by: wal_checkpoint */
- /* 39 */ "log",
- /* 40 */ "checkpointed",
- /* 41 */ "name", /* Used by: function_list */
- /* 42 */ "builtin",
- /* collation_list reuses 26 */
- /* 43 */ "database", /* Used by: lock_status */
- /* 44 */ "status",
- /* 45 */ "cache_size", /* Used by: default_cache_size */
+ /* 41 */ "seq", /* Used by: database_list */
+ /* 42 */ "name",
+ /* 43 */ "file",
+ /* 44 */ "busy", /* Used by: wal_checkpoint */
+ /* 45 */ "log",
+ /* 46 */ "checkpointed",
+ /* collation_list reuses 32 */
+ /* 47 */ "database", /* Used by: lock_status */
+ /* 48 */ "status",
+ /* 49 */ "cache_size", /* Used by: default_cache_size */
/* module_list pragma_list reuses 9 */
- /* 46 */ "timeout", /* Used by: busy_timeout */
+ /* 50 */ "timeout", /* Used by: busy_timeout */
};
/* Definitions of all built-in pragmas */
@@ -121716,7 +123840,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "busy_timeout",
/* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 46, 1,
+ /* ColNames: */ 50, 1,
/* iArg: */ 0 },
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "cache_size",
@@ -121755,7 +123879,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "collation_list",
/* ePragTyp: */ PragTyp_COLLATION_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 26, 2,
+ /* ColNames: */ 32, 2,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
@@ -121790,14 +123914,14 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "database_list",
/* ePragTyp: */ PragTyp_DATABASE_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
- /* ColNames: */ 35, 3,
+ /* ColNames: */ 41, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
{/* zName: */ "default_cache_size",
/* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
- /* ColNames: */ 45, 1,
+ /* ColNames: */ 49, 1,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -121827,7 +123951,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "foreign_key_check",
/* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
- /* ColNames: */ 31, 4,
+ /* ColNames: */ 37, 4,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
@@ -121870,10 +123994,15 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "function_list",
/* ePragTyp: */ PragTyp_FUNCTION_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 41, 2,
+ /* ColNames: */ 21, 6,
/* iArg: */ 0 },
#endif
#endif
+ {/* zName: */ "hard_heap_limit",
+ /* ePragTyp: */ PragTyp_HARD_HEAP_LIMIT,
+ /* ePragFlg: */ PragFlg_Result0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 0 },
#if defined(SQLITE_HAS_CODEC)
{/* zName: */ "hexkey",
/* ePragTyp: */ PragTyp_KEY,
@@ -121911,7 +124040,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "index_list",
/* ePragTyp: */ PragTyp_INDEX_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 26, 5,
+ /* ColNames: */ 32, 5,
/* iArg: */ 0 },
{/* zName: */ "index_xinfo",
/* ePragTyp: */ PragTyp_INDEX_INFO,
@@ -121951,11 +124080,6 @@ static const PragmaName aPragmaName[] = {
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
/* iArg: */ SQLITE_LegacyAlter },
- {/* zName: */ "legacy_file_format",
- /* ePragTyp: */ PragTyp_FLAG,
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
- /* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_LegacyFileFmt },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
{/* zName: */ "lock_proxy_file",
@@ -121968,7 +124092,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "lock_status",
/* ePragTyp: */ PragTyp_LOCK_STATUS,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 43, 2,
+ /* ColNames: */ 47, 2,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -122116,7 +124240,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "stats",
/* ePragTyp: */ PragTyp_STATS,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
- /* ColNames: */ 21, 5,
+ /* ColNames: */ 27, 5,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -122167,6 +124291,13 @@ static const PragmaName aPragmaName[] = {
/* ePragFlg: */ PragFlg_Result0,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+ {/* zName: */ "trusted_schema",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ SQLITE_TrustedSchema },
+#endif
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
{/* zName: */ "user_version",
/* ePragTyp: */ PragTyp_HEADER_VALUE,
@@ -122212,7 +124343,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "wal_checkpoint",
/* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
/* ePragFlg: */ PragFlg_NeedSchema,
- /* ColNames: */ 38, 3,
+ /* ColNames: */ 44, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -122223,7 +124354,7 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
#endif
};
-/* Number of pragmas: 65 on by default, 81 total. */
+/* Number of pragmas: 66 on by default, 82 total. */
/************** End of pragma.h **********************************************/
/************** Continuing where we left off in pragma.c *********************/
@@ -122494,6 +124625,55 @@ static const PragmaName *pragmaLocate(const char *zName){
}
/*
+** Create zero or more entries in the output for the SQL functions
+** defined by FuncDef p.
+*/
+static void pragmaFunclistLine(
+ Vdbe *v, /* The prepared statement being created */
+ FuncDef *p, /* A particular function definition */
+ int isBuiltin, /* True if this is a built-in function */
+ int showInternFuncs /* True if showing internal functions */
+){
+ for(; p; p=p->pNext){
+ const char *zType;
+ static const u32 mask =
+ SQLITE_DETERMINISTIC |
+ SQLITE_DIRECTONLY |
+ SQLITE_SUBTYPE |
+ SQLITE_INNOCUOUS |
+ SQLITE_FUNC_INTERNAL
+ ;
+ static const char *azEnc[] = { 0, "utf8", "utf16le", "utf16be" };
+
+ assert( SQLITE_FUNC_ENCMASK==0x3 );
+ assert( strcmp(azEnc[SQLITE_UTF8],"utf8")==0 );
+ assert( strcmp(azEnc[SQLITE_UTF16LE],"utf16le")==0 );
+ assert( strcmp(azEnc[SQLITE_UTF16BE],"utf16be")==0 );
+
+ if( p->xSFunc==0 ) continue;
+ if( (p->funcFlags & SQLITE_FUNC_INTERNAL)!=0
+ && showInternFuncs==0
+ ){
+ continue;
+ }
+ if( p->xValue!=0 ){
+ zType = "w";
+ }else if( p->xFinalize!=0 ){
+ zType = "a";
+ }else{
+ zType = "s";
+ }
+ sqlite3VdbeMultiLoad(v, 1, "sissii",
+ p->zName, isBuiltin,
+ zType, azEnc[p->funcFlags&SQLITE_FUNC_ENCMASK],
+ p->nArg,
+ (p->funcFlags & mask) ^ SQLITE_INNOCUOUS
+ );
+ }
+}
+
+
+/*
** Helper subroutine for PRAGMA integrity_check:
**
** Generate code to output a single-column result row with a value of the
@@ -123298,10 +125478,19 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3CodeVerifySchema(pParse, iTabDb);
sqlite3ViewGetColumnNames(pParse, pTab);
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
- int isHidden = IsHiddenColumn(pCol);
- if( isHidden && pPragma->iArg==0 ){
- nHidden++;
- continue;
+ int isHidden = 0;
+ if( pCol->colFlags & COLFLAG_NOINSERT ){
+ if( pPragma->iArg==0 ){
+ nHidden++;
+ continue;
+ }
+ if( pCol->colFlags & COLFLAG_VIRTUAL ){
+ isHidden = 2; /* GENERATED ALWAYS AS ... VIRTUAL */
+ }else if( pCol->colFlags & COLFLAG_STORED ){
+ isHidden = 3; /* GENERATED ALWAYS AS ... STORED */
+ }else{ assert( pCol->colFlags & COLFLAG_HIDDEN );
+ isHidden = 1; /* HIDDEN */
+ }
}
if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
k = 0;
@@ -123310,13 +125499,13 @@ SQLITE_PRIVATE void sqlite3Pragma(
}else{
for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
}
- assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN );
+ assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN || isHidden>=2 );
sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
i-nHidden,
pCol->zName,
sqlite3ColumnType(pCol,""),
pCol->notNull ? 1 : 0,
- pCol->pDflt ? pCol->pDflt->u.zToken : 0,
+ pCol->pDflt && isHidden<2 ? pCol->pDflt->u.zToken : 0,
k,
isHidden);
}
@@ -123448,16 +125637,16 @@ SQLITE_PRIVATE void sqlite3Pragma(
int i;
HashElem *j;
FuncDef *p;
- pParse->nMem = 2;
+ int showInternFunc = (db->mDbFlags & DBFLAG_InternalFunc)!=0;
+ pParse->nMem = 6;
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
- if( p->funcFlags & SQLITE_FUNC_INTERNAL ) continue;
- sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1);
+ pragmaFunclistLine(v, p, 1, showInternFunc);
}
}
for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){
p = (FuncDef*)sqliteHashData(j);
- sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 0);
+ pragmaFunclistLine(v, p, 0, showInternFunc);
}
}
break;
@@ -123775,7 +125964,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
if( !isQuick ){
/* Sanity check on record header decoding */
- sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
+ sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nNVCol-1,3);
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
}
/* Verify that all NOT NULL columns really are NOT NULL */
@@ -123964,10 +126153,17 @@ SQLITE_PRIVATE void sqlite3Pragma(
** will be overwritten when the schema is next loaded. If it does not
** already exists, it will be created to use the new encoding value.
*/
- if(
- !(DbHasProperty(db, 0, DB_SchemaLoaded)) ||
- DbHasProperty(db, 0, DB_Empty)
- ){
+ int canChangeEnc = 1; /* True if allowed to change the encoding */
+ int i; /* For looping over all attached databases */
+ for(i=0; i<db->nDb; i++){
+ if( db->aDb[i].pBt!=0
+ && DbHasProperty(db,i,DB_SchemaLoaded)
+ && !DbHasProperty(db,i,DB_Empty)
+ ){
+ canChangeEnc = 0;
+ }
+ }
+ if( canChangeEnc ){
for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
SCHEMA_ENC(db) = ENC(db) =
@@ -124281,6 +126477,27 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
/*
+ ** PRAGMA hard_heap_limit
+ ** PRAGMA hard_heap_limit = N
+ **
+ ** Invoke sqlite3_hard_heap_limit64() to query or set the hard heap
+ ** limit. The hard heap limit can be activated or lowered by this
+ ** pragma, but not raised or deactivated. Only the
+ ** sqlite3_hard_heap_limit64() C-language API can raise or deactivate
+ ** the hard heap limit. This allows an application to set a heap limit
+ ** constraint that cannot be relaxed by an untrusted SQL script.
+ */
+ case PragTyp_HARD_HEAP_LIMIT: {
+ sqlite3_int64 N;
+ if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
+ sqlite3_int64 iPrior = sqlite3_hard_heap_limit64(-1);
+ if( N>0 && (iPrior==0 || iPrior>N) ) sqlite3_hard_heap_limit64(N);
+ }
+ returnSingleInt(v, sqlite3_hard_heap_limit64(-1));
+ break;
+ }
+
+ /*
** PRAGMA threads
** PRAGMA threads = N
**
@@ -124773,6 +126990,18 @@ SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index *pIndex){
return 0;
}
+/* forward declaration */
+static int sqlite3Prepare(
+ sqlite3 *db, /* Database handle. */
+ const char *zSql, /* UTF-8 encoded SQL statement. */
+ int nBytes, /* Length of zSql in bytes. */
+ u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
+ Vdbe *pReprepare, /* VM being reprepared */
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
+ const char **pzTail /* OUT: End of parsed string */
+);
+
+
/*
** This is the callback routine for the code that initializes the
** database. See sqlite3Init() below for additional information.
@@ -124822,7 +127051,8 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
db->init.newTnum = sqlite3Atoi(argv[3]);
db->init.orphanTrigger = 0;
db->init.azInit = argv;
- TESTONLY(rcp = ) sqlite3_prepare(db, argv[4], -1, &pStmt, 0);
+ pStmt = 0;
+ TESTONLY(rcp = ) sqlite3Prepare(db, argv[4], -1, 0, 0, &pStmt, 0);
rc = db->errCode;
assert( (rc&0xFF)==(rcp&0xFF) );
db->init.iDb = saved_iDb;
@@ -125243,6 +127473,7 @@ SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){
if( db ){
assert( db->lookaside.bDisable >= pParse->disableLookaside );
db->lookaside.bDisable -= pParse->disableLookaside;
+ db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue;
}
pParse->disableLookaside = 0;
}
@@ -125276,7 +127507,7 @@ static int sqlite3Prepare(
*/
if( prepFlags & SQLITE_PREPARE_PERSISTENT ){
sParse.disableLookaside++;
- db->lookaside.bDisable++;
+ DisableLookaside;
}
sParse.disableVtab = (prepFlags & SQLITE_PREPARE_NO_VTAB)!=0;
@@ -125303,16 +127534,18 @@ static int sqlite3Prepare(
** but it does *not* override schema lock detection, so this all still
** works even if READ_UNCOMMITTED is set.
*/
- for(i=0; i<db->nDb; i++) {
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- assert( sqlite3BtreeHoldsMutex(pBt) );
- rc = sqlite3BtreeSchemaLocked(pBt);
- if( rc ){
- const char *zDb = db->aDb[i].zDbSName;
- sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
- testcase( db->flags & SQLITE_ReadUncommit );
- goto end_prepare;
+ if( !db->noSharedCache ){
+ for(i=0; i<db->nDb; i++) {
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt ){
+ assert( sqlite3BtreeHoldsMutex(pBt) );
+ rc = sqlite3BtreeSchemaLocked(pBt);
+ if( rc ){
+ const char *zDb = db->aDb[i].zDbSName;
+ sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
+ testcase( db->flags & SQLITE_ReadUncommit );
+ goto end_prepare;
+ }
}
}
}
@@ -125343,48 +127576,24 @@ static int sqlite3Prepare(
}
assert( 0==sParse.nQueryLoop );
- if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
+ if( sParse.rc==SQLITE_DONE ){
+ sParse.rc = SQLITE_OK;
+ }
if( sParse.checkSchema ){
schemaIsValid(&sParse);
}
- if( db->mallocFailed ){
- sParse.rc = SQLITE_NOMEM_BKPT;
- }
if( pzTail ){
*pzTail = sParse.zTail;
}
- rc = sParse.rc;
-
-#ifndef SQLITE_OMIT_EXPLAIN
- /* Justification for the ALWAYS(): The only way for rc to be SQLITE_OK and
- ** sParse.pVdbe to be NULL is if the input SQL is an empty string, but in
- ** that case, sParse.explain will be false. */
- if( sParse.explain && rc==SQLITE_OK && ALWAYS(sParse.pVdbe) ){
- static const char * const azColName[] = {
- "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
- "id", "parent", "notused", "detail"
- };
- int iFirst, mx;
- if( sParse.explain==2 ){
- sqlite3VdbeSetNumCols(sParse.pVdbe, 4);
- iFirst = 8;
- mx = 12;
- }else{
- sqlite3VdbeSetNumCols(sParse.pVdbe, 8);
- iFirst = 0;
- mx = 8;
- }
- for(i=iFirst; i<mx; i++){
- sqlite3VdbeSetColName(sParse.pVdbe, i-iFirst, COLNAME_NAME,
- azColName[i], SQLITE_STATIC);
- }
- }
-#endif
if( db->init.busy==0 ){
sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags);
}
- if( rc!=SQLITE_OK || db->mallocFailed ){
+ if( db->mallocFailed ){
+ sParse.rc = SQLITE_NOMEM_BKPT;
+ }
+ rc = sParse.rc;
+ if( rc!=SQLITE_OK ){
if( sParse.pVdbe ) sqlite3VdbeFinalize(sParse.pVdbe);
assert(!(*ppStmt));
}else{
@@ -125740,7 +127949,10 @@ struct SortCtx {
/*
** Delete all the content of a Select structure. Deallocate the structure
-** itself only if bFree is true.
+** itself depending on the value of bFree
+**
+** If bFree==1, call sqlite3DbFree() on the p object.
+** If bFree==0, Leave the first Select object unfreed
*/
static void clearSelect(sqlite3 *db, Select *p, int bFree){
while( p ){
@@ -125845,6 +128057,21 @@ SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){
}
/*
+** Delete all the substructure for p, but keep p allocated. Redefine
+** p to be a single SELECT where every column of the result set has a
+** value of NULL.
+*/
+SQLITE_PRIVATE void sqlite3SelectReset(Parse *pParse, Select *p){
+ if( ALWAYS(p) ){
+ clearSelect(pParse->db, p, 0);
+ memset(&p->iLimit, 0, sizeof(Select) - offsetof(Select,iLimit));
+ p->pEList = sqlite3ExprListAppend(pParse, 0,
+ sqlite3ExprAlloc(pParse->db,TK_NULL,0,0));
+ p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(SrcList));
+ }
+}
+
+/*
** Return a pointer to the right-most SELECT statement in a compound.
*/
static Select *findRightmost(Select *p){
@@ -125952,7 +128179,8 @@ static int tableAndColumnIndex(
int N, /* Number of tables in pSrc->a[] to search */
const char *zCol, /* Name of the column we are looking for */
int *piTab, /* Write index of pSrc->a[] here */
- int *piCol /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
+ int *piCol, /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
+ int bIgnoreHidden /* True to ignore hidden columns */
){
int i; /* For looping over tables in pSrc */
int iCol; /* Index of column matching zCol */
@@ -125960,7 +128188,9 @@ static int tableAndColumnIndex(
assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
for(i=0; i<N; i++){
iCol = columnIndex(pSrc->a[i].pTab, zCol);
- if( iCol>=0 ){
+ if( iCol>=0
+ && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
+ ){
if( piTab ){
*piTab = i;
*piCol = iCol;
@@ -126041,7 +128271,7 @@ static void addWhereTerm(
** after the t1 loop and rows with t1.x!=5 will never appear in
** the output, which is incorrect.
*/
-static void setJoinExpr(Expr *p, int iTable){
+SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr *p, int iTable){
while( p ){
ExprSetProperty(p, EP_FromJoin);
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
@@ -126050,15 +128280,15 @@ static void setJoinExpr(Expr *p, int iTable){
if( p->op==TK_FUNCTION && p->x.pList ){
int i;
for(i=0; i<p->x.pList->nExpr; i++){
- setJoinExpr(p->x.pList->a[i].pExpr, iTable);
+ sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable);
}
}
- setJoinExpr(p->pLeft, iTable);
+ sqlite3SetJoinExpr(p->pLeft, iTable);
p = p->pRight;
}
}
-/* Undo the work of setJoinExpr(). In the expression tree p, convert every
+/* Undo the work of sqlite3SetJoinExpr(). In the expression p, convert every
** term that is marked with EP_FromJoin and iRightJoinTable==iTable into
** an ordinary term that omits the EP_FromJoin mark.
**
@@ -126125,10 +128355,11 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
int iLeft; /* Matching left table */
int iLeftCol; /* Matching column in the left table */
+ if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue;
zName = pRightTab->aCol[j].zName;
- if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){
+ if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 1) ){
addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
- isOuter, &p->pWhere);
+ isOuter, &p->pWhere);
}
}
}
@@ -126145,7 +128376,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
** an AND operator.
*/
if( pRight->pOn ){
- if( isOuter ) setJoinExpr(pRight->pOn, pRight->iCursor);
+ if( isOuter ) sqlite3SetJoinExpr(pRight->pOn, pRight->iCursor);
p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->pOn);
pRight->pOn = 0;
}
@@ -126168,7 +128399,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
zName = pList->a[j].zName;
iRightCol = columnIndex(pRightTab, zName);
if( iRightCol<0
- || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol)
+ || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 0)
){
sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
"not present in both tables", zName);
@@ -126325,6 +128556,7 @@ static void pushOntoSorter(
testcase( pKI->nAllField > pKI->nKeyField+2 );
pOp->p4.pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pSort->pOrderBy,nOBSat,
pKI->nAllField-pKI->nKeyField-1);
+ pOp = 0; /* Ensure pOp not used after sqltie3VdbeAddOp3() */
addrJmp = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
pSort->labelBkOut = sqlite3VdbeMakeLabel(pParse);
@@ -126573,7 +128805,7 @@ static void selectInnerLoop(
if( srcTab>=0 ){
for(i=0; i<nResultCol; i++){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
- VdbeComment((v, "%s", p->pEList->a[i].zName));
+ VdbeComment((v, "%s", p->pEList->a[i].zEName));
}
}else if( eDest!=SRT_Exists ){
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
@@ -126687,6 +128919,7 @@ static void selectInnerLoop(
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++){
@@ -127193,7 +129426,7 @@ static void generateSortTail(
iRead = iCol--;
}
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
- VdbeComment((v, "%s", aOutEx[i].zName?aOutEx[i].zName : aOutEx[i].zSpan));
+ VdbeComment((v, "%s", aOutEx[i].zEName));
}
}
switch( eDest ){
@@ -127527,9 +129760,9 @@ static void generateColumnNames(
assert( p!=0 );
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */
- if( pEList->a[i].zName ){
+ if( pEList->a[i].zEName && pEList->a[i].eEName==ENAME_NAME ){
/* An AS clause always takes first priority */
- char *zName = pEList->a[i].zName;
+ char *zName = pEList->a[i].zEName;
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
}else if( srcName && p->op==TK_COLUMN ){
char *zCol;
@@ -127551,7 +129784,7 @@ static void generateColumnNames(
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
}
}else{
- const char *z = pEList->a[i].zSpan;
+ const char *z = pEList->a[i].zEName;
z = z==0 ? sqlite3MPrintf(db, "column%d", i+1) : sqlite3DbStrDup(db, z);
sqlite3VdbeSetColName(v, i, COLNAME_NAME, z, SQLITE_DYNAMIC);
}
@@ -127613,7 +129846,7 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList(
for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){
/* Get an appropriate name for the column
*/
- if( (zName = pEList->a[i].zName)!=0 ){
+ if( (zName = pEList->a[i].zEName)!=0 && pEList->a[i].eEName==ENAME_NAME ){
/* If the column contains an "AS <name>" phrase, use <name> as the name */
}else{
Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr);
@@ -127633,10 +129866,10 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList(
zName = pColExpr->u.zToken;
}else{
/* Use the original text of the column expression as its name */
- zName = pEList->a[i].zSpan;
+ zName = pEList->a[i].zEName;
}
}
- if( zName ){
+ if( zName && !sqlite3IsTrueOrFalse(zName) ){
zName = sqlite3DbStrDup(db, zName);
}else{
zName = sqlite3MPrintf(db,"column%d",i+1);
@@ -128128,6 +130361,9 @@ static int multiSelectValues(
assert( p->selFlags & SF_Values );
assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr );
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( p->pWin ) return -1;
+#endif
if( p->pPrior==0 ) break;
assert( p->pPrior->pNext==p );
p = p->pPrior;
@@ -128218,7 +130454,8 @@ static int multiSelect(
*/
if( p->selFlags & SF_MultiValue ){
rc = multiSelectValues(pParse, p, &dest);
- goto multi_select_end;
+ if( rc>=0 ) goto multi_select_end;
+ rc = SQLITE_OK;
}
/* Make sure all SELECTs in the statement have the same number of elements
@@ -128363,9 +130600,9 @@ static int multiSelect(
** it is that we currently need.
*/
assert( unionTab==dest.iSDParm || dest.eDest!=priorOp );
- if( dest.eDest!=priorOp ){
+ assert( p->pEList || db->mallocFailed );
+ if( dest.eDest!=priorOp && db->mallocFailed==0 ){
int iCont, iBreak, iStart;
- assert( p->pEList );
iBreak = sqlite3VdbeMakeLabel(pParse);
iCont = sqlite3VdbeMakeLabel(pParse);
computeLimitRegisters(pParse, p, iBreak);
@@ -128461,6 +130698,7 @@ static int multiSelect(
}
#endif
}
+ if( pParse->nErr ) goto multi_select_end;
/* Compute collating sequences used by
** temporary tables needed to implement the compound select.
@@ -129252,6 +131490,7 @@ static void substSelect(
** (3b) the FROM clause of the subquery may not contain a virtual
** table and
** (3c) the outer query may not be an aggregate.
+** (3d) the outer query may not be DISTINCT.
**
** (4) The subquery can not be DISTINCT.
**
@@ -129302,6 +131541,7 @@ static void substSelect(
** (17d1) aggregate, or
** (17d2) DISTINCT, or
** (17d3) a join.
+** (17e) the subquery may not contain window functions
**
** The parent and sub-query may contain WHERE clauses. Subject to
** rules (11), (13) and (14), they may also contain ORDER BY,
@@ -129448,8 +131688,11 @@ static int flattenSubquery(
*/
if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
isLeftJoin = 1;
- if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){
- /* (3a) (3c) (3b) */
+ if( pSubSrc->nSrc>1 /* (3a) */
+ || isAgg /* (3b) */
+ || IsVirtual(pSubSrc->a[0].pTab) /* (3c) */
+ || (p->selFlags & SF_Distinct)!=0 /* (3d) */
+ ){
return 0;
}
}
@@ -129483,6 +131726,9 @@ static int flattenSubquery(
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */
|| (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */
|| pSub1->pSrc->nSrc<1 /* (17c) */
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ || pSub1->pWin /* (17e) */
+#endif
){
return 0;
}
@@ -129709,7 +131955,7 @@ static int flattenSubquery(
pWhere = pSub->pWhere;
pSub->pWhere = 0;
if( isLeftJoin>0 ){
- setJoinExpr(pWhere, iNewParent);
+ sqlite3SetJoinExpr(pWhere, iNewParent);
}
pParent->pWhere = sqlite3ExprAnd(pParse, pWhere, pParent->pWhere);
if( db->mallocFailed==0 ){
@@ -129769,23 +132015,36 @@ struct WhereConst {
/*
** Add a new entry to the pConst object. Except, do not add duplicate
-** pColumn entires.
+** pColumn entires. Also, do not add if doing so would not be appropriate.
+**
+** The caller guarantees the pColumn is a column and pValue is a constant.
+** This routine has to do some additional checks before completing the
+** insert.
*/
static void constInsert(
- WhereConst *pConst, /* The WhereConst into which we are inserting */
- Expr *pColumn, /* The COLUMN part of the constraint */
- Expr *pValue /* The VALUE part of the constraint */
+ WhereConst *pConst, /* The WhereConst into which we are inserting */
+ Expr *pColumn, /* The COLUMN part of the constraint */
+ Expr *pValue, /* The VALUE part of the constraint */
+ Expr *pExpr /* Overall expression: COLUMN=VALUE or VALUE=COLUMN */
){
int i;
assert( pColumn->op==TK_COLUMN );
+ assert( sqlite3ExprIsConstant(pValue) );
+
+ if( !ExprHasProperty(pValue, EP_FixedCol) && sqlite3ExprAffinity(pValue)!=0 ){
+ return;
+ }
+ if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pConst->pParse,pExpr)) ){
+ return;
+ }
/* 2018-10-25 ticket [cf5ed20f]
** Make sure the same pColumn is not inserted more than once */
for(i=0; i<pConst->nConst; i++){
- const Expr *pExpr = pConst->apExpr[i*2];
- assert( pExpr->op==TK_COLUMN );
- if( pExpr->iTable==pColumn->iTable
- && pExpr->iColumn==pColumn->iColumn
+ const Expr *pE2 = pConst->apExpr[i*2];
+ assert( pE2->op==TK_COLUMN );
+ if( pE2->iTable==pColumn->iTable
+ && pE2->iColumn==pColumn->iColumn
){
return; /* Already present. Return without doing anything. */
}
@@ -129797,7 +132056,9 @@ static void constInsert(
if( pConst->apExpr==0 ){
pConst->nConst = 0;
}else{
- if( ExprHasProperty(pValue, EP_FixedCol) ) pValue = pValue->pLeft;
+ if( ExprHasProperty(pValue, EP_FixedCol) ){
+ pValue = pValue->pLeft;
+ }
pConst->apExpr[pConst->nConst*2-2] = pColumn;
pConst->apExpr[pConst->nConst*2-1] = pValue;
}
@@ -129823,19 +132084,11 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
pLeft = pExpr->pLeft;
assert( pRight!=0 );
assert( pLeft!=0 );
- if( pRight->op==TK_COLUMN
- && !ExprHasProperty(pRight, EP_FixedCol)
- && sqlite3ExprIsConstant(pLeft)
- && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
- ){
- constInsert(pConst, pRight, pLeft);
- }else
- if( pLeft->op==TK_COLUMN
- && !ExprHasProperty(pLeft, EP_FixedCol)
- && sqlite3ExprIsConstant(pRight)
- && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
- ){
- constInsert(pConst, pLeft, pRight);
+ if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pLeft) ){
+ constInsert(pConst,pRight,pLeft,pExpr);
+ }
+ if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pRight) ){
+ constInsert(pConst,pLeft,pRight,pExpr);
}
}
@@ -129849,7 +132102,11 @@ static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
int i;
WhereConst *pConst;
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
- if( ExprHasProperty(pExpr, EP_FixedCol) ) return WRC_Continue;
+ if( ExprHasProperty(pExpr, EP_FixedCol|EP_FromJoin) ){
+ testcase( ExprHasProperty(pExpr, EP_FixedCol) );
+ testcase( ExprHasProperty(pExpr, EP_FromJoin) );
+ return WRC_Continue;
+ }
pConst = pWalker->u.pConst;
for(i=0; i<pConst->nConst; i++){
Expr *pColumn = pConst->apExpr[i*2];
@@ -129871,10 +132128,9 @@ static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
** The WHERE-clause constant propagation optimization.
**
** If the WHERE clause contains terms of the form COLUMN=CONSTANT or
-** CONSTANT=COLUMN that must be tree (in other words, if the terms top-level
-** AND-connected terms that are not part of a ON clause from a LEFT JOIN)
-** then throughout the query replace all other occurrences of COLUMN
-** with CONSTANT within the WHERE clause.
+** CONSTANT=COLUMN that are top-level AND-connected terms that are not
+** part of a ON clause from a LEFT JOIN, then throughout the query
+** replace all other occurrences of COLUMN with CONSTANT.
**
** For example, the query:
**
@@ -130223,6 +132479,9 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
p->pPrior = 0;
p->pNext = 0;
p->pWith = 0;
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ p->pWinDefn = 0;
+#endif
p->selFlags &= ~SF_Compound;
assert( (p->selFlags & SF_Converted)==0 );
p->selFlags |= SF_Converted;
@@ -130322,6 +132581,9 @@ static int withExpand(
With *pWith; /* WITH clause that pCte belongs to */
assert( pFrom->pTab==0 );
+ if( pParse->nErr ){
+ return SQLITE_ERROR;
+ }
pCte = searchWith(pParse->pWith, pFrom, &pWith);
if( pCte ){
@@ -130442,7 +132704,7 @@ static void selectPopWith(Walker *pWalker, Select *p){
if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){
With *pWith = findRightmost(p)->pWith;
if( pWith!=0 ){
- assert( pParse->pWith==pWith );
+ assert( pParse->pWith==pWith || pParse->nErr );
pParse->pWith = pWith->pOuter;
}
}
@@ -130573,7 +132835,7 @@ static int selectExpander(Walker *pWalker, Select *p){
if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){
return WRC_Abort;
}
-#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
if( IsVirtual(pTab) || pTab->pSelect ){
i16 nCol;
u8 eCodeOrig = pWalker->eCode;
@@ -130581,8 +132843,18 @@ static int selectExpander(Walker *pWalker, Select *p){
assert( pFrom->pSelect==0 );
if( pTab->pSelect && (db->flags & SQLITE_EnableView)==0 ){
sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
- pTab->zName);
+ pTab->zName);
+ }
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab)
+ && pFrom->fg.fromDDL
+ && ALWAYS(pTab->pVTable!=0)
+ && pTab->pVTable->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
+ ){
+ sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
+ pTab->zName);
}
+#endif
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
nCol = pTab->nCol;
pTab->nCol = -1;
@@ -130602,7 +132874,7 @@ static int selectExpander(Walker *pWalker, Select *p){
/* Process NATURAL keywords, and ON and USING clauses of joins.
*/
- if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){
+ if( pParse->nErr || db->mallocFailed || sqliteProcessJoin(pParse, p) ){
return WRC_Abort;
}
@@ -130649,10 +132921,9 @@ static int selectExpander(Walker *pWalker, Select *p){
*/
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
if( pNew ){
- pNew->a[pNew->nExpr-1].zName = a[k].zName;
- pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan;
- a[k].zName = 0;
- a[k].zSpan = 0;
+ pNew->a[pNew->nExpr-1].zEName = a[k].zEName;
+ pNew->a[pNew->nExpr-1].eEName = a[k].eEName;
+ a[k].zEName = 0;
}
a[k].pExpr = 0;
}else{
@@ -130691,7 +132962,7 @@ static int selectExpander(Walker *pWalker, Select *p){
assert( zName );
if( zTName && pSub
- && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
+ && sqlite3MatchEName(&pSub->pEList->a[j], 0, zTName, 0)==0
){
continue;
}
@@ -130709,7 +132980,7 @@ static int selectExpander(Walker *pWalker, Select *p){
if( i>0 && zTName==0 ){
if( (pFrom->fg.jointype & JT_NATURAL)!=0
- && tableAndColumnIndex(pTabList, i, zName, 0, 0)
+ && tableAndColumnIndex(pTabList, i, zName, 0, 0, 1)
){
/* In a NATURAL join, omit the join columns from the
** table to the right of the join */
@@ -130744,15 +133015,16 @@ static int selectExpander(Walker *pWalker, Select *p){
sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
+ sqlite3DbFree(db, pX->zEName);
if( pSub ){
- pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
- testcase( pX->zSpan==0 );
+ pX->zEName = sqlite3DbStrDup(db, pSub->pEList->a[j].zEName);
+ testcase( pX->zEName==0 );
}else{
- pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
+ pX->zEName = sqlite3MPrintf(db, "%s.%s.%s",
zSchemaName, zTabName, zColname);
- testcase( pX->zSpan==0 );
+ testcase( pX->zEName==0 );
}
- pX->bSpanIsTab = 1;
+ pX->eEName = ENAME_TAB;
}
sqlite3DbFree(db, zToFree);
}
@@ -131379,11 +133651,13 @@ SQLITE_PRIVATE int sqlite3Select(
}
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( sqlite3WindowRewrite(pParse, p) ){
+ rc = sqlite3WindowRewrite(pParse, p);
+ if( rc ){
+ assert( db->mallocFailed || pParse->nErr>0 );
goto select_end;
}
#if SELECTTRACE_ENABLED
- if( sqlite3SelectTrace & 0x108 ){
+ if( p->pWin && (sqlite3SelectTrace & 0x108)!=0 ){
SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -131715,10 +133989,13 @@ SQLITE_PRIVATE int sqlite3Select(
*/
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
+#ifndef SQLITE_OMIT_WINDOWFUNC
&& p->pWin==0
+#endif
){
p->selFlags &= ~SF_Distinct;
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
+ p->selFlags |= SF_Aggregate;
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
** the sDistinct.isTnct is still set. Hence, isTnct represents the
** original setting of the SF_Distinct flag, not the current setting */
@@ -131793,7 +134070,7 @@ SQLITE_PRIVATE int sqlite3Select(
#ifndef SQLITE_OMIT_WINDOWFUNC
Window *pWin = p->pWin; /* Master window object (or NULL) */
if( pWin ){
- sqlite3WindowCodeInit(pParse, pWin);
+ sqlite3WindowCodeInit(pParse, p);
}
#endif
assert( WHERE_USE_LIMIT==SF_FixedLimit );
@@ -133239,8 +135516,12 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const ch
Table *pTab = tableOfTrigger(pTrigger);
if( pTab ){
Trigger **pp;
- for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext));
- *pp = (*pp)->pNext;
+ for(pp=&pTab->pTrigger; *pp; pp=&((*pp)->pNext)){
+ if( *pp==pTrigger ){
+ *pp = (*pp)->pNext;
+ break;
+ }
+ }
}
}
sqlite3DeleteTrigger(db, pTrigger);
@@ -133261,7 +135542,7 @@ static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){
int e;
if( pIdList==0 || NEVER(pEList==0) ) return 1;
for(e=0; e<pEList->nExpr; e++){
- if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
+ if( sqlite3IdListIndex(pIdList, pEList->a[e].zEName)>=0 ) return 1;
}
return 0;
}
@@ -133921,7 +136202,7 @@ SQLITE_PRIVATE void sqlite3Update(
Expr *pLimit, /* LIMIT clause. May be null */
Upsert *pUpsert /* ON CONFLICT clause, or null */
){
- int i, j; /* Loop counters */
+ int i, j, k; /* Loop counters */
Table *pTab; /* The table to be updated */
int addrTop = 0; /* VDBE instruction address of the start of the loop */
WhereInfo *pWInfo; /* Information about the WHERE clause */
@@ -133965,6 +136246,7 @@ SQLITE_PRIVATE void sqlite3Update(
int iPk = 0; /* First of nPk cells holding PRIMARY KEY value */
i16 nPk = 0; /* Number of components of the PRIMARY KEY */
int bReplace = 0; /* True if REPLACE conflict resolution might happen */
+ int bFinishSeek = 1; /* The OP_FinishSeek opcode is needed */
/* Register Allocations */
int regRowCount = 0; /* A count of rows changed */
@@ -134063,6 +136345,10 @@ SQLITE_PRIVATE void sqlite3Update(
sNC.uNC.pUpsert = pUpsert;
sNC.ncFlags = NC_UUpsert;
+ /* Begin generating code. */
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ) goto update_cleanup;
+
/* Resolve the column names in all the expressions of the
** of the UPDATE statement. Also find the column index
** for each column to be updated in the pChanges array. For each
@@ -134075,24 +136361,34 @@ SQLITE_PRIVATE void sqlite3Update(
goto update_cleanup;
}
for(j=0; j<pTab->nCol; j++){
- if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
+ if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zEName)==0 ){
if( j==pTab->iPKey ){
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
}else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
chngPk = 1;
}
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
+ testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
+ testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
+ sqlite3ErrorMsg(pParse,
+ "cannot UPDATE generated column \"%s\"",
+ pTab->aCol[j].zName);
+ goto update_cleanup;
+ }
+#endif
aXRef[j] = i;
break;
}
}
if( j>=pTab->nCol ){
- if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zName) ){
+ if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zEName) ){
j = -1;
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
}else{
- sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
+ sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zEName);
pParse->checkSchema = 1;
goto update_cleanup;
}
@@ -134116,6 +136412,33 @@ SQLITE_PRIVATE void sqlite3Update(
assert( chngPk==0 || chngPk==1 );
chngKey = chngRowid + chngPk;
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ /* Mark generated columns as changing if their generator expressions
+ ** reference any changing column. The actual aXRef[] value for
+ ** generated expressions is not used, other than to check to see that it
+ ** is non-negative, so the value of aXRef[] for generated columns can be
+ ** set to any non-negative number. We use 99999 so that the value is
+ ** obvious when looking at aXRef[] in a symbolic debugger.
+ */
+ if( pTab->tabFlags & TF_HasGenerated ){
+ int bProgress;
+ testcase( pTab->tabFlags & TF_HasVirtual );
+ testcase( pTab->tabFlags & TF_HasStored );
+ do{
+ bProgress = 0;
+ for(i=0; i<pTab->nCol; i++){
+ if( aXRef[i]>=0 ) continue;
+ if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue;
+ if( sqlite3ExprReferencesUpdatedColumn(pTab->aCol[i].pDflt,
+ aXRef, chngRowid) ){
+ aXRef[i] = 99999;
+ bProgress = 1;
+ }
+ }
+ }while( bProgress );
+ }
+#endif
+
/* The SET expressions are not actually used inside the WHERE loop.
** So reset the colUsed mask. Unless this is a virtual table. In that
** case, set all bits of the colUsed mask (to ensure that the virtual
@@ -134160,9 +136483,6 @@ SQLITE_PRIVATE void sqlite3Update(
memset(aToOpen, 1, nIdx+1);
}
- /* Begin generating code. */
- v = sqlite3GetVdbe(pParse);
- if( v==0 ) goto update_cleanup;
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb);
@@ -134260,6 +136580,7 @@ SQLITE_PRIVATE void sqlite3Update(
pWInfo = 0;
eOnePass = ONEPASS_SINGLE;
sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL);
+ bFinishSeek = 0;
}else{
/* Begin the database scan.
**
@@ -134286,6 +136607,7 @@ SQLITE_PRIVATE void sqlite3Update(
** strategy that uses an index for which one or more columns are being
** updated. */
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
+ bFinishSeek = sqlite3WhereUsesDeferredSeek(pWInfo);
if( eOnePass!=ONEPASS_SINGLE ){
sqlite3MultiWrite(pParse);
if( eOnePass==ONEPASS_MULTI ){
@@ -134316,7 +136638,8 @@ SQLITE_PRIVATE void sqlite3Update(
** is not required) and leave the PK fields in the array of registers. */
for(i=0; i<nPk; i++){
assert( pPk->aiColumn[i]>=0 );
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,
+ pPk->aiColumn[i], iPk+i);
}
if( eOnePass ){
if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen);
@@ -134397,14 +136720,16 @@ SQLITE_PRIVATE void sqlite3Update(
pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
);
for(i=0; i<pTab->nCol; i++){
+ u32 colFlags = pTab->aCol[i].colFlags;
+ k = sqlite3TableColumnToStorage(pTab, i) + regOld;
if( oldmask==0xffffffff
|| (i<32 && (oldmask & MASKBIT32(i))!=0)
- || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
+ || (colFlags & COLFLAG_PRIMKEY)!=0
){
testcase( oldmask!=0xffffffff && i==31 );
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
}else{
- sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, k);
}
}
if( chngRowid==0 && pPk==0 ){
@@ -134428,13 +136753,15 @@ SQLITE_PRIVATE void sqlite3Update(
newmask = sqlite3TriggerColmask(
pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
);
- for(i=0; i<pTab->nCol; i++){
+ for(i=0, k=regNew; i<pTab->nCol; i++, k++){
if( i==pTab->iPKey ){
- sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, k);
+ }else if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)!=0 ){
+ if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--;
}else{
j = aXRef[i];
if( j>=0 ){
- sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
+ sqlite3ExprCode(pParse, pChanges->a[j].pExpr, k);
}else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
/* This branch loads the value of a column that will not be changed
** into a register. This is done if there are no BEFORE triggers, or
@@ -134443,12 +136770,20 @@ SQLITE_PRIVATE void sqlite3Update(
*/
testcase( i==31 );
testcase( i==32 );
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
+ bFinishSeek = 0;
}else{
- sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, k);
}
}
}
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ if( pTab->tabFlags & TF_HasGenerated ){
+ testcase( pTab->tabFlags & TF_HasVirtual );
+ testcase( pTab->tabFlags & TF_HasStored );
+ sqlite3ComputeGeneratedColumns(pParse, regNew, pTab);
+ }
+#endif
/* Fire any BEFORE UPDATE triggers. This happens before constraints are
** verified. One could argue that this is wrong.
@@ -134481,11 +136816,20 @@ SQLITE_PRIVATE void sqlite3Update(
** BEFORE trigger runs. See test case trigger1-18.0 (added 2018-04-26)
** for an example.
*/
- for(i=0; i<pTab->nCol; i++){
- if( aXRef[i]<0 && i!=pTab->iPKey ){
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
+ for(i=0, k=regNew; i<pTab->nCol; i++, k++){
+ if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
+ if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--;
+ }else if( aXRef[i]<0 && i!=pTab->iPKey ){
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
}
}
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ if( pTab->tabFlags & TF_HasGenerated ){
+ testcase( pTab->tabFlags & TF_HasVirtual );
+ testcase( pTab->tabFlags & TF_HasStored );
+ sqlite3ComputeGeneratedColumns(pParse, regNew, pTab);
+ }
+#endif
}
if( !isView ){
@@ -134515,6 +136859,15 @@ SQLITE_PRIVATE void sqlite3Update(
/* Delete the index entries associated with the current record. */
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1);
+ /* We must run the OP_FinishSeek opcode to resolve a prior
+ ** OP_DeferredSeek if there is any possibility that there have been
+ ** no OP_Column opcodes since the OP_DeferredSeek was issued. But
+ ** we want to avoid the OP_FinishSeek if possible, as running it
+ ** costs CPU cycles. */
+ if( bFinishSeek ){
+ sqlite3VdbeAddOp1(v, OP_FinishSeek, iDataCur);
+ }
+
/* If changing the rowid value, or if there are foreign key constraints
** to process, delete the old record. Otherwise, add a noop OP_Delete
** to invoke the pre-update hook.
@@ -134691,6 +137044,7 @@ static void updateVirtualTable(
/* Populate the argument registers. */
for(i=0; i<pTab->nCol; i++){
+ assert( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 );
if( aXRef[i]>=0 ){
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
}else{
@@ -135001,7 +137355,7 @@ SQLITE_PRIVATE void sqlite3UpsertDoUpdate(
for(i=0; i<nPk; i++){
int k;
assert( pPk->aiColumn[i]>=0 );
- k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
+ k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i);
VdbeComment((v, "%s.%s", pIdx->zName,
pTab->aCol[pPk->aiColumn[i]].zName));
@@ -135011,6 +137365,7 @@ SQLITE_PRIVATE void sqlite3UpsertDoUpdate(
VdbeCoverage(v);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0,
"corrupt database", P4_STATIC);
+ sqlite3MayAbort(pParse);
sqlite3VdbeJumpHere(v, i);
}
}
@@ -135759,12 +138114,12 @@ SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p){
*/
SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3 *db){
VTable *p = db->pDisconnect;
- db->pDisconnect = 0;
assert( sqlite3BtreeHoldsAllMutexes(db) );
assert( sqlite3_mutex_held(db->mutex) );
if( p ){
+ db->pDisconnect = 0;
sqlite3ExpirePreparedStatements(db, 0);
do {
VTable *pNext = p->pNext;
@@ -135911,6 +138266,8 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
int iReg;
Vdbe *v;
+ sqlite3MayAbort(pParse);
+
/* Compute the complete text of the CREATE VIRTUAL TABLE statement */
if( pEnd ){
pParse->sNameToken.n = (int)(pEnd->z - pParse->sNameToken.z) + pEnd->n;
@@ -135936,13 +138293,13 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
zStmt,
pParse->regRowid
);
- sqlite3DbFree(db, zStmt);
v = sqlite3GetVdbe(pParse);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddOp0(v, OP_Expire);
- zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
+ zWhere = sqlite3MPrintf(db, "name=%Q AND sql=%Q", pTab->zName, zStmt);
sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
+ sqlite3DbFree(db, zStmt);
iReg = ++pParse->nMem;
sqlite3VdbeLoadString(v, iReg, pTab->zName);
@@ -136039,6 +138396,7 @@ static int vtabCallConstructor(
}
pVTable->db = db;
pVTable->pMod = pMod;
+ pVTable->eVtabRisk = SQLITE_VTABRISK_Normal;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
pTab->azModuleArg[1] = db->aDb[iDb].zDbSName;
@@ -136078,7 +138436,7 @@ static int vtabCallConstructor(
rc = SQLITE_ERROR;
}else{
int iCol;
- u8 oooHidden = 0;
+ u16 oooHidden = 0;
/* If everything went according to plan, link the new VTable structure
** into the linked list headed by pTab->pVTable. Then loop through the
** columns of the table to see if any of them contain the token "hidden".
@@ -136344,7 +138702,8 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab
}
p = vtabDisconnectAll(db, pTab);
xDestroy = p->pMod->pModule->xDestroy;
- assert( xDestroy!=0 ); /* Checked before the virtual table is created */
+ if( xDestroy==0 ) xDestroy = p->pMod->pModule->xDisconnect;
+ assert( xDestroy!=0 );
pTab->nTabRef++;
rc = xDestroy(p->pVtab);
/* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
@@ -136727,28 +139086,38 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){
SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
va_list ap;
int rc = SQLITE_OK;
+ VtabCtx *p;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
sqlite3_mutex_enter(db->mutex);
- va_start(ap, op);
- switch( op ){
- case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
- VtabCtx *p = db->pVtabCtx;
- if( !p ){
- rc = SQLITE_MISUSE_BKPT;
- }else{
- assert( p->pTab==0 || IsVirtual(p->pTab) );
+ p = db->pVtabCtx;
+ if( !p ){
+ rc = SQLITE_MISUSE_BKPT;
+ }else{
+ assert( p->pTab==0 || IsVirtual(p->pTab) );
+ va_start(ap, op);
+ switch( op ){
+ case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
p->pVTable->bConstraint = (u8)va_arg(ap, int);
+ break;
+ }
+ case SQLITE_VTAB_INNOCUOUS: {
+ p->pVTable->eVtabRisk = SQLITE_VTABRISK_Low;
+ break;
+ }
+ case SQLITE_VTAB_DIRECTONLY: {
+ p->pVTable->eVtabRisk = SQLITE_VTABRISK_High;
+ break;
+ }
+ default: {
+ rc = SQLITE_MISUSE_BKPT;
+ break;
}
- break;
}
- default:
- rc = SQLITE_MISUSE_BKPT;
- break;
+ va_end(ap);
}
- va_end(ap);
if( rc!=SQLITE_OK ) sqlite3Error(db, rc);
sqlite3_mutex_leave(db->mutex);
@@ -137057,24 +139426,23 @@ struct WhereTerm {
/*
** Allowed values of WhereTerm.wtFlags
*/
-#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(db, pExpr) */
-#define TERM_VIRTUAL 0x02 /* Added by the optimizer. Do not code */
-#define TERM_CODED 0x04 /* This term is already coded */
-#define TERM_COPIED 0x08 /* Has a child */
-#define TERM_ORINFO 0x10 /* Need to free the WhereTerm.u.pOrInfo object */
-#define TERM_ANDINFO 0x20 /* Need to free the WhereTerm.u.pAndInfo obj */
-#define TERM_OR_OK 0x40 /* Used during OR-clause processing */
+#define TERM_DYNAMIC 0x0001 /* Need to call sqlite3ExprDelete(db, pExpr) */
+#define TERM_VIRTUAL 0x0002 /* Added by the optimizer. Do not code */
+#define TERM_CODED 0x0004 /* This term is already coded */
+#define TERM_COPIED 0x0008 /* Has a child */
+#define TERM_ORINFO 0x0010 /* Need to free the WhereTerm.u.pOrInfo object */
+#define TERM_ANDINFO 0x0020 /* Need to free the WhereTerm.u.pAndInfo obj */
+#define TERM_OR_OK 0x0040 /* Used during OR-clause processing */
#ifdef SQLITE_ENABLE_STAT4
-# define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */
+# define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */
#else
-# define TERM_VNULL 0x00 /* Disabled if not using stat4 */
+# define TERM_VNULL 0x0000 /* Disabled if not using stat4 */
#endif
-#define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */
-#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */
-#define TERM_LIKE 0x400 /* The original LIKE operator */
-#define TERM_IS 0x800 /* Term.pExpr is an IS operator */
+#define TERM_LIKEOPT 0x0100 /* Virtual terms from the LIKE optimization */
+#define TERM_LIKECOND 0x0200 /* Conditionally this LIKE operator term */
+#define TERM_LIKE 0x0400 /* The original LIKE operator */
+#define TERM_IS 0x0800 /* Term.pExpr is an IS operator */
#define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */
-#define TERM_NOPARTIDX 0x2000 /* Not for use to enable a partial index */
/*
** An instance of the WhereScan object is used as an iterator for locating
@@ -137218,6 +139586,20 @@ struct WhereLoopBuilder {
#endif
/*
+** Each instance of this object records a change to a single node
+** in an expression tree to cause that node to point to a column
+** of an index rather than an expression or a virtual column. All
+** such transformations need to be undone at the end of WHERE clause
+** processing.
+*/
+typedef struct WhereExprMod WhereExprMod;
+struct WhereExprMod {
+ WhereExprMod *pNext; /* Next translation on a list of them all */
+ Expr *pExpr; /* The Expr node that was transformed */
+ Expr orig; /* Original value of the Expr node */
+};
+
+/*
** The WHERE clause processing routine has two halves. The
** first part does the start of the WHERE loop and the second
** half does the tail of the WHERE loop. An instance of
@@ -137233,23 +139615,25 @@ struct WhereInfo {
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
ExprList *pResultSet; /* Result set of the query */
Expr *pWhere; /* The complete WHERE clause */
- LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
int iContinue; /* Jump here to continue with next record */
int iBreak; /* Jump here to break out of the loop */
int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
+ LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
u8 nLevel; /* Number of nested loop */
i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
- u8 sorted; /* True if really sorted (not just grouped) */
u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */
- u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
u8 eDistinct; /* One of the WHERE_DISTINCT_* values */
- u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */
+ unsigned bDeferredSeek :1; /* Uses OP_DeferredSeek */
+ unsigned untestedTerms :1; /* Not all WHERE terms resolved by outer loop */
+ unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */
+ unsigned sorted :1; /* True if really sorted (not just grouped) */
+ LogEst nRowOut; /* Estimated number of output rows */
int iTop; /* The very beginning of the WHERE loop */
WhereLoop *pLoops; /* List of all WhereLoop objects */
+ WhereExprMod *pExprMods; /* Expression modifications */
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
- LogEst nRowOut; /* Estimated number of output rows */
WhereClause sWC; /* Decomposition of the WHERE clause */
WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
WhereLevel a[1]; /* Information about each nest loop in WHERE */
@@ -137263,6 +139647,8 @@ struct WhereInfo {
SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet*,int);
#ifdef WHERETRACE_ENABLED
SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC);
+SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm);
+SQLITE_PRIVATE void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC);
#endif
SQLITE_PRIVATE WhereTerm *sqlite3WhereFindTerm(
WhereClause *pWC, /* The WHERE clause to be searched */
@@ -137774,7 +140160,8 @@ static Expr *removeUnindexableInClauseTerms(
Expr *pX /* The IN expression to be reduced */
){
sqlite3 *db = pParse->db;
- Expr *pNew = sqlite3ExprDup(db, pX, 0);
+ Expr *pNew;
+ pNew = sqlite3ExprDup(db, pX, 0);
if( db->mallocFailed==0 ){
ExprList *pOrigRhs = pNew->x.pSelect->pEList; /* Original unmodified RHS */
ExprList *pOrigLhs = pNew->pLeft->x.pList; /* Original unmodified LHS */
@@ -137951,7 +140338,7 @@ static int codeEqualityTerm(
if( i==iEq ){
pIn->iCur = iTab;
pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
- if( iEq>0 && (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
+ if( iEq>0 ){
pIn->iBase = iReg - i;
pIn->nPrefix = i;
pLoop->wsFlags |= WHERE_IN_EARLYOUT;
@@ -138182,7 +140569,7 @@ static int codeCursorHintCheckExpr(Walker *pWalker, Expr *pExpr){
assert( pHint->pIdx!=0 );
if( pExpr->op==TK_COLUMN
&& pExpr->iTable==pHint->iTabCur
- && sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn)<0
+ && sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn)<0
){
pWalker->eCode = 1;
}
@@ -138250,7 +140637,7 @@ static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){
pExpr->iTable = reg;
}else if( pHint->pIdx!=0 ){
pExpr->iTable = pHint->iIdxCur;
- pExpr->iColumn = sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn);
+ pExpr->iColumn = sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn);
assert( pExpr->iColumn>=0 );
}
}else if( pExpr->op==TK_AGG_FUNCTION ){
@@ -138403,6 +140790,7 @@ static void codeDeferredSeek(
assert( iIdxCur>0 );
assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
+ pWInfo->bDeferredSeek = 1;
sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur);
if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)
&& DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask)
@@ -138413,8 +140801,12 @@ static void codeDeferredSeek(
if( ai ){
ai[0] = pTab->nCol;
for(i=0; i<pIdx->nColumn-1; i++){
+ int x1, x2;
assert( pIdx->aiColumn[i]<pTab->nCol );
- if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]+1] = i+1;
+ x1 = pIdx->aiColumn[i];
+ x2 = sqlite3TableColumnToStorage(pTab, x1);
+ testcase( x1!=x2 );
+ if( x1>=0 ) ai[x2+1] = i+1;
}
sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY);
}
@@ -138465,8 +140857,24 @@ typedef struct IdxExprTrans {
int iTabCur; /* The cursor of the corresponding table */
int iIdxCur; /* The cursor for the index */
int iIdxCol; /* The column for the index */
+ int iTabCol; /* The column for the table */
+ WhereInfo *pWInfo; /* Complete WHERE clause information */
+ sqlite3 *db; /* Database connection (for malloc()) */
} IdxExprTrans;
+/*
+** Preserve pExpr on the WhereETrans list of the WhereInfo.
+*/
+static void preserveExpr(IdxExprTrans *pTrans, Expr *pExpr){
+ WhereExprMod *pNew;
+ pNew = sqlite3DbMallocRaw(pTrans->db, sizeof(*pNew));
+ if( pNew==0 ) return;
+ pNew->pNext = pTrans->pWInfo->pExprMods;
+ pTrans->pWInfo->pExprMods = pNew;
+ pNew->pExpr = pExpr;
+ memcpy(&pNew->orig, pExpr, sizeof(*pExpr));
+}
+
/* The walker node callback used to transform matching expressions into
** a reference to an index column for an index on an expression.
**
@@ -138476,21 +140884,49 @@ typedef struct IdxExprTrans {
static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
IdxExprTrans *pX = p->u.pIdxTrans;
if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
+ preserveExpr(pX, pExpr);
pExpr->affExpr = sqlite3ExprAffinity(pExpr);
pExpr->op = TK_COLUMN;
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
pExpr->y.pTab = 0;
+ testcase( ExprHasProperty(pExpr, EP_Skip) );
+ testcase( ExprHasProperty(pExpr, EP_Unlikely) );
+ ExprClearProperty(pExpr, EP_Skip|EP_Unlikely);
return WRC_Prune;
}else{
return WRC_Continue;
}
}
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+/* A walker node callback that translates a column reference to a table
+** into a corresponding column reference of an index.
+*/
+static int whereIndexExprTransColumn(Walker *p, Expr *pExpr){
+ if( pExpr->op==TK_COLUMN ){
+ IdxExprTrans *pX = p->u.pIdxTrans;
+ if( pExpr->iTable==pX->iTabCur && pExpr->iColumn==pX->iTabCol ){
+ assert( pExpr->y.pTab!=0 );
+ preserveExpr(pX, pExpr);
+ pExpr->affExpr = sqlite3TableColumnAffinity(pExpr->y.pTab,pExpr->iColumn);
+ pExpr->iTable = pX->iIdxCur;
+ pExpr->iColumn = pX->iIdxCol;
+ pExpr->y.pTab = 0;
+ }
+ }
+ return WRC_Continue;
+}
+#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
+
/*
** For an indexes on expression X, locate every instance of expression X
** in pExpr and change that subexpression into a reference to the appropriate
** column of the index.
+**
+** 2019-10-24: Updated to also translate references to a VIRTUAL column in
+** the table into references to the corresponding (stored) column of the
+** index.
*/
static void whereIndexExprTrans(
Index *pIdx, /* The Index */
@@ -138500,20 +140936,48 @@ static void whereIndexExprTrans(
){
int iIdxCol; /* Column number of the index */
ExprList *aColExpr; /* Expressions that are indexed */
+ Table *pTab;
Walker w;
IdxExprTrans x;
aColExpr = pIdx->aColExpr;
- if( aColExpr==0 ) return; /* Not an index on expressions */
+ if( aColExpr==0 && !pIdx->bHasVCol ){
+ /* The index does not reference any expressions or virtual columns
+ ** so no translations are needed. */
+ return;
+ }
+ pTab = pIdx->pTable;
memset(&w, 0, sizeof(w));
- w.xExprCallback = whereIndexExprTransNode;
w.u.pIdxTrans = &x;
x.iTabCur = iTabCur;
x.iIdxCur = iIdxCur;
- for(iIdxCol=0; iIdxCol<aColExpr->nExpr; iIdxCol++){
- if( pIdx->aiColumn[iIdxCol]!=XN_EXPR ) continue;
- assert( aColExpr->a[iIdxCol].pExpr!=0 );
+ x.pWInfo = pWInfo;
+ x.db = pWInfo->pParse->db;
+ for(iIdxCol=0; iIdxCol<pIdx->nColumn; iIdxCol++){
+ i16 iRef = pIdx->aiColumn[iIdxCol];
+ if( iRef==XN_EXPR ){
+ assert( aColExpr->a[iIdxCol].pExpr!=0 );
+ x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
+ if( sqlite3ExprIsConstant(x.pIdxExpr) ) continue;
+ w.xExprCallback = whereIndexExprTransNode;
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ }else if( iRef>=0
+ && (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0
+ && (pTab->aCol[iRef].zColl==0
+ || sqlite3StrICmp(pTab->aCol[iRef].zColl, sqlite3StrBINARY)==0)
+ ){
+ /* Check to see if there are direct references to generated columns
+ ** that are contained in the index. Pulling the generated column
+ ** out of the index is an optimization only - the main table is always
+ ** available if the index cannot be used. To avoid unnecessary
+ ** complication, omit this optimization if the collating sequence for
+ ** the column is non-standard */
+ x.iTabCol = iRef;
+ w.xExprCallback = whereIndexExprTransColumn;
+#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
+ }else{
+ continue;
+ }
x.iIdxCol = iIdxCol;
- x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
sqlite3WalkExpr(&w, pWInfo->pWhere);
sqlite3WalkExprList(&w, pWInfo->pOrderBy);
sqlite3WalkExprList(&w, pWInfo->pResultSet);
@@ -138585,6 +141049,21 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur);
bRev = (pWInfo->revMask>>iLevel)&1;
VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
+#if WHERETRACE_ENABLED /* 0x20800 */
+ if( sqlite3WhereTrace & 0x800 ){
+ sqlite3DebugPrintf("Coding level %d of %d: notReady=%llx iFrom=%d\n",
+ iLevel, pWInfo->nLevel, (u64)notReady, pLevel->iFrom);
+ sqlite3WhereLoopPrint(pLoop, pWC);
+ }
+ if( sqlite3WhereTrace & 0x20000 ){
+ if( iLevel==0 ){
+ sqlite3DebugPrintf("WHERE clause being coded:\n");
+ sqlite3TreeViewExpr(0, pWInfo->pWhere, 0);
+ }
+ sqlite3DebugPrintf("All WHERE-clause terms before coding:\n");
+ sqlite3WhereClausePrint(pWC);
+ }
+#endif
/* Create labels for the "break" and "continue" instructions
** for the current loop. Jump to addrBrk to break out of a loop.
@@ -138664,9 +141143,12 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
iIn = pLevel->u.in.nIn;
for(j=nConstraint-1; j>=0; j--){
pTerm = pLoop->aLTerm[j];
+ if( (pTerm->eOperator & WO_IN)!=0 ) iIn--;
if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){
disableTerm(pLevel, pTerm);
- }else if( (pTerm->eOperator & WO_IN)!=0 ){
+ }else if( (pTerm->eOperator & WO_IN)!=0
+ && sqlite3ExprVectorSize(pTerm->pExpr->pLeft)==1
+ ){
Expr *pCompare; /* The comparison operator */
Expr *pRight; /* RHS of the comparison */
VdbeOp *pOp; /* Opcode to access the value of the IN constraint */
@@ -138677,8 +141159,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
** encoding of the value in the register, so it *must* be reloaded. */
assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed );
if( !db->mallocFailed ){
- assert( iIn>0 );
- pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[--iIn].addrInTop);
+ assert( iIn>=0 && iIn<pLevel->u.in.nIn );
+ pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[iIn].addrInTop);
assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid );
assert( pOp->opcode!=OP_Column || pOp->p3==iReg+j+2 );
assert( pOp->opcode!=OP_Rowid || pOp->p2==iReg+j+2 );
@@ -138702,6 +141184,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
}
}
}
+ assert( iIn==0 || db->mallocFailed );
/* These registers need to be preserved in case there is an IN operator
** loop. So we could deallocate the registers here (and potentially
** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems
@@ -138967,7 +141450,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
){
assert( bSeekPastNull==0 && nExtraReg==0 && nBtm==0 && nTop==0 );
assert( pRangeEnd==0 && pRangeStart==0 );
- assert( pLoop->nSkip==0 );
+ testcase( pLoop->nSkip>0 );
nExtraReg = 1;
bSeekPastNull = 1;
pLevel->regBignull = regBignull = ++pParse->nMem;
@@ -139166,10 +141649,10 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
}else if( HasRowid(pIdx->pTable) ){
- if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE) || (
- (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE)
- && (pWInfo->eOnePass==ONEPASS_SINGLE)
- )){
+ if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE)
+ || ( (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE)!=0
+ && (pWInfo->eOnePass==ONEPASS_SINGLE || pLoop->nLTerm==0) )
+ ){
iRowidReg = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
@@ -139181,40 +141664,53 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
for(j=0; j<pPk->nKeyCol; j++){
- k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
+ k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j);
}
sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont,
iRowidReg, pPk->nKeyCol); VdbeCoverage(v);
}
- /* If pIdx is an index on one or more expressions, then look through
- ** all the expressions in pWInfo and try to transform matching expressions
- ** into reference to index columns.
- **
- ** Do not do this for the RHS of a LEFT JOIN. This is because the
- ** expression may be evaluated after OP_NullRow has been executed on
- ** the cursor. In this case it is important to do the full evaluation,
- ** as the result of the expression may not be NULL, even if all table
- ** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a
- **
- ** Also, do not do this when processing one index an a multi-index
- ** OR clause, since the transformation will become invalid once we
- ** move forward to the next index.
- ** https://sqlite.org/src/info/4e8e4857d32d401f
- */
- if( pLevel->iLeftJoin==0 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){
- whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
- }
-
- /* If a partial index is driving the loop, try to eliminate WHERE clause
- ** terms from the query that must be true due to the WHERE clause of
- ** the partial index
- */
- if( pIdx->pPartIdxWhere ){
- whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC);
+ if( pLevel->iLeftJoin==0 ){
+ /* If pIdx is an index on one or more expressions, then look through
+ ** all the expressions in pWInfo and try to transform matching expressions
+ ** into reference to index columns. Also attempt to translate references
+ ** to virtual columns in the table into references to (stored) columns
+ ** of the index.
+ **
+ ** Do not do this for the RHS of a LEFT JOIN. This is because the
+ ** expression may be evaluated after OP_NullRow has been executed on
+ ** the cursor. In this case it is important to do the full evaluation,
+ ** as the result of the expression may not be NULL, even if all table
+ ** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a
+ **
+ ** Also, do not do this when processing one index an a multi-index
+ ** OR clause, since the transformation will become invalid once we
+ ** move forward to the next index.
+ ** https://sqlite.org/src/info/4e8e4857d32d401f
+ */
+ if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){
+ whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
+ }
+
+ /* If a partial index is driving the loop, try to eliminate WHERE clause
+ ** terms from the query that must be true due to the WHERE clause of
+ ** the partial index.
+ **
+ ** 2019-11-02 ticket 623eff57e76d45f6: This optimization does not work
+ ** for a LEFT JOIN.
+ */
+ if( pIdx->pPartIdxWhere ){
+ whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC);
+ }
+ }else{
+ testcase( pIdx->pPartIdxWhere );
+ /* The following assert() is not a requirement, merely an observation:
+ ** The OR-optimization doesn't work for the right hand table of
+ ** a LEFT JOIN: */
+ assert( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 );
}
-
+
/* Record the instruction used to terminate the loop. */
if( pLoop->wsFlags & WHERE_ONEROW ){
pLevel->op = OP_Noop;
@@ -139399,9 +141895,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
int jmp1 = 0; /* Address of jump operation */
- assert( (pTabItem[0].fg.jointype & JT_LEFT)==0
- || ExprHasProperty(pOrExpr, EP_FromJoin)
- );
+ testcase( (pTabItem[0].fg.jointype & JT_LEFT)!=0
+ && !ExprHasProperty(pOrExpr, EP_FromJoin)
+ ); /* See TH3 vtab25.400 and ticket 614b25314c766238 */
if( pAndExpr ){
pAndExpr->pLeft = pOrExpr;
pOrExpr = pAndExpr;
@@ -139441,7 +141937,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
r = sqlite3GetTempRange(pParse, nPk);
for(iPk=0; iPk<nPk; iPk++){
int iCol = pPk->aiColumn[iPk];
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, r+iPk);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk);
}
/* Check if the temp table already contains this key. If so,
@@ -139623,6 +142119,10 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
VdbeNoopComment((v, "WhereTerm[%d] (%p) priority=%d",
pWC->nTerm-j, pTerm, iLoop));
}
+ if( sqlite3WhereTrace & 0x800 ){
+ sqlite3DebugPrintf("Coding auxiliary constraint:\n");
+ sqlite3WhereTermPrint(pTerm, pWC->nTerm-j);
+ }
#endif
sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
@@ -139646,8 +142146,14 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
if( (pTerm->eOperator & WO_EQUIV)==0 ) continue;
if( pTerm->leftCursor!=iCur ) continue;
- if( pLevel->iLeftJoin ) continue;
+ if( pTabItem->fg.jointype & JT_LEFT ) continue;
pE = pTerm->pExpr;
+#ifdef WHERETRACE_ENABLED /* 0x800 */
+ if( sqlite3WhereTrace & 0x800 ){
+ sqlite3DebugPrintf("Coding transitive constraint:\n");
+ sqlite3WhereTermPrint(pTerm, pWC->nTerm-j);
+ }
+#endif
assert( !ExprHasProperty(pE, EP_FromJoin) );
assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.leftColumn, notReady,
@@ -139690,6 +142196,17 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
}
}
+#if WHERETRACE_ENABLED /* 0x20800 */
+ if( sqlite3WhereTrace & 0x20000 ){
+ sqlite3DebugPrintf("All WHERE-clause terms after coding level %d:\n",
+ iLevel);
+ sqlite3WhereClausePrint(pWC);
+ }
+ if( sqlite3WhereTrace & 0x800 ){
+ sqlite3DebugPrintf("End Coding level %d: notReady=%llx\n",
+ iLevel, (u64)pLevel->notReady);
+ }
+#endif
return pLevel->notReady;
}
@@ -139806,39 +142323,14 @@ static int allowedOp(int op){
/*
** Commute a comparison operator. Expressions of the form "X op Y"
** are converted into "Y op X".
-**
-** If left/right precedence rules come into play when determining the
-** collating sequence, then COLLATE operators are adjusted to ensure
-** that the collating sequence does not change. For example:
-** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on
-** the left hand side of a comparison overrides any collation sequence
-** attached to the right. For the same reason the EP_Collate flag
-** is not commuted.
-**
-** The return value is extra flags that are added to the WhereTerm object
-** after it is commuted. The only extra flag ever added is TERM_NOPARTIDX
-** which prevents the term from being used to enable a partial index if
-** COLLATE changes have been made.
*/
static u16 exprCommute(Parse *pParse, Expr *pExpr){
- u16 expRight = (pExpr->pRight->flags & EP_Collate);
- u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
- u16 wtFlags = 0;
- assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
- if( expRight==expLeft ){
- /* Either X and Y both have COLLATE operator or neither do */
- if( expRight ){
- /* Both X and Y have COLLATE operators. Make sure X is always
- ** used by clearing the EP_Collate flag from Y. */
- pExpr->pRight->flags &= ~EP_Collate;
- wtFlags |= TERM_NOPARTIDX;
- }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
- /* Neither X nor Y have COLLATE operators, but X has a non-default
- ** collating sequence. So add the EP_Collate marker on X to cause
- ** it to be searched first. */
- pExpr->pLeft->flags |= EP_Collate;
- wtFlags |= TERM_NOPARTIDX;
- }
+ if( pExpr->pLeft->op==TK_VECTOR
+ || pExpr->pRight->op==TK_VECTOR
+ || sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight) !=
+ sqlite3BinaryCompareCollSeq(pParse, pExpr->pRight, pExpr->pLeft)
+ ){
+ pExpr->flags ^= EP_Commuted;
}
SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
if( pExpr->op>=TK_GT ){
@@ -139849,7 +142341,7 @@ static u16 exprCommute(Parse *pParse, Expr *pExpr){
assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE );
pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT;
}
- return wtFlags;
+ return 0;
}
/*
@@ -140627,7 +143119,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr){
){
return 0;
}
- pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
+ pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
if( sqlite3IsBinary(pColl) ) return 1;
return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
}
@@ -141020,6 +143512,7 @@ static void exprAnalyze(
0, sqlite3ExprDup(db, pRight, 0));
if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){
ExprSetProperty(pNewExpr, EP_FromJoin);
+ pNewExpr->iRightJoinTable = pExpr->iRightJoinTable;
}
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
@@ -141076,11 +143569,15 @@ static void exprAnalyze(
** expression). The WhereTerm.iField variable identifies the index within
** the vector on the LHS that the virtual term represents.
**
- ** This only works if the RHS is a simple SELECT, not a compound
+ ** This only works if the RHS is a simple SELECT (not a compound) that does
+ ** not use window functions.
*/
if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->iField==0
&& pExpr->pLeft->op==TK_VECTOR
&& pExpr->x.pSelect->pPrior==0
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ && pExpr->x.pSelect->pWin==0
+#endif
){
int i;
for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
@@ -141238,9 +143735,10 @@ SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( p->op==TK_FUNCTION && p->y.pWin ){
+ if( (p->op==TK_FUNCTION || p->op==TK_AGG_FUNCTION) && p->y.pWin ){
mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pPartition);
mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pOrderBy);
+ mask |= sqlite3WhereExprUsage(pMaskSet, p->y.pWin->pFilter);
}
#endif
return mask;
@@ -141316,6 +143814,9 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(
pRhs = sqlite3PExpr(pParse, TK_UPLUS,
sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs);
+ if( pItem->fg.jointype & JT_LEFT ){
+ sqlite3SetJoinExpr(pTerm, pItem->iCursor);
+ }
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
}
}
@@ -141444,7 +143945,7 @@ SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo *pWInfo){
/*
** Return ONEPASS_OFF (0) if an UPDATE or DELETE statement is unable to
-** operate directly on the rowis returned by a WHERE clause. Return
+** operate directly on the rowids returned by a WHERE clause. Return
** ONEPASS_SINGLE (1) if the statement can operation directly because only
** a single row is to be changed. Return ONEPASS_MULTI (2) if the one-pass
** optimization can be used on multiple
@@ -141472,6 +143973,14 @@ SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){
}
/*
+** Return TRUE if the WHERE loop uses the OP_DeferredSeek opcode to move
+** the data cursor to the row selected by the index cursor.
+*/
+SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo *pWInfo){
+ return pWInfo->bDeferredSeek;
+}
+
+/*
** Move the content of pSrc into pDest
*/
static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){
@@ -141603,8 +144112,7 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
continue;
}
assert(pX->pLeft);
- pColl = sqlite3BinaryCompareCollSeq(pParse,
- pX->pLeft, pX->pRight);
+ pColl = sqlite3ExprCompareCollSeq(pParse, pX);
if( pColl==0 ) pColl = pParse->db->pDfltColl;
if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
continue;
@@ -141930,7 +144438,7 @@ static void translateColumnToCopy(
** are no-ops.
*/
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED)
-static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
+static void whereTraceIndexInfoInputs(sqlite3_index_info *p){
int i;
if( !sqlite3WhereTrace ) return;
for(i=0; i<p->nConstraint; i++){
@@ -141948,7 +144456,7 @@ static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
p->aOrderBy[i].desc);
}
}
-static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
+static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){
int i;
if( !sqlite3WhereTrace ) return;
for(i=0; i<p->nConstraint; i++){
@@ -141964,8 +144472,8 @@ static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows);
}
#else
-#define TRACE_IDX_INPUTS(A)
-#define TRACE_IDX_OUTPUTS(A)
+#define whereTraceIndexInfoInputs(A)
+#define whereTraceIndexInfoOutputs(A)
#endif
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
@@ -142125,7 +144633,8 @@ static void constructAutomaticIndex(
Expr *pX = pTerm->pExpr;
idxCols |= cMask;
pIdx->aiColumn[n] = pTerm->u.leftColumn;
- pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
+ pColl = sqlite3ExprCompareCollSeq(pParse, pX);
+ assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */
pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
n++;
}
@@ -142194,8 +144703,8 @@ static void constructAutomaticIndex(
pTabItem->fg.viaCoroutine = 0;
}else{
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
+ sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
}
- sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
sqlite3VdbeJumpHere(v, addrTop);
sqlite3ReleaseTempReg(pParse, regRecord);
@@ -142274,23 +144783,14 @@ static sqlite3_index_info *allocateIndexInfo(
sqlite3ErrorMsg(pParse, "out of memory");
return 0;
}
-
- /* Initialize the structure. The sqlite3_index_info structure contains
- ** many fields that are declared "const" to prevent xBestIndex from
- ** changing them. We have to do some funky casting in order to
- ** initialize those fields.
- */
pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1];
pIdxCons = (struct sqlite3_index_constraint*)&pHidden[1];
pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm];
pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy];
- *(int*)&pIdxInfo->nConstraint = nTerm;
- *(int*)&pIdxInfo->nOrderBy = nOrderBy;
- *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons;
- *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
- *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
- pUsage;
-
+ pIdxInfo->nOrderBy = nOrderBy;
+ pIdxInfo->aConstraint = pIdxCons;
+ pIdxInfo->aOrderBy = pIdxOrderBy;
+ pIdxInfo->aConstraintUsage = pUsage;
pHidden->pWC = pWC;
pHidden->pParse = pParse;
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
@@ -142304,18 +144804,13 @@ static sqlite3_index_info *allocateIndexInfo(
testcase( pTerm->eOperator & WO_ALL );
if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
+
+ /* tag-20191211-002: WHERE-clause constraints are not useful to the
+ ** right-hand table of a LEFT JOIN. See tag-20191211-001 for the
+ ** equivalent restriction for ordinary tables. */
if( (pSrc->fg.jointype & JT_LEFT)!=0
&& !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
- && (pTerm->eOperator & (WO_IS|WO_ISNULL))
){
- /* An "IS" term in the WHERE clause where the virtual table is the rhs
- ** of a LEFT JOIN. Do not pass this term to the virtual table
- ** implementation, as this can lead to incorrect results from SQL such
- ** as:
- **
- ** "LEFT JOIN vtab WHERE vtab.col IS NULL" */
- testcase( pTerm->eOperator & WO_ISNULL );
- testcase( pTerm->eOperator & WO_IS );
continue;
}
assert( pTerm->u.leftColumn>=(-1) );
@@ -142346,7 +144841,8 @@ static sqlite3_index_info *allocateIndexInfo(
if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
&& sqlite3ExprIsVector(pTerm->pExpr->pRight)
){
- if( i<16 ) mNoOmit |= (1 << i);
+ testcase( j!=i );
+ if( j<16 ) mNoOmit |= (1 << j);
if( op==WO_LT ) pIdxCons[j].op = WO_LE;
if( op==WO_GT ) pIdxCons[j].op = WO_GE;
}
@@ -142354,6 +144850,7 @@ static sqlite3_index_info *allocateIndexInfo(
j++;
}
+ pIdxInfo->nConstraint = j;
for(i=0; i<nOrderBy; i++){
Expr *pExpr = pOrderBy->a[i].pExpr;
pIdxOrderBy[i].iColumn = pExpr->iColumn;
@@ -142384,9 +144881,9 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
int rc;
- TRACE_IDX_INPUTS(p);
+ whereTraceIndexInfoInputs(p);
rc = pVtab->pModule->xBestIndex(pVtab, p);
- TRACE_IDX_OUTPUTS(p);
+ whereTraceIndexInfoOutputs(p);
if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){
if( rc==SQLITE_NOMEM ){
@@ -143067,16 +145564,17 @@ static int whereInScanEst(
/*
** Print the content of a WhereTerm object
*/
-static void whereTermPrint(WhereTerm *pTerm, int iTerm){
+SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
if( pTerm==0 ){
sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm);
}else{
- char zType[4];
+ char zType[8];
char zLeft[50];
- memcpy(zType, "...", 4);
+ memcpy(zType, "....", 5);
if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E';
if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
+ if( pTerm->wtFlags & TERM_CODED ) zType[3] = 'C';
if( pTerm->eOperator & WO_SINGLE ){
sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}",
pTerm->leftCursor, pTerm->u.leftColumn);
@@ -143087,14 +145585,21 @@ static void whereTermPrint(WhereTerm *pTerm, int iTerm){
sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor);
}
sqlite3DebugPrintf(
- "TERM-%-3d %p %s %-12s prob=%-3d op=0x%03x wtFlags=0x%04x",
- iTerm, pTerm, zType, zLeft, pTerm->truthProb,
- pTerm->eOperator, pTerm->wtFlags);
+ "TERM-%-3d %p %s %-12s op=%03x wtFlags=%04x",
+ iTerm, pTerm, zType, zLeft, pTerm->eOperator, pTerm->wtFlags);
+ /* The 0x10000 .wheretrace flag causes extra information to be
+ ** shown about each Term */
+ if( sqlite3WhereTrace & 0x10000 ){
+ sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx",
+ pTerm->truthProb, (u64)pTerm->prereqAll, (u64)pTerm->prereqRight);
+ }
if( pTerm->iField ){
- sqlite3DebugPrintf(" iField=%d\n", pTerm->iField);
- }else{
- sqlite3DebugPrintf("\n");
+ sqlite3DebugPrintf(" iField=%d", pTerm->iField);
}
+ if( pTerm->iParent>=0 ){
+ sqlite3DebugPrintf(" iParent=%d", pTerm->iParent);
+ }
+ sqlite3DebugPrintf("\n");
sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
}
}
@@ -143107,7 +145612,7 @@ static void whereTermPrint(WhereTerm *pTerm, int iTerm){
SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC){
int i;
for(i=0; i<pWC->nTerm; i++){
- whereTermPrint(&pWC->a[i], i);
+ sqlite3WhereTermPrint(&pWC->a[i], i);
}
}
#endif
@@ -143116,7 +145621,7 @@ SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC){
/*
** Print a WhereLoop object for debugging purposes
*/
-static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
+SQLITE_PRIVATE void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC){
WhereInfo *pWInfo = pWC->pWInfo;
int nb = 1+(pWInfo->pTabList->nSrc+3)/4;
struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab;
@@ -143141,7 +145646,7 @@ static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
}else{
char *z;
if( p->u.vtab.idxStr ){
- z = sqlite3_mprintf("(%d,\"%s\",%x)",
+ z = sqlite3_mprintf("(%d,\"%s\",%#x)",
p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask);
}else{
z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask);
@@ -143158,7 +145663,7 @@ static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){
int i;
for(i=0; i<p->nLTerm; i++){
- whereTermPrint(p->aLTerm[i], i);
+ sqlite3WhereTermPrint(p->aLTerm[i], i);
}
}
}
@@ -143262,6 +145767,7 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
pWInfo->pLoops = p->pNextLoop;
whereLoopDelete(db, p);
}
+ assert( pWInfo->pExprMods==0 );
sqlite3DbFreeNN(db, pWInfo);
}
@@ -143463,6 +145969,8 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
}
pBuilder->iPlanLimit--;
+ whereLoopAdjustCost(pWInfo->pLoops, pTemplate);
+
/* If pBuilder->pOrSet is defined, then only keep track of the costs
** and prereqs.
*/
@@ -143477,7 +145985,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n);
- whereLoopPrint(pTemplate, pBuilder->pWC);
+ sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC);
}
#endif
}
@@ -143486,7 +145994,6 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
/* Look for an existing WhereLoop to replace with pTemplate
*/
- whereLoopAdjustCost(pWInfo->pLoops, pTemplate);
ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate);
if( ppPrev==0 ){
@@ -143495,7 +146002,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf(" skip: ");
- whereLoopPrint(pTemplate, pBuilder->pWC);
+ sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC);
}
#endif
return SQLITE_OK;
@@ -143511,12 +146018,12 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
if( sqlite3WhereTrace & 0x8 ){
if( p!=0 ){
sqlite3DebugPrintf("replace: ");
- whereLoopPrint(p, pBuilder->pWC);
+ sqlite3WhereLoopPrint(p, pBuilder->pWC);
sqlite3DebugPrintf(" with: ");
}else{
sqlite3DebugPrintf(" add: ");
}
- whereLoopPrint(pTemplate, pBuilder->pWC);
+ sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC);
}
#endif
if( p==0 ){
@@ -143540,7 +146047,7 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf(" delete: ");
- whereLoopPrint(pToDel, pBuilder->pWC);
+ sqlite3WhereLoopPrint(pToDel, pBuilder->pWC);
}
#endif
whereLoopDelete(db, pToDel);
@@ -143749,8 +146256,9 @@ static int whereLoopAddBtreeIndex(
pNew = pBuilder->pNew;
if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
- WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d\n",
- pProbe->pTable->zName,pProbe->zName, pNew->u.btree.nEq));
+ WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d, nSkip=%d\n",
+ pProbe->pTable->zName,pProbe->zName,
+ pNew->u.btree.nEq, pNew->nSkip));
assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
@@ -143796,9 +146304,9 @@ static int whereLoopAddBtreeIndex(
** to mix with a lower range bound from some other source */
if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue;
- /* Do not allow constraints from the WHERE clause to be used by the
- ** right table of a LEFT JOIN. Only constraints in the ON clause are
- ** allowed */
+ /* tag-20191211-001: Do not allow constraints from the WHERE clause to
+ ** be used by the right table of a LEFT JOIN. Only constraints in the
+ ** ON clause are allowed. See tag-20191211-002 for the vtab equivalent. */
if( (pSrc->fg.jointype & JT_LEFT)!=0
&& !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
){
@@ -144047,6 +146555,7 @@ static int whereLoopAddBtreeIndex(
assert( 42==sqlite3LogEst(18) );
if( saved_nEq==saved_nSkip
&& saved_nEq+1<pProbe->nKeyCol
+ && saved_nEq==pNew->nLTerm
&& pProbe->noSkipScan==0
&& OptimizationEnabled(db, SQLITE_SkipScan)
&& pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */
@@ -144115,20 +146624,25 @@ static int indexMightHelpWithOrderBy(
/* Check to see if a partial index with pPartIndexWhere can be used
** in the current query. Return true if it can be and false if not.
*/
-static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
+static int whereUsablePartialIndex(
+ int iTab, /* The table for which we want an index */
+ int isLeft, /* True if iTab is the right table of a LEFT JOIN */
+ WhereClause *pWC, /* The WHERE clause of the query */
+ Expr *pWhere /* The WHERE clause from the partial index */
+){
int i;
WhereTerm *pTerm;
Parse *pParse = pWC->pWInfo->pParse;
while( pWhere->op==TK_AND ){
- if( !whereUsablePartialIndex(iTab,pWC,pWhere->pLeft) ) return 0;
+ if( !whereUsablePartialIndex(iTab,isLeft,pWC,pWhere->pLeft) ) return 0;
pWhere = pWhere->pRight;
}
if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
Expr *pExpr;
- if( pTerm->wtFlags & TERM_NOPARTIDX ) continue;
pExpr = pTerm->pExpr;
if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab)
+ && (isLeft==0 || ExprHasProperty(pExpr, EP_FromJoin))
&& sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
){
return 1;
@@ -144291,8 +146805,11 @@ static int whereLoopAddBtree(
for(; rc==SQLITE_OK && pProbe;
pProbe=(pSrc->pIBIndex ? 0 : pProbe->pNext), iSortIdx++
){
+ int isLeft = (pSrc->fg.jointype & JT_OUTER)!=0;
if( pProbe->pPartIdxWhere!=0
- && !whereUsablePartialIndex(pSrc->iCursor, pWC, pProbe->pPartIdxWhere) ){
+ && !whereUsablePartialIndex(pSrc->iCursor, isLeft, pWC,
+ pProbe->pPartIdxWhere)
+ ){
testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */
continue; /* Partial index inappropriate for this query */
}
@@ -144519,7 +147036,14 @@ static int whereLoopAddVirtualOne(
if( iTerm>mxTerm ) mxTerm = iTerm;
testcase( iTerm==15 );
testcase( iTerm==16 );
- if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<<iTerm;
+ if( pUsage[i].omit ){
+ if( i<16 && ((1<<i)&mNoOmit)==0 ){
+ testcase( i!=iTerm );
+ pNew->u.vtab.omitMask |= 1<<iTerm;
+ }else{
+ testcase( i!=iTerm );
+ }
+ }
if( (pTerm->eOperator & WO_IN)!=0 ){
/* A virtual table that is constrained by an IN clause may not
** consume the ORDER BY clause because (1) the order of IN terms
@@ -144532,7 +147056,6 @@ static int whereLoopAddVirtualOne(
}
}
}
- pNew->u.vtab.omitMask &= ~mNoOmit;
pNew->nLTerm = mxTerm+1;
for(i=0; i<=mxTerm; i++){
@@ -144589,7 +147112,7 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int
int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
Expr *pX = pHidden->pWC->a[iTerm].pExpr;
if( pX->pLeft ){
- pC = sqlite3BinaryCompareCollSeq(pHidden->pParse, pX->pLeft, pX->pRight);
+ pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX);
}
zRet = (pC ? pC->zName : sqlite3StrBINARY);
}
@@ -144814,7 +147337,8 @@ static int whereLoopAddOr(
if( rc==SQLITE_OK ){
rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
}
- assert( rc==SQLITE_OK || sCur.n==0 );
+ assert( rc==SQLITE_OK || rc==SQLITE_DONE || sCur.n==0 );
+ testcase( rc==SQLITE_DONE );
if( sCur.n==0 ){
sSum.n = 0;
break;
@@ -145022,7 +147546,9 @@ static i8 wherePathSatisfiesOrderBy(
pLoop = pLast;
}
if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
- if( pLoop->u.vtab.isOrdered ) obSat = obDone;
+ if( pLoop->u.vtab.isOrdered && (wctrlFlags & WHERE_DISTINCTBY)==0 ){
+ obSat = obDone;
+ }
break;
}else if( wctrlFlags & WHERE_DISTINCTBY ){
pLoop->u.btree.nDistinctCol = 0;
@@ -146125,6 +148651,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
}
}
if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */
+ sqlite3DebugPrintf("---- WHERE clause at start of analysis:\n");
sqlite3WhereClausePrint(sWLB.pWC);
}
#endif
@@ -146141,7 +148668,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
"ABCDEFGHIJKLMNOPQRSTUVWYXZ";
for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
p->cId = zLabel[i%(sizeof(zLabel)-1)];
- whereLoopPrint(p, sWLB.pWC);
+ sqlite3WhereLoopPrint(p, sWLB.pWC);
}
}
#endif
@@ -146181,7 +148708,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
}
sqlite3DebugPrintf("\n");
for(ii=0; ii<pWInfo->nLevel; ii++){
- whereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC);
+ sqlite3WhereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC);
}
}
#endif
@@ -146206,14 +148733,14 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** then table t2 can be omitted from the following:
**
** SELECT v1, v3 FROM t1
- ** LEFT JOIN t2 USING (t1.ipk=t2.ipk)
- ** LEFT JOIN t3 USING (t1.ipk=t3.ipk)
+ ** LEFT JOIN t2 ON (t1.ipk=t2.ipk)
+ ** LEFT JOIN t3 ON (t1.ipk=t3.ipk)
**
** or from:
**
** SELECT DISTINCT v1, v3 FROM t1
** LEFT JOIN t2
- ** LEFT JOIN t3 USING (t1.ipk=t3.ipk)
+ ** LEFT JOIN t3 ON (t1.ipk=t3.ipk)
*/
notReady = ~(Bitmask)0;
if( pWInfo->nLevel>=2
@@ -146263,7 +148790,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
nTabList--;
}
}
+#if defined(WHERETRACE_ENABLED)
+ if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */
+ sqlite3DebugPrintf("---- WHERE clause at end of analysis:\n");
+ sqlite3WhereClausePrint(sWLB.pWC);
+ }
WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
+#endif
pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
/* If the caller is an UPDATE or DELETE statement that is requesting
@@ -146340,7 +148873,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
assert( pTabItem->iCursor==pLevel->iTabCur );
testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS-1 );
testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS );
- if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol<BMS && HasRowid(pTab) ){
+ if( pWInfo->eOnePass==ONEPASS_OFF
+ && pTab->nCol<BMS
+ && (pTab->tabFlags & (TF_HasGenerated|TF_WithoutRowid))==0
+ ){
+ /* If we know that only a prefix of the record will be used,
+ ** it is advantageous to reduce the "column count" field in
+ ** the P4 operand of the OP_OpenRead/Write opcode. */
Bitmask b = pTabItem->colUsed;
int n = 0;
for(; b; b=b>>1, n++){}
@@ -146561,10 +149100,26 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
if( pIn->eEndLoopOp!=OP_Noop ){
if( pIn->nPrefix ){
assert( pLoop->wsFlags & WHERE_IN_EARLYOUT );
- sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
- sqlite3VdbeCurrentAddr(v)+2,
- pIn->iBase, pIn->nPrefix);
- VdbeCoverage(v);
+ if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
+ sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
+ sqlite3VdbeCurrentAddr(v)+2+(pLevel->iLeftJoin!=0),
+ pIn->iBase, pIn->nPrefix);
+ VdbeCoverage(v);
+ }
+ if( pLevel->iLeftJoin ){
+ /* For LEFT JOIN queries, cursor pIn->iCur may not have been
+ ** opened yet. This occurs for WHERE clauses such as
+ ** "a = ? AND b IN (...)", where the index is on (a, b). If
+ ** the RHS of the (a=?) is NULL, then the "b IN (...)" may
+ ** never have been coded, but the body of the loop run to
+ ** return the null-row. So, if the cursor is not open yet,
+ ** jump over the OP_Next or OP_Prev instruction about to
+ ** be coded. */
+ sqlite3VdbeAddOp2(v, OP_IfNotOpen, pIn->iCur,
+ sqlite3VdbeCurrentAddr(v) + 2
+ );
+ VdbeCoverage(v);
+ }
}
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
VdbeCoverage(v);
@@ -146702,8 +149257,11 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
x = pPk->aiColumn[x];
assert( x>=0 );
+ }else{
+ testcase( x!=sqlite3StorageColumnToTable(pTab,x) );
+ x = sqlite3StorageColumnToTable(pTab,x);
}
- x = sqlite3ColumnOfIndex(pIdx, x);
+ x = sqlite3TableColumnToIndex(pIdx, x);
if( x>=0 ){
pOp->p2 = x;
pOp->p1 = pLevel->iIdxCur;
@@ -146726,6 +149284,14 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
}
}
+ /* 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;
@@ -147524,8 +150090,21 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
case TK_AGG_FUNCTION:
case TK_COLUMN: {
- Expr *pDup = sqlite3ExprDup(pParse->db, pExpr, 0);
- p->pSub = sqlite3ExprListAppend(pParse, p->pSub, pDup);
+ 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;
+ }
+ }
+ }
+ if( iCol<0 ){
+ Expr *pDup = sqlite3ExprDup(pParse->db, pExpr, 0);
+ if( pDup && pDup->op==TK_AGG_FUNCTION ) pDup->op = TK_FUNCTION;
+ p->pSub = sqlite3ExprListAppend(pParse, p->pSub, pDup);
+ }
if( p->pSub ){
assert( ExprHasProperty(pExpr, EP_Static)==0 );
ExprSetProperty(pExpr, EP_Static);
@@ -147534,11 +150113,11 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
memset(pExpr, 0, sizeof(Expr));
pExpr->op = TK_COLUMN;
- pExpr->iColumn = p->pSub->nExpr-1;
+ pExpr->iColumn = (iCol<0 ? p->pSub->nExpr-1: iCol);
pExpr->iTable = p->pWin->iEphCsr;
pExpr->y.pTab = p->pTab;
}
-
+ if( pParse->db->mallocFailed ) return WRC_Abort;
break;
}
@@ -147619,10 +150198,13 @@ static ExprList *exprListAppendList(
int i;
int nInit = pList ? pList->nExpr : 0;
for(i=0; i<pAppend->nExpr; i++){
+ int iDummy;
Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
- if( bIntToNull && pDup && pDup->op==TK_INTEGER ){
+ assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
+ if( bIntToNull && pDup && sqlite3ExprIsInteger(pDup, &iDummy) ){
pDup->op = TK_NULL;
pDup->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
+ pDup->u.zToken = 0;
}
pList = sqlite3ExprListAppend(pParse, pList, pDup);
if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags;
@@ -147640,7 +150222,7 @@ static ExprList *exprListAppendList(
*/
SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
int rc = SQLITE_OK;
- if( p->pWin && p->pPrior==0 ){
+ if( p->pWin && p->pPrior==0 && (p->selFlags & SF_WinRewrite)==0 ){
Vdbe *v = sqlite3GetVdbe(pParse);
sqlite3 *db = pParse->db;
Select *pSub = 0; /* The subquery */
@@ -147657,7 +150239,7 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ){
- return SQLITE_NOMEM;
+ return sqlite3ErrorToParser(db, SQLITE_NOMEM);
}
p->pSrc = 0;
@@ -147665,11 +150247,12 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
p->pGroupBy = 0;
p->pHaving = 0;
p->selFlags &= ~SF_Aggregate;
+ p->selFlags |= SF_WinRewrite;
/* Create the ORDER BY clause for the sub-select. This is the concatenation
** of the window PARTITION and ORDER BY clauses. Then, if this makes it
** redundant, remove the ORDER BY from the parent SELECT. */
- pSort = sqlite3ExprListDup(db, pMWin->pPartition, 0);
+ pSort = exprListAppendList(pParse, 0, pMWin->pPartition, 1);
pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy, 1);
if( pSort && p->pOrderBy && p->pOrderBy->nExpr<=pSort->nExpr ){
int nSave = pSort->nExpr;
@@ -147743,6 +150326,9 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
pSub->selFlags |= SF_Expanded;
pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
if( pTab2==0 ){
+ /* Might actually be some other kind of error, but in that case
+ ** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get
+ ** the correct error message regardless. */
rc = SQLITE_NOMEM;
}else{
memcpy(pTab, pTab2, sizeof(Table));
@@ -147750,10 +150336,6 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
p->pSrc->a[0].pTab = pTab;
pTab = pTab2;
}
- sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, pSublist->nExpr);
- sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+1, pMWin->iEphCsr);
- sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+2, pMWin->iEphCsr);
- sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+3, pMWin->iEphCsr);
}else{
sqlite3SelectDelete(db, pSub);
}
@@ -147761,6 +150343,13 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
sqlite3DbFree(db, pTab);
}
+ if( rc ){
+ if( pParse->nErr==0 ){
+ assert( pParse->db->mallocFailed );
+ sqlite3ErrorToParser(pParse->db, SQLITE_NOMEM);
+ }
+ sqlite3SelectReset(pParse, p);
+ }
return rc;
}
@@ -147980,8 +150569,8 @@ SQLITE_PRIVATE void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
** SELECT, or (b) the windows already linked use a compatible window frame.
*/
SQLITE_PRIVATE void sqlite3WindowLink(Select *pSel, Window *pWin){
- if( 0==pSel->pWin
- || 0==sqlite3WindowCompare(0, pSel->pWin, pWin, 0)
+ if( pSel!=0
+ && (0==pSel->pWin || 0==sqlite3WindowCompare(0, pSel->pWin, pWin, 0))
){
pWin->pNextWin = pSel->pWin;
if( pSel->pWin ){
@@ -147993,20 +150582,29 @@ SQLITE_PRIVATE void sqlite3WindowLink(Select *pSel, Window *pWin){
}
/*
-** Return 0 if the two window objects are identical, or non-zero otherwise.
-** Identical window objects can be processed in a single scan.
+** Return 0 if the two window objects are identical, 1 if they are
+** different, or 2 if it cannot be determined if the objects are identical
+** or not. Identical window objects can be processed in a single scan.
*/
SQLITE_PRIVATE int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2, int bFilter){
+ int res;
+ if( NEVER(p1==0) || NEVER(p2==0) ) return 1;
if( p1->eFrmType!=p2->eFrmType ) return 1;
if( p1->eStart!=p2->eStart ) return 1;
if( p1->eEnd!=p2->eEnd ) return 1;
if( p1->eExclude!=p2->eExclude ) return 1;
if( sqlite3ExprCompare(pParse, p1->pStart, p2->pStart, -1) ) return 1;
if( sqlite3ExprCompare(pParse, p1->pEnd, p2->pEnd, -1) ) return 1;
- if( sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1) ) return 1;
- if( sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1) ) return 1;
+ if( (res = sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1)) ){
+ return res;
+ }
+ if( (res = sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1)) ){
+ return res;
+ }
if( bFilter ){
- if( sqlite3ExprCompare(pParse, p1->pFilter, p2->pFilter, -1) ) return 1;
+ if( (res = sqlite3ExprCompare(pParse, p1->pFilter, p2->pFilter, -1)) ){
+ return res;
+ }
}
return 0;
}
@@ -148017,10 +150615,17 @@ SQLITE_PRIVATE int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2, i
** to begin iterating through the sub-query results. It is used to allocate
** and initialize registers and cursors used by sqlite3WindowCodeStep().
*/
-SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){
+SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Select *pSelect){
+ int nEphExpr = pSelect->pSrc->a[0].pSelect->pEList->nExpr;
+ Window *pMWin = pSelect->pWin;
Window *pWin;
Vdbe *v = sqlite3GetVdbe(pParse);
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, nEphExpr);
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+1, pMWin->iEphCsr);
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+2, pMWin->iEphCsr);
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+3, pMWin->iEphCsr);
+
/* Allocate registers to use for PARTITION BY values, if any. Initialize
** said registers to NULL. */
if( pMWin->pPartition ){
@@ -148286,7 +150891,7 @@ static void windowAggStep(
/* All OVER clauses in the same window function aggregate step must
** be the same. */
- assert( pWin==pMWin || sqlite3WindowCompare(pParse,pWin,pMWin,0)==0 );
+ assert( pWin==pMWin || sqlite3WindowCompare(pParse,pWin,pMWin,0)!=1 );
for(i=0; i<nArg; i++){
if( i!=1 || pFunc->zName!=nth_valueName ){
@@ -149782,8 +152387,9 @@ struct FrameBound { int eType; Expr *pExpr; };
** shared across database connections.
*/
static void disableLookaside(Parse *pParse){
+ sqlite3 *db = pParse->db;
pParse->disableLookaside++;
- pParse->db->lookaside.bDisable++;
+ DisableLookaside;
}
@@ -149947,28 +152553,28 @@ static void disableLookaside(Parse *pParse){
#endif
/************* Begin control #defines *****************************************/
#define YYCODETYPE unsigned short int
-#define YYNOCODE 307
+#define YYNOCODE 310
#define YYACTIONTYPE unsigned short int
-#define YYWILDCARD 98
+#define YYWILDCARD 100
#define sqlite3ParserTOKENTYPE Token
typedef union {
int yyinit;
sqlite3ParserTOKENTYPE yy0;
- const char* yy8;
- Select* yy25;
- int yy32;
- Expr* yy46;
- struct FrameBound yy57;
- u8 yy118;
- ExprList* yy138;
- Upsert* yy288;
- With* yy297;
- IdList* yy406;
- Window* yy455;
- struct {int value; int mask;} yy495;
- TriggerStep* yy527;
- struct TrigEvent yy572;
- SrcList* yy609;
+ SrcList* yy47;
+ u8 yy58;
+ struct FrameBound yy77;
+ With* yy131;
+ int yy192;
+ Expr* yy202;
+ struct {int value; int mask;} yy207;
+ struct TrigEvent yy230;
+ ExprList* yy242;
+ Window* yy303;
+ Upsert* yy318;
+ const char* yy436;
+ TriggerStep* yy447;
+ Select* yy539;
+ IdList* yy600;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
@@ -149984,17 +152590,18 @@ typedef union {
#define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse;
#define sqlite3ParserCTX_STORE yypParser->pParse=pParse;
#define YYFALLBACK 1
-#define YYNSTATE 543
-#define YYNRULE 381
-#define YYNTOKEN 179
-#define YY_MAX_SHIFT 542
-#define YY_MIN_SHIFTREDUCE 790
-#define YY_MAX_SHIFTREDUCE 1170
-#define YY_ERROR_ACTION 1171
-#define YY_ACCEPT_ACTION 1172
-#define YY_NO_ACTION 1173
-#define YY_MIN_REDUCE 1174
-#define YY_MAX_REDUCE 1554
+#define YYNSTATE 551
+#define YYNRULE 385
+#define YYNRULE_WITH_ACTION 325
+#define YYNTOKEN 181
+#define YY_MAX_SHIFT 550
+#define YY_MIN_SHIFTREDUCE 801
+#define YY_MAX_SHIFTREDUCE 1185
+#define YY_ERROR_ACTION 1186
+#define YY_ACCEPT_ACTION 1187
+#define YY_NO_ACTION 1188
+#define YY_MIN_REDUCE 1189
+#define YY_MAX_REDUCE 1573
/************* End control #defines *******************************************/
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
@@ -150061,573 +152668,583 @@ typedef union {
** yy_default[] Default action for each state.
**
*********** Begin parsing tables **********************************************/
-#define YY_ACTTAB_COUNT (1913)
+#define YY_ACTTAB_COUNT (1958)
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 537, 339, 537, 1241, 1220, 537, 12, 537, 112, 109,
- /* 10 */ 209, 537, 1241, 537, 1205, 462, 112, 109, 209, 386,
- /* 20 */ 338, 462, 42, 42, 42, 42, 445, 42, 42, 70,
- /* 30 */ 70, 922, 1208, 70, 70, 70, 70, 1443, 403, 923,
- /* 40 */ 531, 531, 531, 119, 120, 110, 1148, 1148, 991, 994,
- /* 50 */ 984, 984, 117, 117, 118, 118, 118, 118, 425, 386,
- /* 60 */ 1498, 542, 2, 1176, 1442, 519, 141, 1518, 289, 519,
- /* 70 */ 134, 519, 95, 259, 495, 1215, 189, 1254, 518, 494,
- /* 80 */ 484, 437, 296, 119, 120, 110, 1148, 1148, 991, 994,
- /* 90 */ 984, 984, 117, 117, 118, 118, 118, 118, 270, 116,
- /* 100 */ 116, 116, 116, 115, 115, 114, 114, 114, 113, 418,
- /* 110 */ 264, 264, 264, 264, 423, 1479, 352, 1481, 123, 351,
- /* 120 */ 1479, 508, 1094, 534, 1034, 534, 1099, 386, 1099, 239,
- /* 130 */ 206, 112, 109, 209, 96, 1094, 376, 219, 1094, 116,
- /* 140 */ 116, 116, 116, 115, 115, 114, 114, 114, 113, 418,
- /* 150 */ 480, 119, 120, 110, 1148, 1148, 991, 994, 984, 984,
- /* 160 */ 117, 117, 118, 118, 118, 118, 353, 422, 1407, 264,
- /* 170 */ 264, 114, 114, 114, 113, 418, 883, 121, 416, 416,
- /* 180 */ 416, 882, 534, 116, 116, 116, 116, 115, 115, 114,
- /* 190 */ 114, 114, 113, 418, 212, 415, 414, 386, 443, 383,
- /* 200 */ 382, 118, 118, 118, 118, 111, 177, 116, 116, 116,
- /* 210 */ 116, 115, 115, 114, 114, 114, 113, 418, 112, 109,
- /* 220 */ 209, 119, 120, 110, 1148, 1148, 991, 994, 984, 984,
- /* 230 */ 117, 117, 118, 118, 118, 118, 386, 438, 312, 1163,
- /* 240 */ 1155, 80, 1155, 1127, 514, 79, 116, 116, 116, 116,
- /* 250 */ 115, 115, 114, 114, 114, 113, 418, 514, 428, 418,
- /* 260 */ 119, 120, 110, 1148, 1148, 991, 994, 984, 984, 117,
- /* 270 */ 117, 118, 118, 118, 118, 428, 427, 116, 116, 116,
- /* 280 */ 116, 115, 115, 114, 114, 114, 113, 418, 115, 115,
- /* 290 */ 114, 114, 114, 113, 418, 1127, 1127, 1128, 1129, 1094,
- /* 300 */ 258, 258, 192, 386, 408, 371, 1168, 326, 118, 118,
- /* 310 */ 118, 118, 1094, 534, 374, 1094, 116, 116, 116, 116,
- /* 320 */ 115, 115, 114, 114, 114, 113, 418, 119, 120, 110,
- /* 330 */ 1148, 1148, 991, 994, 984, 984, 117, 117, 118, 118,
- /* 340 */ 118, 118, 386, 354, 445, 428, 829, 238, 1127, 1128,
- /* 350 */ 1129, 515, 1466, 116, 116, 116, 116, 115, 115, 114,
- /* 360 */ 114, 114, 113, 418, 1127, 1467, 119, 120, 110, 1148,
- /* 370 */ 1148, 991, 994, 984, 984, 117, 117, 118, 118, 118,
- /* 380 */ 118, 1169, 82, 116, 116, 116, 116, 115, 115, 114,
- /* 390 */ 114, 114, 113, 418, 405, 112, 109, 209, 161, 445,
- /* 400 */ 250, 267, 336, 478, 331, 477, 236, 951, 1127, 386,
- /* 410 */ 888, 1521, 329, 822, 852, 162, 274, 1127, 1128, 1129,
- /* 420 */ 338, 169, 116, 116, 116, 116, 115, 115, 114, 114,
- /* 430 */ 114, 113, 418, 119, 120, 110, 1148, 1148, 991, 994,
- /* 440 */ 984, 984, 117, 117, 118, 118, 118, 118, 386, 438,
- /* 450 */ 312, 1502, 1112, 1176, 161, 288, 528, 311, 289, 883,
- /* 460 */ 134, 1127, 1128, 1129, 882, 537, 143, 1254, 288, 528,
- /* 470 */ 297, 275, 119, 120, 110, 1148, 1148, 991, 994, 984,
- /* 480 */ 984, 117, 117, 118, 118, 118, 118, 70, 70, 116,
- /* 490 */ 116, 116, 116, 115, 115, 114, 114, 114, 113, 418,
- /* 500 */ 264, 264, 12, 264, 264, 395, 1127, 483, 1473, 1094,
- /* 510 */ 204, 482, 6, 534, 1258, 386, 534, 1474, 825, 972,
- /* 520 */ 504, 6, 1094, 500, 95, 1094, 534, 219, 116, 116,
- /* 530 */ 116, 116, 115, 115, 114, 114, 114, 113, 418, 119,
- /* 540 */ 120, 110, 1148, 1148, 991, 994, 984, 984, 117, 117,
- /* 550 */ 118, 118, 118, 118, 386, 1339, 971, 422, 956, 1127,
- /* 560 */ 1128, 1129, 231, 512, 1473, 475, 472, 471, 6, 113,
- /* 570 */ 418, 825, 962, 298, 503, 470, 961, 452, 119, 120,
- /* 580 */ 110, 1148, 1148, 991, 994, 984, 984, 117, 117, 118,
- /* 590 */ 118, 118, 118, 395, 537, 116, 116, 116, 116, 115,
- /* 600 */ 115, 114, 114, 114, 113, 418, 202, 961, 961, 963,
- /* 610 */ 231, 971, 1127, 475, 472, 471, 13, 13, 951, 1127,
- /* 620 */ 834, 386, 1207, 470, 399, 183, 447, 962, 462, 162,
- /* 630 */ 397, 961, 1246, 1246, 116, 116, 116, 116, 115, 115,
- /* 640 */ 114, 114, 114, 113, 418, 119, 120, 110, 1148, 1148,
- /* 650 */ 991, 994, 984, 984, 117, 117, 118, 118, 118, 118,
- /* 660 */ 386, 271, 961, 961, 963, 1127, 1128, 1129, 311, 433,
- /* 670 */ 299, 1406, 1127, 1128, 1129, 178, 1471, 138, 162, 32,
- /* 680 */ 6, 1127, 288, 528, 119, 120, 110, 1148, 1148, 991,
- /* 690 */ 994, 984, 984, 117, 117, 118, 118, 118, 118, 909,
- /* 700 */ 390, 116, 116, 116, 116, 115, 115, 114, 114, 114,
- /* 710 */ 113, 418, 1127, 429, 817, 537, 1127, 265, 265, 981,
- /* 720 */ 981, 992, 995, 324, 1055, 93, 520, 5, 338, 537,
- /* 730 */ 534, 288, 528, 1522, 1127, 1128, 1129, 70, 70, 1056,
- /* 740 */ 116, 116, 116, 116, 115, 115, 114, 114, 114, 113,
- /* 750 */ 418, 70, 70, 1495, 1057, 537, 98, 1244, 1244, 264,
- /* 760 */ 264, 908, 371, 1076, 1127, 1127, 1128, 1129, 817, 1127,
- /* 770 */ 1128, 1129, 534, 519, 140, 863, 386, 13, 13, 456,
- /* 780 */ 192, 193, 521, 453, 319, 864, 322, 284, 365, 430,
- /* 790 */ 985, 402, 379, 1077, 1548, 101, 386, 1548, 3, 395,
- /* 800 */ 119, 120, 110, 1148, 1148, 991, 994, 984, 984, 117,
- /* 810 */ 117, 118, 118, 118, 118, 386, 451, 1127, 1128, 1129,
- /* 820 */ 119, 120, 110, 1148, 1148, 991, 994, 984, 984, 117,
- /* 830 */ 117, 118, 118, 118, 118, 1127, 1354, 1412, 1169, 119,
- /* 840 */ 108, 110, 1148, 1148, 991, 994, 984, 984, 117, 117,
- /* 850 */ 118, 118, 118, 118, 1412, 1414, 116, 116, 116, 116,
- /* 860 */ 115, 115, 114, 114, 114, 113, 418, 272, 535, 1075,
- /* 870 */ 877, 877, 337, 1492, 309, 462, 116, 116, 116, 116,
- /* 880 */ 115, 115, 114, 114, 114, 113, 418, 537, 1127, 1128,
- /* 890 */ 1129, 537, 360, 537, 356, 116, 116, 116, 116, 115,
- /* 900 */ 115, 114, 114, 114, 113, 418, 386, 264, 264, 13,
- /* 910 */ 13, 273, 1127, 13, 13, 13, 13, 304, 1253, 386,
- /* 920 */ 534, 1077, 1549, 404, 1412, 1549, 496, 277, 451, 186,
- /* 930 */ 1252, 120, 110, 1148, 1148, 991, 994, 984, 984, 117,
- /* 940 */ 117, 118, 118, 118, 118, 110, 1148, 1148, 991, 994,
- /* 950 */ 984, 984, 117, 117, 118, 118, 118, 118, 105, 529,
- /* 960 */ 537, 4, 1339, 264, 264, 1127, 1128, 1129, 1039, 1039,
- /* 970 */ 459, 795, 796, 797, 536, 532, 534, 242, 301, 807,
- /* 980 */ 303, 462, 69, 69, 451, 1353, 116, 116, 116, 116,
- /* 990 */ 115, 115, 114, 114, 114, 113, 418, 1075, 419, 116,
- /* 1000 */ 116, 116, 116, 115, 115, 114, 114, 114, 113, 418,
- /* 1010 */ 526, 537, 1146, 192, 350, 105, 529, 537, 4, 497,
- /* 1020 */ 162, 337, 1492, 310, 1249, 385, 1550, 372, 9, 462,
- /* 1030 */ 242, 400, 532, 13, 13, 499, 971, 843, 436, 70,
- /* 1040 */ 70, 359, 103, 103, 8, 339, 278, 187, 278, 104,
- /* 1050 */ 1127, 419, 539, 538, 1339, 419, 961, 302, 1339, 1172,
- /* 1060 */ 1, 1, 542, 2, 1176, 1146, 1146, 526, 476, 289,
- /* 1070 */ 30, 134, 317, 288, 528, 285, 844, 1014, 1254, 276,
- /* 1080 */ 1472, 506, 410, 1194, 6, 207, 505, 961, 961, 963,
- /* 1090 */ 964, 27, 449, 971, 415, 414, 234, 233, 232, 103,
- /* 1100 */ 103, 31, 1152, 1127, 1128, 1129, 104, 1154, 419, 539,
- /* 1110 */ 538, 264, 264, 961, 1399, 1153, 264, 264, 1470, 1146,
- /* 1120 */ 537, 216, 6, 401, 534, 1197, 392, 458, 406, 534,
- /* 1130 */ 537, 485, 358, 537, 261, 537, 1339, 907, 219, 1155,
- /* 1140 */ 467, 1155, 50, 50, 961, 961, 963, 964, 27, 1497,
- /* 1150 */ 1116, 421, 70, 70, 268, 70, 70, 13, 13, 369,
- /* 1160 */ 369, 368, 253, 366, 264, 264, 804, 235, 422, 105,
- /* 1170 */ 529, 516, 4, 287, 487, 510, 493, 534, 486, 213,
- /* 1180 */ 1055, 294, 490, 384, 1127, 450, 532, 338, 413, 293,
- /* 1190 */ 522, 417, 335, 1036, 509, 1056, 107, 1036, 16, 16,
- /* 1200 */ 1469, 1094, 334, 1105, 6, 411, 1145, 264, 264, 419,
- /* 1210 */ 1057, 102, 511, 100, 1094, 264, 264, 1094, 922, 215,
- /* 1220 */ 534, 526, 907, 264, 264, 208, 923, 154, 534, 457,
- /* 1230 */ 156, 525, 391, 142, 218, 506, 534, 1127, 1128, 1129,
- /* 1240 */ 507, 139, 1131, 38, 214, 530, 392, 971, 329, 1454,
- /* 1250 */ 907, 1105, 537, 103, 103, 105, 529, 537, 4, 537,
- /* 1260 */ 104, 424, 419, 539, 538, 537, 502, 961, 517, 537,
- /* 1270 */ 1072, 537, 532, 373, 54, 54, 288, 528, 387, 55,
- /* 1280 */ 55, 15, 15, 288, 528, 17, 136, 44, 44, 1451,
- /* 1290 */ 537, 56, 56, 57, 57, 419, 1131, 291, 961, 961,
- /* 1300 */ 963, 964, 27, 393, 163, 537, 426, 526, 263, 206,
- /* 1310 */ 208, 517, 58, 58, 235, 440, 842, 841, 197, 105,
- /* 1320 */ 529, 506, 4, 1033, 439, 1033, 505, 59, 59, 308,
- /* 1330 */ 849, 850, 95, 971, 537, 907, 532, 948, 832, 103,
- /* 1340 */ 103, 105, 529, 537, 4, 1021, 104, 537, 419, 539,
- /* 1350 */ 538, 1116, 421, 961, 537, 268, 60, 60, 532, 419,
- /* 1360 */ 369, 369, 368, 253, 366, 61, 61, 804, 965, 45,
- /* 1370 */ 45, 526, 537, 1032, 1277, 1032, 46, 46, 537, 391,
- /* 1380 */ 213, 419, 294, 266, 961, 961, 963, 964, 27, 292,
- /* 1390 */ 293, 295, 832, 526, 48, 48, 1290, 971, 1289, 1021,
- /* 1400 */ 49, 49, 432, 103, 103, 887, 953, 537, 1457, 241,
- /* 1410 */ 104, 305, 419, 539, 538, 925, 926, 961, 444, 971,
- /* 1420 */ 215, 241, 965, 1224, 537, 103, 103, 1431, 154, 62,
- /* 1430 */ 62, 156, 104, 1430, 419, 539, 538, 97, 529, 961,
- /* 1440 */ 4, 537, 454, 537, 314, 214, 63, 63, 961, 961,
- /* 1450 */ 963, 964, 27, 537, 532, 446, 1286, 318, 241, 537,
- /* 1460 */ 321, 323, 325, 64, 64, 14, 14, 1237, 537, 1223,
- /* 1470 */ 961, 961, 963, 964, 27, 65, 65, 419, 537, 387,
- /* 1480 */ 537, 125, 125, 537, 288, 528, 537, 1486, 537, 526,
- /* 1490 */ 66, 66, 313, 524, 537, 95, 468, 1221, 1511, 237,
- /* 1500 */ 51, 51, 67, 67, 330, 68, 68, 426, 52, 52,
- /* 1510 */ 149, 149, 1222, 340, 341, 971, 150, 150, 1298, 463,
- /* 1520 */ 327, 103, 103, 95, 537, 1338, 1273, 537, 104, 537,
- /* 1530 */ 419, 539, 538, 1284, 537, 961, 268, 283, 523, 1344,
- /* 1540 */ 1204, 369, 369, 368, 253, 366, 75, 75, 804, 53,
- /* 1550 */ 53, 71, 71, 537, 1196, 537, 126, 126, 537, 1017,
- /* 1560 */ 537, 213, 237, 294, 537, 1185, 961, 961, 963, 964,
- /* 1570 */ 27, 293, 537, 1184, 537, 72, 72, 127, 127, 1186,
- /* 1580 */ 128, 128, 124, 124, 1505, 537, 148, 148, 537, 256,
- /* 1590 */ 195, 537, 1270, 537, 147, 147, 132, 132, 537, 11,
- /* 1600 */ 537, 215, 537, 199, 343, 345, 347, 131, 131, 154,
- /* 1610 */ 129, 129, 156, 130, 130, 74, 74, 537, 370, 1323,
- /* 1620 */ 76, 76, 73, 73, 43, 43, 214, 431, 211, 1331,
- /* 1630 */ 300, 916, 880, 815, 241, 107, 137, 307, 881, 47,
- /* 1640 */ 47, 107, 473, 378, 203, 448, 333, 1403, 1220, 1402,
- /* 1650 */ 349, 190, 527, 191, 363, 198, 1508, 1163, 245, 165,
- /* 1660 */ 387, 1450, 1448, 1160, 78, 288, 528, 1408, 81, 394,
- /* 1670 */ 82, 442, 175, 159, 167, 93, 1328, 35, 1320, 434,
- /* 1680 */ 170, 171, 172, 173, 435, 466, 221, 375, 426, 377,
- /* 1690 */ 1334, 179, 455, 441, 1397, 225, 87, 36, 461, 1419,
- /* 1700 */ 316, 257, 227, 184, 320, 464, 228, 479, 1187, 229,
- /* 1710 */ 380, 1240, 1239, 407, 1238, 1212, 834, 332, 1231, 381,
- /* 1720 */ 409, 1211, 204, 1210, 1491, 498, 1520, 1281, 92, 281,
- /* 1730 */ 1230, 489, 282, 492, 342, 243, 1282, 344, 244, 1280,
- /* 1740 */ 346, 412, 1279, 1477, 348, 122, 1476, 517, 10, 357,
- /* 1750 */ 286, 1305, 1304, 99, 1383, 94, 501, 251, 1193, 34,
- /* 1760 */ 1263, 355, 540, 194, 1262, 361, 362, 1122, 252, 254,
- /* 1770 */ 255, 388, 541, 1182, 1177, 151, 1435, 389, 1436, 1434,
- /* 1780 */ 1433, 791, 152, 135, 279, 200, 201, 420, 196, 77,
- /* 1790 */ 153, 290, 269, 210, 1031, 133, 1029, 945, 166, 155,
- /* 1800 */ 217, 168, 866, 306, 220, 1045, 174, 949, 157, 396,
- /* 1810 */ 83, 398, 176, 84, 85, 164, 86, 158, 1048, 222,
- /* 1820 */ 223, 1044, 144, 18, 224, 315, 1037, 180, 241, 460,
- /* 1830 */ 1157, 226, 181, 37, 806, 465, 334, 230, 328, 469,
- /* 1840 */ 182, 88, 474, 19, 20, 160, 89, 280, 145, 90,
- /* 1850 */ 481, 845, 1110, 146, 997, 205, 1080, 39, 91, 40,
- /* 1860 */ 488, 1081, 915, 491, 260, 262, 185, 910, 240, 107,
- /* 1870 */ 1100, 1096, 1098, 1104, 21, 1084, 33, 513, 247, 22,
- /* 1880 */ 23, 24, 1103, 25, 188, 95, 1012, 998, 996, 26,
- /* 1890 */ 1000, 1054, 7, 1053, 1001, 246, 28, 41, 533, 966,
- /* 1900 */ 816, 106, 29, 367, 248, 249, 1513, 1512, 364, 1117,
- /* 1910 */ 1173, 1173, 876,
+ /* 0 */ 544, 1220, 544, 449, 1258, 544, 1237, 544, 114, 111,
+ /* 10 */ 211, 544, 1535, 544, 1258, 521, 114, 111, 211, 390,
+ /* 20 */ 1230, 342, 42, 42, 42, 42, 1223, 42, 42, 71,
+ /* 30 */ 71, 935, 1222, 71, 71, 71, 71, 1460, 1491, 936,
+ /* 40 */ 818, 451, 6, 121, 122, 112, 1163, 1163, 1004, 1007,
+ /* 50 */ 997, 997, 119, 119, 120, 120, 120, 120, 1541, 390,
+ /* 60 */ 1356, 1515, 550, 2, 1191, 194, 526, 434, 143, 291,
+ /* 70 */ 526, 136, 526, 369, 261, 502, 272, 383, 1271, 525,
+ /* 80 */ 501, 491, 164, 121, 122, 112, 1163, 1163, 1004, 1007,
+ /* 90 */ 997, 997, 119, 119, 120, 120, 120, 120, 1356, 440,
+ /* 100 */ 1512, 118, 118, 118, 118, 117, 117, 116, 116, 116,
+ /* 110 */ 115, 422, 266, 266, 266, 266, 1496, 356, 1498, 433,
+ /* 120 */ 355, 1496, 515, 522, 1483, 541, 1112, 541, 1112, 390,
+ /* 130 */ 403, 241, 208, 114, 111, 211, 98, 290, 535, 221,
+ /* 140 */ 1027, 118, 118, 118, 118, 117, 117, 116, 116, 116,
+ /* 150 */ 115, 422, 1140, 121, 122, 112, 1163, 1163, 1004, 1007,
+ /* 160 */ 997, 997, 119, 119, 120, 120, 120, 120, 404, 426,
+ /* 170 */ 117, 117, 116, 116, 116, 115, 422, 1416, 466, 123,
+ /* 180 */ 118, 118, 118, 118, 117, 117, 116, 116, 116, 115,
+ /* 190 */ 422, 116, 116, 116, 115, 422, 538, 538, 538, 390,
+ /* 200 */ 503, 120, 120, 120, 120, 113, 1049, 1140, 1141, 1142,
+ /* 210 */ 1049, 118, 118, 118, 118, 117, 117, 116, 116, 116,
+ /* 220 */ 115, 422, 1459, 121, 122, 112, 1163, 1163, 1004, 1007,
+ /* 230 */ 997, 997, 119, 119, 120, 120, 120, 120, 390, 442,
+ /* 240 */ 314, 83, 461, 81, 357, 380, 1140, 80, 118, 118,
+ /* 250 */ 118, 118, 117, 117, 116, 116, 116, 115, 422, 179,
+ /* 260 */ 432, 422, 121, 122, 112, 1163, 1163, 1004, 1007, 997,
+ /* 270 */ 997, 119, 119, 120, 120, 120, 120, 432, 431, 266,
+ /* 280 */ 266, 118, 118, 118, 118, 117, 117, 116, 116, 116,
+ /* 290 */ 115, 422, 541, 1107, 901, 504, 1140, 114, 111, 211,
+ /* 300 */ 1429, 1140, 1141, 1142, 206, 489, 1107, 390, 447, 1107,
+ /* 310 */ 543, 328, 120, 120, 120, 120, 298, 1429, 1431, 17,
+ /* 320 */ 118, 118, 118, 118, 117, 117, 116, 116, 116, 115,
+ /* 330 */ 422, 121, 122, 112, 1163, 1163, 1004, 1007, 997, 997,
+ /* 340 */ 119, 119, 120, 120, 120, 120, 390, 1356, 432, 1140,
+ /* 350 */ 480, 1140, 1141, 1142, 994, 994, 1005, 1008, 443, 118,
+ /* 360 */ 118, 118, 118, 117, 117, 116, 116, 116, 115, 422,
+ /* 370 */ 121, 122, 112, 1163, 1163, 1004, 1007, 997, 997, 119,
+ /* 380 */ 119, 120, 120, 120, 120, 1052, 1052, 463, 1429, 118,
+ /* 390 */ 118, 118, 118, 117, 117, 116, 116, 116, 115, 422,
+ /* 400 */ 1140, 449, 544, 1424, 1140, 1141, 1142, 233, 964, 1140,
+ /* 410 */ 479, 476, 475, 171, 358, 390, 164, 405, 412, 840,
+ /* 420 */ 474, 164, 185, 332, 71, 71, 1241, 998, 118, 118,
+ /* 430 */ 118, 118, 117, 117, 116, 116, 116, 115, 422, 121,
+ /* 440 */ 122, 112, 1163, 1163, 1004, 1007, 997, 997, 119, 119,
+ /* 450 */ 120, 120, 120, 120, 390, 1140, 1141, 1142, 833, 12,
+ /* 460 */ 313, 507, 163, 354, 1140, 1141, 1142, 114, 111, 211,
+ /* 470 */ 506, 290, 535, 544, 276, 180, 290, 535, 121, 122,
+ /* 480 */ 112, 1163, 1163, 1004, 1007, 997, 997, 119, 119, 120,
+ /* 490 */ 120, 120, 120, 343, 482, 71, 71, 118, 118, 118,
+ /* 500 */ 118, 117, 117, 116, 116, 116, 115, 422, 1140, 209,
+ /* 510 */ 409, 521, 1140, 1107, 1569, 376, 252, 269, 340, 485,
+ /* 520 */ 335, 484, 238, 390, 511, 362, 1107, 1125, 331, 1107,
+ /* 530 */ 191, 407, 286, 32, 455, 441, 118, 118, 118, 118,
+ /* 540 */ 117, 117, 116, 116, 116, 115, 422, 121, 122, 112,
+ /* 550 */ 1163, 1163, 1004, 1007, 997, 997, 119, 119, 120, 120,
+ /* 560 */ 120, 120, 390, 1140, 1141, 1142, 985, 1140, 1141, 1142,
+ /* 570 */ 1140, 233, 490, 1490, 479, 476, 475, 6, 163, 544,
+ /* 580 */ 510, 544, 115, 422, 474, 5, 121, 122, 112, 1163,
+ /* 590 */ 1163, 1004, 1007, 997, 997, 119, 119, 120, 120, 120,
+ /* 600 */ 120, 13, 13, 13, 13, 118, 118, 118, 118, 117,
+ /* 610 */ 117, 116, 116, 116, 115, 422, 401, 500, 406, 544,
+ /* 620 */ 1484, 542, 1140, 890, 890, 1140, 1141, 1142, 1471, 1140,
+ /* 630 */ 275, 390, 806, 807, 808, 969, 420, 420, 420, 16,
+ /* 640 */ 16, 55, 55, 1240, 118, 118, 118, 118, 117, 117,
+ /* 650 */ 116, 116, 116, 115, 422, 121, 122, 112, 1163, 1163,
+ /* 660 */ 1004, 1007, 997, 997, 119, 119, 120, 120, 120, 120,
+ /* 670 */ 390, 1187, 1, 1, 550, 2, 1191, 1140, 1141, 1142,
+ /* 680 */ 194, 291, 896, 136, 1140, 1141, 1142, 895, 519, 1490,
+ /* 690 */ 1271, 3, 378, 6, 121, 122, 112, 1163, 1163, 1004,
+ /* 700 */ 1007, 997, 997, 119, 119, 120, 120, 120, 120, 856,
+ /* 710 */ 544, 922, 544, 118, 118, 118, 118, 117, 117, 116,
+ /* 720 */ 116, 116, 115, 422, 266, 266, 1090, 1567, 1140, 549,
+ /* 730 */ 1567, 1191, 13, 13, 13, 13, 291, 541, 136, 390,
+ /* 740 */ 483, 419, 418, 964, 342, 1271, 466, 408, 857, 279,
+ /* 750 */ 140, 221, 118, 118, 118, 118, 117, 117, 116, 116,
+ /* 760 */ 116, 115, 422, 121, 122, 112, 1163, 1163, 1004, 1007,
+ /* 770 */ 997, 997, 119, 119, 120, 120, 120, 120, 544, 266,
+ /* 780 */ 266, 426, 390, 1140, 1141, 1142, 1170, 828, 1170, 466,
+ /* 790 */ 429, 145, 541, 1144, 399, 313, 437, 301, 836, 1488,
+ /* 800 */ 71, 71, 410, 6, 1088, 471, 221, 100, 112, 1163,
+ /* 810 */ 1163, 1004, 1007, 997, 997, 119, 119, 120, 120, 120,
+ /* 820 */ 120, 118, 118, 118, 118, 117, 117, 116, 116, 116,
+ /* 830 */ 115, 422, 237, 1423, 544, 449, 426, 287, 984, 544,
+ /* 840 */ 236, 235, 234, 828, 97, 527, 427, 1263, 1263, 1144,
+ /* 850 */ 492, 306, 428, 836, 975, 544, 71, 71, 974, 1239,
+ /* 860 */ 544, 51, 51, 300, 118, 118, 118, 118, 117, 117,
+ /* 870 */ 116, 116, 116, 115, 422, 194, 103, 70, 70, 266,
+ /* 880 */ 266, 544, 71, 71, 266, 266, 30, 389, 342, 974,
+ /* 890 */ 974, 976, 541, 526, 1107, 326, 390, 541, 493, 395,
+ /* 900 */ 1468, 195, 528, 13, 13, 1356, 240, 1107, 277, 280,
+ /* 910 */ 1107, 280, 303, 455, 305, 331, 390, 31, 188, 417,
+ /* 920 */ 121, 122, 112, 1163, 1163, 1004, 1007, 997, 997, 119,
+ /* 930 */ 119, 120, 120, 120, 120, 142, 390, 363, 455, 984,
+ /* 940 */ 121, 122, 112, 1163, 1163, 1004, 1007, 997, 997, 119,
+ /* 950 */ 119, 120, 120, 120, 120, 975, 321, 1140, 324, 974,
+ /* 960 */ 121, 110, 112, 1163, 1163, 1004, 1007, 997, 997, 119,
+ /* 970 */ 119, 120, 120, 120, 120, 462, 375, 1183, 118, 118,
+ /* 980 */ 118, 118, 117, 117, 116, 116, 116, 115, 422, 1140,
+ /* 990 */ 974, 974, 976, 304, 9, 364, 244, 360, 118, 118,
+ /* 1000 */ 118, 118, 117, 117, 116, 116, 116, 115, 422, 312,
+ /* 1010 */ 544, 342, 1140, 1141, 1142, 299, 290, 535, 118, 118,
+ /* 1020 */ 118, 118, 117, 117, 116, 116, 116, 115, 422, 1261,
+ /* 1030 */ 1261, 1161, 13, 13, 278, 419, 418, 466, 390, 921,
+ /* 1040 */ 260, 260, 289, 1167, 1140, 1141, 1142, 189, 1169, 266,
+ /* 1050 */ 266, 466, 388, 541, 1184, 544, 1168, 263, 144, 487,
+ /* 1060 */ 920, 544, 541, 122, 112, 1163, 1163, 1004, 1007, 997,
+ /* 1070 */ 997, 119, 119, 120, 120, 120, 120, 71, 71, 1140,
+ /* 1080 */ 1170, 1270, 1170, 13, 13, 896, 1068, 1161, 544, 466,
+ /* 1090 */ 895, 107, 536, 1489, 4, 1266, 1107, 6, 523, 1047,
+ /* 1100 */ 12, 1069, 1090, 1568, 311, 453, 1568, 518, 539, 1107,
+ /* 1110 */ 56, 56, 1107, 1487, 421, 1356, 1070, 6, 343, 285,
+ /* 1120 */ 118, 118, 118, 118, 117, 117, 116, 116, 116, 115,
+ /* 1130 */ 422, 423, 1269, 319, 1140, 1141, 1142, 876, 266, 266,
+ /* 1140 */ 1275, 107, 536, 533, 4, 1486, 293, 877, 1209, 6,
+ /* 1150 */ 210, 541, 541, 164, 1540, 494, 414, 865, 539, 267,
+ /* 1160 */ 267, 1212, 396, 509, 497, 204, 266, 266, 394, 529,
+ /* 1170 */ 8, 984, 541, 517, 544, 920, 456, 105, 105, 541,
+ /* 1180 */ 1088, 423, 266, 266, 106, 415, 423, 546, 545, 266,
+ /* 1190 */ 266, 974, 516, 533, 1371, 541, 15, 15, 266, 266,
+ /* 1200 */ 454, 1118, 541, 266, 266, 1068, 1370, 513, 290, 535,
+ /* 1210 */ 544, 541, 512, 97, 442, 314, 541, 544, 920, 125,
+ /* 1220 */ 1069, 984, 974, 974, 976, 977, 27, 105, 105, 399,
+ /* 1230 */ 341, 1509, 44, 44, 106, 1070, 423, 546, 545, 57,
+ /* 1240 */ 57, 974, 341, 1509, 107, 536, 544, 4, 460, 399,
+ /* 1250 */ 214, 1118, 457, 294, 375, 1089, 532, 297, 544, 537,
+ /* 1260 */ 396, 539, 290, 535, 104, 244, 102, 524, 58, 58,
+ /* 1270 */ 544, 109, 974, 974, 976, 977, 27, 1514, 1129, 425,
+ /* 1280 */ 59, 59, 270, 237, 423, 138, 95, 373, 373, 372,
+ /* 1290 */ 255, 370, 60, 60, 815, 1178, 533, 544, 273, 544,
+ /* 1300 */ 1161, 843, 387, 386, 544, 1307, 544, 215, 210, 296,
+ /* 1310 */ 513, 847, 544, 265, 208, 514, 1306, 295, 274, 61,
+ /* 1320 */ 61, 62, 62, 436, 984, 1160, 45, 45, 46, 46,
+ /* 1330 */ 105, 105, 1184, 920, 47, 47, 1474, 106, 544, 423,
+ /* 1340 */ 546, 545, 218, 544, 974, 935, 1085, 217, 544, 377,
+ /* 1350 */ 395, 107, 536, 936, 4, 156, 1161, 843, 158, 544,
+ /* 1360 */ 49, 49, 141, 544, 38, 50, 50, 544, 539, 307,
+ /* 1370 */ 63, 63, 544, 1448, 216, 974, 974, 976, 977, 27,
+ /* 1380 */ 444, 64, 64, 544, 1447, 65, 65, 544, 524, 14,
+ /* 1390 */ 14, 423, 458, 544, 66, 66, 310, 544, 316, 97,
+ /* 1400 */ 1034, 544, 961, 533, 268, 127, 127, 544, 391, 67,
+ /* 1410 */ 67, 544, 978, 290, 535, 52, 52, 513, 544, 68,
+ /* 1420 */ 68, 1294, 512, 69, 69, 397, 165, 855, 854, 53,
+ /* 1430 */ 53, 984, 966, 151, 151, 243, 430, 105, 105, 199,
+ /* 1440 */ 152, 152, 448, 1303, 106, 243, 423, 546, 545, 1129,
+ /* 1450 */ 425, 974, 320, 270, 862, 863, 1034, 220, 373, 373,
+ /* 1460 */ 372, 255, 370, 450, 323, 815, 243, 544, 978, 544,
+ /* 1470 */ 107, 536, 544, 4, 544, 938, 939, 325, 215, 1046,
+ /* 1480 */ 296, 1046, 974, 974, 976, 977, 27, 539, 295, 76,
+ /* 1490 */ 76, 54, 54, 327, 72, 72, 128, 128, 1503, 1254,
+ /* 1500 */ 107, 536, 544, 4, 1045, 544, 1045, 531, 1238, 544,
+ /* 1510 */ 423, 544, 315, 334, 544, 97, 544, 539, 217, 544,
+ /* 1520 */ 472, 1528, 533, 239, 73, 73, 156, 129, 129, 158,
+ /* 1530 */ 467, 130, 130, 126, 126, 344, 150, 150, 149, 149,
+ /* 1540 */ 423, 134, 134, 329, 1030, 216, 97, 239, 929, 345,
+ /* 1550 */ 984, 243, 533, 1315, 339, 544, 105, 105, 900, 1355,
+ /* 1560 */ 544, 1290, 258, 106, 338, 423, 546, 545, 544, 1301,
+ /* 1570 */ 974, 893, 99, 536, 109, 4, 544, 133, 133, 391,
+ /* 1580 */ 984, 197, 131, 131, 290, 535, 105, 105, 530, 539,
+ /* 1590 */ 132, 132, 1361, 106, 1219, 423, 546, 545, 75, 75,
+ /* 1600 */ 974, 974, 974, 976, 977, 27, 544, 430, 826, 1211,
+ /* 1610 */ 894, 139, 423, 109, 544, 1200, 1199, 1201, 1522, 544,
+ /* 1620 */ 201, 544, 11, 374, 533, 1287, 347, 349, 77, 77,
+ /* 1630 */ 1340, 974, 974, 976, 977, 27, 74, 74, 351, 213,
+ /* 1640 */ 435, 43, 43, 48, 48, 302, 477, 309, 1348, 382,
+ /* 1650 */ 353, 452, 984, 337, 1237, 1420, 1419, 205, 105, 105,
+ /* 1660 */ 192, 367, 193, 534, 1525, 106, 1178, 423, 546, 545,
+ /* 1670 */ 247, 167, 974, 270, 1467, 200, 1465, 1175, 373, 373,
+ /* 1680 */ 372, 255, 370, 398, 79, 815, 83, 82, 1425, 446,
+ /* 1690 */ 161, 177, 169, 95, 1337, 438, 172, 173, 215, 174,
+ /* 1700 */ 296, 175, 35, 974, 974, 976, 977, 27, 295, 1345,
+ /* 1710 */ 439, 470, 223, 36, 379, 445, 1414, 381, 459, 1351,
+ /* 1720 */ 181, 227, 88, 465, 259, 229, 1436, 318, 186, 468,
+ /* 1730 */ 322, 230, 384, 1202, 231, 486, 1257, 1256, 217, 411,
+ /* 1740 */ 1255, 1248, 90, 847, 206, 413, 156, 505, 1539, 158,
+ /* 1750 */ 1226, 1538, 283, 1508, 1227, 336, 385, 284, 1225, 496,
+ /* 1760 */ 1537, 1298, 94, 346, 348, 216, 1247, 499, 1299, 245,
+ /* 1770 */ 246, 1297, 416, 350, 1494, 124, 1493, 10, 524, 361,
+ /* 1780 */ 1400, 101, 96, 288, 508, 253, 1135, 1208, 34, 1296,
+ /* 1790 */ 547, 254, 256, 257, 392, 548, 1197, 1192, 359, 391,
+ /* 1800 */ 1280, 1279, 196, 365, 290, 535, 366, 352, 1452, 1322,
+ /* 1810 */ 1321, 1453, 153, 137, 281, 154, 802, 424, 155, 1451,
+ /* 1820 */ 1450, 198, 292, 202, 203, 78, 212, 430, 271, 135,
+ /* 1830 */ 1044, 1042, 958, 168, 219, 157, 170, 879, 308, 222,
+ /* 1840 */ 1058, 176, 159, 962, 400, 84, 402, 178, 85, 86,
+ /* 1850 */ 87, 166, 160, 393, 1061, 224, 225, 1057, 146, 18,
+ /* 1860 */ 226, 317, 1050, 1172, 243, 464, 182, 228, 37, 183,
+ /* 1870 */ 817, 469, 338, 232, 330, 481, 184, 89, 845, 19,
+ /* 1880 */ 20, 92, 473, 478, 333, 91, 162, 858, 147, 488,
+ /* 1890 */ 282, 1123, 148, 1010, 928, 1093, 39, 93, 40, 495,
+ /* 1900 */ 1094, 187, 498, 207, 262, 264, 923, 242, 1109, 109,
+ /* 1910 */ 1113, 1111, 1097, 33, 21, 1117, 520, 1025, 22, 23,
+ /* 1920 */ 24, 1116, 25, 190, 97, 1011, 1009, 26, 1013, 1067,
+ /* 1930 */ 248, 7, 1066, 249, 1014, 28, 41, 889, 979, 827,
+ /* 1940 */ 108, 29, 250, 540, 251, 1530, 371, 368, 1131, 1130,
+ /* 1950 */ 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1529,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 187, 187, 187, 216, 217, 187, 206, 187, 264, 265,
- /* 10 */ 266, 187, 225, 187, 209, 187, 264, 265, 266, 19,
- /* 20 */ 187, 187, 209, 210, 209, 210, 187, 209, 210, 209,
- /* 30 */ 210, 31, 209, 209, 210, 209, 210, 285, 224, 39,
- /* 40 */ 203, 204, 205, 43, 44, 45, 46, 47, 48, 49,
- /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 230, 19,
- /* 60 */ 181, 182, 183, 184, 230, 245, 233, 208, 189, 245,
- /* 70 */ 191, 245, 26, 206, 254, 216, 276, 198, 254, 198,
- /* 80 */ 254, 281, 187, 43, 44, 45, 46, 47, 48, 49,
- /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 259, 99,
- /* 100 */ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
- /* 110 */ 231, 232, 231, 232, 286, 302, 303, 302, 22, 304,
- /* 120 */ 302, 303, 76, 244, 11, 244, 86, 19, 88, 248,
- /* 130 */ 249, 264, 265, 266, 26, 89, 198, 258, 92, 99,
- /* 140 */ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
- /* 150 */ 105, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- /* 160 */ 52, 53, 54, 55, 56, 57, 212, 288, 273, 231,
- /* 170 */ 232, 105, 106, 107, 108, 109, 131, 69, 203, 204,
- /* 180 */ 205, 136, 244, 99, 100, 101, 102, 103, 104, 105,
- /* 190 */ 106, 107, 108, 109, 15, 103, 104, 19, 260, 103,
- /* 200 */ 104, 54, 55, 56, 57, 58, 22, 99, 100, 101,
- /* 210 */ 102, 103, 104, 105, 106, 107, 108, 109, 264, 265,
- /* 220 */ 266, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- /* 230 */ 52, 53, 54, 55, 56, 57, 19, 124, 125, 60,
- /* 240 */ 148, 24, 150, 59, 187, 67, 99, 100, 101, 102,
- /* 250 */ 103, 104, 105, 106, 107, 108, 109, 187, 187, 109,
- /* 260 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 270 */ 53, 54, 55, 56, 57, 204, 205, 99, 100, 101,
- /* 280 */ 102, 103, 104, 105, 106, 107, 108, 109, 103, 104,
- /* 290 */ 105, 106, 107, 108, 109, 59, 112, 113, 114, 76,
- /* 300 */ 231, 232, 187, 19, 19, 22, 23, 23, 54, 55,
- /* 310 */ 56, 57, 89, 244, 199, 92, 99, 100, 101, 102,
- /* 320 */ 103, 104, 105, 106, 107, 108, 109, 43, 44, 45,
- /* 330 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- /* 340 */ 56, 57, 19, 212, 187, 274, 23, 26, 112, 113,
- /* 350 */ 114, 294, 295, 99, 100, 101, 102, 103, 104, 105,
- /* 360 */ 106, 107, 108, 109, 59, 295, 43, 44, 45, 46,
- /* 370 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 380 */ 57, 98, 146, 99, 100, 101, 102, 103, 104, 105,
- /* 390 */ 106, 107, 108, 109, 109, 264, 265, 266, 187, 187,
- /* 400 */ 115, 116, 117, 118, 119, 120, 121, 73, 59, 19,
- /* 410 */ 105, 23, 127, 23, 26, 81, 259, 112, 113, 114,
- /* 420 */ 187, 72, 99, 100, 101, 102, 103, 104, 105, 106,
- /* 430 */ 107, 108, 109, 43, 44, 45, 46, 47, 48, 49,
- /* 440 */ 50, 51, 52, 53, 54, 55, 56, 57, 19, 124,
- /* 450 */ 125, 182, 23, 184, 187, 134, 135, 123, 189, 131,
- /* 460 */ 191, 112, 113, 114, 136, 187, 233, 198, 134, 135,
- /* 470 */ 198, 259, 43, 44, 45, 46, 47, 48, 49, 50,
- /* 480 */ 51, 52, 53, 54, 55, 56, 57, 209, 210, 99,
- /* 490 */ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
- /* 500 */ 231, 232, 206, 231, 232, 187, 59, 296, 297, 76,
- /* 510 */ 160, 161, 301, 244, 232, 19, 244, 297, 59, 23,
- /* 520 */ 87, 301, 89, 245, 26, 92, 244, 258, 99, 100,
- /* 530 */ 101, 102, 103, 104, 105, 106, 107, 108, 109, 43,
- /* 540 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- /* 550 */ 54, 55, 56, 57, 19, 187, 97, 288, 23, 112,
- /* 560 */ 113, 114, 115, 296, 297, 118, 119, 120, 301, 108,
- /* 570 */ 109, 112, 113, 255, 141, 128, 117, 281, 43, 44,
- /* 580 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- /* 590 */ 55, 56, 57, 187, 187, 99, 100, 101, 102, 103,
- /* 600 */ 104, 105, 106, 107, 108, 109, 26, 148, 149, 150,
- /* 610 */ 115, 97, 59, 118, 119, 120, 209, 210, 73, 59,
- /* 620 */ 122, 19, 209, 128, 256, 72, 187, 113, 187, 81,
- /* 630 */ 223, 117, 227, 228, 99, 100, 101, 102, 103, 104,
- /* 640 */ 105, 106, 107, 108, 109, 43, 44, 45, 46, 47,
- /* 650 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- /* 660 */ 19, 255, 148, 149, 150, 112, 113, 114, 123, 124,
- /* 670 */ 125, 230, 112, 113, 114, 22, 297, 22, 81, 22,
- /* 680 */ 301, 59, 134, 135, 43, 44, 45, 46, 47, 48,
- /* 690 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 139,
- /* 700 */ 192, 99, 100, 101, 102, 103, 104, 105, 106, 107,
- /* 710 */ 108, 109, 59, 116, 59, 187, 59, 231, 232, 46,
- /* 720 */ 47, 48, 49, 16, 12, 145, 198, 22, 187, 187,
- /* 730 */ 244, 134, 135, 222, 112, 113, 114, 209, 210, 27,
- /* 740 */ 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
- /* 750 */ 109, 209, 210, 187, 42, 187, 154, 227, 228, 231,
- /* 760 */ 232, 139, 22, 23, 59, 112, 113, 114, 113, 112,
- /* 770 */ 113, 114, 244, 245, 233, 63, 19, 209, 210, 271,
- /* 780 */ 187, 24, 254, 275, 77, 73, 79, 245, 195, 260,
- /* 790 */ 117, 223, 199, 22, 23, 154, 19, 26, 22, 187,
- /* 800 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 810 */ 53, 54, 55, 56, 57, 19, 187, 112, 113, 114,
- /* 820 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 830 */ 53, 54, 55, 56, 57, 59, 263, 187, 98, 43,
- /* 840 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- /* 850 */ 54, 55, 56, 57, 204, 205, 99, 100, 101, 102,
- /* 860 */ 103, 104, 105, 106, 107, 108, 109, 255, 130, 98,
- /* 870 */ 132, 133, 299, 300, 198, 187, 99, 100, 101, 102,
- /* 880 */ 103, 104, 105, 106, 107, 108, 109, 187, 112, 113,
- /* 890 */ 114, 187, 241, 187, 243, 99, 100, 101, 102, 103,
- /* 900 */ 104, 105, 106, 107, 108, 109, 19, 231, 232, 209,
- /* 910 */ 210, 282, 59, 209, 210, 209, 210, 16, 230, 19,
- /* 920 */ 244, 22, 23, 223, 274, 26, 19, 223, 187, 223,
- /* 930 */ 198, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 940 */ 53, 54, 55, 56, 57, 45, 46, 47, 48, 49,
- /* 950 */ 50, 51, 52, 53, 54, 55, 56, 57, 19, 20,
- /* 960 */ 187, 22, 187, 231, 232, 112, 113, 114, 123, 124,
- /* 970 */ 125, 7, 8, 9, 187, 36, 244, 24, 77, 21,
- /* 980 */ 79, 187, 209, 210, 187, 263, 99, 100, 101, 102,
- /* 990 */ 103, 104, 105, 106, 107, 108, 109, 98, 59, 99,
- /* 1000 */ 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
- /* 1010 */ 71, 187, 59, 187, 187, 19, 20, 187, 22, 112,
- /* 1020 */ 81, 299, 300, 282, 230, 199, 291, 292, 22, 187,
- /* 1030 */ 24, 256, 36, 209, 210, 187, 97, 35, 80, 209,
- /* 1040 */ 210, 268, 103, 104, 48, 187, 220, 223, 222, 110,
- /* 1050 */ 59, 112, 113, 114, 187, 59, 117, 156, 187, 179,
- /* 1060 */ 180, 181, 182, 183, 184, 59, 113, 71, 66, 189,
- /* 1070 */ 22, 191, 230, 134, 135, 245, 74, 119, 198, 282,
- /* 1080 */ 297, 85, 224, 198, 301, 187, 90, 148, 149, 150,
- /* 1090 */ 151, 152, 19, 97, 103, 104, 123, 124, 125, 103,
- /* 1100 */ 104, 53, 111, 112, 113, 114, 110, 116, 112, 113,
- /* 1110 */ 114, 231, 232, 117, 156, 124, 231, 232, 297, 113,
- /* 1120 */ 187, 24, 301, 256, 244, 201, 202, 256, 126, 244,
- /* 1130 */ 187, 198, 187, 187, 23, 187, 187, 26, 258, 148,
- /* 1140 */ 19, 150, 209, 210, 148, 149, 150, 151, 152, 0,
- /* 1150 */ 1, 2, 209, 210, 5, 209, 210, 209, 210, 10,
- /* 1160 */ 11, 12, 13, 14, 231, 232, 17, 46, 288, 19,
- /* 1170 */ 20, 223, 22, 236, 198, 66, 187, 244, 245, 30,
- /* 1180 */ 12, 32, 198, 246, 59, 112, 36, 187, 245, 40,
- /* 1190 */ 198, 245, 117, 29, 85, 27, 26, 33, 209, 210,
- /* 1200 */ 297, 76, 127, 94, 301, 256, 26, 231, 232, 59,
- /* 1210 */ 42, 153, 87, 155, 89, 231, 232, 92, 31, 70,
- /* 1220 */ 244, 71, 26, 231, 232, 114, 39, 78, 244, 65,
- /* 1230 */ 81, 63, 111, 233, 137, 85, 244, 112, 113, 114,
- /* 1240 */ 90, 22, 59, 24, 95, 201, 202, 97, 127, 187,
- /* 1250 */ 139, 142, 187, 103, 104, 19, 20, 187, 22, 187,
- /* 1260 */ 110, 187, 112, 113, 114, 187, 141, 117, 141, 187,
- /* 1270 */ 23, 187, 36, 26, 209, 210, 134, 135, 129, 209,
- /* 1280 */ 210, 209, 210, 134, 135, 22, 159, 209, 210, 187,
- /* 1290 */ 187, 209, 210, 209, 210, 59, 113, 187, 148, 149,
- /* 1300 */ 150, 151, 152, 289, 290, 187, 157, 71, 248, 249,
- /* 1310 */ 114, 141, 209, 210, 46, 125, 116, 117, 138, 19,
- /* 1320 */ 20, 85, 22, 148, 61, 150, 90, 209, 210, 23,
- /* 1330 */ 7, 8, 26, 97, 187, 139, 36, 147, 59, 103,
- /* 1340 */ 104, 19, 20, 187, 22, 59, 110, 187, 112, 113,
- /* 1350 */ 114, 1, 2, 117, 187, 5, 209, 210, 36, 59,
- /* 1360 */ 10, 11, 12, 13, 14, 209, 210, 17, 59, 209,
- /* 1370 */ 210, 71, 187, 148, 250, 150, 209, 210, 187, 111,
- /* 1380 */ 30, 59, 32, 22, 148, 149, 150, 151, 152, 187,
- /* 1390 */ 40, 187, 113, 71, 209, 210, 187, 97, 187, 113,
- /* 1400 */ 209, 210, 187, 103, 104, 105, 23, 187, 187, 26,
- /* 1410 */ 110, 187, 112, 113, 114, 83, 84, 117, 23, 97,
- /* 1420 */ 70, 26, 113, 218, 187, 103, 104, 187, 78, 209,
- /* 1430 */ 210, 81, 110, 187, 112, 113, 114, 19, 20, 117,
- /* 1440 */ 22, 187, 187, 187, 187, 95, 209, 210, 148, 149,
- /* 1450 */ 150, 151, 152, 187, 36, 23, 187, 187, 26, 187,
- /* 1460 */ 187, 187, 187, 209, 210, 209, 210, 187, 187, 218,
- /* 1470 */ 148, 149, 150, 151, 152, 209, 210, 59, 187, 129,
- /* 1480 */ 187, 209, 210, 187, 134, 135, 187, 306, 187, 71,
- /* 1490 */ 209, 210, 23, 228, 187, 26, 23, 187, 137, 26,
- /* 1500 */ 209, 210, 209, 210, 187, 209, 210, 157, 209, 210,
- /* 1510 */ 209, 210, 218, 187, 187, 97, 209, 210, 187, 278,
- /* 1520 */ 23, 103, 104, 26, 187, 187, 187, 187, 110, 187,
- /* 1530 */ 112, 113, 114, 187, 187, 117, 5, 247, 187, 187,
- /* 1540 */ 187, 10, 11, 12, 13, 14, 209, 210, 17, 209,
- /* 1550 */ 210, 209, 210, 187, 187, 187, 209, 210, 187, 23,
- /* 1560 */ 187, 30, 26, 32, 187, 187, 148, 149, 150, 151,
- /* 1570 */ 152, 40, 187, 187, 187, 209, 210, 209, 210, 187,
- /* 1580 */ 209, 210, 209, 210, 187, 187, 209, 210, 187, 277,
- /* 1590 */ 234, 187, 247, 187, 209, 210, 209, 210, 187, 235,
- /* 1600 */ 187, 70, 187, 207, 247, 247, 247, 209, 210, 78,
- /* 1610 */ 209, 210, 81, 209, 210, 209, 210, 187, 185, 238,
- /* 1620 */ 209, 210, 209, 210, 209, 210, 95, 251, 287, 238,
- /* 1630 */ 251, 23, 23, 23, 26, 26, 26, 283, 23, 209,
- /* 1640 */ 210, 26, 213, 238, 221, 283, 212, 212, 217, 212,
- /* 1650 */ 251, 241, 270, 241, 237, 235, 190, 60, 137, 287,
- /* 1660 */ 129, 194, 194, 38, 284, 134, 135, 273, 284, 194,
- /* 1670 */ 146, 111, 22, 43, 226, 145, 262, 261, 238, 18,
- /* 1680 */ 229, 229, 229, 229, 194, 18, 193, 238, 157, 262,
- /* 1690 */ 226, 226, 194, 238, 238, 193, 153, 261, 62, 280,
- /* 1700 */ 279, 194, 193, 22, 194, 214, 193, 111, 194, 193,
- /* 1710 */ 214, 211, 211, 64, 211, 211, 122, 211, 219, 214,
- /* 1720 */ 109, 213, 160, 211, 300, 140, 211, 253, 111, 272,
- /* 1730 */ 219, 214, 272, 214, 252, 194, 253, 252, 91, 253,
- /* 1740 */ 252, 82, 253, 305, 252, 144, 305, 141, 22, 194,
- /* 1750 */ 269, 257, 257, 153, 267, 143, 142, 25, 197, 26,
- /* 1760 */ 242, 241, 196, 240, 242, 239, 238, 13, 188, 188,
- /* 1770 */ 6, 293, 186, 186, 186, 200, 206, 293, 206, 206,
- /* 1780 */ 206, 4, 200, 215, 215, 207, 207, 3, 22, 206,
- /* 1790 */ 200, 158, 96, 15, 23, 16, 23, 135, 146, 126,
- /* 1800 */ 24, 138, 20, 16, 140, 1, 138, 147, 126, 61,
- /* 1810 */ 53, 37, 146, 53, 53, 290, 53, 126, 112, 34,
- /* 1820 */ 137, 1, 5, 22, 111, 156, 68, 68, 26, 41,
- /* 1830 */ 75, 137, 111, 24, 20, 19, 127, 121, 23, 67,
- /* 1840 */ 22, 22, 67, 22, 22, 37, 22, 67, 23, 145,
- /* 1850 */ 22, 28, 23, 23, 23, 137, 23, 22, 26, 22,
- /* 1860 */ 24, 23, 112, 24, 23, 23, 22, 139, 34, 26,
- /* 1870 */ 75, 88, 86, 75, 34, 23, 22, 24, 22, 34,
- /* 1880 */ 34, 34, 93, 34, 26, 26, 23, 23, 23, 34,
- /* 1890 */ 23, 23, 44, 23, 11, 26, 22, 22, 26, 23,
- /* 1900 */ 23, 22, 22, 15, 137, 137, 137, 137, 23, 1,
- /* 1910 */ 307, 307, 131, 307, 307, 307, 307, 307, 307, 307,
- /* 1920 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 1930 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 1940 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 1950 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 1960 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 1970 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 1980 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 1990 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 2000 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 2010 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 2020 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 2030 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 2040 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 2050 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 2060 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 2070 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 2080 */ 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- /* 2090 */ 307, 307,
+ /* 0 */ 189, 211, 189, 189, 218, 189, 220, 189, 267, 268,
+ /* 10 */ 269, 189, 210, 189, 228, 189, 267, 268, 269, 19,
+ /* 20 */ 218, 189, 211, 212, 211, 212, 211, 211, 212, 211,
+ /* 30 */ 212, 31, 211, 211, 212, 211, 212, 288, 300, 39,
+ /* 40 */ 21, 189, 304, 43, 44, 45, 46, 47, 48, 49,
+ /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 225, 19,
+ /* 60 */ 189, 183, 184, 185, 186, 189, 248, 263, 236, 191,
+ /* 70 */ 248, 193, 248, 197, 208, 257, 262, 201, 200, 257,
+ /* 80 */ 200, 257, 81, 43, 44, 45, 46, 47, 48, 49,
+ /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 189, 80,
+ /* 100 */ 189, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ /* 110 */ 110, 111, 234, 235, 234, 235, 305, 306, 305, 118,
+ /* 120 */ 307, 305, 306, 297, 298, 247, 86, 247, 88, 19,
+ /* 130 */ 259, 251, 252, 267, 268, 269, 26, 136, 137, 261,
+ /* 140 */ 121, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ /* 150 */ 110, 111, 59, 43, 44, 45, 46, 47, 48, 49,
+ /* 160 */ 50, 51, 52, 53, 54, 55, 56, 57, 259, 291,
+ /* 170 */ 105, 106, 107, 108, 109, 110, 111, 158, 189, 69,
+ /* 180 */ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+ /* 190 */ 111, 107, 108, 109, 110, 111, 205, 206, 207, 19,
+ /* 200 */ 19, 54, 55, 56, 57, 58, 29, 114, 115, 116,
+ /* 210 */ 33, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ /* 220 */ 110, 111, 233, 43, 44, 45, 46, 47, 48, 49,
+ /* 230 */ 50, 51, 52, 53, 54, 55, 56, 57, 19, 126,
+ /* 240 */ 127, 148, 65, 24, 214, 200, 59, 67, 101, 102,
+ /* 250 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 22,
+ /* 260 */ 189, 111, 43, 44, 45, 46, 47, 48, 49, 50,
+ /* 270 */ 51, 52, 53, 54, 55, 56, 57, 206, 207, 234,
+ /* 280 */ 235, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ /* 290 */ 110, 111, 247, 76, 107, 114, 59, 267, 268, 269,
+ /* 300 */ 189, 114, 115, 116, 162, 163, 89, 19, 263, 92,
+ /* 310 */ 189, 23, 54, 55, 56, 57, 189, 206, 207, 22,
+ /* 320 */ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+ /* 330 */ 111, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ /* 340 */ 52, 53, 54, 55, 56, 57, 19, 189, 277, 59,
+ /* 350 */ 23, 114, 115, 116, 46, 47, 48, 49, 61, 101,
+ /* 360 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ /* 370 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ /* 380 */ 53, 54, 55, 56, 57, 125, 126, 127, 277, 101,
+ /* 390 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ /* 400 */ 59, 189, 189, 276, 114, 115, 116, 117, 73, 59,
+ /* 410 */ 120, 121, 122, 72, 214, 19, 81, 259, 19, 23,
+ /* 420 */ 130, 81, 72, 24, 211, 212, 221, 119, 101, 102,
+ /* 430 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 43,
+ /* 440 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ /* 450 */ 54, 55, 56, 57, 19, 114, 115, 116, 23, 208,
+ /* 460 */ 125, 248, 189, 189, 114, 115, 116, 267, 268, 269,
+ /* 470 */ 189, 136, 137, 189, 262, 22, 136, 137, 43, 44,
+ /* 480 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ /* 490 */ 55, 56, 57, 189, 95, 211, 212, 101, 102, 103,
+ /* 500 */ 104, 105, 106, 107, 108, 109, 110, 111, 59, 189,
+ /* 510 */ 111, 189, 59, 76, 294, 295, 117, 118, 119, 120,
+ /* 520 */ 121, 122, 123, 19, 87, 189, 89, 23, 129, 92,
+ /* 530 */ 279, 227, 248, 22, 189, 284, 101, 102, 103, 104,
+ /* 540 */ 105, 106, 107, 108, 109, 110, 111, 43, 44, 45,
+ /* 550 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ /* 560 */ 56, 57, 19, 114, 115, 116, 23, 114, 115, 116,
+ /* 570 */ 59, 117, 299, 300, 120, 121, 122, 304, 189, 189,
+ /* 580 */ 143, 189, 110, 111, 130, 22, 43, 44, 45, 46,
+ /* 590 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 600 */ 57, 211, 212, 211, 212, 101, 102, 103, 104, 105,
+ /* 610 */ 106, 107, 108, 109, 110, 111, 226, 189, 226, 189,
+ /* 620 */ 298, 132, 59, 134, 135, 114, 115, 116, 189, 59,
+ /* 630 */ 285, 19, 7, 8, 9, 23, 205, 206, 207, 211,
+ /* 640 */ 212, 211, 212, 221, 101, 102, 103, 104, 105, 106,
+ /* 650 */ 107, 108, 109, 110, 111, 43, 44, 45, 46, 47,
+ /* 660 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ /* 670 */ 19, 181, 182, 183, 184, 185, 186, 114, 115, 116,
+ /* 680 */ 189, 191, 133, 193, 114, 115, 116, 138, 299, 300,
+ /* 690 */ 200, 22, 201, 304, 43, 44, 45, 46, 47, 48,
+ /* 700 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 35,
+ /* 710 */ 189, 141, 189, 101, 102, 103, 104, 105, 106, 107,
+ /* 720 */ 108, 109, 110, 111, 234, 235, 22, 23, 59, 184,
+ /* 730 */ 26, 186, 211, 212, 211, 212, 191, 247, 193, 19,
+ /* 740 */ 66, 105, 106, 73, 189, 200, 189, 226, 74, 226,
+ /* 750 */ 22, 261, 101, 102, 103, 104, 105, 106, 107, 108,
+ /* 760 */ 109, 110, 111, 43, 44, 45, 46, 47, 48, 49,
+ /* 770 */ 50, 51, 52, 53, 54, 55, 56, 57, 189, 234,
+ /* 780 */ 235, 291, 19, 114, 115, 116, 150, 59, 152, 189,
+ /* 790 */ 233, 236, 247, 59, 189, 125, 126, 127, 59, 300,
+ /* 800 */ 211, 212, 128, 304, 100, 19, 261, 156, 45, 46,
+ /* 810 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 820 */ 57, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+ /* 830 */ 110, 111, 46, 233, 189, 189, 291, 248, 99, 189,
+ /* 840 */ 125, 126, 127, 115, 26, 200, 289, 230, 231, 115,
+ /* 850 */ 200, 16, 189, 114, 115, 189, 211, 212, 119, 221,
+ /* 860 */ 189, 211, 212, 258, 101, 102, 103, 104, 105, 106,
+ /* 870 */ 107, 108, 109, 110, 111, 189, 156, 211, 212, 234,
+ /* 880 */ 235, 189, 211, 212, 234, 235, 22, 201, 189, 150,
+ /* 890 */ 151, 152, 247, 248, 76, 16, 19, 247, 248, 113,
+ /* 900 */ 189, 24, 257, 211, 212, 189, 26, 89, 262, 223,
+ /* 910 */ 92, 225, 77, 189, 79, 129, 19, 53, 226, 248,
+ /* 920 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ /* 930 */ 53, 54, 55, 56, 57, 236, 19, 271, 189, 99,
+ /* 940 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ /* 950 */ 53, 54, 55, 56, 57, 115, 77, 59, 79, 119,
+ /* 960 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+ /* 970 */ 53, 54, 55, 56, 57, 259, 22, 23, 101, 102,
+ /* 980 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 59,
+ /* 990 */ 150, 151, 152, 158, 22, 244, 24, 246, 101, 102,
+ /* 1000 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 285,
+ /* 1010 */ 189, 189, 114, 115, 116, 200, 136, 137, 101, 102,
+ /* 1020 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 230,
+ /* 1030 */ 231, 59, 211, 212, 285, 105, 106, 189, 19, 141,
+ /* 1040 */ 234, 235, 239, 113, 114, 115, 116, 226, 118, 234,
+ /* 1050 */ 235, 189, 249, 247, 100, 189, 126, 23, 236, 107,
+ /* 1060 */ 26, 189, 247, 44, 45, 46, 47, 48, 49, 50,
+ /* 1070 */ 51, 52, 53, 54, 55, 56, 57, 211, 212, 59,
+ /* 1080 */ 150, 233, 152, 211, 212, 133, 12, 115, 189, 189,
+ /* 1090 */ 138, 19, 20, 300, 22, 233, 76, 304, 226, 11,
+ /* 1100 */ 208, 27, 22, 23, 200, 19, 26, 87, 36, 89,
+ /* 1110 */ 211, 212, 92, 300, 248, 189, 42, 304, 189, 250,
+ /* 1120 */ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+ /* 1130 */ 111, 59, 200, 233, 114, 115, 116, 63, 234, 235,
+ /* 1140 */ 235, 19, 20, 71, 22, 300, 189, 73, 200, 304,
+ /* 1150 */ 116, 247, 247, 81, 23, 200, 227, 26, 36, 234,
+ /* 1160 */ 235, 203, 204, 143, 200, 26, 234, 235, 194, 200,
+ /* 1170 */ 48, 99, 247, 66, 189, 141, 284, 105, 106, 247,
+ /* 1180 */ 100, 59, 234, 235, 112, 259, 114, 115, 116, 234,
+ /* 1190 */ 235, 119, 85, 71, 266, 247, 211, 212, 234, 235,
+ /* 1200 */ 114, 94, 247, 234, 235, 12, 266, 85, 136, 137,
+ /* 1210 */ 189, 247, 90, 26, 126, 127, 247, 189, 26, 22,
+ /* 1220 */ 27, 99, 150, 151, 152, 153, 154, 105, 106, 189,
+ /* 1230 */ 302, 303, 211, 212, 112, 42, 114, 115, 116, 211,
+ /* 1240 */ 212, 119, 302, 303, 19, 20, 189, 22, 274, 189,
+ /* 1250 */ 15, 144, 278, 189, 22, 23, 63, 189, 189, 203,
+ /* 1260 */ 204, 36, 136, 137, 155, 24, 157, 143, 211, 212,
+ /* 1270 */ 189, 26, 150, 151, 152, 153, 154, 0, 1, 2,
+ /* 1280 */ 211, 212, 5, 46, 59, 161, 147, 10, 11, 12,
+ /* 1290 */ 13, 14, 211, 212, 17, 60, 71, 189, 258, 189,
+ /* 1300 */ 59, 59, 105, 106, 189, 189, 189, 30, 116, 32,
+ /* 1310 */ 85, 124, 189, 251, 252, 90, 189, 40, 258, 211,
+ /* 1320 */ 212, 211, 212, 189, 99, 26, 211, 212, 211, 212,
+ /* 1330 */ 105, 106, 100, 141, 211, 212, 189, 112, 189, 114,
+ /* 1340 */ 115, 116, 24, 189, 119, 31, 23, 70, 189, 26,
+ /* 1350 */ 113, 19, 20, 39, 22, 78, 115, 115, 81, 189,
+ /* 1360 */ 211, 212, 22, 189, 24, 211, 212, 189, 36, 189,
+ /* 1370 */ 211, 212, 189, 189, 97, 150, 151, 152, 153, 154,
+ /* 1380 */ 127, 211, 212, 189, 189, 211, 212, 189, 143, 211,
+ /* 1390 */ 212, 59, 189, 189, 211, 212, 23, 189, 189, 26,
+ /* 1400 */ 59, 189, 149, 71, 22, 211, 212, 189, 131, 211,
+ /* 1410 */ 212, 189, 59, 136, 137, 211, 212, 85, 189, 211,
+ /* 1420 */ 212, 253, 90, 211, 212, 292, 293, 118, 119, 211,
+ /* 1430 */ 212, 99, 23, 211, 212, 26, 159, 105, 106, 140,
+ /* 1440 */ 211, 212, 23, 189, 112, 26, 114, 115, 116, 1,
+ /* 1450 */ 2, 119, 189, 5, 7, 8, 115, 139, 10, 11,
+ /* 1460 */ 12, 13, 14, 23, 189, 17, 26, 189, 115, 189,
+ /* 1470 */ 19, 20, 189, 22, 189, 83, 84, 189, 30, 150,
+ /* 1480 */ 32, 152, 150, 151, 152, 153, 154, 36, 40, 211,
+ /* 1490 */ 212, 211, 212, 189, 211, 212, 211, 212, 309, 189,
+ /* 1500 */ 19, 20, 189, 22, 150, 189, 152, 231, 189, 189,
+ /* 1510 */ 59, 189, 23, 189, 189, 26, 189, 36, 70, 189,
+ /* 1520 */ 23, 139, 71, 26, 211, 212, 78, 211, 212, 81,
+ /* 1530 */ 281, 211, 212, 211, 212, 189, 211, 212, 211, 212,
+ /* 1540 */ 59, 211, 212, 23, 23, 97, 26, 26, 23, 189,
+ /* 1550 */ 99, 26, 71, 189, 119, 189, 105, 106, 107, 189,
+ /* 1560 */ 189, 189, 280, 112, 129, 114, 115, 116, 189, 189,
+ /* 1570 */ 119, 23, 19, 20, 26, 22, 189, 211, 212, 131,
+ /* 1580 */ 99, 237, 211, 212, 136, 137, 105, 106, 189, 36,
+ /* 1590 */ 211, 212, 189, 112, 189, 114, 115, 116, 211, 212,
+ /* 1600 */ 119, 150, 151, 152, 153, 154, 189, 159, 23, 189,
+ /* 1610 */ 23, 26, 59, 26, 189, 189, 189, 189, 189, 189,
+ /* 1620 */ 209, 189, 238, 187, 71, 250, 250, 250, 211, 212,
+ /* 1630 */ 241, 150, 151, 152, 153, 154, 211, 212, 250, 290,
+ /* 1640 */ 254, 211, 212, 211, 212, 254, 215, 286, 241, 241,
+ /* 1650 */ 254, 286, 99, 214, 220, 214, 214, 224, 105, 106,
+ /* 1660 */ 244, 240, 244, 273, 192, 112, 60, 114, 115, 116,
+ /* 1670 */ 139, 290, 119, 5, 196, 238, 196, 38, 10, 11,
+ /* 1680 */ 12, 13, 14, 196, 287, 17, 148, 287, 276, 113,
+ /* 1690 */ 43, 22, 229, 147, 241, 18, 232, 232, 30, 232,
+ /* 1700 */ 32, 232, 264, 150, 151, 152, 153, 154, 40, 265,
+ /* 1710 */ 196, 18, 195, 264, 241, 241, 241, 265, 196, 229,
+ /* 1720 */ 229, 195, 155, 62, 196, 195, 283, 282, 22, 216,
+ /* 1730 */ 196, 195, 216, 196, 195, 113, 213, 213, 70, 64,
+ /* 1740 */ 213, 222, 22, 124, 162, 111, 78, 142, 219, 81,
+ /* 1750 */ 215, 219, 275, 303, 213, 213, 216, 275, 213, 216,
+ /* 1760 */ 213, 256, 113, 255, 255, 97, 222, 216, 256, 196,
+ /* 1770 */ 91, 256, 82, 255, 308, 146, 308, 22, 143, 196,
+ /* 1780 */ 270, 155, 145, 272, 144, 25, 13, 199, 26, 256,
+ /* 1790 */ 198, 190, 190, 6, 296, 188, 188, 188, 244, 131,
+ /* 1800 */ 245, 245, 243, 242, 136, 137, 241, 255, 208, 260,
+ /* 1810 */ 260, 208, 202, 217, 217, 202, 4, 3, 202, 208,
+ /* 1820 */ 208, 22, 160, 209, 209, 208, 15, 159, 98, 16,
+ /* 1830 */ 23, 23, 137, 148, 24, 128, 140, 20, 16, 142,
+ /* 1840 */ 1, 140, 128, 149, 61, 53, 37, 148, 53, 53,
+ /* 1850 */ 53, 293, 128, 296, 114, 34, 139, 1, 5, 22,
+ /* 1860 */ 113, 158, 68, 75, 26, 41, 68, 139, 24, 113,
+ /* 1870 */ 20, 19, 129, 123, 23, 96, 22, 22, 59, 22,
+ /* 1880 */ 22, 147, 67, 67, 24, 22, 37, 28, 23, 22,
+ /* 1890 */ 67, 23, 23, 23, 114, 23, 22, 26, 22, 24,
+ /* 1900 */ 23, 22, 24, 139, 23, 23, 141, 34, 88, 26,
+ /* 1910 */ 75, 86, 23, 22, 34, 75, 24, 23, 34, 34,
+ /* 1920 */ 34, 93, 34, 26, 26, 23, 23, 34, 23, 23,
+ /* 1930 */ 26, 44, 23, 22, 11, 22, 22, 133, 23, 23,
+ /* 1940 */ 22, 22, 139, 26, 139, 139, 15, 23, 1, 1,
+ /* 1950 */ 310, 310, 310, 310, 310, 310, 310, 139, 310, 310,
+ /* 1960 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 1970 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 1980 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 1990 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 2000 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 2010 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 2020 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 2030 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 2040 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 2050 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 2060 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 2070 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 2080 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 2090 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 2100 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 2110 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 2120 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
+ /* 2130 */ 310, 310, 310, 310, 310, 310, 310, 310, 310,
};
-#define YY_SHIFT_COUNT (542)
+#define YY_SHIFT_COUNT (550)
#define YY_SHIFT_MIN (0)
-#define YY_SHIFT_MAX (1908)
+#define YY_SHIFT_MAX (1948)
static const unsigned short int yy_shift_ofst[] = {
- /* 0 */ 1350, 1149, 1531, 939, 939, 548, 996, 1150, 1236, 1322,
- /* 10 */ 1322, 1322, 334, 0, 0, 178, 777, 1322, 1322, 1322,
- /* 20 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
- /* 30 */ 991, 991, 1125, 1125, 447, 597, 548, 548, 548, 548,
- /* 40 */ 548, 548, 40, 108, 217, 284, 323, 390, 429, 496,
- /* 50 */ 535, 602, 641, 757, 777, 777, 777, 777, 777, 777,
- /* 60 */ 777, 777, 777, 777, 777, 777, 777, 777, 777, 777,
- /* 70 */ 777, 777, 796, 777, 887, 900, 900, 1300, 1322, 1322,
- /* 80 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
- /* 90 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
- /* 100 */ 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
- /* 110 */ 1418, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322, 1322,
- /* 120 */ 1322, 1322, 1322, 1322, 147, 254, 254, 254, 254, 254,
- /* 130 */ 84, 185, 66, 853, 958, 1121, 853, 92, 92, 853,
- /* 140 */ 321, 321, 321, 321, 325, 350, 350, 461, 150, 1913,
- /* 150 */ 1913, 285, 285, 285, 236, 184, 349, 184, 184, 712,
- /* 160 */ 712, 433, 553, 771, 899, 853, 853, 853, 853, 853,
- /* 170 */ 853, 853, 853, 853, 853, 853, 853, 853, 853, 853,
- /* 180 */ 853, 853, 853, 853, 853, 853, 46, 46, 853, 113,
- /* 190 */ 223, 223, 1183, 1183, 1127, 1142, 1913, 1913, 1913, 459,
- /* 200 */ 514, 514, 653, 495, 657, 305, 705, 560, 622, 776,
- /* 210 */ 853, 853, 853, 853, 853, 853, 853, 853, 853, 545,
- /* 220 */ 853, 853, 853, 853, 853, 853, 853, 853, 853, 853,
- /* 230 */ 853, 853, 1002, 1002, 1002, 853, 853, 853, 853, 1111,
- /* 240 */ 853, 853, 853, 1006, 1109, 853, 853, 1168, 853, 853,
- /* 250 */ 853, 853, 853, 853, 853, 853, 845, 1164, 738, 953,
- /* 260 */ 953, 953, 953, 1196, 738, 738, 45, 96, 964, 179,
- /* 270 */ 580, 907, 907, 1073, 580, 580, 1073, 498, 388, 1268,
- /* 280 */ 1187, 1187, 1187, 907, 1170, 1170, 1058, 1180, 328, 1219,
- /* 290 */ 1597, 1521, 1521, 1625, 1625, 1521, 1524, 1560, 1650, 1630,
- /* 300 */ 1530, 1661, 1661, 1661, 1661, 1521, 1667, 1530, 1530, 1560,
- /* 310 */ 1650, 1630, 1630, 1530, 1521, 1667, 1543, 1636, 1521, 1667,
- /* 320 */ 1681, 1521, 1667, 1521, 1667, 1681, 1596, 1596, 1596, 1649,
- /* 330 */ 1681, 1596, 1594, 1596, 1649, 1596, 1596, 1562, 1681, 1611,
- /* 340 */ 1611, 1681, 1585, 1617, 1585, 1617, 1585, 1617, 1585, 1617,
- /* 350 */ 1521, 1647, 1647, 1659, 1659, 1601, 1606, 1726, 1521, 1600,
- /* 360 */ 1601, 1612, 1614, 1530, 1732, 1733, 1754, 1754, 1764, 1764,
- /* 370 */ 1764, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913, 1913,
- /* 380 */ 1913, 1913, 1913, 1913, 1913, 1913, 673, 901, 283, 740,
- /* 390 */ 707, 973, 655, 1247, 1048, 1097, 1190, 1306, 1263, 1383,
- /* 400 */ 1395, 1432, 1469, 1473, 1497, 1279, 1200, 1323, 1075, 1286,
- /* 410 */ 1536, 1608, 1332, 1609, 1175, 1225, 1610, 1615, 1309, 1361,
- /* 420 */ 1777, 1784, 1766, 1633, 1778, 1696, 1779, 1771, 1773, 1662,
- /* 430 */ 1652, 1673, 1776, 1663, 1782, 1664, 1787, 1804, 1668, 1660,
- /* 440 */ 1682, 1748, 1774, 1666, 1757, 1760, 1761, 1763, 1691, 1706,
- /* 450 */ 1785, 1683, 1820, 1817, 1801, 1713, 1669, 1758, 1802, 1759,
- /* 460 */ 1755, 1788, 1694, 1721, 1809, 1814, 1816, 1709, 1716, 1818,
- /* 470 */ 1772, 1819, 1821, 1815, 1822, 1775, 1823, 1824, 1780, 1808,
- /* 480 */ 1825, 1704, 1828, 1829, 1830, 1831, 1832, 1833, 1835, 1836,
- /* 490 */ 1838, 1837, 1839, 1718, 1841, 1842, 1750, 1834, 1844, 1728,
- /* 500 */ 1843, 1840, 1845, 1846, 1847, 1783, 1795, 1786, 1848, 1798,
- /* 510 */ 1789, 1849, 1852, 1854, 1853, 1858, 1859, 1855, 1863, 1843,
- /* 520 */ 1864, 1865, 1867, 1868, 1869, 1870, 1856, 1883, 1874, 1875,
- /* 530 */ 1876, 1877, 1879, 1880, 1872, 1781, 1767, 1768, 1769, 1770,
- /* 540 */ 1885, 1888, 1908,
+ /* 0 */ 1448, 1277, 1668, 1072, 1072, 340, 1122, 1225, 1332, 1481,
+ /* 10 */ 1481, 1481, 335, 0, 0, 180, 897, 1481, 1481, 1481,
+ /* 20 */ 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
+ /* 30 */ 930, 930, 1020, 1020, 290, 1, 340, 340, 340, 340,
+ /* 40 */ 340, 340, 40, 110, 219, 288, 327, 396, 435, 504,
+ /* 50 */ 543, 612, 651, 720, 877, 897, 897, 897, 897, 897,
+ /* 60 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897,
+ /* 70 */ 897, 897, 897, 917, 897, 1019, 763, 763, 1451, 1481,
+ /* 80 */ 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
+ /* 90 */ 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
+ /* 100 */ 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
+ /* 110 */ 1481, 1481, 1553, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
+ /* 120 */ 1481, 1481, 1481, 1481, 1481, 1481, 147, 258, 258, 258,
+ /* 130 */ 258, 258, 79, 65, 84, 449, 19, 786, 449, 636,
+ /* 140 */ 636, 449, 880, 880, 880, 880, 113, 142, 142, 472,
+ /* 150 */ 150, 1958, 1958, 399, 399, 399, 93, 237, 341, 237,
+ /* 160 */ 237, 1074, 1074, 437, 350, 704, 1080, 449, 449, 449,
+ /* 170 */ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ /* 180 */ 449, 449, 449, 449, 449, 449, 449, 449, 818, 818,
+ /* 190 */ 449, 1088, 217, 217, 734, 734, 1124, 1126, 1958, 1958,
+ /* 200 */ 1958, 739, 840, 840, 453, 454, 511, 187, 563, 570,
+ /* 210 */ 898, 669, 449, 449, 449, 449, 449, 449, 449, 449,
+ /* 220 */ 449, 670, 449, 449, 449, 449, 449, 449, 449, 449,
+ /* 230 */ 449, 449, 449, 449, 674, 674, 674, 449, 449, 449,
+ /* 240 */ 449, 1034, 449, 449, 449, 972, 1107, 449, 449, 1193,
+ /* 250 */ 449, 449, 449, 449, 449, 449, 449, 449, 260, 177,
+ /* 260 */ 489, 1241, 1241, 1241, 1241, 1192, 489, 489, 952, 1197,
+ /* 270 */ 625, 1235, 1139, 181, 181, 1086, 1139, 1139, 1086, 1187,
+ /* 280 */ 1131, 1237, 1314, 1314, 1314, 181, 1245, 1245, 1109, 1299,
+ /* 290 */ 549, 1340, 1606, 1531, 1531, 1639, 1639, 1531, 1538, 1576,
+ /* 300 */ 1669, 1647, 1546, 1677, 1677, 1677, 1677, 1531, 1693, 1546,
+ /* 310 */ 1546, 1576, 1669, 1647, 1647, 1546, 1531, 1693, 1567, 1661,
+ /* 320 */ 1531, 1693, 1706, 1531, 1693, 1531, 1693, 1706, 1622, 1622,
+ /* 330 */ 1622, 1675, 1720, 1720, 1706, 1622, 1619, 1622, 1675, 1622,
+ /* 340 */ 1622, 1582, 1706, 1634, 1634, 1706, 1605, 1649, 1605, 1649,
+ /* 350 */ 1605, 1649, 1605, 1649, 1531, 1679, 1679, 1690, 1690, 1629,
+ /* 360 */ 1635, 1755, 1531, 1626, 1629, 1637, 1640, 1546, 1760, 1762,
+ /* 370 */ 1773, 1773, 1787, 1787, 1787, 1958, 1958, 1958, 1958, 1958,
+ /* 380 */ 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958,
+ /* 390 */ 308, 835, 954, 1232, 879, 715, 728, 1323, 864, 1318,
+ /* 400 */ 1253, 1373, 297, 1409, 1419, 1440, 1489, 1497, 1520, 1242,
+ /* 410 */ 1309, 1447, 1435, 1341, 1521, 1525, 1392, 1548, 1329, 1354,
+ /* 420 */ 1585, 1587, 1353, 1382, 1812, 1814, 1799, 1662, 1811, 1730,
+ /* 430 */ 1813, 1807, 1808, 1695, 1685, 1707, 1810, 1696, 1817, 1697,
+ /* 440 */ 1822, 1839, 1701, 1694, 1714, 1783, 1809, 1699, 1792, 1795,
+ /* 450 */ 1796, 1797, 1724, 1740, 1821, 1717, 1856, 1853, 1837, 1747,
+ /* 460 */ 1703, 1794, 1838, 1798, 1788, 1824, 1728, 1756, 1844, 1850,
+ /* 470 */ 1852, 1743, 1750, 1854, 1815, 1855, 1857, 1851, 1858, 1816,
+ /* 480 */ 1819, 1860, 1779, 1859, 1863, 1823, 1849, 1865, 1734, 1867,
+ /* 490 */ 1868, 1869, 1870, 1871, 1872, 1874, 1875, 1877, 1876, 1878,
+ /* 500 */ 1764, 1881, 1882, 1780, 1873, 1879, 1765, 1883, 1880, 1884,
+ /* 510 */ 1885, 1886, 1820, 1835, 1825, 1887, 1840, 1828, 1888, 1889,
+ /* 520 */ 1891, 1892, 1897, 1898, 1893, 1894, 1883, 1902, 1903, 1905,
+ /* 530 */ 1906, 1904, 1909, 1911, 1923, 1913, 1914, 1915, 1916, 1918,
+ /* 540 */ 1919, 1917, 1804, 1803, 1805, 1806, 1818, 1924, 1931, 1947,
+ /* 550 */ 1948,
};
-#define YY_REDUCE_COUNT (385)
-#define YY_REDUCE_MIN (-256)
-#define YY_REDUCE_MAX (1590)
+#define YY_REDUCE_COUNT (389)
+#define YY_REDUCE_MIN (-262)
+#define YY_REDUCE_MAX (1617)
static const short yy_reduce_ofst[] = {
- /* 0 */ 880, -121, 269, 528, 933, -119, -187, -185, -182, -180,
- /* 10 */ -176, -174, -62, -46, 131, -248, -133, 407, 568, 700,
- /* 20 */ 704, 278, 706, 824, 542, 830, 948, 773, 943, 946,
- /* 30 */ 71, 650, 211, 267, 826, 272, 676, 732, 885, 976,
- /* 40 */ 984, 992, -256, -256, -256, -256, -256, -256, -256, -256,
- /* 50 */ -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
- /* 60 */ -256, -256, -256, -256, -256, -256, -256, -256, -256, -256,
- /* 70 */ -256, -256, -256, -256, -256, -256, -256, 989, 1065, 1070,
- /* 80 */ 1072, 1078, 1082, 1084, 1103, 1118, 1147, 1156, 1160, 1167,
- /* 90 */ 1185, 1191, 1220, 1237, 1254, 1256, 1266, 1272, 1281, 1291,
- /* 100 */ 1293, 1296, 1299, 1301, 1307, 1337, 1340, 1342, 1347, 1366,
- /* 110 */ 1368, 1371, 1373, 1377, 1385, 1387, 1398, 1401, 1404, 1406,
- /* 120 */ 1411, 1413, 1415, 1430, -256, -256, -256, -256, -256, -256,
- /* 130 */ -256, -256, -256, -172, 508, -213, 57, -163, -25, 593,
- /* 140 */ 69, 486, 69, 486, -200, 573, 722, -256, -256, -256,
- /* 150 */ -256, -141, -141, -141, -105, -161, -167, 157, 212, 405,
- /* 160 */ 530, 220, 233, 735, 735, 115, 318, 406, 612, 541,
- /* 170 */ -166, 441, 688, 794, 629, 368, 741, 775, 867, 797,
- /* 180 */ 871, 842, -186, 1000, 858, 949, 379, 783, 70, 296,
- /* 190 */ 821, 903, 924, 1044, 651, 282, 1014, 1060, 937, -195,
- /* 200 */ -177, 413, 439, 511, 566, 787, 827, 848, 898, 945,
- /* 210 */ 1062, 1074, 1102, 1110, 1202, 1204, 1209, 1211, 1215, 529,
- /* 220 */ 1221, 1224, 1240, 1246, 1255, 1257, 1269, 1270, 1273, 1274,
- /* 230 */ 1275, 1280, 1205, 1251, 1294, 1310, 1317, 1326, 1327, 1124,
- /* 240 */ 1331, 1338, 1339, 1290, 1181, 1346, 1351, 1265, 1352, 787,
- /* 250 */ 1353, 1367, 1378, 1386, 1392, 1397, 1241, 1312, 1356, 1345,
- /* 260 */ 1357, 1358, 1359, 1124, 1356, 1356, 1364, 1396, 1433, 1341,
- /* 270 */ 1381, 1376, 1379, 1354, 1391, 1405, 1362, 1429, 1423, 1431,
- /* 280 */ 1434, 1435, 1437, 1399, 1410, 1412, 1382, 1417, 1420, 1466,
- /* 290 */ 1372, 1467, 1468, 1380, 1384, 1475, 1394, 1414, 1416, 1448,
- /* 300 */ 1440, 1451, 1452, 1453, 1454, 1490, 1493, 1449, 1455, 1427,
- /* 310 */ 1436, 1464, 1465, 1456, 1498, 1502, 1419, 1421, 1507, 1509,
- /* 320 */ 1491, 1510, 1513, 1514, 1516, 1496, 1500, 1501, 1503, 1499,
- /* 330 */ 1505, 1504, 1508, 1506, 1511, 1512, 1515, 1424, 1517, 1457,
- /* 340 */ 1460, 1519, 1474, 1482, 1483, 1485, 1486, 1488, 1489, 1492,
- /* 350 */ 1541, 1438, 1441, 1494, 1495, 1518, 1520, 1487, 1555, 1481,
- /* 360 */ 1522, 1523, 1526, 1528, 1561, 1566, 1580, 1581, 1586, 1587,
- /* 370 */ 1588, 1478, 1484, 1525, 1575, 1570, 1572, 1573, 1574, 1582,
- /* 380 */ 1568, 1569, 1578, 1579, 1583, 1590,
+ /* 0 */ 490, -122, 545, 645, 650, -120, -189, -187, -184, -182,
+ /* 10 */ -178, -176, 45, 30, 200, -251, -134, 390, 392, 521,
+ /* 20 */ 523, 213, 692, 821, 284, 589, 872, 666, 671, 866,
+ /* 30 */ 71, 111, 273, 389, 686, 815, 904, 932, 948, 955,
+ /* 40 */ 964, 969, -259, -259, -259, -259, -259, -259, -259, -259,
+ /* 50 */ -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+ /* 60 */ -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
+ /* 70 */ -259, -259, -259, -259, -259, -259, -259, -259, 428, 430,
+ /* 80 */ 899, 985, 1021, 1028, 1057, 1069, 1081, 1108, 1110, 1115,
+ /* 90 */ 1117, 1123, 1149, 1154, 1159, 1170, 1174, 1178, 1183, 1194,
+ /* 100 */ 1198, 1204, 1208, 1212, 1218, 1222, 1229, 1278, 1280, 1283,
+ /* 110 */ 1285, 1313, 1316, 1320, 1322, 1325, 1327, 1330, 1366, 1371,
+ /* 120 */ 1379, 1387, 1417, 1425, 1430, 1432, -259, -259, -259, -259,
+ /* 130 */ -259, -259, -259, -259, -259, 557, 974, -214, -174, -9,
+ /* 140 */ 431, -124, 806, 925, 806, 925, 251, 928, 940, -259,
+ /* 150 */ -259, -259, -259, -198, -198, -198, 127, -186, -168, 212,
+ /* 160 */ 646, 617, 799, -262, 555, 220, 220, 491, 605, 1040,
+ /* 170 */ 1060, 699, -11, 600, 848, 862, 345, -129, 724, -91,
+ /* 180 */ 158, 749, 716, 900, 304, 822, 929, 926, 499, 793,
+ /* 190 */ 322, 892, 813, 845, 958, 1056, 751, 905, 1133, 1062,
+ /* 200 */ 803, -210, -185, -179, -148, -167, -89, 121, 274, 281,
+ /* 210 */ 320, 336, 439, 663, 711, 957, 1064, 1068, 1116, 1127,
+ /* 220 */ 1134, -196, 1147, 1180, 1184, 1195, 1203, 1209, 1254, 1263,
+ /* 230 */ 1275, 1288, 1304, 1310, 205, 422, 638, 1319, 1324, 1346,
+ /* 240 */ 1360, 1168, 1364, 1370, 1372, 869, 1189, 1380, 1399, 1276,
+ /* 250 */ 1403, 121, 1405, 1420, 1426, 1427, 1428, 1429, 1249, 1282,
+ /* 260 */ 1344, 1375, 1376, 1377, 1388, 1168, 1344, 1344, 1384, 1411,
+ /* 270 */ 1436, 1349, 1389, 1386, 1391, 1361, 1407, 1408, 1365, 1431,
+ /* 280 */ 1433, 1434, 1439, 1441, 1442, 1396, 1416, 1418, 1390, 1421,
+ /* 290 */ 1437, 1472, 1381, 1478, 1480, 1397, 1400, 1487, 1412, 1444,
+ /* 300 */ 1438, 1463, 1453, 1464, 1465, 1467, 1469, 1514, 1517, 1473,
+ /* 310 */ 1474, 1452, 1449, 1490, 1491, 1475, 1522, 1526, 1443, 1445,
+ /* 320 */ 1528, 1530, 1513, 1534, 1536, 1537, 1539, 1516, 1523, 1524,
+ /* 330 */ 1527, 1519, 1529, 1532, 1540, 1541, 1535, 1542, 1544, 1545,
+ /* 340 */ 1547, 1450, 1543, 1477, 1482, 1551, 1505, 1508, 1512, 1509,
+ /* 350 */ 1515, 1518, 1533, 1552, 1573, 1466, 1468, 1549, 1550, 1555,
+ /* 360 */ 1554, 1510, 1583, 1511, 1556, 1559, 1561, 1565, 1588, 1592,
+ /* 370 */ 1601, 1602, 1607, 1608, 1609, 1498, 1557, 1558, 1610, 1600,
+ /* 380 */ 1603, 1611, 1612, 1613, 1596, 1597, 1614, 1615, 1617, 1616,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 1554, 1554, 1554, 1392, 1171, 1278, 1171, 1171, 1171, 1392,
- /* 10 */ 1392, 1392, 1171, 1308, 1308, 1445, 1202, 1171, 1171, 1171,
- /* 20 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1391, 1171, 1171,
- /* 30 */ 1171, 1171, 1475, 1475, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 40 */ 1171, 1171, 1171, 1317, 1171, 1171, 1171, 1171, 1171, 1393,
- /* 50 */ 1394, 1171, 1171, 1171, 1444, 1446, 1409, 1327, 1326, 1325,
- /* 60 */ 1324, 1427, 1295, 1322, 1315, 1319, 1387, 1388, 1386, 1390,
- /* 70 */ 1394, 1393, 1171, 1318, 1358, 1372, 1357, 1171, 1171, 1171,
- /* 80 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 90 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 100 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 110 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 120 */ 1171, 1171, 1171, 1171, 1366, 1371, 1377, 1370, 1367, 1360,
- /* 130 */ 1359, 1361, 1362, 1171, 1192, 1242, 1171, 1171, 1171, 1171,
- /* 140 */ 1463, 1462, 1171, 1171, 1202, 1352, 1351, 1363, 1364, 1374,
- /* 150 */ 1373, 1452, 1510, 1509, 1410, 1171, 1171, 1171, 1171, 1171,
- /* 160 */ 1171, 1475, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 170 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 180 */ 1171, 1171, 1171, 1171, 1171, 1171, 1475, 1475, 1171, 1202,
- /* 190 */ 1475, 1475, 1198, 1198, 1302, 1171, 1458, 1278, 1269, 1171,
- /* 200 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 210 */ 1171, 1171, 1171, 1449, 1447, 1171, 1171, 1171, 1171, 1171,
- /* 220 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 230 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 240 */ 1171, 1171, 1171, 1274, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 250 */ 1171, 1171, 1171, 1171, 1171, 1504, 1171, 1422, 1256, 1274,
- /* 260 */ 1274, 1274, 1274, 1276, 1257, 1255, 1268, 1203, 1178, 1546,
- /* 270 */ 1321, 1297, 1297, 1543, 1321, 1321, 1543, 1217, 1524, 1214,
- /* 280 */ 1308, 1308, 1308, 1297, 1302, 1302, 1389, 1275, 1268, 1171,
- /* 290 */ 1546, 1283, 1283, 1545, 1545, 1283, 1410, 1330, 1336, 1245,
- /* 300 */ 1321, 1251, 1251, 1251, 1251, 1283, 1189, 1321, 1321, 1330,
- /* 310 */ 1336, 1245, 1245, 1321, 1283, 1189, 1426, 1540, 1283, 1189,
- /* 320 */ 1400, 1283, 1189, 1283, 1189, 1400, 1243, 1243, 1243, 1232,
- /* 330 */ 1400, 1243, 1217, 1243, 1232, 1243, 1243, 1493, 1400, 1404,
- /* 340 */ 1404, 1400, 1301, 1296, 1301, 1296, 1301, 1296, 1301, 1296,
- /* 350 */ 1283, 1485, 1485, 1311, 1311, 1316, 1302, 1395, 1283, 1171,
- /* 360 */ 1316, 1314, 1312, 1321, 1195, 1235, 1507, 1507, 1503, 1503,
- /* 370 */ 1503, 1551, 1551, 1458, 1519, 1202, 1202, 1202, 1202, 1519,
- /* 380 */ 1219, 1219, 1203, 1203, 1202, 1519, 1171, 1171, 1171, 1171,
- /* 390 */ 1171, 1171, 1514, 1171, 1411, 1287, 1171, 1171, 1171, 1171,
- /* 400 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 410 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1341,
- /* 420 */ 1171, 1174, 1455, 1171, 1171, 1453, 1171, 1171, 1171, 1171,
- /* 430 */ 1171, 1171, 1288, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 440 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 450 */ 1171, 1542, 1171, 1171, 1171, 1171, 1171, 1171, 1425, 1424,
- /* 460 */ 1171, 1171, 1285, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 470 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 480 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 490 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 500 */ 1313, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 510 */ 1171, 1171, 1171, 1171, 1171, 1490, 1303, 1171, 1171, 1533,
- /* 520 */ 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171, 1171,
- /* 530 */ 1171, 1171, 1171, 1171, 1528, 1259, 1343, 1171, 1342, 1346,
- /* 540 */ 1171, 1183, 1171,
+ /* 0 */ 1573, 1573, 1573, 1409, 1186, 1295, 1186, 1186, 1186, 1409,
+ /* 10 */ 1409, 1409, 1186, 1325, 1325, 1462, 1217, 1186, 1186, 1186,
+ /* 20 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1408, 1186, 1186,
+ /* 30 */ 1186, 1186, 1492, 1492, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 40 */ 1186, 1186, 1186, 1334, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 50 */ 1410, 1411, 1186, 1186, 1186, 1461, 1463, 1426, 1344, 1343,
+ /* 60 */ 1342, 1341, 1444, 1312, 1339, 1332, 1336, 1404, 1405, 1403,
+ /* 70 */ 1407, 1411, 1410, 1186, 1335, 1375, 1389, 1374, 1186, 1186,
+ /* 80 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 90 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 100 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 110 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 120 */ 1186, 1186, 1186, 1186, 1186, 1186, 1383, 1388, 1394, 1387,
+ /* 130 */ 1384, 1377, 1376, 1378, 1379, 1186, 1207, 1259, 1186, 1186,
+ /* 140 */ 1186, 1186, 1480, 1479, 1186, 1186, 1217, 1369, 1368, 1380,
+ /* 150 */ 1381, 1391, 1390, 1469, 1527, 1526, 1427, 1186, 1186, 1186,
+ /* 160 */ 1186, 1186, 1186, 1492, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 170 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 180 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1492, 1492,
+ /* 190 */ 1186, 1217, 1492, 1492, 1213, 1213, 1319, 1186, 1475, 1295,
+ /* 200 */ 1286, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 210 */ 1186, 1186, 1186, 1186, 1186, 1466, 1464, 1186, 1186, 1186,
+ /* 220 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 230 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 240 */ 1186, 1186, 1186, 1186, 1186, 1291, 1186, 1186, 1186, 1186,
+ /* 250 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1521, 1186, 1439,
+ /* 260 */ 1273, 1291, 1291, 1291, 1291, 1293, 1274, 1272, 1285, 1218,
+ /* 270 */ 1193, 1565, 1338, 1314, 1314, 1562, 1338, 1338, 1562, 1234,
+ /* 280 */ 1543, 1229, 1325, 1325, 1325, 1314, 1319, 1319, 1406, 1292,
+ /* 290 */ 1285, 1186, 1565, 1300, 1300, 1564, 1564, 1300, 1427, 1347,
+ /* 300 */ 1353, 1262, 1338, 1268, 1268, 1268, 1268, 1300, 1204, 1338,
+ /* 310 */ 1338, 1347, 1353, 1262, 1262, 1338, 1300, 1204, 1443, 1559,
+ /* 320 */ 1300, 1204, 1417, 1300, 1204, 1300, 1204, 1417, 1260, 1260,
+ /* 330 */ 1260, 1249, 1186, 1186, 1417, 1260, 1234, 1260, 1249, 1260,
+ /* 340 */ 1260, 1510, 1417, 1421, 1421, 1417, 1318, 1313, 1318, 1313,
+ /* 350 */ 1318, 1313, 1318, 1313, 1300, 1502, 1502, 1328, 1328, 1333,
+ /* 360 */ 1319, 1412, 1300, 1186, 1333, 1331, 1329, 1338, 1210, 1252,
+ /* 370 */ 1524, 1524, 1520, 1520, 1520, 1570, 1570, 1475, 1536, 1217,
+ /* 380 */ 1217, 1217, 1217, 1536, 1236, 1236, 1218, 1218, 1217, 1536,
+ /* 390 */ 1186, 1186, 1186, 1186, 1186, 1186, 1531, 1186, 1428, 1304,
+ /* 400 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 410 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 420 */ 1186, 1186, 1186, 1358, 1186, 1189, 1472, 1186, 1186, 1470,
+ /* 430 */ 1186, 1186, 1186, 1186, 1186, 1186, 1305, 1186, 1186, 1186,
+ /* 440 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 450 */ 1186, 1186, 1186, 1186, 1186, 1561, 1186, 1186, 1186, 1186,
+ /* 460 */ 1186, 1186, 1442, 1441, 1186, 1186, 1302, 1186, 1186, 1186,
+ /* 470 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 480 */ 1232, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 490 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 500 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1330, 1186, 1186,
+ /* 510 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 520 */ 1186, 1186, 1507, 1320, 1186, 1186, 1552, 1186, 1186, 1186,
+ /* 530 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
+ /* 540 */ 1186, 1547, 1276, 1360, 1186, 1359, 1363, 1186, 1198, 1186,
+ /* 550 */ 1186,
};
/********** End of lemon-generated parsing tables *****************************/
@@ -150742,6 +153359,8 @@ static const YYCODETYPE yyFallback[] = {
59, /* GROUPS => ID */
59, /* OTHERS => ID */
59, /* TIES => ID */
+ 59, /* GENERATED => ID */
+ 59, /* ALWAYS => ID */
59, /* REINDEX => ID */
59, /* RENAME => ID */
59, /* CTIME_KW => ID */
@@ -151008,218 +153627,221 @@ static const char *const yyTokenName[] = {
/* 92 */ "GROUPS",
/* 93 */ "OTHERS",
/* 94 */ "TIES",
- /* 95 */ "REINDEX",
- /* 96 */ "RENAME",
- /* 97 */ "CTIME_KW",
- /* 98 */ "ANY",
- /* 99 */ "BITAND",
- /* 100 */ "BITOR",
- /* 101 */ "LSHIFT",
- /* 102 */ "RSHIFT",
- /* 103 */ "PLUS",
- /* 104 */ "MINUS",
- /* 105 */ "STAR",
- /* 106 */ "SLASH",
- /* 107 */ "REM",
- /* 108 */ "CONCAT",
- /* 109 */ "COLLATE",
- /* 110 */ "BITNOT",
- /* 111 */ "ON",
- /* 112 */ "INDEXED",
- /* 113 */ "STRING",
- /* 114 */ "JOIN_KW",
- /* 115 */ "CONSTRAINT",
- /* 116 */ "DEFAULT",
- /* 117 */ "NULL",
- /* 118 */ "PRIMARY",
- /* 119 */ "UNIQUE",
- /* 120 */ "CHECK",
- /* 121 */ "REFERENCES",
- /* 122 */ "AUTOINCR",
- /* 123 */ "INSERT",
- /* 124 */ "DELETE",
- /* 125 */ "UPDATE",
- /* 126 */ "SET",
- /* 127 */ "DEFERRABLE",
- /* 128 */ "FOREIGN",
- /* 129 */ "DROP",
- /* 130 */ "UNION",
- /* 131 */ "ALL",
- /* 132 */ "EXCEPT",
- /* 133 */ "INTERSECT",
- /* 134 */ "SELECT",
- /* 135 */ "VALUES",
- /* 136 */ "DISTINCT",
- /* 137 */ "DOT",
- /* 138 */ "FROM",
- /* 139 */ "JOIN",
- /* 140 */ "USING",
- /* 141 */ "ORDER",
- /* 142 */ "GROUP",
- /* 143 */ "HAVING",
- /* 144 */ "LIMIT",
- /* 145 */ "WHERE",
- /* 146 */ "INTO",
- /* 147 */ "NOTHING",
- /* 148 */ "FLOAT",
- /* 149 */ "BLOB",
- /* 150 */ "INTEGER",
- /* 151 */ "VARIABLE",
- /* 152 */ "CASE",
- /* 153 */ "WHEN",
- /* 154 */ "THEN",
- /* 155 */ "ELSE",
- /* 156 */ "INDEX",
- /* 157 */ "ALTER",
- /* 158 */ "ADD",
- /* 159 */ "WINDOW",
- /* 160 */ "OVER",
- /* 161 */ "FILTER",
- /* 162 */ "COLUMN",
- /* 163 */ "AGG_FUNCTION",
- /* 164 */ "AGG_COLUMN",
- /* 165 */ "TRUEFALSE",
- /* 166 */ "ISNOT",
- /* 167 */ "FUNCTION",
- /* 168 */ "UMINUS",
- /* 169 */ "UPLUS",
- /* 170 */ "TRUTH",
- /* 171 */ "REGISTER",
- /* 172 */ "VECTOR",
- /* 173 */ "SELECT_COLUMN",
- /* 174 */ "IF_NULL_ROW",
- /* 175 */ "ASTERISK",
- /* 176 */ "SPAN",
- /* 177 */ "SPACE",
- /* 178 */ "ILLEGAL",
- /* 179 */ "input",
- /* 180 */ "cmdlist",
- /* 181 */ "ecmd",
- /* 182 */ "cmdx",
- /* 183 */ "explain",
- /* 184 */ "cmd",
- /* 185 */ "transtype",
- /* 186 */ "trans_opt",
- /* 187 */ "nm",
- /* 188 */ "savepoint_opt",
- /* 189 */ "create_table",
- /* 190 */ "create_table_args",
- /* 191 */ "createkw",
- /* 192 */ "temp",
- /* 193 */ "ifnotexists",
- /* 194 */ "dbnm",
- /* 195 */ "columnlist",
- /* 196 */ "conslist_opt",
- /* 197 */ "table_options",
- /* 198 */ "select",
- /* 199 */ "columnname",
- /* 200 */ "carglist",
- /* 201 */ "typetoken",
- /* 202 */ "typename",
- /* 203 */ "signed",
- /* 204 */ "plus_num",
- /* 205 */ "minus_num",
- /* 206 */ "scanpt",
- /* 207 */ "scantok",
- /* 208 */ "ccons",
- /* 209 */ "term",
- /* 210 */ "expr",
- /* 211 */ "onconf",
- /* 212 */ "sortorder",
- /* 213 */ "autoinc",
- /* 214 */ "eidlist_opt",
- /* 215 */ "refargs",
- /* 216 */ "defer_subclause",
- /* 217 */ "refarg",
- /* 218 */ "refact",
- /* 219 */ "init_deferred_pred_opt",
- /* 220 */ "conslist",
- /* 221 */ "tconscomma",
- /* 222 */ "tcons",
- /* 223 */ "sortlist",
- /* 224 */ "eidlist",
- /* 225 */ "defer_subclause_opt",
- /* 226 */ "orconf",
- /* 227 */ "resolvetype",
- /* 228 */ "raisetype",
- /* 229 */ "ifexists",
- /* 230 */ "fullname",
- /* 231 */ "selectnowith",
- /* 232 */ "oneselect",
- /* 233 */ "wqlist",
- /* 234 */ "multiselect_op",
- /* 235 */ "distinct",
- /* 236 */ "selcollist",
- /* 237 */ "from",
- /* 238 */ "where_opt",
- /* 239 */ "groupby_opt",
- /* 240 */ "having_opt",
- /* 241 */ "orderby_opt",
- /* 242 */ "limit_opt",
- /* 243 */ "window_clause",
- /* 244 */ "values",
- /* 245 */ "nexprlist",
- /* 246 */ "sclp",
- /* 247 */ "as",
- /* 248 */ "seltablist",
- /* 249 */ "stl_prefix",
- /* 250 */ "joinop",
- /* 251 */ "indexed_opt",
- /* 252 */ "on_opt",
- /* 253 */ "using_opt",
- /* 254 */ "exprlist",
- /* 255 */ "xfullname",
- /* 256 */ "idlist",
- /* 257 */ "nulls",
- /* 258 */ "with",
- /* 259 */ "setlist",
- /* 260 */ "insert_cmd",
- /* 261 */ "idlist_opt",
- /* 262 */ "upsert",
- /* 263 */ "filter_over",
- /* 264 */ "likeop",
- /* 265 */ "between_op",
- /* 266 */ "in_op",
- /* 267 */ "paren_exprlist",
- /* 268 */ "case_operand",
- /* 269 */ "case_exprlist",
- /* 270 */ "case_else",
- /* 271 */ "uniqueflag",
- /* 272 */ "collate",
- /* 273 */ "vinto",
- /* 274 */ "nmnum",
- /* 275 */ "trigger_decl",
- /* 276 */ "trigger_cmd_list",
- /* 277 */ "trigger_time",
- /* 278 */ "trigger_event",
- /* 279 */ "foreach_clause",
- /* 280 */ "when_clause",
- /* 281 */ "trigger_cmd",
- /* 282 */ "trnm",
- /* 283 */ "tridxby",
- /* 284 */ "database_kw_opt",
- /* 285 */ "key_opt",
- /* 286 */ "add_column_fullname",
- /* 287 */ "kwcolumn_opt",
- /* 288 */ "create_vtab",
- /* 289 */ "vtabarglist",
- /* 290 */ "vtabarg",
- /* 291 */ "vtabargtoken",
- /* 292 */ "lp",
- /* 293 */ "anylist",
- /* 294 */ "windowdefn_list",
- /* 295 */ "windowdefn",
- /* 296 */ "window",
- /* 297 */ "frame_opt",
- /* 298 */ "part_opt",
- /* 299 */ "filter_clause",
- /* 300 */ "over_clause",
- /* 301 */ "range_or_rows",
- /* 302 */ "frame_bound",
- /* 303 */ "frame_bound_s",
- /* 304 */ "frame_bound_e",
- /* 305 */ "frame_exclude_opt",
- /* 306 */ "frame_exclude",
+ /* 95 */ "GENERATED",
+ /* 96 */ "ALWAYS",
+ /* 97 */ "REINDEX",
+ /* 98 */ "RENAME",
+ /* 99 */ "CTIME_KW",
+ /* 100 */ "ANY",
+ /* 101 */ "BITAND",
+ /* 102 */ "BITOR",
+ /* 103 */ "LSHIFT",
+ /* 104 */ "RSHIFT",
+ /* 105 */ "PLUS",
+ /* 106 */ "MINUS",
+ /* 107 */ "STAR",
+ /* 108 */ "SLASH",
+ /* 109 */ "REM",
+ /* 110 */ "CONCAT",
+ /* 111 */ "COLLATE",
+ /* 112 */ "BITNOT",
+ /* 113 */ "ON",
+ /* 114 */ "INDEXED",
+ /* 115 */ "STRING",
+ /* 116 */ "JOIN_KW",
+ /* 117 */ "CONSTRAINT",
+ /* 118 */ "DEFAULT",
+ /* 119 */ "NULL",
+ /* 120 */ "PRIMARY",
+ /* 121 */ "UNIQUE",
+ /* 122 */ "CHECK",
+ /* 123 */ "REFERENCES",
+ /* 124 */ "AUTOINCR",
+ /* 125 */ "INSERT",
+ /* 126 */ "DELETE",
+ /* 127 */ "UPDATE",
+ /* 128 */ "SET",
+ /* 129 */ "DEFERRABLE",
+ /* 130 */ "FOREIGN",
+ /* 131 */ "DROP",
+ /* 132 */ "UNION",
+ /* 133 */ "ALL",
+ /* 134 */ "EXCEPT",
+ /* 135 */ "INTERSECT",
+ /* 136 */ "SELECT",
+ /* 137 */ "VALUES",
+ /* 138 */ "DISTINCT",
+ /* 139 */ "DOT",
+ /* 140 */ "FROM",
+ /* 141 */ "JOIN",
+ /* 142 */ "USING",
+ /* 143 */ "ORDER",
+ /* 144 */ "GROUP",
+ /* 145 */ "HAVING",
+ /* 146 */ "LIMIT",
+ /* 147 */ "WHERE",
+ /* 148 */ "INTO",
+ /* 149 */ "NOTHING",
+ /* 150 */ "FLOAT",
+ /* 151 */ "BLOB",
+ /* 152 */ "INTEGER",
+ /* 153 */ "VARIABLE",
+ /* 154 */ "CASE",
+ /* 155 */ "WHEN",
+ /* 156 */ "THEN",
+ /* 157 */ "ELSE",
+ /* 158 */ "INDEX",
+ /* 159 */ "ALTER",
+ /* 160 */ "ADD",
+ /* 161 */ "WINDOW",
+ /* 162 */ "OVER",
+ /* 163 */ "FILTER",
+ /* 164 */ "COLUMN",
+ /* 165 */ "AGG_FUNCTION",
+ /* 166 */ "AGG_COLUMN",
+ /* 167 */ "TRUEFALSE",
+ /* 168 */ "ISNOT",
+ /* 169 */ "FUNCTION",
+ /* 170 */ "UMINUS",
+ /* 171 */ "UPLUS",
+ /* 172 */ "TRUTH",
+ /* 173 */ "REGISTER",
+ /* 174 */ "VECTOR",
+ /* 175 */ "SELECT_COLUMN",
+ /* 176 */ "IF_NULL_ROW",
+ /* 177 */ "ASTERISK",
+ /* 178 */ "SPAN",
+ /* 179 */ "SPACE",
+ /* 180 */ "ILLEGAL",
+ /* 181 */ "input",
+ /* 182 */ "cmdlist",
+ /* 183 */ "ecmd",
+ /* 184 */ "cmdx",
+ /* 185 */ "explain",
+ /* 186 */ "cmd",
+ /* 187 */ "transtype",
+ /* 188 */ "trans_opt",
+ /* 189 */ "nm",
+ /* 190 */ "savepoint_opt",
+ /* 191 */ "create_table",
+ /* 192 */ "create_table_args",
+ /* 193 */ "createkw",
+ /* 194 */ "temp",
+ /* 195 */ "ifnotexists",
+ /* 196 */ "dbnm",
+ /* 197 */ "columnlist",
+ /* 198 */ "conslist_opt",
+ /* 199 */ "table_options",
+ /* 200 */ "select",
+ /* 201 */ "columnname",
+ /* 202 */ "carglist",
+ /* 203 */ "typetoken",
+ /* 204 */ "typename",
+ /* 205 */ "signed",
+ /* 206 */ "plus_num",
+ /* 207 */ "minus_num",
+ /* 208 */ "scanpt",
+ /* 209 */ "scantok",
+ /* 210 */ "ccons",
+ /* 211 */ "term",
+ /* 212 */ "expr",
+ /* 213 */ "onconf",
+ /* 214 */ "sortorder",
+ /* 215 */ "autoinc",
+ /* 216 */ "eidlist_opt",
+ /* 217 */ "refargs",
+ /* 218 */ "defer_subclause",
+ /* 219 */ "generated",
+ /* 220 */ "refarg",
+ /* 221 */ "refact",
+ /* 222 */ "init_deferred_pred_opt",
+ /* 223 */ "conslist",
+ /* 224 */ "tconscomma",
+ /* 225 */ "tcons",
+ /* 226 */ "sortlist",
+ /* 227 */ "eidlist",
+ /* 228 */ "defer_subclause_opt",
+ /* 229 */ "orconf",
+ /* 230 */ "resolvetype",
+ /* 231 */ "raisetype",
+ /* 232 */ "ifexists",
+ /* 233 */ "fullname",
+ /* 234 */ "selectnowith",
+ /* 235 */ "oneselect",
+ /* 236 */ "wqlist",
+ /* 237 */ "multiselect_op",
+ /* 238 */ "distinct",
+ /* 239 */ "selcollist",
+ /* 240 */ "from",
+ /* 241 */ "where_opt",
+ /* 242 */ "groupby_opt",
+ /* 243 */ "having_opt",
+ /* 244 */ "orderby_opt",
+ /* 245 */ "limit_opt",
+ /* 246 */ "window_clause",
+ /* 247 */ "values",
+ /* 248 */ "nexprlist",
+ /* 249 */ "sclp",
+ /* 250 */ "as",
+ /* 251 */ "seltablist",
+ /* 252 */ "stl_prefix",
+ /* 253 */ "joinop",
+ /* 254 */ "indexed_opt",
+ /* 255 */ "on_opt",
+ /* 256 */ "using_opt",
+ /* 257 */ "exprlist",
+ /* 258 */ "xfullname",
+ /* 259 */ "idlist",
+ /* 260 */ "nulls",
+ /* 261 */ "with",
+ /* 262 */ "setlist",
+ /* 263 */ "insert_cmd",
+ /* 264 */ "idlist_opt",
+ /* 265 */ "upsert",
+ /* 266 */ "filter_over",
+ /* 267 */ "likeop",
+ /* 268 */ "between_op",
+ /* 269 */ "in_op",
+ /* 270 */ "paren_exprlist",
+ /* 271 */ "case_operand",
+ /* 272 */ "case_exprlist",
+ /* 273 */ "case_else",
+ /* 274 */ "uniqueflag",
+ /* 275 */ "collate",
+ /* 276 */ "vinto",
+ /* 277 */ "nmnum",
+ /* 278 */ "trigger_decl",
+ /* 279 */ "trigger_cmd_list",
+ /* 280 */ "trigger_time",
+ /* 281 */ "trigger_event",
+ /* 282 */ "foreach_clause",
+ /* 283 */ "when_clause",
+ /* 284 */ "trigger_cmd",
+ /* 285 */ "trnm",
+ /* 286 */ "tridxby",
+ /* 287 */ "database_kw_opt",
+ /* 288 */ "key_opt",
+ /* 289 */ "add_column_fullname",
+ /* 290 */ "kwcolumn_opt",
+ /* 291 */ "create_vtab",
+ /* 292 */ "vtabarglist",
+ /* 293 */ "vtabarg",
+ /* 294 */ "vtabargtoken",
+ /* 295 */ "lp",
+ /* 296 */ "anylist",
+ /* 297 */ "windowdefn_list",
+ /* 298 */ "windowdefn",
+ /* 299 */ "window",
+ /* 300 */ "frame_opt",
+ /* 301 */ "part_opt",
+ /* 302 */ "filter_clause",
+ /* 303 */ "over_clause",
+ /* 304 */ "range_or_rows",
+ /* 305 */ "frame_bound",
+ /* 306 */ "frame_bound_s",
+ /* 307 */ "frame_bound_e",
+ /* 308 */ "frame_exclude_opt",
+ /* 309 */ "frame_exclude",
};
#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
@@ -151270,344 +153892,348 @@ static const char *const yyRuleName[] = {
/* 40 */ "ccons ::= REFERENCES nm eidlist_opt refargs",
/* 41 */ "ccons ::= defer_subclause",
/* 42 */ "ccons ::= COLLATE ID|STRING",
- /* 43 */ "autoinc ::=",
- /* 44 */ "autoinc ::= AUTOINCR",
- /* 45 */ "refargs ::=",
- /* 46 */ "refargs ::= refargs refarg",
- /* 47 */ "refarg ::= MATCH nm",
- /* 48 */ "refarg ::= ON INSERT refact",
- /* 49 */ "refarg ::= ON DELETE refact",
- /* 50 */ "refarg ::= ON UPDATE refact",
- /* 51 */ "refact ::= SET NULL",
- /* 52 */ "refact ::= SET DEFAULT",
- /* 53 */ "refact ::= CASCADE",
- /* 54 */ "refact ::= RESTRICT",
- /* 55 */ "refact ::= NO ACTION",
- /* 56 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
- /* 57 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
- /* 58 */ "init_deferred_pred_opt ::=",
- /* 59 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
- /* 60 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
- /* 61 */ "conslist_opt ::=",
- /* 62 */ "tconscomma ::= COMMA",
- /* 63 */ "tcons ::= CONSTRAINT nm",
- /* 64 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf",
- /* 65 */ "tcons ::= UNIQUE LP sortlist RP onconf",
- /* 66 */ "tcons ::= CHECK LP expr RP onconf",
- /* 67 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt",
- /* 68 */ "defer_subclause_opt ::=",
- /* 69 */ "onconf ::=",
- /* 70 */ "onconf ::= ON CONFLICT resolvetype",
- /* 71 */ "orconf ::=",
- /* 72 */ "orconf ::= OR resolvetype",
- /* 73 */ "resolvetype ::= IGNORE",
- /* 74 */ "resolvetype ::= REPLACE",
- /* 75 */ "cmd ::= DROP TABLE ifexists fullname",
- /* 76 */ "ifexists ::= IF EXISTS",
- /* 77 */ "ifexists ::=",
- /* 78 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select",
- /* 79 */ "cmd ::= DROP VIEW ifexists fullname",
- /* 80 */ "cmd ::= select",
- /* 81 */ "select ::= WITH wqlist selectnowith",
- /* 82 */ "select ::= WITH RECURSIVE wqlist selectnowith",
- /* 83 */ "select ::= selectnowith",
- /* 84 */ "selectnowith ::= selectnowith multiselect_op oneselect",
- /* 85 */ "multiselect_op ::= UNION",
- /* 86 */ "multiselect_op ::= UNION ALL",
- /* 87 */ "multiselect_op ::= EXCEPT|INTERSECT",
- /* 88 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
- /* 89 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt",
- /* 90 */ "values ::= VALUES LP nexprlist RP",
- /* 91 */ "values ::= values COMMA LP nexprlist RP",
- /* 92 */ "distinct ::= DISTINCT",
- /* 93 */ "distinct ::= ALL",
- /* 94 */ "distinct ::=",
- /* 95 */ "sclp ::=",
- /* 96 */ "selcollist ::= sclp scanpt expr scanpt as",
- /* 97 */ "selcollist ::= sclp scanpt STAR",
- /* 98 */ "selcollist ::= sclp scanpt nm DOT STAR",
- /* 99 */ "as ::= AS nm",
- /* 100 */ "as ::=",
- /* 101 */ "from ::=",
- /* 102 */ "from ::= FROM seltablist",
- /* 103 */ "stl_prefix ::= seltablist joinop",
- /* 104 */ "stl_prefix ::=",
- /* 105 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
- /* 106 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt",
- /* 107 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
- /* 108 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
- /* 109 */ "dbnm ::=",
- /* 110 */ "dbnm ::= DOT nm",
- /* 111 */ "fullname ::= nm",
- /* 112 */ "fullname ::= nm DOT nm",
- /* 113 */ "xfullname ::= nm",
- /* 114 */ "xfullname ::= nm DOT nm",
- /* 115 */ "xfullname ::= nm DOT nm AS nm",
- /* 116 */ "xfullname ::= nm AS nm",
- /* 117 */ "joinop ::= COMMA|JOIN",
- /* 118 */ "joinop ::= JOIN_KW JOIN",
- /* 119 */ "joinop ::= JOIN_KW nm JOIN",
- /* 120 */ "joinop ::= JOIN_KW nm nm JOIN",
- /* 121 */ "on_opt ::= ON expr",
- /* 122 */ "on_opt ::=",
- /* 123 */ "indexed_opt ::=",
- /* 124 */ "indexed_opt ::= INDEXED BY nm",
- /* 125 */ "indexed_opt ::= NOT INDEXED",
- /* 126 */ "using_opt ::= USING LP idlist RP",
- /* 127 */ "using_opt ::=",
- /* 128 */ "orderby_opt ::=",
- /* 129 */ "orderby_opt ::= ORDER BY sortlist",
- /* 130 */ "sortlist ::= sortlist COMMA expr sortorder nulls",
- /* 131 */ "sortlist ::= expr sortorder nulls",
- /* 132 */ "sortorder ::= ASC",
- /* 133 */ "sortorder ::= DESC",
- /* 134 */ "sortorder ::=",
- /* 135 */ "nulls ::= NULLS FIRST",
- /* 136 */ "nulls ::= NULLS LAST",
- /* 137 */ "nulls ::=",
- /* 138 */ "groupby_opt ::=",
- /* 139 */ "groupby_opt ::= GROUP BY nexprlist",
- /* 140 */ "having_opt ::=",
- /* 141 */ "having_opt ::= HAVING expr",
- /* 142 */ "limit_opt ::=",
- /* 143 */ "limit_opt ::= LIMIT expr",
- /* 144 */ "limit_opt ::= LIMIT expr OFFSET expr",
- /* 145 */ "limit_opt ::= LIMIT expr COMMA expr",
- /* 146 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt",
- /* 147 */ "where_opt ::=",
- /* 148 */ "where_opt ::= WHERE expr",
- /* 149 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt",
- /* 150 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 151 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
- /* 152 */ "setlist ::= nm EQ expr",
- /* 153 */ "setlist ::= LP idlist RP EQ expr",
- /* 154 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert",
- /* 155 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES",
- /* 156 */ "upsert ::=",
- /* 157 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt",
- /* 158 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING",
- /* 159 */ "upsert ::= ON CONFLICT DO NOTHING",
- /* 160 */ "insert_cmd ::= INSERT orconf",
- /* 161 */ "insert_cmd ::= REPLACE",
- /* 162 */ "idlist_opt ::=",
- /* 163 */ "idlist_opt ::= LP idlist RP",
- /* 164 */ "idlist ::= idlist COMMA nm",
- /* 165 */ "idlist ::= nm",
- /* 166 */ "expr ::= LP expr RP",
- /* 167 */ "expr ::= ID|INDEXED",
- /* 168 */ "expr ::= JOIN_KW",
- /* 169 */ "expr ::= nm DOT nm",
- /* 170 */ "expr ::= nm DOT nm DOT nm",
- /* 171 */ "term ::= NULL|FLOAT|BLOB",
- /* 172 */ "term ::= STRING",
- /* 173 */ "term ::= INTEGER",
- /* 174 */ "expr ::= VARIABLE",
- /* 175 */ "expr ::= expr COLLATE ID|STRING",
- /* 176 */ "expr ::= CAST LP expr AS typetoken RP",
- /* 177 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
- /* 178 */ "expr ::= ID|INDEXED LP STAR RP",
- /* 179 */ "expr ::= ID|INDEXED LP distinct exprlist RP filter_over",
- /* 180 */ "expr ::= ID|INDEXED LP STAR RP filter_over",
- /* 181 */ "term ::= CTIME_KW",
- /* 182 */ "expr ::= LP nexprlist COMMA expr RP",
- /* 183 */ "expr ::= expr AND expr",
- /* 184 */ "expr ::= expr OR expr",
- /* 185 */ "expr ::= expr LT|GT|GE|LE expr",
- /* 186 */ "expr ::= expr EQ|NE expr",
- /* 187 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
- /* 188 */ "expr ::= expr PLUS|MINUS expr",
- /* 189 */ "expr ::= expr STAR|SLASH|REM expr",
- /* 190 */ "expr ::= expr CONCAT expr",
- /* 191 */ "likeop ::= NOT LIKE_KW|MATCH",
- /* 192 */ "expr ::= expr likeop expr",
- /* 193 */ "expr ::= expr likeop expr ESCAPE expr",
- /* 194 */ "expr ::= expr ISNULL|NOTNULL",
- /* 195 */ "expr ::= expr NOT NULL",
- /* 196 */ "expr ::= expr IS expr",
- /* 197 */ "expr ::= expr IS NOT expr",
- /* 198 */ "expr ::= NOT expr",
- /* 199 */ "expr ::= BITNOT expr",
- /* 200 */ "expr ::= PLUS|MINUS expr",
- /* 201 */ "between_op ::= BETWEEN",
- /* 202 */ "between_op ::= NOT BETWEEN",
- /* 203 */ "expr ::= expr between_op expr AND expr",
- /* 204 */ "in_op ::= IN",
- /* 205 */ "in_op ::= NOT IN",
- /* 206 */ "expr ::= expr in_op LP exprlist RP",
- /* 207 */ "expr ::= LP select RP",
- /* 208 */ "expr ::= expr in_op LP select RP",
- /* 209 */ "expr ::= expr in_op nm dbnm paren_exprlist",
- /* 210 */ "expr ::= EXISTS LP select RP",
- /* 211 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 212 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 213 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 214 */ "case_else ::= ELSE expr",
- /* 215 */ "case_else ::=",
- /* 216 */ "case_operand ::= expr",
- /* 217 */ "case_operand ::=",
- /* 218 */ "exprlist ::=",
- /* 219 */ "nexprlist ::= nexprlist COMMA expr",
- /* 220 */ "nexprlist ::= expr",
- /* 221 */ "paren_exprlist ::=",
- /* 222 */ "paren_exprlist ::= LP exprlist RP",
- /* 223 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
- /* 224 */ "uniqueflag ::= UNIQUE",
- /* 225 */ "uniqueflag ::=",
- /* 226 */ "eidlist_opt ::=",
- /* 227 */ "eidlist_opt ::= LP eidlist RP",
- /* 228 */ "eidlist ::= eidlist COMMA nm collate sortorder",
- /* 229 */ "eidlist ::= nm collate sortorder",
- /* 230 */ "collate ::=",
- /* 231 */ "collate ::= COLLATE ID|STRING",
- /* 232 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 233 */ "cmd ::= VACUUM vinto",
- /* 234 */ "cmd ::= VACUUM nm vinto",
- /* 235 */ "vinto ::= INTO expr",
- /* 236 */ "vinto ::=",
- /* 237 */ "cmd ::= PRAGMA nm dbnm",
- /* 238 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
- /* 239 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
- /* 240 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 241 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
- /* 242 */ "plus_num ::= PLUS INTEGER|FLOAT",
- /* 243 */ "minus_num ::= MINUS INTEGER|FLOAT",
- /* 244 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
- /* 245 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 246 */ "trigger_time ::= BEFORE|AFTER",
- /* 247 */ "trigger_time ::= INSTEAD OF",
- /* 248 */ "trigger_time ::=",
- /* 249 */ "trigger_event ::= DELETE|INSERT",
- /* 250 */ "trigger_event ::= UPDATE",
- /* 251 */ "trigger_event ::= UPDATE OF idlist",
- /* 252 */ "when_clause ::=",
- /* 253 */ "when_clause ::= WHEN expr",
- /* 254 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 255 */ "trigger_cmd_list ::= trigger_cmd SEMI",
- /* 256 */ "trnm ::= nm DOT nm",
- /* 257 */ "tridxby ::= INDEXED BY nm",
- /* 258 */ "tridxby ::= NOT INDEXED",
- /* 259 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt",
- /* 260 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
- /* 261 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
- /* 262 */ "trigger_cmd ::= scanpt select scanpt",
- /* 263 */ "expr ::= RAISE LP IGNORE RP",
- /* 264 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 265 */ "raisetype ::= ROLLBACK",
- /* 266 */ "raisetype ::= ABORT",
- /* 267 */ "raisetype ::= FAIL",
- /* 268 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 269 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 270 */ "cmd ::= DETACH database_kw_opt expr",
- /* 271 */ "key_opt ::=",
- /* 272 */ "key_opt ::= KEY expr",
- /* 273 */ "cmd ::= REINDEX",
- /* 274 */ "cmd ::= REINDEX nm dbnm",
- /* 275 */ "cmd ::= ANALYZE",
- /* 276 */ "cmd ::= ANALYZE nm dbnm",
- /* 277 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 278 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
- /* 279 */ "add_column_fullname ::= fullname",
- /* 280 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm",
- /* 281 */ "cmd ::= create_vtab",
- /* 282 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 283 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
- /* 284 */ "vtabarg ::=",
- /* 285 */ "vtabargtoken ::= ANY",
- /* 286 */ "vtabargtoken ::= lp anylist RP",
- /* 287 */ "lp ::= LP",
- /* 288 */ "with ::= WITH wqlist",
- /* 289 */ "with ::= WITH RECURSIVE wqlist",
- /* 290 */ "wqlist ::= nm eidlist_opt AS LP select RP",
- /* 291 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP",
- /* 292 */ "windowdefn_list ::= windowdefn",
- /* 293 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn",
- /* 294 */ "windowdefn ::= nm AS LP window RP",
- /* 295 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt",
- /* 296 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt",
- /* 297 */ "window ::= ORDER BY sortlist frame_opt",
- /* 298 */ "window ::= nm ORDER BY sortlist frame_opt",
- /* 299 */ "window ::= frame_opt",
- /* 300 */ "window ::= nm frame_opt",
- /* 301 */ "frame_opt ::=",
- /* 302 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt",
- /* 303 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt",
- /* 304 */ "range_or_rows ::= RANGE|ROWS|GROUPS",
- /* 305 */ "frame_bound_s ::= frame_bound",
- /* 306 */ "frame_bound_s ::= UNBOUNDED PRECEDING",
- /* 307 */ "frame_bound_e ::= frame_bound",
- /* 308 */ "frame_bound_e ::= UNBOUNDED FOLLOWING",
- /* 309 */ "frame_bound ::= expr PRECEDING|FOLLOWING",
- /* 310 */ "frame_bound ::= CURRENT ROW",
- /* 311 */ "frame_exclude_opt ::=",
- /* 312 */ "frame_exclude_opt ::= EXCLUDE frame_exclude",
- /* 313 */ "frame_exclude ::= NO OTHERS",
- /* 314 */ "frame_exclude ::= CURRENT ROW",
- /* 315 */ "frame_exclude ::= GROUP|TIES",
- /* 316 */ "window_clause ::= WINDOW windowdefn_list",
- /* 317 */ "filter_over ::= filter_clause over_clause",
- /* 318 */ "filter_over ::= over_clause",
- /* 319 */ "filter_over ::= filter_clause",
- /* 320 */ "over_clause ::= OVER LP window RP",
- /* 321 */ "over_clause ::= OVER nm",
- /* 322 */ "filter_clause ::= FILTER LP WHERE expr RP",
- /* 323 */ "input ::= cmdlist",
- /* 324 */ "cmdlist ::= cmdlist ecmd",
- /* 325 */ "cmdlist ::= ecmd",
- /* 326 */ "ecmd ::= SEMI",
- /* 327 */ "ecmd ::= cmdx SEMI",
- /* 328 */ "ecmd ::= explain cmdx",
- /* 329 */ "trans_opt ::=",
- /* 330 */ "trans_opt ::= TRANSACTION",
- /* 331 */ "trans_opt ::= TRANSACTION nm",
- /* 332 */ "savepoint_opt ::= SAVEPOINT",
- /* 333 */ "savepoint_opt ::=",
- /* 334 */ "cmd ::= create_table create_table_args",
- /* 335 */ "columnlist ::= columnlist COMMA columnname carglist",
- /* 336 */ "columnlist ::= columnname carglist",
- /* 337 */ "nm ::= ID|INDEXED",
- /* 338 */ "nm ::= STRING",
- /* 339 */ "nm ::= JOIN_KW",
- /* 340 */ "typetoken ::= typename",
- /* 341 */ "typename ::= ID|STRING",
- /* 342 */ "signed ::= plus_num",
- /* 343 */ "signed ::= minus_num",
- /* 344 */ "carglist ::= carglist ccons",
- /* 345 */ "carglist ::=",
- /* 346 */ "ccons ::= NULL onconf",
- /* 347 */ "conslist_opt ::= COMMA conslist",
- /* 348 */ "conslist ::= conslist tconscomma tcons",
- /* 349 */ "conslist ::= tcons",
- /* 350 */ "tconscomma ::=",
- /* 351 */ "defer_subclause_opt ::= defer_subclause",
- /* 352 */ "resolvetype ::= raisetype",
- /* 353 */ "selectnowith ::= oneselect",
- /* 354 */ "oneselect ::= values",
- /* 355 */ "sclp ::= selcollist COMMA",
- /* 356 */ "as ::= ID|STRING",
- /* 357 */ "expr ::= term",
- /* 358 */ "likeop ::= LIKE_KW|MATCH",
- /* 359 */ "exprlist ::= nexprlist",
- /* 360 */ "nmnum ::= plus_num",
- /* 361 */ "nmnum ::= nm",
- /* 362 */ "nmnum ::= ON",
- /* 363 */ "nmnum ::= DELETE",
- /* 364 */ "nmnum ::= DEFAULT",
- /* 365 */ "plus_num ::= INTEGER|FLOAT",
- /* 366 */ "foreach_clause ::=",
- /* 367 */ "foreach_clause ::= FOR EACH ROW",
- /* 368 */ "trnm ::= nm",
- /* 369 */ "tridxby ::=",
- /* 370 */ "database_kw_opt ::= DATABASE",
- /* 371 */ "database_kw_opt ::=",
- /* 372 */ "kwcolumn_opt ::=",
- /* 373 */ "kwcolumn_opt ::= COLUMNKW",
- /* 374 */ "vtabarglist ::= vtabarg",
- /* 375 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 376 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 377 */ "anylist ::=",
- /* 378 */ "anylist ::= anylist LP anylist RP",
- /* 379 */ "anylist ::= anylist ANY",
- /* 380 */ "with ::=",
+ /* 43 */ "generated ::= LP expr RP",
+ /* 44 */ "generated ::= LP expr RP ID",
+ /* 45 */ "autoinc ::=",
+ /* 46 */ "autoinc ::= AUTOINCR",
+ /* 47 */ "refargs ::=",
+ /* 48 */ "refargs ::= refargs refarg",
+ /* 49 */ "refarg ::= MATCH nm",
+ /* 50 */ "refarg ::= ON INSERT refact",
+ /* 51 */ "refarg ::= ON DELETE refact",
+ /* 52 */ "refarg ::= ON UPDATE refact",
+ /* 53 */ "refact ::= SET NULL",
+ /* 54 */ "refact ::= SET DEFAULT",
+ /* 55 */ "refact ::= CASCADE",
+ /* 56 */ "refact ::= RESTRICT",
+ /* 57 */ "refact ::= NO ACTION",
+ /* 58 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
+ /* 59 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
+ /* 60 */ "init_deferred_pred_opt ::=",
+ /* 61 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
+ /* 62 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
+ /* 63 */ "conslist_opt ::=",
+ /* 64 */ "tconscomma ::= COMMA",
+ /* 65 */ "tcons ::= CONSTRAINT nm",
+ /* 66 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf",
+ /* 67 */ "tcons ::= UNIQUE LP sortlist RP onconf",
+ /* 68 */ "tcons ::= CHECK LP expr RP onconf",
+ /* 69 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt",
+ /* 70 */ "defer_subclause_opt ::=",
+ /* 71 */ "onconf ::=",
+ /* 72 */ "onconf ::= ON CONFLICT resolvetype",
+ /* 73 */ "orconf ::=",
+ /* 74 */ "orconf ::= OR resolvetype",
+ /* 75 */ "resolvetype ::= IGNORE",
+ /* 76 */ "resolvetype ::= REPLACE",
+ /* 77 */ "cmd ::= DROP TABLE ifexists fullname",
+ /* 78 */ "ifexists ::= IF EXISTS",
+ /* 79 */ "ifexists ::=",
+ /* 80 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select",
+ /* 81 */ "cmd ::= DROP VIEW ifexists fullname",
+ /* 82 */ "cmd ::= select",
+ /* 83 */ "select ::= WITH wqlist selectnowith",
+ /* 84 */ "select ::= WITH RECURSIVE wqlist selectnowith",
+ /* 85 */ "select ::= selectnowith",
+ /* 86 */ "selectnowith ::= selectnowith multiselect_op oneselect",
+ /* 87 */ "multiselect_op ::= UNION",
+ /* 88 */ "multiselect_op ::= UNION ALL",
+ /* 89 */ "multiselect_op ::= EXCEPT|INTERSECT",
+ /* 90 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
+ /* 91 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt",
+ /* 92 */ "values ::= VALUES LP nexprlist RP",
+ /* 93 */ "values ::= values COMMA LP nexprlist RP",
+ /* 94 */ "distinct ::= DISTINCT",
+ /* 95 */ "distinct ::= ALL",
+ /* 96 */ "distinct ::=",
+ /* 97 */ "sclp ::=",
+ /* 98 */ "selcollist ::= sclp scanpt expr scanpt as",
+ /* 99 */ "selcollist ::= sclp scanpt STAR",
+ /* 100 */ "selcollist ::= sclp scanpt nm DOT STAR",
+ /* 101 */ "as ::= AS nm",
+ /* 102 */ "as ::=",
+ /* 103 */ "from ::=",
+ /* 104 */ "from ::= FROM seltablist",
+ /* 105 */ "stl_prefix ::= seltablist joinop",
+ /* 106 */ "stl_prefix ::=",
+ /* 107 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
+ /* 108 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt",
+ /* 109 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
+ /* 110 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
+ /* 111 */ "dbnm ::=",
+ /* 112 */ "dbnm ::= DOT nm",
+ /* 113 */ "fullname ::= nm",
+ /* 114 */ "fullname ::= nm DOT nm",
+ /* 115 */ "xfullname ::= nm",
+ /* 116 */ "xfullname ::= nm DOT nm",
+ /* 117 */ "xfullname ::= nm DOT nm AS nm",
+ /* 118 */ "xfullname ::= nm AS nm",
+ /* 119 */ "joinop ::= COMMA|JOIN",
+ /* 120 */ "joinop ::= JOIN_KW JOIN",
+ /* 121 */ "joinop ::= JOIN_KW nm JOIN",
+ /* 122 */ "joinop ::= JOIN_KW nm nm JOIN",
+ /* 123 */ "on_opt ::= ON expr",
+ /* 124 */ "on_opt ::=",
+ /* 125 */ "indexed_opt ::=",
+ /* 126 */ "indexed_opt ::= INDEXED BY nm",
+ /* 127 */ "indexed_opt ::= NOT INDEXED",
+ /* 128 */ "using_opt ::= USING LP idlist RP",
+ /* 129 */ "using_opt ::=",
+ /* 130 */ "orderby_opt ::=",
+ /* 131 */ "orderby_opt ::= ORDER BY sortlist",
+ /* 132 */ "sortlist ::= sortlist COMMA expr sortorder nulls",
+ /* 133 */ "sortlist ::= expr sortorder nulls",
+ /* 134 */ "sortorder ::= ASC",
+ /* 135 */ "sortorder ::= DESC",
+ /* 136 */ "sortorder ::=",
+ /* 137 */ "nulls ::= NULLS FIRST",
+ /* 138 */ "nulls ::= NULLS LAST",
+ /* 139 */ "nulls ::=",
+ /* 140 */ "groupby_opt ::=",
+ /* 141 */ "groupby_opt ::= GROUP BY nexprlist",
+ /* 142 */ "having_opt ::=",
+ /* 143 */ "having_opt ::= HAVING expr",
+ /* 144 */ "limit_opt ::=",
+ /* 145 */ "limit_opt ::= LIMIT expr",
+ /* 146 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 147 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 148 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt",
+ /* 149 */ "where_opt ::=",
+ /* 150 */ "where_opt ::= WHERE expr",
+ /* 151 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt",
+ /* 152 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 153 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
+ /* 154 */ "setlist ::= nm EQ expr",
+ /* 155 */ "setlist ::= LP idlist RP EQ expr",
+ /* 156 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert",
+ /* 157 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES",
+ /* 158 */ "upsert ::=",
+ /* 159 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt",
+ /* 160 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING",
+ /* 161 */ "upsert ::= ON CONFLICT DO NOTHING",
+ /* 162 */ "insert_cmd ::= INSERT orconf",
+ /* 163 */ "insert_cmd ::= REPLACE",
+ /* 164 */ "idlist_opt ::=",
+ /* 165 */ "idlist_opt ::= LP idlist RP",
+ /* 166 */ "idlist ::= idlist COMMA nm",
+ /* 167 */ "idlist ::= nm",
+ /* 168 */ "expr ::= LP expr RP",
+ /* 169 */ "expr ::= ID|INDEXED",
+ /* 170 */ "expr ::= JOIN_KW",
+ /* 171 */ "expr ::= nm DOT nm",
+ /* 172 */ "expr ::= nm DOT nm DOT nm",
+ /* 173 */ "term ::= NULL|FLOAT|BLOB",
+ /* 174 */ "term ::= STRING",
+ /* 175 */ "term ::= INTEGER",
+ /* 176 */ "expr ::= VARIABLE",
+ /* 177 */ "expr ::= expr COLLATE ID|STRING",
+ /* 178 */ "expr ::= CAST LP expr AS typetoken RP",
+ /* 179 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
+ /* 180 */ "expr ::= ID|INDEXED LP STAR RP",
+ /* 181 */ "expr ::= ID|INDEXED LP distinct exprlist RP filter_over",
+ /* 182 */ "expr ::= ID|INDEXED LP STAR RP filter_over",
+ /* 183 */ "term ::= CTIME_KW",
+ /* 184 */ "expr ::= LP nexprlist COMMA expr RP",
+ /* 185 */ "expr ::= expr AND expr",
+ /* 186 */ "expr ::= expr OR expr",
+ /* 187 */ "expr ::= expr LT|GT|GE|LE expr",
+ /* 188 */ "expr ::= expr EQ|NE expr",
+ /* 189 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
+ /* 190 */ "expr ::= expr PLUS|MINUS expr",
+ /* 191 */ "expr ::= expr STAR|SLASH|REM expr",
+ /* 192 */ "expr ::= expr CONCAT expr",
+ /* 193 */ "likeop ::= NOT LIKE_KW|MATCH",
+ /* 194 */ "expr ::= expr likeop expr",
+ /* 195 */ "expr ::= expr likeop expr ESCAPE expr",
+ /* 196 */ "expr ::= expr ISNULL|NOTNULL",
+ /* 197 */ "expr ::= expr NOT NULL",
+ /* 198 */ "expr ::= expr IS expr",
+ /* 199 */ "expr ::= expr IS NOT expr",
+ /* 200 */ "expr ::= NOT expr",
+ /* 201 */ "expr ::= BITNOT expr",
+ /* 202 */ "expr ::= PLUS|MINUS expr",
+ /* 203 */ "between_op ::= BETWEEN",
+ /* 204 */ "between_op ::= NOT BETWEEN",
+ /* 205 */ "expr ::= expr between_op expr AND expr",
+ /* 206 */ "in_op ::= IN",
+ /* 207 */ "in_op ::= NOT IN",
+ /* 208 */ "expr ::= expr in_op LP exprlist RP",
+ /* 209 */ "expr ::= LP select RP",
+ /* 210 */ "expr ::= expr in_op LP select RP",
+ /* 211 */ "expr ::= expr in_op nm dbnm paren_exprlist",
+ /* 212 */ "expr ::= EXISTS LP select RP",
+ /* 213 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 214 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 215 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 216 */ "case_else ::= ELSE expr",
+ /* 217 */ "case_else ::=",
+ /* 218 */ "case_operand ::= expr",
+ /* 219 */ "case_operand ::=",
+ /* 220 */ "exprlist ::=",
+ /* 221 */ "nexprlist ::= nexprlist COMMA expr",
+ /* 222 */ "nexprlist ::= expr",
+ /* 223 */ "paren_exprlist ::=",
+ /* 224 */ "paren_exprlist ::= LP exprlist RP",
+ /* 225 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
+ /* 226 */ "uniqueflag ::= UNIQUE",
+ /* 227 */ "uniqueflag ::=",
+ /* 228 */ "eidlist_opt ::=",
+ /* 229 */ "eidlist_opt ::= LP eidlist RP",
+ /* 230 */ "eidlist ::= eidlist COMMA nm collate sortorder",
+ /* 231 */ "eidlist ::= nm collate sortorder",
+ /* 232 */ "collate ::=",
+ /* 233 */ "collate ::= COLLATE ID|STRING",
+ /* 234 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 235 */ "cmd ::= VACUUM vinto",
+ /* 236 */ "cmd ::= VACUUM nm vinto",
+ /* 237 */ "vinto ::= INTO expr",
+ /* 238 */ "vinto ::=",
+ /* 239 */ "cmd ::= PRAGMA nm dbnm",
+ /* 240 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 241 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 242 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 243 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
+ /* 244 */ "plus_num ::= PLUS INTEGER|FLOAT",
+ /* 245 */ "minus_num ::= MINUS INTEGER|FLOAT",
+ /* 246 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
+ /* 247 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 248 */ "trigger_time ::= BEFORE|AFTER",
+ /* 249 */ "trigger_time ::= INSTEAD OF",
+ /* 250 */ "trigger_time ::=",
+ /* 251 */ "trigger_event ::= DELETE|INSERT",
+ /* 252 */ "trigger_event ::= UPDATE",
+ /* 253 */ "trigger_event ::= UPDATE OF idlist",
+ /* 254 */ "when_clause ::=",
+ /* 255 */ "when_clause ::= WHEN expr",
+ /* 256 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 257 */ "trigger_cmd_list ::= trigger_cmd SEMI",
+ /* 258 */ "trnm ::= nm DOT nm",
+ /* 259 */ "tridxby ::= INDEXED BY nm",
+ /* 260 */ "tridxby ::= NOT INDEXED",
+ /* 261 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt",
+ /* 262 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
+ /* 263 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
+ /* 264 */ "trigger_cmd ::= scanpt select scanpt",
+ /* 265 */ "expr ::= RAISE LP IGNORE RP",
+ /* 266 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 267 */ "raisetype ::= ROLLBACK",
+ /* 268 */ "raisetype ::= ABORT",
+ /* 269 */ "raisetype ::= FAIL",
+ /* 270 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 271 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 272 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 273 */ "key_opt ::=",
+ /* 274 */ "key_opt ::= KEY expr",
+ /* 275 */ "cmd ::= REINDEX",
+ /* 276 */ "cmd ::= REINDEX nm dbnm",
+ /* 277 */ "cmd ::= ANALYZE",
+ /* 278 */ "cmd ::= ANALYZE nm dbnm",
+ /* 279 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 280 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
+ /* 281 */ "add_column_fullname ::= fullname",
+ /* 282 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm",
+ /* 283 */ "cmd ::= create_vtab",
+ /* 284 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 285 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
+ /* 286 */ "vtabarg ::=",
+ /* 287 */ "vtabargtoken ::= ANY",
+ /* 288 */ "vtabargtoken ::= lp anylist RP",
+ /* 289 */ "lp ::= LP",
+ /* 290 */ "with ::= WITH wqlist",
+ /* 291 */ "with ::= WITH RECURSIVE wqlist",
+ /* 292 */ "wqlist ::= nm eidlist_opt AS LP select RP",
+ /* 293 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP",
+ /* 294 */ "windowdefn_list ::= windowdefn",
+ /* 295 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn",
+ /* 296 */ "windowdefn ::= nm AS LP window RP",
+ /* 297 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt",
+ /* 298 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt",
+ /* 299 */ "window ::= ORDER BY sortlist frame_opt",
+ /* 300 */ "window ::= nm ORDER BY sortlist frame_opt",
+ /* 301 */ "window ::= frame_opt",
+ /* 302 */ "window ::= nm frame_opt",
+ /* 303 */ "frame_opt ::=",
+ /* 304 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt",
+ /* 305 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt",
+ /* 306 */ "range_or_rows ::= RANGE|ROWS|GROUPS",
+ /* 307 */ "frame_bound_s ::= frame_bound",
+ /* 308 */ "frame_bound_s ::= UNBOUNDED PRECEDING",
+ /* 309 */ "frame_bound_e ::= frame_bound",
+ /* 310 */ "frame_bound_e ::= UNBOUNDED FOLLOWING",
+ /* 311 */ "frame_bound ::= expr PRECEDING|FOLLOWING",
+ /* 312 */ "frame_bound ::= CURRENT ROW",
+ /* 313 */ "frame_exclude_opt ::=",
+ /* 314 */ "frame_exclude_opt ::= EXCLUDE frame_exclude",
+ /* 315 */ "frame_exclude ::= NO OTHERS",
+ /* 316 */ "frame_exclude ::= CURRENT ROW",
+ /* 317 */ "frame_exclude ::= GROUP|TIES",
+ /* 318 */ "window_clause ::= WINDOW windowdefn_list",
+ /* 319 */ "filter_over ::= filter_clause over_clause",
+ /* 320 */ "filter_over ::= over_clause",
+ /* 321 */ "filter_over ::= filter_clause",
+ /* 322 */ "over_clause ::= OVER LP window RP",
+ /* 323 */ "over_clause ::= OVER nm",
+ /* 324 */ "filter_clause ::= FILTER LP WHERE expr RP",
+ /* 325 */ "input ::= cmdlist",
+ /* 326 */ "cmdlist ::= cmdlist ecmd",
+ /* 327 */ "cmdlist ::= ecmd",
+ /* 328 */ "ecmd ::= SEMI",
+ /* 329 */ "ecmd ::= cmdx SEMI",
+ /* 330 */ "ecmd ::= explain cmdx SEMI",
+ /* 331 */ "trans_opt ::=",
+ /* 332 */ "trans_opt ::= TRANSACTION",
+ /* 333 */ "trans_opt ::= TRANSACTION nm",
+ /* 334 */ "savepoint_opt ::= SAVEPOINT",
+ /* 335 */ "savepoint_opt ::=",
+ /* 336 */ "cmd ::= create_table create_table_args",
+ /* 337 */ "columnlist ::= columnlist COMMA columnname carglist",
+ /* 338 */ "columnlist ::= columnname carglist",
+ /* 339 */ "nm ::= ID|INDEXED",
+ /* 340 */ "nm ::= STRING",
+ /* 341 */ "nm ::= JOIN_KW",
+ /* 342 */ "typetoken ::= typename",
+ /* 343 */ "typename ::= ID|STRING",
+ /* 344 */ "signed ::= plus_num",
+ /* 345 */ "signed ::= minus_num",
+ /* 346 */ "carglist ::= carglist ccons",
+ /* 347 */ "carglist ::=",
+ /* 348 */ "ccons ::= NULL onconf",
+ /* 349 */ "ccons ::= GENERATED ALWAYS AS generated",
+ /* 350 */ "ccons ::= AS generated",
+ /* 351 */ "conslist_opt ::= COMMA conslist",
+ /* 352 */ "conslist ::= conslist tconscomma tcons",
+ /* 353 */ "conslist ::= tcons",
+ /* 354 */ "tconscomma ::=",
+ /* 355 */ "defer_subclause_opt ::= defer_subclause",
+ /* 356 */ "resolvetype ::= raisetype",
+ /* 357 */ "selectnowith ::= oneselect",
+ /* 358 */ "oneselect ::= values",
+ /* 359 */ "sclp ::= selcollist COMMA",
+ /* 360 */ "as ::= ID|STRING",
+ /* 361 */ "expr ::= term",
+ /* 362 */ "likeop ::= LIKE_KW|MATCH",
+ /* 363 */ "exprlist ::= nexprlist",
+ /* 364 */ "nmnum ::= plus_num",
+ /* 365 */ "nmnum ::= nm",
+ /* 366 */ "nmnum ::= ON",
+ /* 367 */ "nmnum ::= DELETE",
+ /* 368 */ "nmnum ::= DEFAULT",
+ /* 369 */ "plus_num ::= INTEGER|FLOAT",
+ /* 370 */ "foreach_clause ::=",
+ /* 371 */ "foreach_clause ::= FOR EACH ROW",
+ /* 372 */ "trnm ::= nm",
+ /* 373 */ "tridxby ::=",
+ /* 374 */ "database_kw_opt ::= DATABASE",
+ /* 375 */ "database_kw_opt ::=",
+ /* 376 */ "kwcolumn_opt ::=",
+ /* 377 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 378 */ "vtabarglist ::= vtabarg",
+ /* 379 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 380 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 381 */ "anylist ::=",
+ /* 382 */ "anylist ::= anylist LP anylist RP",
+ /* 383 */ "anylist ::= anylist ANY",
+ /* 384 */ "with ::=",
};
#endif /* NDEBUG */
@@ -151733,98 +154359,98 @@ static void yy_destructor(
** inside the C code.
*/
/********* Begin destructor definitions ***************************************/
- case 198: /* select */
- case 231: /* selectnowith */
- case 232: /* oneselect */
- case 244: /* values */
+ case 200: /* select */
+ case 234: /* selectnowith */
+ case 235: /* oneselect */
+ case 247: /* values */
{
-sqlite3SelectDelete(pParse->db, (yypminor->yy25));
+sqlite3SelectDelete(pParse->db, (yypminor->yy539));
}
break;
- case 209: /* term */
- case 210: /* expr */
- case 238: /* where_opt */
- case 240: /* having_opt */
- case 252: /* on_opt */
- case 268: /* case_operand */
- case 270: /* case_else */
- case 273: /* vinto */
- case 280: /* when_clause */
- case 285: /* key_opt */
- case 299: /* filter_clause */
+ case 211: /* term */
+ case 212: /* expr */
+ case 241: /* where_opt */
+ case 243: /* having_opt */
+ case 255: /* on_opt */
+ case 271: /* case_operand */
+ case 273: /* case_else */
+ case 276: /* vinto */
+ case 283: /* when_clause */
+ case 288: /* key_opt */
+ case 302: /* filter_clause */
{
-sqlite3ExprDelete(pParse->db, (yypminor->yy46));
+sqlite3ExprDelete(pParse->db, (yypminor->yy202));
}
break;
- case 214: /* eidlist_opt */
- case 223: /* sortlist */
- case 224: /* eidlist */
- case 236: /* selcollist */
- case 239: /* groupby_opt */
- case 241: /* orderby_opt */
- case 245: /* nexprlist */
- case 246: /* sclp */
- case 254: /* exprlist */
- case 259: /* setlist */
- case 267: /* paren_exprlist */
- case 269: /* case_exprlist */
- case 298: /* part_opt */
+ case 216: /* eidlist_opt */
+ case 226: /* sortlist */
+ case 227: /* eidlist */
+ case 239: /* selcollist */
+ case 242: /* groupby_opt */
+ case 244: /* orderby_opt */
+ case 248: /* nexprlist */
+ case 249: /* sclp */
+ case 257: /* exprlist */
+ case 262: /* setlist */
+ case 270: /* paren_exprlist */
+ case 272: /* case_exprlist */
+ case 301: /* part_opt */
{
-sqlite3ExprListDelete(pParse->db, (yypminor->yy138));
+sqlite3ExprListDelete(pParse->db, (yypminor->yy242));
}
break;
- case 230: /* fullname */
- case 237: /* from */
- case 248: /* seltablist */
- case 249: /* stl_prefix */
- case 255: /* xfullname */
+ case 233: /* fullname */
+ case 240: /* from */
+ case 251: /* seltablist */
+ case 252: /* stl_prefix */
+ case 258: /* xfullname */
{
-sqlite3SrcListDelete(pParse->db, (yypminor->yy609));
+sqlite3SrcListDelete(pParse->db, (yypminor->yy47));
}
break;
- case 233: /* wqlist */
+ case 236: /* wqlist */
{
-sqlite3WithDelete(pParse->db, (yypminor->yy297));
+sqlite3WithDelete(pParse->db, (yypminor->yy131));
}
break;
- case 243: /* window_clause */
- case 294: /* windowdefn_list */
+ case 246: /* window_clause */
+ case 297: /* windowdefn_list */
{
-sqlite3WindowListDelete(pParse->db, (yypminor->yy455));
+sqlite3WindowListDelete(pParse->db, (yypminor->yy303));
}
break;
- case 253: /* using_opt */
- case 256: /* idlist */
- case 261: /* idlist_opt */
+ case 256: /* using_opt */
+ case 259: /* idlist */
+ case 264: /* idlist_opt */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy406));
+sqlite3IdListDelete(pParse->db, (yypminor->yy600));
}
break;
- case 263: /* filter_over */
- case 295: /* windowdefn */
- case 296: /* window */
- case 297: /* frame_opt */
- case 300: /* over_clause */
+ case 266: /* filter_over */
+ case 298: /* windowdefn */
+ case 299: /* window */
+ case 300: /* frame_opt */
+ case 303: /* over_clause */
{
-sqlite3WindowDelete(pParse->db, (yypminor->yy455));
+sqlite3WindowDelete(pParse->db, (yypminor->yy303));
}
break;
- case 276: /* trigger_cmd_list */
- case 281: /* trigger_cmd */
+ case 279: /* trigger_cmd_list */
+ case 284: /* trigger_cmd */
{
-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy527));
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy447));
}
break;
- case 278: /* trigger_event */
+ case 281: /* trigger_event */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy572).b);
+sqlite3IdListDelete(pParse->db, (yypminor->yy230).b);
}
break;
- case 302: /* frame_bound */
- case 303: /* frame_bound_s */
- case 304: /* frame_bound_e */
+ case 305: /* frame_bound */
+ case 306: /* frame_bound_s */
+ case 307: /* frame_bound_e */
{
-sqlite3ExprDelete(pParse->db, (yypminor->yy57).pExpr);
+sqlite3ExprDelete(pParse->db, (yypminor->yy77).pExpr);
}
break;
/********* End destructor definitions *****************************************/
@@ -152115,387 +154741,391 @@ static void yy_shift(
/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
** of that rule */
static const YYCODETYPE yyRuleInfoLhs[] = {
- 183, /* (0) explain ::= EXPLAIN */
- 183, /* (1) explain ::= EXPLAIN QUERY PLAN */
- 182, /* (2) cmdx ::= cmd */
- 184, /* (3) cmd ::= BEGIN transtype trans_opt */
- 185, /* (4) transtype ::= */
- 185, /* (5) transtype ::= DEFERRED */
- 185, /* (6) transtype ::= IMMEDIATE */
- 185, /* (7) transtype ::= EXCLUSIVE */
- 184, /* (8) cmd ::= COMMIT|END trans_opt */
- 184, /* (9) cmd ::= ROLLBACK trans_opt */
- 184, /* (10) cmd ::= SAVEPOINT nm */
- 184, /* (11) cmd ::= RELEASE savepoint_opt nm */
- 184, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
- 189, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
- 191, /* (14) createkw ::= CREATE */
- 193, /* (15) ifnotexists ::= */
- 193, /* (16) ifnotexists ::= IF NOT EXISTS */
- 192, /* (17) temp ::= TEMP */
- 192, /* (18) temp ::= */
- 190, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */
- 190, /* (20) create_table_args ::= AS select */
- 197, /* (21) table_options ::= */
- 197, /* (22) table_options ::= WITHOUT nm */
- 199, /* (23) columnname ::= nm typetoken */
- 201, /* (24) typetoken ::= */
- 201, /* (25) typetoken ::= typename LP signed RP */
- 201, /* (26) typetoken ::= typename LP signed COMMA signed RP */
- 202, /* (27) typename ::= typename ID|STRING */
- 206, /* (28) scanpt ::= */
- 207, /* (29) scantok ::= */
- 208, /* (30) ccons ::= CONSTRAINT nm */
- 208, /* (31) ccons ::= DEFAULT scantok term */
- 208, /* (32) ccons ::= DEFAULT LP expr RP */
- 208, /* (33) ccons ::= DEFAULT PLUS scantok term */
- 208, /* (34) ccons ::= DEFAULT MINUS scantok term */
- 208, /* (35) ccons ::= DEFAULT scantok ID|INDEXED */
- 208, /* (36) ccons ::= NOT NULL onconf */
- 208, /* (37) ccons ::= PRIMARY KEY sortorder onconf autoinc */
- 208, /* (38) ccons ::= UNIQUE onconf */
- 208, /* (39) ccons ::= CHECK LP expr RP */
- 208, /* (40) ccons ::= REFERENCES nm eidlist_opt refargs */
- 208, /* (41) ccons ::= defer_subclause */
- 208, /* (42) ccons ::= COLLATE ID|STRING */
- 213, /* (43) autoinc ::= */
- 213, /* (44) autoinc ::= AUTOINCR */
- 215, /* (45) refargs ::= */
- 215, /* (46) refargs ::= refargs refarg */
- 217, /* (47) refarg ::= MATCH nm */
- 217, /* (48) refarg ::= ON INSERT refact */
- 217, /* (49) refarg ::= ON DELETE refact */
- 217, /* (50) refarg ::= ON UPDATE refact */
- 218, /* (51) refact ::= SET NULL */
- 218, /* (52) refact ::= SET DEFAULT */
- 218, /* (53) refact ::= CASCADE */
- 218, /* (54) refact ::= RESTRICT */
- 218, /* (55) refact ::= NO ACTION */
- 216, /* (56) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
- 216, /* (57) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
- 219, /* (58) init_deferred_pred_opt ::= */
- 219, /* (59) init_deferred_pred_opt ::= INITIALLY DEFERRED */
- 219, /* (60) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
- 196, /* (61) conslist_opt ::= */
- 221, /* (62) tconscomma ::= COMMA */
- 222, /* (63) tcons ::= CONSTRAINT nm */
- 222, /* (64) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
- 222, /* (65) tcons ::= UNIQUE LP sortlist RP onconf */
- 222, /* (66) tcons ::= CHECK LP expr RP onconf */
- 222, /* (67) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
- 225, /* (68) defer_subclause_opt ::= */
- 211, /* (69) onconf ::= */
- 211, /* (70) onconf ::= ON CONFLICT resolvetype */
- 226, /* (71) orconf ::= */
- 226, /* (72) orconf ::= OR resolvetype */
- 227, /* (73) resolvetype ::= IGNORE */
- 227, /* (74) resolvetype ::= REPLACE */
- 184, /* (75) cmd ::= DROP TABLE ifexists fullname */
- 229, /* (76) ifexists ::= IF EXISTS */
- 229, /* (77) ifexists ::= */
- 184, /* (78) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
- 184, /* (79) cmd ::= DROP VIEW ifexists fullname */
- 184, /* (80) cmd ::= select */
- 198, /* (81) select ::= WITH wqlist selectnowith */
- 198, /* (82) select ::= WITH RECURSIVE wqlist selectnowith */
- 198, /* (83) select ::= selectnowith */
- 231, /* (84) selectnowith ::= selectnowith multiselect_op oneselect */
- 234, /* (85) multiselect_op ::= UNION */
- 234, /* (86) multiselect_op ::= UNION ALL */
- 234, /* (87) multiselect_op ::= EXCEPT|INTERSECT */
- 232, /* (88) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
- 232, /* (89) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
- 244, /* (90) values ::= VALUES LP nexprlist RP */
- 244, /* (91) values ::= values COMMA LP nexprlist RP */
- 235, /* (92) distinct ::= DISTINCT */
- 235, /* (93) distinct ::= ALL */
- 235, /* (94) distinct ::= */
- 246, /* (95) sclp ::= */
- 236, /* (96) selcollist ::= sclp scanpt expr scanpt as */
- 236, /* (97) selcollist ::= sclp scanpt STAR */
- 236, /* (98) selcollist ::= sclp scanpt nm DOT STAR */
- 247, /* (99) as ::= AS nm */
- 247, /* (100) as ::= */
- 237, /* (101) from ::= */
- 237, /* (102) from ::= FROM seltablist */
- 249, /* (103) stl_prefix ::= seltablist joinop */
- 249, /* (104) stl_prefix ::= */
- 248, /* (105) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
- 248, /* (106) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
- 248, /* (107) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
- 248, /* (108) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
- 194, /* (109) dbnm ::= */
- 194, /* (110) dbnm ::= DOT nm */
- 230, /* (111) fullname ::= nm */
- 230, /* (112) fullname ::= nm DOT nm */
- 255, /* (113) xfullname ::= nm */
- 255, /* (114) xfullname ::= nm DOT nm */
- 255, /* (115) xfullname ::= nm DOT nm AS nm */
- 255, /* (116) xfullname ::= nm AS nm */
- 250, /* (117) joinop ::= COMMA|JOIN */
- 250, /* (118) joinop ::= JOIN_KW JOIN */
- 250, /* (119) joinop ::= JOIN_KW nm JOIN */
- 250, /* (120) joinop ::= JOIN_KW nm nm JOIN */
- 252, /* (121) on_opt ::= ON expr */
- 252, /* (122) on_opt ::= */
- 251, /* (123) indexed_opt ::= */
- 251, /* (124) indexed_opt ::= INDEXED BY nm */
- 251, /* (125) indexed_opt ::= NOT INDEXED */
- 253, /* (126) using_opt ::= USING LP idlist RP */
- 253, /* (127) using_opt ::= */
- 241, /* (128) orderby_opt ::= */
- 241, /* (129) orderby_opt ::= ORDER BY sortlist */
- 223, /* (130) sortlist ::= sortlist COMMA expr sortorder nulls */
- 223, /* (131) sortlist ::= expr sortorder nulls */
- 212, /* (132) sortorder ::= ASC */
- 212, /* (133) sortorder ::= DESC */
- 212, /* (134) sortorder ::= */
- 257, /* (135) nulls ::= NULLS FIRST */
- 257, /* (136) nulls ::= NULLS LAST */
- 257, /* (137) nulls ::= */
- 239, /* (138) groupby_opt ::= */
- 239, /* (139) groupby_opt ::= GROUP BY nexprlist */
- 240, /* (140) having_opt ::= */
- 240, /* (141) having_opt ::= HAVING expr */
- 242, /* (142) limit_opt ::= */
- 242, /* (143) limit_opt ::= LIMIT expr */
- 242, /* (144) limit_opt ::= LIMIT expr OFFSET expr */
- 242, /* (145) limit_opt ::= LIMIT expr COMMA expr */
- 184, /* (146) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
- 238, /* (147) where_opt ::= */
- 238, /* (148) where_opt ::= WHERE expr */
- 184, /* (149) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
- 259, /* (150) setlist ::= setlist COMMA nm EQ expr */
- 259, /* (151) setlist ::= setlist COMMA LP idlist RP EQ expr */
- 259, /* (152) setlist ::= nm EQ expr */
- 259, /* (153) setlist ::= LP idlist RP EQ expr */
- 184, /* (154) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
- 184, /* (155) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
- 262, /* (156) upsert ::= */
- 262, /* (157) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
- 262, /* (158) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
- 262, /* (159) upsert ::= ON CONFLICT DO NOTHING */
- 260, /* (160) insert_cmd ::= INSERT orconf */
- 260, /* (161) insert_cmd ::= REPLACE */
- 261, /* (162) idlist_opt ::= */
- 261, /* (163) idlist_opt ::= LP idlist RP */
- 256, /* (164) idlist ::= idlist COMMA nm */
- 256, /* (165) idlist ::= nm */
- 210, /* (166) expr ::= LP expr RP */
- 210, /* (167) expr ::= ID|INDEXED */
- 210, /* (168) expr ::= JOIN_KW */
- 210, /* (169) expr ::= nm DOT nm */
- 210, /* (170) expr ::= nm DOT nm DOT nm */
- 209, /* (171) term ::= NULL|FLOAT|BLOB */
- 209, /* (172) term ::= STRING */
- 209, /* (173) term ::= INTEGER */
- 210, /* (174) expr ::= VARIABLE */
- 210, /* (175) expr ::= expr COLLATE ID|STRING */
- 210, /* (176) expr ::= CAST LP expr AS typetoken RP */
- 210, /* (177) expr ::= ID|INDEXED LP distinct exprlist RP */
- 210, /* (178) expr ::= ID|INDEXED LP STAR RP */
- 210, /* (179) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
- 210, /* (180) expr ::= ID|INDEXED LP STAR RP filter_over */
- 209, /* (181) term ::= CTIME_KW */
- 210, /* (182) expr ::= LP nexprlist COMMA expr RP */
- 210, /* (183) expr ::= expr AND expr */
- 210, /* (184) expr ::= expr OR expr */
- 210, /* (185) expr ::= expr LT|GT|GE|LE expr */
- 210, /* (186) expr ::= expr EQ|NE expr */
- 210, /* (187) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
- 210, /* (188) expr ::= expr PLUS|MINUS expr */
- 210, /* (189) expr ::= expr STAR|SLASH|REM expr */
- 210, /* (190) expr ::= expr CONCAT expr */
- 264, /* (191) likeop ::= NOT LIKE_KW|MATCH */
- 210, /* (192) expr ::= expr likeop expr */
- 210, /* (193) expr ::= expr likeop expr ESCAPE expr */
- 210, /* (194) expr ::= expr ISNULL|NOTNULL */
- 210, /* (195) expr ::= expr NOT NULL */
- 210, /* (196) expr ::= expr IS expr */
- 210, /* (197) expr ::= expr IS NOT expr */
- 210, /* (198) expr ::= NOT expr */
- 210, /* (199) expr ::= BITNOT expr */
- 210, /* (200) expr ::= PLUS|MINUS expr */
- 265, /* (201) between_op ::= BETWEEN */
- 265, /* (202) between_op ::= NOT BETWEEN */
- 210, /* (203) expr ::= expr between_op expr AND expr */
- 266, /* (204) in_op ::= IN */
- 266, /* (205) in_op ::= NOT IN */
- 210, /* (206) expr ::= expr in_op LP exprlist RP */
- 210, /* (207) expr ::= LP select RP */
- 210, /* (208) expr ::= expr in_op LP select RP */
- 210, /* (209) expr ::= expr in_op nm dbnm paren_exprlist */
- 210, /* (210) expr ::= EXISTS LP select RP */
- 210, /* (211) expr ::= CASE case_operand case_exprlist case_else END */
- 269, /* (212) case_exprlist ::= case_exprlist WHEN expr THEN expr */
- 269, /* (213) case_exprlist ::= WHEN expr THEN expr */
- 270, /* (214) case_else ::= ELSE expr */
- 270, /* (215) case_else ::= */
- 268, /* (216) case_operand ::= expr */
- 268, /* (217) case_operand ::= */
- 254, /* (218) exprlist ::= */
- 245, /* (219) nexprlist ::= nexprlist COMMA expr */
- 245, /* (220) nexprlist ::= expr */
- 267, /* (221) paren_exprlist ::= */
- 267, /* (222) paren_exprlist ::= LP exprlist RP */
- 184, /* (223) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
- 271, /* (224) uniqueflag ::= UNIQUE */
- 271, /* (225) uniqueflag ::= */
- 214, /* (226) eidlist_opt ::= */
- 214, /* (227) eidlist_opt ::= LP eidlist RP */
- 224, /* (228) eidlist ::= eidlist COMMA nm collate sortorder */
- 224, /* (229) eidlist ::= nm collate sortorder */
- 272, /* (230) collate ::= */
- 272, /* (231) collate ::= COLLATE ID|STRING */
- 184, /* (232) cmd ::= DROP INDEX ifexists fullname */
- 184, /* (233) cmd ::= VACUUM vinto */
- 184, /* (234) cmd ::= VACUUM nm vinto */
- 273, /* (235) vinto ::= INTO expr */
- 273, /* (236) vinto ::= */
- 184, /* (237) cmd ::= PRAGMA nm dbnm */
- 184, /* (238) cmd ::= PRAGMA nm dbnm EQ nmnum */
- 184, /* (239) cmd ::= PRAGMA nm dbnm LP nmnum RP */
- 184, /* (240) cmd ::= PRAGMA nm dbnm EQ minus_num */
- 184, /* (241) cmd ::= PRAGMA nm dbnm LP minus_num RP */
- 204, /* (242) plus_num ::= PLUS INTEGER|FLOAT */
- 205, /* (243) minus_num ::= MINUS INTEGER|FLOAT */
- 184, /* (244) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
- 275, /* (245) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
- 277, /* (246) trigger_time ::= BEFORE|AFTER */
- 277, /* (247) trigger_time ::= INSTEAD OF */
- 277, /* (248) trigger_time ::= */
- 278, /* (249) trigger_event ::= DELETE|INSERT */
- 278, /* (250) trigger_event ::= UPDATE */
- 278, /* (251) trigger_event ::= UPDATE OF idlist */
- 280, /* (252) when_clause ::= */
- 280, /* (253) when_clause ::= WHEN expr */
- 276, /* (254) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
- 276, /* (255) trigger_cmd_list ::= trigger_cmd SEMI */
- 282, /* (256) trnm ::= nm DOT nm */
- 283, /* (257) tridxby ::= INDEXED BY nm */
- 283, /* (258) tridxby ::= NOT INDEXED */
- 281, /* (259) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
- 281, /* (260) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
- 281, /* (261) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
- 281, /* (262) trigger_cmd ::= scanpt select scanpt */
- 210, /* (263) expr ::= RAISE LP IGNORE RP */
- 210, /* (264) expr ::= RAISE LP raisetype COMMA nm RP */
- 228, /* (265) raisetype ::= ROLLBACK */
- 228, /* (266) raisetype ::= ABORT */
- 228, /* (267) raisetype ::= FAIL */
- 184, /* (268) cmd ::= DROP TRIGGER ifexists fullname */
- 184, /* (269) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
- 184, /* (270) cmd ::= DETACH database_kw_opt expr */
- 285, /* (271) key_opt ::= */
- 285, /* (272) key_opt ::= KEY expr */
- 184, /* (273) cmd ::= REINDEX */
- 184, /* (274) cmd ::= REINDEX nm dbnm */
- 184, /* (275) cmd ::= ANALYZE */
- 184, /* (276) cmd ::= ANALYZE nm dbnm */
- 184, /* (277) cmd ::= ALTER TABLE fullname RENAME TO nm */
- 184, /* (278) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
- 286, /* (279) add_column_fullname ::= fullname */
- 184, /* (280) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
- 184, /* (281) cmd ::= create_vtab */
- 184, /* (282) cmd ::= create_vtab LP vtabarglist RP */
- 288, /* (283) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
- 290, /* (284) vtabarg ::= */
- 291, /* (285) vtabargtoken ::= ANY */
- 291, /* (286) vtabargtoken ::= lp anylist RP */
- 292, /* (287) lp ::= LP */
- 258, /* (288) with ::= WITH wqlist */
- 258, /* (289) with ::= WITH RECURSIVE wqlist */
- 233, /* (290) wqlist ::= nm eidlist_opt AS LP select RP */
- 233, /* (291) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
- 294, /* (292) windowdefn_list ::= windowdefn */
- 294, /* (293) windowdefn_list ::= windowdefn_list COMMA windowdefn */
- 295, /* (294) windowdefn ::= nm AS LP window RP */
- 296, /* (295) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
- 296, /* (296) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
- 296, /* (297) window ::= ORDER BY sortlist frame_opt */
- 296, /* (298) window ::= nm ORDER BY sortlist frame_opt */
- 296, /* (299) window ::= frame_opt */
- 296, /* (300) window ::= nm frame_opt */
- 297, /* (301) frame_opt ::= */
- 297, /* (302) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
- 297, /* (303) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
- 301, /* (304) range_or_rows ::= RANGE|ROWS|GROUPS */
- 303, /* (305) frame_bound_s ::= frame_bound */
- 303, /* (306) frame_bound_s ::= UNBOUNDED PRECEDING */
- 304, /* (307) frame_bound_e ::= frame_bound */
- 304, /* (308) frame_bound_e ::= UNBOUNDED FOLLOWING */
- 302, /* (309) frame_bound ::= expr PRECEDING|FOLLOWING */
- 302, /* (310) frame_bound ::= CURRENT ROW */
- 305, /* (311) frame_exclude_opt ::= */
- 305, /* (312) frame_exclude_opt ::= EXCLUDE frame_exclude */
- 306, /* (313) frame_exclude ::= NO OTHERS */
- 306, /* (314) frame_exclude ::= CURRENT ROW */
- 306, /* (315) frame_exclude ::= GROUP|TIES */
- 243, /* (316) window_clause ::= WINDOW windowdefn_list */
- 263, /* (317) filter_over ::= filter_clause over_clause */
- 263, /* (318) filter_over ::= over_clause */
- 263, /* (319) filter_over ::= filter_clause */
- 300, /* (320) over_clause ::= OVER LP window RP */
- 300, /* (321) over_clause ::= OVER nm */
- 299, /* (322) filter_clause ::= FILTER LP WHERE expr RP */
- 179, /* (323) input ::= cmdlist */
- 180, /* (324) cmdlist ::= cmdlist ecmd */
- 180, /* (325) cmdlist ::= ecmd */
- 181, /* (326) ecmd ::= SEMI */
- 181, /* (327) ecmd ::= cmdx SEMI */
- 181, /* (328) ecmd ::= explain cmdx */
- 186, /* (329) trans_opt ::= */
- 186, /* (330) trans_opt ::= TRANSACTION */
- 186, /* (331) trans_opt ::= TRANSACTION nm */
- 188, /* (332) savepoint_opt ::= SAVEPOINT */
- 188, /* (333) savepoint_opt ::= */
- 184, /* (334) cmd ::= create_table create_table_args */
- 195, /* (335) columnlist ::= columnlist COMMA columnname carglist */
- 195, /* (336) columnlist ::= columnname carglist */
- 187, /* (337) nm ::= ID|INDEXED */
- 187, /* (338) nm ::= STRING */
- 187, /* (339) nm ::= JOIN_KW */
- 201, /* (340) typetoken ::= typename */
- 202, /* (341) typename ::= ID|STRING */
- 203, /* (342) signed ::= plus_num */
- 203, /* (343) signed ::= minus_num */
- 200, /* (344) carglist ::= carglist ccons */
- 200, /* (345) carglist ::= */
- 208, /* (346) ccons ::= NULL onconf */
- 196, /* (347) conslist_opt ::= COMMA conslist */
- 220, /* (348) conslist ::= conslist tconscomma tcons */
- 220, /* (349) conslist ::= tcons */
- 221, /* (350) tconscomma ::= */
- 225, /* (351) defer_subclause_opt ::= defer_subclause */
- 227, /* (352) resolvetype ::= raisetype */
- 231, /* (353) selectnowith ::= oneselect */
- 232, /* (354) oneselect ::= values */
- 246, /* (355) sclp ::= selcollist COMMA */
- 247, /* (356) as ::= ID|STRING */
- 210, /* (357) expr ::= term */
- 264, /* (358) likeop ::= LIKE_KW|MATCH */
- 254, /* (359) exprlist ::= nexprlist */
- 274, /* (360) nmnum ::= plus_num */
- 274, /* (361) nmnum ::= nm */
- 274, /* (362) nmnum ::= ON */
- 274, /* (363) nmnum ::= DELETE */
- 274, /* (364) nmnum ::= DEFAULT */
- 204, /* (365) plus_num ::= INTEGER|FLOAT */
- 279, /* (366) foreach_clause ::= */
- 279, /* (367) foreach_clause ::= FOR EACH ROW */
- 282, /* (368) trnm ::= nm */
- 283, /* (369) tridxby ::= */
- 284, /* (370) database_kw_opt ::= DATABASE */
- 284, /* (371) database_kw_opt ::= */
- 287, /* (372) kwcolumn_opt ::= */
- 287, /* (373) kwcolumn_opt ::= COLUMNKW */
- 289, /* (374) vtabarglist ::= vtabarg */
- 289, /* (375) vtabarglist ::= vtabarglist COMMA vtabarg */
- 290, /* (376) vtabarg ::= vtabarg vtabargtoken */
- 293, /* (377) anylist ::= */
- 293, /* (378) anylist ::= anylist LP anylist RP */
- 293, /* (379) anylist ::= anylist ANY */
- 258, /* (380) with ::= */
+ 185, /* (0) explain ::= EXPLAIN */
+ 185, /* (1) explain ::= EXPLAIN QUERY PLAN */
+ 184, /* (2) cmdx ::= cmd */
+ 186, /* (3) cmd ::= BEGIN transtype trans_opt */
+ 187, /* (4) transtype ::= */
+ 187, /* (5) transtype ::= DEFERRED */
+ 187, /* (6) transtype ::= IMMEDIATE */
+ 187, /* (7) transtype ::= EXCLUSIVE */
+ 186, /* (8) cmd ::= COMMIT|END trans_opt */
+ 186, /* (9) cmd ::= ROLLBACK trans_opt */
+ 186, /* (10) cmd ::= SAVEPOINT nm */
+ 186, /* (11) cmd ::= RELEASE savepoint_opt nm */
+ 186, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
+ 191, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
+ 193, /* (14) createkw ::= CREATE */
+ 195, /* (15) ifnotexists ::= */
+ 195, /* (16) ifnotexists ::= IF NOT EXISTS */
+ 194, /* (17) temp ::= TEMP */
+ 194, /* (18) temp ::= */
+ 192, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */
+ 192, /* (20) create_table_args ::= AS select */
+ 199, /* (21) table_options ::= */
+ 199, /* (22) table_options ::= WITHOUT nm */
+ 201, /* (23) columnname ::= nm typetoken */
+ 203, /* (24) typetoken ::= */
+ 203, /* (25) typetoken ::= typename LP signed RP */
+ 203, /* (26) typetoken ::= typename LP signed COMMA signed RP */
+ 204, /* (27) typename ::= typename ID|STRING */
+ 208, /* (28) scanpt ::= */
+ 209, /* (29) scantok ::= */
+ 210, /* (30) ccons ::= CONSTRAINT nm */
+ 210, /* (31) ccons ::= DEFAULT scantok term */
+ 210, /* (32) ccons ::= DEFAULT LP expr RP */
+ 210, /* (33) ccons ::= DEFAULT PLUS scantok term */
+ 210, /* (34) ccons ::= DEFAULT MINUS scantok term */
+ 210, /* (35) ccons ::= DEFAULT scantok ID|INDEXED */
+ 210, /* (36) ccons ::= NOT NULL onconf */
+ 210, /* (37) ccons ::= PRIMARY KEY sortorder onconf autoinc */
+ 210, /* (38) ccons ::= UNIQUE onconf */
+ 210, /* (39) ccons ::= CHECK LP expr RP */
+ 210, /* (40) ccons ::= REFERENCES nm eidlist_opt refargs */
+ 210, /* (41) ccons ::= defer_subclause */
+ 210, /* (42) ccons ::= COLLATE ID|STRING */
+ 219, /* (43) generated ::= LP expr RP */
+ 219, /* (44) generated ::= LP expr RP ID */
+ 215, /* (45) autoinc ::= */
+ 215, /* (46) autoinc ::= AUTOINCR */
+ 217, /* (47) refargs ::= */
+ 217, /* (48) refargs ::= refargs refarg */
+ 220, /* (49) refarg ::= MATCH nm */
+ 220, /* (50) refarg ::= ON INSERT refact */
+ 220, /* (51) refarg ::= ON DELETE refact */
+ 220, /* (52) refarg ::= ON UPDATE refact */
+ 221, /* (53) refact ::= SET NULL */
+ 221, /* (54) refact ::= SET DEFAULT */
+ 221, /* (55) refact ::= CASCADE */
+ 221, /* (56) refact ::= RESTRICT */
+ 221, /* (57) refact ::= NO ACTION */
+ 218, /* (58) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
+ 218, /* (59) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+ 222, /* (60) init_deferred_pred_opt ::= */
+ 222, /* (61) init_deferred_pred_opt ::= INITIALLY DEFERRED */
+ 222, /* (62) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
+ 198, /* (63) conslist_opt ::= */
+ 224, /* (64) tconscomma ::= COMMA */
+ 225, /* (65) tcons ::= CONSTRAINT nm */
+ 225, /* (66) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
+ 225, /* (67) tcons ::= UNIQUE LP sortlist RP onconf */
+ 225, /* (68) tcons ::= CHECK LP expr RP onconf */
+ 225, /* (69) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
+ 228, /* (70) defer_subclause_opt ::= */
+ 213, /* (71) onconf ::= */
+ 213, /* (72) onconf ::= ON CONFLICT resolvetype */
+ 229, /* (73) orconf ::= */
+ 229, /* (74) orconf ::= OR resolvetype */
+ 230, /* (75) resolvetype ::= IGNORE */
+ 230, /* (76) resolvetype ::= REPLACE */
+ 186, /* (77) cmd ::= DROP TABLE ifexists fullname */
+ 232, /* (78) ifexists ::= IF EXISTS */
+ 232, /* (79) ifexists ::= */
+ 186, /* (80) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
+ 186, /* (81) cmd ::= DROP VIEW ifexists fullname */
+ 186, /* (82) cmd ::= select */
+ 200, /* (83) select ::= WITH wqlist selectnowith */
+ 200, /* (84) select ::= WITH RECURSIVE wqlist selectnowith */
+ 200, /* (85) select ::= selectnowith */
+ 234, /* (86) selectnowith ::= selectnowith multiselect_op oneselect */
+ 237, /* (87) multiselect_op ::= UNION */
+ 237, /* (88) multiselect_op ::= UNION ALL */
+ 237, /* (89) multiselect_op ::= EXCEPT|INTERSECT */
+ 235, /* (90) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ 235, /* (91) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
+ 247, /* (92) values ::= VALUES LP nexprlist RP */
+ 247, /* (93) values ::= values COMMA LP nexprlist RP */
+ 238, /* (94) distinct ::= DISTINCT */
+ 238, /* (95) distinct ::= ALL */
+ 238, /* (96) distinct ::= */
+ 249, /* (97) sclp ::= */
+ 239, /* (98) selcollist ::= sclp scanpt expr scanpt as */
+ 239, /* (99) selcollist ::= sclp scanpt STAR */
+ 239, /* (100) selcollist ::= sclp scanpt nm DOT STAR */
+ 250, /* (101) as ::= AS nm */
+ 250, /* (102) as ::= */
+ 240, /* (103) from ::= */
+ 240, /* (104) from ::= FROM seltablist */
+ 252, /* (105) stl_prefix ::= seltablist joinop */
+ 252, /* (106) stl_prefix ::= */
+ 251, /* (107) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+ 251, /* (108) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
+ 251, /* (109) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+ 251, /* (110) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+ 196, /* (111) dbnm ::= */
+ 196, /* (112) dbnm ::= DOT nm */
+ 233, /* (113) fullname ::= nm */
+ 233, /* (114) fullname ::= nm DOT nm */
+ 258, /* (115) xfullname ::= nm */
+ 258, /* (116) xfullname ::= nm DOT nm */
+ 258, /* (117) xfullname ::= nm DOT nm AS nm */
+ 258, /* (118) xfullname ::= nm AS nm */
+ 253, /* (119) joinop ::= COMMA|JOIN */
+ 253, /* (120) joinop ::= JOIN_KW JOIN */
+ 253, /* (121) joinop ::= JOIN_KW nm JOIN */
+ 253, /* (122) joinop ::= JOIN_KW nm nm JOIN */
+ 255, /* (123) on_opt ::= ON expr */
+ 255, /* (124) on_opt ::= */
+ 254, /* (125) indexed_opt ::= */
+ 254, /* (126) indexed_opt ::= INDEXED BY nm */
+ 254, /* (127) indexed_opt ::= NOT INDEXED */
+ 256, /* (128) using_opt ::= USING LP idlist RP */
+ 256, /* (129) using_opt ::= */
+ 244, /* (130) orderby_opt ::= */
+ 244, /* (131) orderby_opt ::= ORDER BY sortlist */
+ 226, /* (132) sortlist ::= sortlist COMMA expr sortorder nulls */
+ 226, /* (133) sortlist ::= expr sortorder nulls */
+ 214, /* (134) sortorder ::= ASC */
+ 214, /* (135) sortorder ::= DESC */
+ 214, /* (136) sortorder ::= */
+ 260, /* (137) nulls ::= NULLS FIRST */
+ 260, /* (138) nulls ::= NULLS LAST */
+ 260, /* (139) nulls ::= */
+ 242, /* (140) groupby_opt ::= */
+ 242, /* (141) groupby_opt ::= GROUP BY nexprlist */
+ 243, /* (142) having_opt ::= */
+ 243, /* (143) having_opt ::= HAVING expr */
+ 245, /* (144) limit_opt ::= */
+ 245, /* (145) limit_opt ::= LIMIT expr */
+ 245, /* (146) limit_opt ::= LIMIT expr OFFSET expr */
+ 245, /* (147) limit_opt ::= LIMIT expr COMMA expr */
+ 186, /* (148) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
+ 241, /* (149) where_opt ::= */
+ 241, /* (150) where_opt ::= WHERE expr */
+ 186, /* (151) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
+ 262, /* (152) setlist ::= setlist COMMA nm EQ expr */
+ 262, /* (153) setlist ::= setlist COMMA LP idlist RP EQ expr */
+ 262, /* (154) setlist ::= nm EQ expr */
+ 262, /* (155) setlist ::= LP idlist RP EQ expr */
+ 186, /* (156) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+ 186, /* (157) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
+ 265, /* (158) upsert ::= */
+ 265, /* (159) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
+ 265, /* (160) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
+ 265, /* (161) upsert ::= ON CONFLICT DO NOTHING */
+ 263, /* (162) insert_cmd ::= INSERT orconf */
+ 263, /* (163) insert_cmd ::= REPLACE */
+ 264, /* (164) idlist_opt ::= */
+ 264, /* (165) idlist_opt ::= LP idlist RP */
+ 259, /* (166) idlist ::= idlist COMMA nm */
+ 259, /* (167) idlist ::= nm */
+ 212, /* (168) expr ::= LP expr RP */
+ 212, /* (169) expr ::= ID|INDEXED */
+ 212, /* (170) expr ::= JOIN_KW */
+ 212, /* (171) expr ::= nm DOT nm */
+ 212, /* (172) expr ::= nm DOT nm DOT nm */
+ 211, /* (173) term ::= NULL|FLOAT|BLOB */
+ 211, /* (174) term ::= STRING */
+ 211, /* (175) term ::= INTEGER */
+ 212, /* (176) expr ::= VARIABLE */
+ 212, /* (177) expr ::= expr COLLATE ID|STRING */
+ 212, /* (178) expr ::= CAST LP expr AS typetoken RP */
+ 212, /* (179) expr ::= ID|INDEXED LP distinct exprlist RP */
+ 212, /* (180) expr ::= ID|INDEXED LP STAR RP */
+ 212, /* (181) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
+ 212, /* (182) expr ::= ID|INDEXED LP STAR RP filter_over */
+ 211, /* (183) term ::= CTIME_KW */
+ 212, /* (184) expr ::= LP nexprlist COMMA expr RP */
+ 212, /* (185) expr ::= expr AND expr */
+ 212, /* (186) expr ::= expr OR expr */
+ 212, /* (187) expr ::= expr LT|GT|GE|LE expr */
+ 212, /* (188) expr ::= expr EQ|NE expr */
+ 212, /* (189) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+ 212, /* (190) expr ::= expr PLUS|MINUS expr */
+ 212, /* (191) expr ::= expr STAR|SLASH|REM expr */
+ 212, /* (192) expr ::= expr CONCAT expr */
+ 267, /* (193) likeop ::= NOT LIKE_KW|MATCH */
+ 212, /* (194) expr ::= expr likeop expr */
+ 212, /* (195) expr ::= expr likeop expr ESCAPE expr */
+ 212, /* (196) expr ::= expr ISNULL|NOTNULL */
+ 212, /* (197) expr ::= expr NOT NULL */
+ 212, /* (198) expr ::= expr IS expr */
+ 212, /* (199) expr ::= expr IS NOT expr */
+ 212, /* (200) expr ::= NOT expr */
+ 212, /* (201) expr ::= BITNOT expr */
+ 212, /* (202) expr ::= PLUS|MINUS expr */
+ 268, /* (203) between_op ::= BETWEEN */
+ 268, /* (204) between_op ::= NOT BETWEEN */
+ 212, /* (205) expr ::= expr between_op expr AND expr */
+ 269, /* (206) in_op ::= IN */
+ 269, /* (207) in_op ::= NOT IN */
+ 212, /* (208) expr ::= expr in_op LP exprlist RP */
+ 212, /* (209) expr ::= LP select RP */
+ 212, /* (210) expr ::= expr in_op LP select RP */
+ 212, /* (211) expr ::= expr in_op nm dbnm paren_exprlist */
+ 212, /* (212) expr ::= EXISTS LP select RP */
+ 212, /* (213) expr ::= CASE case_operand case_exprlist case_else END */
+ 272, /* (214) case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ 272, /* (215) case_exprlist ::= WHEN expr THEN expr */
+ 273, /* (216) case_else ::= ELSE expr */
+ 273, /* (217) case_else ::= */
+ 271, /* (218) case_operand ::= expr */
+ 271, /* (219) case_operand ::= */
+ 257, /* (220) exprlist ::= */
+ 248, /* (221) nexprlist ::= nexprlist COMMA expr */
+ 248, /* (222) nexprlist ::= expr */
+ 270, /* (223) paren_exprlist ::= */
+ 270, /* (224) paren_exprlist ::= LP exprlist RP */
+ 186, /* (225) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ 274, /* (226) uniqueflag ::= UNIQUE */
+ 274, /* (227) uniqueflag ::= */
+ 216, /* (228) eidlist_opt ::= */
+ 216, /* (229) eidlist_opt ::= LP eidlist RP */
+ 227, /* (230) eidlist ::= eidlist COMMA nm collate sortorder */
+ 227, /* (231) eidlist ::= nm collate sortorder */
+ 275, /* (232) collate ::= */
+ 275, /* (233) collate ::= COLLATE ID|STRING */
+ 186, /* (234) cmd ::= DROP INDEX ifexists fullname */
+ 186, /* (235) cmd ::= VACUUM vinto */
+ 186, /* (236) cmd ::= VACUUM nm vinto */
+ 276, /* (237) vinto ::= INTO expr */
+ 276, /* (238) vinto ::= */
+ 186, /* (239) cmd ::= PRAGMA nm dbnm */
+ 186, /* (240) cmd ::= PRAGMA nm dbnm EQ nmnum */
+ 186, /* (241) cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ 186, /* (242) cmd ::= PRAGMA nm dbnm EQ minus_num */
+ 186, /* (243) cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ 206, /* (244) plus_num ::= PLUS INTEGER|FLOAT */
+ 207, /* (245) minus_num ::= MINUS INTEGER|FLOAT */
+ 186, /* (246) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ 278, /* (247) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ 280, /* (248) trigger_time ::= BEFORE|AFTER */
+ 280, /* (249) trigger_time ::= INSTEAD OF */
+ 280, /* (250) trigger_time ::= */
+ 281, /* (251) trigger_event ::= DELETE|INSERT */
+ 281, /* (252) trigger_event ::= UPDATE */
+ 281, /* (253) trigger_event ::= UPDATE OF idlist */
+ 283, /* (254) when_clause ::= */
+ 283, /* (255) when_clause ::= WHEN expr */
+ 279, /* (256) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ 279, /* (257) trigger_cmd_list ::= trigger_cmd SEMI */
+ 285, /* (258) trnm ::= nm DOT nm */
+ 286, /* (259) tridxby ::= INDEXED BY nm */
+ 286, /* (260) tridxby ::= NOT INDEXED */
+ 284, /* (261) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
+ 284, /* (262) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ 284, /* (263) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+ 284, /* (264) trigger_cmd ::= scanpt select scanpt */
+ 212, /* (265) expr ::= RAISE LP IGNORE RP */
+ 212, /* (266) expr ::= RAISE LP raisetype COMMA nm RP */
+ 231, /* (267) raisetype ::= ROLLBACK */
+ 231, /* (268) raisetype ::= ABORT */
+ 231, /* (269) raisetype ::= FAIL */
+ 186, /* (270) cmd ::= DROP TRIGGER ifexists fullname */
+ 186, /* (271) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ 186, /* (272) cmd ::= DETACH database_kw_opt expr */
+ 288, /* (273) key_opt ::= */
+ 288, /* (274) key_opt ::= KEY expr */
+ 186, /* (275) cmd ::= REINDEX */
+ 186, /* (276) cmd ::= REINDEX nm dbnm */
+ 186, /* (277) cmd ::= ANALYZE */
+ 186, /* (278) cmd ::= ANALYZE nm dbnm */
+ 186, /* (279) cmd ::= ALTER TABLE fullname RENAME TO nm */
+ 186, /* (280) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ 289, /* (281) add_column_fullname ::= fullname */
+ 186, /* (282) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ 186, /* (283) cmd ::= create_vtab */
+ 186, /* (284) cmd ::= create_vtab LP vtabarglist RP */
+ 291, /* (285) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ 293, /* (286) vtabarg ::= */
+ 294, /* (287) vtabargtoken ::= ANY */
+ 294, /* (288) vtabargtoken ::= lp anylist RP */
+ 295, /* (289) lp ::= LP */
+ 261, /* (290) with ::= WITH wqlist */
+ 261, /* (291) with ::= WITH RECURSIVE wqlist */
+ 236, /* (292) wqlist ::= nm eidlist_opt AS LP select RP */
+ 236, /* (293) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
+ 297, /* (294) windowdefn_list ::= windowdefn */
+ 297, /* (295) windowdefn_list ::= windowdefn_list COMMA windowdefn */
+ 298, /* (296) windowdefn ::= nm AS LP window RP */
+ 299, /* (297) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
+ 299, /* (298) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
+ 299, /* (299) window ::= ORDER BY sortlist frame_opt */
+ 299, /* (300) window ::= nm ORDER BY sortlist frame_opt */
+ 299, /* (301) window ::= frame_opt */
+ 299, /* (302) window ::= nm frame_opt */
+ 300, /* (303) frame_opt ::= */
+ 300, /* (304) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
+ 300, /* (305) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
+ 304, /* (306) range_or_rows ::= RANGE|ROWS|GROUPS */
+ 306, /* (307) frame_bound_s ::= frame_bound */
+ 306, /* (308) frame_bound_s ::= UNBOUNDED PRECEDING */
+ 307, /* (309) frame_bound_e ::= frame_bound */
+ 307, /* (310) frame_bound_e ::= UNBOUNDED FOLLOWING */
+ 305, /* (311) frame_bound ::= expr PRECEDING|FOLLOWING */
+ 305, /* (312) frame_bound ::= CURRENT ROW */
+ 308, /* (313) frame_exclude_opt ::= */
+ 308, /* (314) frame_exclude_opt ::= EXCLUDE frame_exclude */
+ 309, /* (315) frame_exclude ::= NO OTHERS */
+ 309, /* (316) frame_exclude ::= CURRENT ROW */
+ 309, /* (317) frame_exclude ::= GROUP|TIES */
+ 246, /* (318) window_clause ::= WINDOW windowdefn_list */
+ 266, /* (319) filter_over ::= filter_clause over_clause */
+ 266, /* (320) filter_over ::= over_clause */
+ 266, /* (321) filter_over ::= filter_clause */
+ 303, /* (322) over_clause ::= OVER LP window RP */
+ 303, /* (323) over_clause ::= OVER nm */
+ 302, /* (324) filter_clause ::= FILTER LP WHERE expr RP */
+ 181, /* (325) input ::= cmdlist */
+ 182, /* (326) cmdlist ::= cmdlist ecmd */
+ 182, /* (327) cmdlist ::= ecmd */
+ 183, /* (328) ecmd ::= SEMI */
+ 183, /* (329) ecmd ::= cmdx SEMI */
+ 183, /* (330) ecmd ::= explain cmdx SEMI */
+ 188, /* (331) trans_opt ::= */
+ 188, /* (332) trans_opt ::= TRANSACTION */
+ 188, /* (333) trans_opt ::= TRANSACTION nm */
+ 190, /* (334) savepoint_opt ::= SAVEPOINT */
+ 190, /* (335) savepoint_opt ::= */
+ 186, /* (336) cmd ::= create_table create_table_args */
+ 197, /* (337) columnlist ::= columnlist COMMA columnname carglist */
+ 197, /* (338) columnlist ::= columnname carglist */
+ 189, /* (339) nm ::= ID|INDEXED */
+ 189, /* (340) nm ::= STRING */
+ 189, /* (341) nm ::= JOIN_KW */
+ 203, /* (342) typetoken ::= typename */
+ 204, /* (343) typename ::= ID|STRING */
+ 205, /* (344) signed ::= plus_num */
+ 205, /* (345) signed ::= minus_num */
+ 202, /* (346) carglist ::= carglist ccons */
+ 202, /* (347) carglist ::= */
+ 210, /* (348) ccons ::= NULL onconf */
+ 210, /* (349) ccons ::= GENERATED ALWAYS AS generated */
+ 210, /* (350) ccons ::= AS generated */
+ 198, /* (351) conslist_opt ::= COMMA conslist */
+ 223, /* (352) conslist ::= conslist tconscomma tcons */
+ 223, /* (353) conslist ::= tcons */
+ 224, /* (354) tconscomma ::= */
+ 228, /* (355) defer_subclause_opt ::= defer_subclause */
+ 230, /* (356) resolvetype ::= raisetype */
+ 234, /* (357) selectnowith ::= oneselect */
+ 235, /* (358) oneselect ::= values */
+ 249, /* (359) sclp ::= selcollist COMMA */
+ 250, /* (360) as ::= ID|STRING */
+ 212, /* (361) expr ::= term */
+ 267, /* (362) likeop ::= LIKE_KW|MATCH */
+ 257, /* (363) exprlist ::= nexprlist */
+ 277, /* (364) nmnum ::= plus_num */
+ 277, /* (365) nmnum ::= nm */
+ 277, /* (366) nmnum ::= ON */
+ 277, /* (367) nmnum ::= DELETE */
+ 277, /* (368) nmnum ::= DEFAULT */
+ 206, /* (369) plus_num ::= INTEGER|FLOAT */
+ 282, /* (370) foreach_clause ::= */
+ 282, /* (371) foreach_clause ::= FOR EACH ROW */
+ 285, /* (372) trnm ::= nm */
+ 286, /* (373) tridxby ::= */
+ 287, /* (374) database_kw_opt ::= DATABASE */
+ 287, /* (375) database_kw_opt ::= */
+ 290, /* (376) kwcolumn_opt ::= */
+ 290, /* (377) kwcolumn_opt ::= COLUMNKW */
+ 292, /* (378) vtabarglist ::= vtabarg */
+ 292, /* (379) vtabarglist ::= vtabarglist COMMA vtabarg */
+ 293, /* (380) vtabarg ::= vtabarg vtabargtoken */
+ 296, /* (381) anylist ::= */
+ 296, /* (382) anylist ::= anylist LP anylist RP */
+ 296, /* (383) anylist ::= anylist ANY */
+ 261, /* (384) with ::= */
};
/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
@@ -152544,344 +155174,348 @@ static const signed char yyRuleInfoNRhs[] = {
-4, /* (40) ccons ::= REFERENCES nm eidlist_opt refargs */
-1, /* (41) ccons ::= defer_subclause */
-2, /* (42) ccons ::= COLLATE ID|STRING */
- 0, /* (43) autoinc ::= */
- -1, /* (44) autoinc ::= AUTOINCR */
- 0, /* (45) refargs ::= */
- -2, /* (46) refargs ::= refargs refarg */
- -2, /* (47) refarg ::= MATCH nm */
- -3, /* (48) refarg ::= ON INSERT refact */
- -3, /* (49) refarg ::= ON DELETE refact */
- -3, /* (50) refarg ::= ON UPDATE refact */
- -2, /* (51) refact ::= SET NULL */
- -2, /* (52) refact ::= SET DEFAULT */
- -1, /* (53) refact ::= CASCADE */
- -1, /* (54) refact ::= RESTRICT */
- -2, /* (55) refact ::= NO ACTION */
- -3, /* (56) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
- -2, /* (57) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
- 0, /* (58) init_deferred_pred_opt ::= */
- -2, /* (59) init_deferred_pred_opt ::= INITIALLY DEFERRED */
- -2, /* (60) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
- 0, /* (61) conslist_opt ::= */
- -1, /* (62) tconscomma ::= COMMA */
- -2, /* (63) tcons ::= CONSTRAINT nm */
- -7, /* (64) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
- -5, /* (65) tcons ::= UNIQUE LP sortlist RP onconf */
- -5, /* (66) tcons ::= CHECK LP expr RP onconf */
- -10, /* (67) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
- 0, /* (68) defer_subclause_opt ::= */
- 0, /* (69) onconf ::= */
- -3, /* (70) onconf ::= ON CONFLICT resolvetype */
- 0, /* (71) orconf ::= */
- -2, /* (72) orconf ::= OR resolvetype */
- -1, /* (73) resolvetype ::= IGNORE */
- -1, /* (74) resolvetype ::= REPLACE */
- -4, /* (75) cmd ::= DROP TABLE ifexists fullname */
- -2, /* (76) ifexists ::= IF EXISTS */
- 0, /* (77) ifexists ::= */
- -9, /* (78) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
- -4, /* (79) cmd ::= DROP VIEW ifexists fullname */
- -1, /* (80) cmd ::= select */
- -3, /* (81) select ::= WITH wqlist selectnowith */
- -4, /* (82) select ::= WITH RECURSIVE wqlist selectnowith */
- -1, /* (83) select ::= selectnowith */
- -3, /* (84) selectnowith ::= selectnowith multiselect_op oneselect */
- -1, /* (85) multiselect_op ::= UNION */
- -2, /* (86) multiselect_op ::= UNION ALL */
- -1, /* (87) multiselect_op ::= EXCEPT|INTERSECT */
- -9, /* (88) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
- -10, /* (89) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
- -4, /* (90) values ::= VALUES LP nexprlist RP */
- -5, /* (91) values ::= values COMMA LP nexprlist RP */
- -1, /* (92) distinct ::= DISTINCT */
- -1, /* (93) distinct ::= ALL */
- 0, /* (94) distinct ::= */
- 0, /* (95) sclp ::= */
- -5, /* (96) selcollist ::= sclp scanpt expr scanpt as */
- -3, /* (97) selcollist ::= sclp scanpt STAR */
- -5, /* (98) selcollist ::= sclp scanpt nm DOT STAR */
- -2, /* (99) as ::= AS nm */
- 0, /* (100) as ::= */
- 0, /* (101) from ::= */
- -2, /* (102) from ::= FROM seltablist */
- -2, /* (103) stl_prefix ::= seltablist joinop */
- 0, /* (104) stl_prefix ::= */
- -7, /* (105) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
- -9, /* (106) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
- -7, /* (107) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
- -7, /* (108) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
- 0, /* (109) dbnm ::= */
- -2, /* (110) dbnm ::= DOT nm */
- -1, /* (111) fullname ::= nm */
- -3, /* (112) fullname ::= nm DOT nm */
- -1, /* (113) xfullname ::= nm */
- -3, /* (114) xfullname ::= nm DOT nm */
- -5, /* (115) xfullname ::= nm DOT nm AS nm */
- -3, /* (116) xfullname ::= nm AS nm */
- -1, /* (117) joinop ::= COMMA|JOIN */
- -2, /* (118) joinop ::= JOIN_KW JOIN */
- -3, /* (119) joinop ::= JOIN_KW nm JOIN */
- -4, /* (120) joinop ::= JOIN_KW nm nm JOIN */
- -2, /* (121) on_opt ::= ON expr */
- 0, /* (122) on_opt ::= */
- 0, /* (123) indexed_opt ::= */
- -3, /* (124) indexed_opt ::= INDEXED BY nm */
- -2, /* (125) indexed_opt ::= NOT INDEXED */
- -4, /* (126) using_opt ::= USING LP idlist RP */
- 0, /* (127) using_opt ::= */
- 0, /* (128) orderby_opt ::= */
- -3, /* (129) orderby_opt ::= ORDER BY sortlist */
- -5, /* (130) sortlist ::= sortlist COMMA expr sortorder nulls */
- -3, /* (131) sortlist ::= expr sortorder nulls */
- -1, /* (132) sortorder ::= ASC */
- -1, /* (133) sortorder ::= DESC */
- 0, /* (134) sortorder ::= */
- -2, /* (135) nulls ::= NULLS FIRST */
- -2, /* (136) nulls ::= NULLS LAST */
- 0, /* (137) nulls ::= */
- 0, /* (138) groupby_opt ::= */
- -3, /* (139) groupby_opt ::= GROUP BY nexprlist */
- 0, /* (140) having_opt ::= */
- -2, /* (141) having_opt ::= HAVING expr */
- 0, /* (142) limit_opt ::= */
- -2, /* (143) limit_opt ::= LIMIT expr */
- -4, /* (144) limit_opt ::= LIMIT expr OFFSET expr */
- -4, /* (145) limit_opt ::= LIMIT expr COMMA expr */
- -6, /* (146) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
- 0, /* (147) where_opt ::= */
- -2, /* (148) where_opt ::= WHERE expr */
- -8, /* (149) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
- -5, /* (150) setlist ::= setlist COMMA nm EQ expr */
- -7, /* (151) setlist ::= setlist COMMA LP idlist RP EQ expr */
- -3, /* (152) setlist ::= nm EQ expr */
- -5, /* (153) setlist ::= LP idlist RP EQ expr */
- -7, /* (154) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
- -7, /* (155) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
- 0, /* (156) upsert ::= */
- -11, /* (157) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
- -8, /* (158) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
- -4, /* (159) upsert ::= ON CONFLICT DO NOTHING */
- -2, /* (160) insert_cmd ::= INSERT orconf */
- -1, /* (161) insert_cmd ::= REPLACE */
- 0, /* (162) idlist_opt ::= */
- -3, /* (163) idlist_opt ::= LP idlist RP */
- -3, /* (164) idlist ::= idlist COMMA nm */
- -1, /* (165) idlist ::= nm */
- -3, /* (166) expr ::= LP expr RP */
- -1, /* (167) expr ::= ID|INDEXED */
- -1, /* (168) expr ::= JOIN_KW */
- -3, /* (169) expr ::= nm DOT nm */
- -5, /* (170) expr ::= nm DOT nm DOT nm */
- -1, /* (171) term ::= NULL|FLOAT|BLOB */
- -1, /* (172) term ::= STRING */
- -1, /* (173) term ::= INTEGER */
- -1, /* (174) expr ::= VARIABLE */
- -3, /* (175) expr ::= expr COLLATE ID|STRING */
- -6, /* (176) expr ::= CAST LP expr AS typetoken RP */
- -5, /* (177) expr ::= ID|INDEXED LP distinct exprlist RP */
- -4, /* (178) expr ::= ID|INDEXED LP STAR RP */
- -6, /* (179) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
- -5, /* (180) expr ::= ID|INDEXED LP STAR RP filter_over */
- -1, /* (181) term ::= CTIME_KW */
- -5, /* (182) expr ::= LP nexprlist COMMA expr RP */
- -3, /* (183) expr ::= expr AND expr */
- -3, /* (184) expr ::= expr OR expr */
- -3, /* (185) expr ::= expr LT|GT|GE|LE expr */
- -3, /* (186) expr ::= expr EQ|NE expr */
- -3, /* (187) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
- -3, /* (188) expr ::= expr PLUS|MINUS expr */
- -3, /* (189) expr ::= expr STAR|SLASH|REM expr */
- -3, /* (190) expr ::= expr CONCAT expr */
- -2, /* (191) likeop ::= NOT LIKE_KW|MATCH */
- -3, /* (192) expr ::= expr likeop expr */
- -5, /* (193) expr ::= expr likeop expr ESCAPE expr */
- -2, /* (194) expr ::= expr ISNULL|NOTNULL */
- -3, /* (195) expr ::= expr NOT NULL */
- -3, /* (196) expr ::= expr IS expr */
- -4, /* (197) expr ::= expr IS NOT expr */
- -2, /* (198) expr ::= NOT expr */
- -2, /* (199) expr ::= BITNOT expr */
- -2, /* (200) expr ::= PLUS|MINUS expr */
- -1, /* (201) between_op ::= BETWEEN */
- -2, /* (202) between_op ::= NOT BETWEEN */
- -5, /* (203) expr ::= expr between_op expr AND expr */
- -1, /* (204) in_op ::= IN */
- -2, /* (205) in_op ::= NOT IN */
- -5, /* (206) expr ::= expr in_op LP exprlist RP */
- -3, /* (207) expr ::= LP select RP */
- -5, /* (208) expr ::= expr in_op LP select RP */
- -5, /* (209) expr ::= expr in_op nm dbnm paren_exprlist */
- -4, /* (210) expr ::= EXISTS LP select RP */
- -5, /* (211) expr ::= CASE case_operand case_exprlist case_else END */
- -5, /* (212) case_exprlist ::= case_exprlist WHEN expr THEN expr */
- -4, /* (213) case_exprlist ::= WHEN expr THEN expr */
- -2, /* (214) case_else ::= ELSE expr */
- 0, /* (215) case_else ::= */
- -1, /* (216) case_operand ::= expr */
- 0, /* (217) case_operand ::= */
- 0, /* (218) exprlist ::= */
- -3, /* (219) nexprlist ::= nexprlist COMMA expr */
- -1, /* (220) nexprlist ::= expr */
- 0, /* (221) paren_exprlist ::= */
- -3, /* (222) paren_exprlist ::= LP exprlist RP */
- -12, /* (223) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
- -1, /* (224) uniqueflag ::= UNIQUE */
- 0, /* (225) uniqueflag ::= */
- 0, /* (226) eidlist_opt ::= */
- -3, /* (227) eidlist_opt ::= LP eidlist RP */
- -5, /* (228) eidlist ::= eidlist COMMA nm collate sortorder */
- -3, /* (229) eidlist ::= nm collate sortorder */
- 0, /* (230) collate ::= */
- -2, /* (231) collate ::= COLLATE ID|STRING */
- -4, /* (232) cmd ::= DROP INDEX ifexists fullname */
- -2, /* (233) cmd ::= VACUUM vinto */
- -3, /* (234) cmd ::= VACUUM nm vinto */
- -2, /* (235) vinto ::= INTO expr */
- 0, /* (236) vinto ::= */
- -3, /* (237) cmd ::= PRAGMA nm dbnm */
- -5, /* (238) cmd ::= PRAGMA nm dbnm EQ nmnum */
- -6, /* (239) cmd ::= PRAGMA nm dbnm LP nmnum RP */
- -5, /* (240) cmd ::= PRAGMA nm dbnm EQ minus_num */
- -6, /* (241) cmd ::= PRAGMA nm dbnm LP minus_num RP */
- -2, /* (242) plus_num ::= PLUS INTEGER|FLOAT */
- -2, /* (243) minus_num ::= MINUS INTEGER|FLOAT */
- -5, /* (244) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
- -11, /* (245) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
- -1, /* (246) trigger_time ::= BEFORE|AFTER */
- -2, /* (247) trigger_time ::= INSTEAD OF */
- 0, /* (248) trigger_time ::= */
- -1, /* (249) trigger_event ::= DELETE|INSERT */
- -1, /* (250) trigger_event ::= UPDATE */
- -3, /* (251) trigger_event ::= UPDATE OF idlist */
- 0, /* (252) when_clause ::= */
- -2, /* (253) when_clause ::= WHEN expr */
- -3, /* (254) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
- -2, /* (255) trigger_cmd_list ::= trigger_cmd SEMI */
- -3, /* (256) trnm ::= nm DOT nm */
- -3, /* (257) tridxby ::= INDEXED BY nm */
- -2, /* (258) tridxby ::= NOT INDEXED */
- -8, /* (259) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
- -8, /* (260) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
- -6, /* (261) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
- -3, /* (262) trigger_cmd ::= scanpt select scanpt */
- -4, /* (263) expr ::= RAISE LP IGNORE RP */
- -6, /* (264) expr ::= RAISE LP raisetype COMMA nm RP */
- -1, /* (265) raisetype ::= ROLLBACK */
- -1, /* (266) raisetype ::= ABORT */
- -1, /* (267) raisetype ::= FAIL */
- -4, /* (268) cmd ::= DROP TRIGGER ifexists fullname */
- -6, /* (269) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
- -3, /* (270) cmd ::= DETACH database_kw_opt expr */
- 0, /* (271) key_opt ::= */
- -2, /* (272) key_opt ::= KEY expr */
- -1, /* (273) cmd ::= REINDEX */
- -3, /* (274) cmd ::= REINDEX nm dbnm */
- -1, /* (275) cmd ::= ANALYZE */
- -3, /* (276) cmd ::= ANALYZE nm dbnm */
- -6, /* (277) cmd ::= ALTER TABLE fullname RENAME TO nm */
- -7, /* (278) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
- -1, /* (279) add_column_fullname ::= fullname */
- -8, /* (280) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
- -1, /* (281) cmd ::= create_vtab */
- -4, /* (282) cmd ::= create_vtab LP vtabarglist RP */
- -8, /* (283) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
- 0, /* (284) vtabarg ::= */
- -1, /* (285) vtabargtoken ::= ANY */
- -3, /* (286) vtabargtoken ::= lp anylist RP */
- -1, /* (287) lp ::= LP */
- -2, /* (288) with ::= WITH wqlist */
- -3, /* (289) with ::= WITH RECURSIVE wqlist */
- -6, /* (290) wqlist ::= nm eidlist_opt AS LP select RP */
- -8, /* (291) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
- -1, /* (292) windowdefn_list ::= windowdefn */
- -3, /* (293) windowdefn_list ::= windowdefn_list COMMA windowdefn */
- -5, /* (294) windowdefn ::= nm AS LP window RP */
- -5, /* (295) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
- -6, /* (296) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
- -4, /* (297) window ::= ORDER BY sortlist frame_opt */
- -5, /* (298) window ::= nm ORDER BY sortlist frame_opt */
- -1, /* (299) window ::= frame_opt */
- -2, /* (300) window ::= nm frame_opt */
- 0, /* (301) frame_opt ::= */
- -3, /* (302) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
- -6, /* (303) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
- -1, /* (304) range_or_rows ::= RANGE|ROWS|GROUPS */
- -1, /* (305) frame_bound_s ::= frame_bound */
- -2, /* (306) frame_bound_s ::= UNBOUNDED PRECEDING */
- -1, /* (307) frame_bound_e ::= frame_bound */
- -2, /* (308) frame_bound_e ::= UNBOUNDED FOLLOWING */
- -2, /* (309) frame_bound ::= expr PRECEDING|FOLLOWING */
- -2, /* (310) frame_bound ::= CURRENT ROW */
- 0, /* (311) frame_exclude_opt ::= */
- -2, /* (312) frame_exclude_opt ::= EXCLUDE frame_exclude */
- -2, /* (313) frame_exclude ::= NO OTHERS */
- -2, /* (314) frame_exclude ::= CURRENT ROW */
- -1, /* (315) frame_exclude ::= GROUP|TIES */
- -2, /* (316) window_clause ::= WINDOW windowdefn_list */
- -2, /* (317) filter_over ::= filter_clause over_clause */
- -1, /* (318) filter_over ::= over_clause */
- -1, /* (319) filter_over ::= filter_clause */
- -4, /* (320) over_clause ::= OVER LP window RP */
- -2, /* (321) over_clause ::= OVER nm */
- -5, /* (322) filter_clause ::= FILTER LP WHERE expr RP */
- -1, /* (323) input ::= cmdlist */
- -2, /* (324) cmdlist ::= cmdlist ecmd */
- -1, /* (325) cmdlist ::= ecmd */
- -1, /* (326) ecmd ::= SEMI */
- -2, /* (327) ecmd ::= cmdx SEMI */
- -2, /* (328) ecmd ::= explain cmdx */
- 0, /* (329) trans_opt ::= */
- -1, /* (330) trans_opt ::= TRANSACTION */
- -2, /* (331) trans_opt ::= TRANSACTION nm */
- -1, /* (332) savepoint_opt ::= SAVEPOINT */
- 0, /* (333) savepoint_opt ::= */
- -2, /* (334) cmd ::= create_table create_table_args */
- -4, /* (335) columnlist ::= columnlist COMMA columnname carglist */
- -2, /* (336) columnlist ::= columnname carglist */
- -1, /* (337) nm ::= ID|INDEXED */
- -1, /* (338) nm ::= STRING */
- -1, /* (339) nm ::= JOIN_KW */
- -1, /* (340) typetoken ::= typename */
- -1, /* (341) typename ::= ID|STRING */
- -1, /* (342) signed ::= plus_num */
- -1, /* (343) signed ::= minus_num */
- -2, /* (344) carglist ::= carglist ccons */
- 0, /* (345) carglist ::= */
- -2, /* (346) ccons ::= NULL onconf */
- -2, /* (347) conslist_opt ::= COMMA conslist */
- -3, /* (348) conslist ::= conslist tconscomma tcons */
- -1, /* (349) conslist ::= tcons */
- 0, /* (350) tconscomma ::= */
- -1, /* (351) defer_subclause_opt ::= defer_subclause */
- -1, /* (352) resolvetype ::= raisetype */
- -1, /* (353) selectnowith ::= oneselect */
- -1, /* (354) oneselect ::= values */
- -2, /* (355) sclp ::= selcollist COMMA */
- -1, /* (356) as ::= ID|STRING */
- -1, /* (357) expr ::= term */
- -1, /* (358) likeop ::= LIKE_KW|MATCH */
- -1, /* (359) exprlist ::= nexprlist */
- -1, /* (360) nmnum ::= plus_num */
- -1, /* (361) nmnum ::= nm */
- -1, /* (362) nmnum ::= ON */
- -1, /* (363) nmnum ::= DELETE */
- -1, /* (364) nmnum ::= DEFAULT */
- -1, /* (365) plus_num ::= INTEGER|FLOAT */
- 0, /* (366) foreach_clause ::= */
- -3, /* (367) foreach_clause ::= FOR EACH ROW */
- -1, /* (368) trnm ::= nm */
- 0, /* (369) tridxby ::= */
- -1, /* (370) database_kw_opt ::= DATABASE */
- 0, /* (371) database_kw_opt ::= */
- 0, /* (372) kwcolumn_opt ::= */
- -1, /* (373) kwcolumn_opt ::= COLUMNKW */
- -1, /* (374) vtabarglist ::= vtabarg */
- -3, /* (375) vtabarglist ::= vtabarglist COMMA vtabarg */
- -2, /* (376) vtabarg ::= vtabarg vtabargtoken */
- 0, /* (377) anylist ::= */
- -4, /* (378) anylist ::= anylist LP anylist RP */
- -2, /* (379) anylist ::= anylist ANY */
- 0, /* (380) with ::= */
+ -3, /* (43) generated ::= LP expr RP */
+ -4, /* (44) generated ::= LP expr RP ID */
+ 0, /* (45) autoinc ::= */
+ -1, /* (46) autoinc ::= AUTOINCR */
+ 0, /* (47) refargs ::= */
+ -2, /* (48) refargs ::= refargs refarg */
+ -2, /* (49) refarg ::= MATCH nm */
+ -3, /* (50) refarg ::= ON INSERT refact */
+ -3, /* (51) refarg ::= ON DELETE refact */
+ -3, /* (52) refarg ::= ON UPDATE refact */
+ -2, /* (53) refact ::= SET NULL */
+ -2, /* (54) refact ::= SET DEFAULT */
+ -1, /* (55) refact ::= CASCADE */
+ -1, /* (56) refact ::= RESTRICT */
+ -2, /* (57) refact ::= NO ACTION */
+ -3, /* (58) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
+ -2, /* (59) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+ 0, /* (60) init_deferred_pred_opt ::= */
+ -2, /* (61) init_deferred_pred_opt ::= INITIALLY DEFERRED */
+ -2, /* (62) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
+ 0, /* (63) conslist_opt ::= */
+ -1, /* (64) tconscomma ::= COMMA */
+ -2, /* (65) tcons ::= CONSTRAINT nm */
+ -7, /* (66) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
+ -5, /* (67) tcons ::= UNIQUE LP sortlist RP onconf */
+ -5, /* (68) tcons ::= CHECK LP expr RP onconf */
+ -10, /* (69) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
+ 0, /* (70) defer_subclause_opt ::= */
+ 0, /* (71) onconf ::= */
+ -3, /* (72) onconf ::= ON CONFLICT resolvetype */
+ 0, /* (73) orconf ::= */
+ -2, /* (74) orconf ::= OR resolvetype */
+ -1, /* (75) resolvetype ::= IGNORE */
+ -1, /* (76) resolvetype ::= REPLACE */
+ -4, /* (77) cmd ::= DROP TABLE ifexists fullname */
+ -2, /* (78) ifexists ::= IF EXISTS */
+ 0, /* (79) ifexists ::= */
+ -9, /* (80) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
+ -4, /* (81) cmd ::= DROP VIEW ifexists fullname */
+ -1, /* (82) cmd ::= select */
+ -3, /* (83) select ::= WITH wqlist selectnowith */
+ -4, /* (84) select ::= WITH RECURSIVE wqlist selectnowith */
+ -1, /* (85) select ::= selectnowith */
+ -3, /* (86) selectnowith ::= selectnowith multiselect_op oneselect */
+ -1, /* (87) multiselect_op ::= UNION */
+ -2, /* (88) multiselect_op ::= UNION ALL */
+ -1, /* (89) multiselect_op ::= EXCEPT|INTERSECT */
+ -9, /* (90) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ -10, /* (91) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
+ -4, /* (92) values ::= VALUES LP nexprlist RP */
+ -5, /* (93) values ::= values COMMA LP nexprlist RP */
+ -1, /* (94) distinct ::= DISTINCT */
+ -1, /* (95) distinct ::= ALL */
+ 0, /* (96) distinct ::= */
+ 0, /* (97) sclp ::= */
+ -5, /* (98) selcollist ::= sclp scanpt expr scanpt as */
+ -3, /* (99) selcollist ::= sclp scanpt STAR */
+ -5, /* (100) selcollist ::= sclp scanpt nm DOT STAR */
+ -2, /* (101) as ::= AS nm */
+ 0, /* (102) as ::= */
+ 0, /* (103) from ::= */
+ -2, /* (104) from ::= FROM seltablist */
+ -2, /* (105) stl_prefix ::= seltablist joinop */
+ 0, /* (106) stl_prefix ::= */
+ -7, /* (107) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+ -9, /* (108) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
+ -7, /* (109) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+ -7, /* (110) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+ 0, /* (111) dbnm ::= */
+ -2, /* (112) dbnm ::= DOT nm */
+ -1, /* (113) fullname ::= nm */
+ -3, /* (114) fullname ::= nm DOT nm */
+ -1, /* (115) xfullname ::= nm */
+ -3, /* (116) xfullname ::= nm DOT nm */
+ -5, /* (117) xfullname ::= nm DOT nm AS nm */
+ -3, /* (118) xfullname ::= nm AS nm */
+ -1, /* (119) joinop ::= COMMA|JOIN */
+ -2, /* (120) joinop ::= JOIN_KW JOIN */
+ -3, /* (121) joinop ::= JOIN_KW nm JOIN */
+ -4, /* (122) joinop ::= JOIN_KW nm nm JOIN */
+ -2, /* (123) on_opt ::= ON expr */
+ 0, /* (124) on_opt ::= */
+ 0, /* (125) indexed_opt ::= */
+ -3, /* (126) indexed_opt ::= INDEXED BY nm */
+ -2, /* (127) indexed_opt ::= NOT INDEXED */
+ -4, /* (128) using_opt ::= USING LP idlist RP */
+ 0, /* (129) using_opt ::= */
+ 0, /* (130) orderby_opt ::= */
+ -3, /* (131) orderby_opt ::= ORDER BY sortlist */
+ -5, /* (132) sortlist ::= sortlist COMMA expr sortorder nulls */
+ -3, /* (133) sortlist ::= expr sortorder nulls */
+ -1, /* (134) sortorder ::= ASC */
+ -1, /* (135) sortorder ::= DESC */
+ 0, /* (136) sortorder ::= */
+ -2, /* (137) nulls ::= NULLS FIRST */
+ -2, /* (138) nulls ::= NULLS LAST */
+ 0, /* (139) nulls ::= */
+ 0, /* (140) groupby_opt ::= */
+ -3, /* (141) groupby_opt ::= GROUP BY nexprlist */
+ 0, /* (142) having_opt ::= */
+ -2, /* (143) having_opt ::= HAVING expr */
+ 0, /* (144) limit_opt ::= */
+ -2, /* (145) limit_opt ::= LIMIT expr */
+ -4, /* (146) limit_opt ::= LIMIT expr OFFSET expr */
+ -4, /* (147) limit_opt ::= LIMIT expr COMMA expr */
+ -6, /* (148) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
+ 0, /* (149) where_opt ::= */
+ -2, /* (150) where_opt ::= WHERE expr */
+ -8, /* (151) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
+ -5, /* (152) setlist ::= setlist COMMA nm EQ expr */
+ -7, /* (153) setlist ::= setlist COMMA LP idlist RP EQ expr */
+ -3, /* (154) setlist ::= nm EQ expr */
+ -5, /* (155) setlist ::= LP idlist RP EQ expr */
+ -7, /* (156) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+ -7, /* (157) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
+ 0, /* (158) upsert ::= */
+ -11, /* (159) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
+ -8, /* (160) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
+ -4, /* (161) upsert ::= ON CONFLICT DO NOTHING */
+ -2, /* (162) insert_cmd ::= INSERT orconf */
+ -1, /* (163) insert_cmd ::= REPLACE */
+ 0, /* (164) idlist_opt ::= */
+ -3, /* (165) idlist_opt ::= LP idlist RP */
+ -3, /* (166) idlist ::= idlist COMMA nm */
+ -1, /* (167) idlist ::= nm */
+ -3, /* (168) expr ::= LP expr RP */
+ -1, /* (169) expr ::= ID|INDEXED */
+ -1, /* (170) expr ::= JOIN_KW */
+ -3, /* (171) expr ::= nm DOT nm */
+ -5, /* (172) expr ::= nm DOT nm DOT nm */
+ -1, /* (173) term ::= NULL|FLOAT|BLOB */
+ -1, /* (174) term ::= STRING */
+ -1, /* (175) term ::= INTEGER */
+ -1, /* (176) expr ::= VARIABLE */
+ -3, /* (177) expr ::= expr COLLATE ID|STRING */
+ -6, /* (178) expr ::= CAST LP expr AS typetoken RP */
+ -5, /* (179) expr ::= ID|INDEXED LP distinct exprlist RP */
+ -4, /* (180) expr ::= ID|INDEXED LP STAR RP */
+ -6, /* (181) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
+ -5, /* (182) expr ::= ID|INDEXED LP STAR RP filter_over */
+ -1, /* (183) term ::= CTIME_KW */
+ -5, /* (184) expr ::= LP nexprlist COMMA expr RP */
+ -3, /* (185) expr ::= expr AND expr */
+ -3, /* (186) expr ::= expr OR expr */
+ -3, /* (187) expr ::= expr LT|GT|GE|LE expr */
+ -3, /* (188) expr ::= expr EQ|NE expr */
+ -3, /* (189) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+ -3, /* (190) expr ::= expr PLUS|MINUS expr */
+ -3, /* (191) expr ::= expr STAR|SLASH|REM expr */
+ -3, /* (192) expr ::= expr CONCAT expr */
+ -2, /* (193) likeop ::= NOT LIKE_KW|MATCH */
+ -3, /* (194) expr ::= expr likeop expr */
+ -5, /* (195) expr ::= expr likeop expr ESCAPE expr */
+ -2, /* (196) expr ::= expr ISNULL|NOTNULL */
+ -3, /* (197) expr ::= expr NOT NULL */
+ -3, /* (198) expr ::= expr IS expr */
+ -4, /* (199) expr ::= expr IS NOT expr */
+ -2, /* (200) expr ::= NOT expr */
+ -2, /* (201) expr ::= BITNOT expr */
+ -2, /* (202) expr ::= PLUS|MINUS expr */
+ -1, /* (203) between_op ::= BETWEEN */
+ -2, /* (204) between_op ::= NOT BETWEEN */
+ -5, /* (205) expr ::= expr between_op expr AND expr */
+ -1, /* (206) in_op ::= IN */
+ -2, /* (207) in_op ::= NOT IN */
+ -5, /* (208) expr ::= expr in_op LP exprlist RP */
+ -3, /* (209) expr ::= LP select RP */
+ -5, /* (210) expr ::= expr in_op LP select RP */
+ -5, /* (211) expr ::= expr in_op nm dbnm paren_exprlist */
+ -4, /* (212) expr ::= EXISTS LP select RP */
+ -5, /* (213) expr ::= CASE case_operand case_exprlist case_else END */
+ -5, /* (214) case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ -4, /* (215) case_exprlist ::= WHEN expr THEN expr */
+ -2, /* (216) case_else ::= ELSE expr */
+ 0, /* (217) case_else ::= */
+ -1, /* (218) case_operand ::= expr */
+ 0, /* (219) case_operand ::= */
+ 0, /* (220) exprlist ::= */
+ -3, /* (221) nexprlist ::= nexprlist COMMA expr */
+ -1, /* (222) nexprlist ::= expr */
+ 0, /* (223) paren_exprlist ::= */
+ -3, /* (224) paren_exprlist ::= LP exprlist RP */
+ -12, /* (225) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ -1, /* (226) uniqueflag ::= UNIQUE */
+ 0, /* (227) uniqueflag ::= */
+ 0, /* (228) eidlist_opt ::= */
+ -3, /* (229) eidlist_opt ::= LP eidlist RP */
+ -5, /* (230) eidlist ::= eidlist COMMA nm collate sortorder */
+ -3, /* (231) eidlist ::= nm collate sortorder */
+ 0, /* (232) collate ::= */
+ -2, /* (233) collate ::= COLLATE ID|STRING */
+ -4, /* (234) cmd ::= DROP INDEX ifexists fullname */
+ -2, /* (235) cmd ::= VACUUM vinto */
+ -3, /* (236) cmd ::= VACUUM nm vinto */
+ -2, /* (237) vinto ::= INTO expr */
+ 0, /* (238) vinto ::= */
+ -3, /* (239) cmd ::= PRAGMA nm dbnm */
+ -5, /* (240) cmd ::= PRAGMA nm dbnm EQ nmnum */
+ -6, /* (241) cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ -5, /* (242) cmd ::= PRAGMA nm dbnm EQ minus_num */
+ -6, /* (243) cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ -2, /* (244) plus_num ::= PLUS INTEGER|FLOAT */
+ -2, /* (245) minus_num ::= MINUS INTEGER|FLOAT */
+ -5, /* (246) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ -11, /* (247) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ -1, /* (248) trigger_time ::= BEFORE|AFTER */
+ -2, /* (249) trigger_time ::= INSTEAD OF */
+ 0, /* (250) trigger_time ::= */
+ -1, /* (251) trigger_event ::= DELETE|INSERT */
+ -1, /* (252) trigger_event ::= UPDATE */
+ -3, /* (253) trigger_event ::= UPDATE OF idlist */
+ 0, /* (254) when_clause ::= */
+ -2, /* (255) when_clause ::= WHEN expr */
+ -3, /* (256) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ -2, /* (257) trigger_cmd_list ::= trigger_cmd SEMI */
+ -3, /* (258) trnm ::= nm DOT nm */
+ -3, /* (259) tridxby ::= INDEXED BY nm */
+ -2, /* (260) tridxby ::= NOT INDEXED */
+ -8, /* (261) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
+ -8, /* (262) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ -6, /* (263) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+ -3, /* (264) trigger_cmd ::= scanpt select scanpt */
+ -4, /* (265) expr ::= RAISE LP IGNORE RP */
+ -6, /* (266) expr ::= RAISE LP raisetype COMMA nm RP */
+ -1, /* (267) raisetype ::= ROLLBACK */
+ -1, /* (268) raisetype ::= ABORT */
+ -1, /* (269) raisetype ::= FAIL */
+ -4, /* (270) cmd ::= DROP TRIGGER ifexists fullname */
+ -6, /* (271) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ -3, /* (272) cmd ::= DETACH database_kw_opt expr */
+ 0, /* (273) key_opt ::= */
+ -2, /* (274) key_opt ::= KEY expr */
+ -1, /* (275) cmd ::= REINDEX */
+ -3, /* (276) cmd ::= REINDEX nm dbnm */
+ -1, /* (277) cmd ::= ANALYZE */
+ -3, /* (278) cmd ::= ANALYZE nm dbnm */
+ -6, /* (279) cmd ::= ALTER TABLE fullname RENAME TO nm */
+ -7, /* (280) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ -1, /* (281) add_column_fullname ::= fullname */
+ -8, /* (282) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ -1, /* (283) cmd ::= create_vtab */
+ -4, /* (284) cmd ::= create_vtab LP vtabarglist RP */
+ -8, /* (285) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ 0, /* (286) vtabarg ::= */
+ -1, /* (287) vtabargtoken ::= ANY */
+ -3, /* (288) vtabargtoken ::= lp anylist RP */
+ -1, /* (289) lp ::= LP */
+ -2, /* (290) with ::= WITH wqlist */
+ -3, /* (291) with ::= WITH RECURSIVE wqlist */
+ -6, /* (292) wqlist ::= nm eidlist_opt AS LP select RP */
+ -8, /* (293) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
+ -1, /* (294) windowdefn_list ::= windowdefn */
+ -3, /* (295) windowdefn_list ::= windowdefn_list COMMA windowdefn */
+ -5, /* (296) windowdefn ::= nm AS LP window RP */
+ -5, /* (297) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
+ -6, /* (298) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
+ -4, /* (299) window ::= ORDER BY sortlist frame_opt */
+ -5, /* (300) window ::= nm ORDER BY sortlist frame_opt */
+ -1, /* (301) window ::= frame_opt */
+ -2, /* (302) window ::= nm frame_opt */
+ 0, /* (303) frame_opt ::= */
+ -3, /* (304) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
+ -6, /* (305) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
+ -1, /* (306) range_or_rows ::= RANGE|ROWS|GROUPS */
+ -1, /* (307) frame_bound_s ::= frame_bound */
+ -2, /* (308) frame_bound_s ::= UNBOUNDED PRECEDING */
+ -1, /* (309) frame_bound_e ::= frame_bound */
+ -2, /* (310) frame_bound_e ::= UNBOUNDED FOLLOWING */
+ -2, /* (311) frame_bound ::= expr PRECEDING|FOLLOWING */
+ -2, /* (312) frame_bound ::= CURRENT ROW */
+ 0, /* (313) frame_exclude_opt ::= */
+ -2, /* (314) frame_exclude_opt ::= EXCLUDE frame_exclude */
+ -2, /* (315) frame_exclude ::= NO OTHERS */
+ -2, /* (316) frame_exclude ::= CURRENT ROW */
+ -1, /* (317) frame_exclude ::= GROUP|TIES */
+ -2, /* (318) window_clause ::= WINDOW windowdefn_list */
+ -2, /* (319) filter_over ::= filter_clause over_clause */
+ -1, /* (320) filter_over ::= over_clause */
+ -1, /* (321) filter_over ::= filter_clause */
+ -4, /* (322) over_clause ::= OVER LP window RP */
+ -2, /* (323) over_clause ::= OVER nm */
+ -5, /* (324) filter_clause ::= FILTER LP WHERE expr RP */
+ -1, /* (325) input ::= cmdlist */
+ -2, /* (326) cmdlist ::= cmdlist ecmd */
+ -1, /* (327) cmdlist ::= ecmd */
+ -1, /* (328) ecmd ::= SEMI */
+ -2, /* (329) ecmd ::= cmdx SEMI */
+ -3, /* (330) ecmd ::= explain cmdx SEMI */
+ 0, /* (331) trans_opt ::= */
+ -1, /* (332) trans_opt ::= TRANSACTION */
+ -2, /* (333) trans_opt ::= TRANSACTION nm */
+ -1, /* (334) savepoint_opt ::= SAVEPOINT */
+ 0, /* (335) savepoint_opt ::= */
+ -2, /* (336) cmd ::= create_table create_table_args */
+ -4, /* (337) columnlist ::= columnlist COMMA columnname carglist */
+ -2, /* (338) columnlist ::= columnname carglist */
+ -1, /* (339) nm ::= ID|INDEXED */
+ -1, /* (340) nm ::= STRING */
+ -1, /* (341) nm ::= JOIN_KW */
+ -1, /* (342) typetoken ::= typename */
+ -1, /* (343) typename ::= ID|STRING */
+ -1, /* (344) signed ::= plus_num */
+ -1, /* (345) signed ::= minus_num */
+ -2, /* (346) carglist ::= carglist ccons */
+ 0, /* (347) carglist ::= */
+ -2, /* (348) ccons ::= NULL onconf */
+ -4, /* (349) ccons ::= GENERATED ALWAYS AS generated */
+ -2, /* (350) ccons ::= AS generated */
+ -2, /* (351) conslist_opt ::= COMMA conslist */
+ -3, /* (352) conslist ::= conslist tconscomma tcons */
+ -1, /* (353) conslist ::= tcons */
+ 0, /* (354) tconscomma ::= */
+ -1, /* (355) defer_subclause_opt ::= defer_subclause */
+ -1, /* (356) resolvetype ::= raisetype */
+ -1, /* (357) selectnowith ::= oneselect */
+ -1, /* (358) oneselect ::= values */
+ -2, /* (359) sclp ::= selcollist COMMA */
+ -1, /* (360) as ::= ID|STRING */
+ -1, /* (361) expr ::= term */
+ -1, /* (362) likeop ::= LIKE_KW|MATCH */
+ -1, /* (363) exprlist ::= nexprlist */
+ -1, /* (364) nmnum ::= plus_num */
+ -1, /* (365) nmnum ::= nm */
+ -1, /* (366) nmnum ::= ON */
+ -1, /* (367) nmnum ::= DELETE */
+ -1, /* (368) nmnum ::= DEFAULT */
+ -1, /* (369) plus_num ::= INTEGER|FLOAT */
+ 0, /* (370) foreach_clause ::= */
+ -3, /* (371) foreach_clause ::= FOR EACH ROW */
+ -1, /* (372) trnm ::= nm */
+ 0, /* (373) tridxby ::= */
+ -1, /* (374) database_kw_opt ::= DATABASE */
+ 0, /* (375) database_kw_opt ::= */
+ 0, /* (376) kwcolumn_opt ::= */
+ -1, /* (377) kwcolumn_opt ::= COLUMNKW */
+ -1, /* (378) vtabarglist ::= vtabarg */
+ -3, /* (379) vtabarglist ::= vtabarglist COMMA vtabarg */
+ -2, /* (380) vtabarg ::= vtabarg vtabargtoken */
+ 0, /* (381) anylist ::= */
+ -4, /* (382) anylist ::= anylist LP anylist RP */
+ -2, /* (383) anylist ::= anylist ANY */
+ 0, /* (384) with ::= */
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -152915,12 +155549,15 @@ static YYACTIONTYPE yy_reduce(
if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){
- fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n",
+ fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
yyTracePrompt,
- yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno);
+ yyruleno, yyRuleName[yyruleno],
+ yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
+ yymsp[yysize].stateno);
}else{
- fprintf(yyTraceFILE, "%sReduce %d [%s].\n",
- yyTracePrompt, yyruleno, yyRuleName[yyruleno]);
+ fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
+ yyTracePrompt, yyruleno, yyRuleName[yyruleno],
+ yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
}
}
#endif /* NDEBUG */
@@ -152978,16 +155615,16 @@ static YYACTIONTYPE yy_reduce(
{ sqlite3FinishCoding(pParse); }
break;
case 3: /* cmd ::= BEGIN transtype trans_opt */
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy32);}
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy192);}
break;
case 4: /* transtype ::= */
-{yymsp[1].minor.yy32 = TK_DEFERRED;}
+{yymsp[1].minor.yy192 = TK_DEFERRED;}
break;
case 5: /* transtype ::= DEFERRED */
case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6);
case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7);
- case 304: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==304);
-{yymsp[0].minor.yy32 = yymsp[0].major; /*A-overwrites-X*/}
+ case 306: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==306);
+{yymsp[0].minor.yy192 = yymsp[0].major; /*A-overwrites-X*/}
break;
case 8: /* cmd ::= COMMIT|END trans_opt */
case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9);
@@ -153010,7 +155647,7 @@ static YYACTIONTYPE yy_reduce(
break;
case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
{
- sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy32,0,0,yymsp[-2].minor.yy32);
+ sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy192,0,0,yymsp[-2].minor.yy192);
}
break;
case 14: /* createkw ::= CREATE */
@@ -153019,38 +155656,38 @@ static YYACTIONTYPE yy_reduce(
case 15: /* ifnotexists ::= */
case 18: /* temp ::= */ yytestcase(yyruleno==18);
case 21: /* table_options ::= */ yytestcase(yyruleno==21);
- case 43: /* autoinc ::= */ yytestcase(yyruleno==43);
- case 58: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==58);
- case 68: /* defer_subclause_opt ::= */ yytestcase(yyruleno==68);
- case 77: /* ifexists ::= */ yytestcase(yyruleno==77);
- case 94: /* distinct ::= */ yytestcase(yyruleno==94);
- case 230: /* collate ::= */ yytestcase(yyruleno==230);
-{yymsp[1].minor.yy32 = 0;}
+ case 45: /* autoinc ::= */ yytestcase(yyruleno==45);
+ case 60: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==60);
+ case 70: /* defer_subclause_opt ::= */ yytestcase(yyruleno==70);
+ case 79: /* ifexists ::= */ yytestcase(yyruleno==79);
+ case 96: /* distinct ::= */ yytestcase(yyruleno==96);
+ case 232: /* collate ::= */ yytestcase(yyruleno==232);
+{yymsp[1].minor.yy192 = 0;}
break;
case 16: /* ifnotexists ::= IF NOT EXISTS */
-{yymsp[-2].minor.yy32 = 1;}
+{yymsp[-2].minor.yy192 = 1;}
break;
case 17: /* temp ::= TEMP */
- case 44: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==44);
-{yymsp[0].minor.yy32 = 1;}
+ case 46: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==46);
+{yymsp[0].minor.yy192 = 1;}
break;
case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_options */
{
- sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy32,0);
+ sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy192,0);
}
break;
case 20: /* create_table_args ::= AS select */
{
- sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy25);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy25);
+ sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy539);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy539);
}
break;
case 22: /* table_options ::= WITHOUT nm */
{
if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){
- yymsp[-1].minor.yy32 = TF_WithoutRowid | TF_NoVisibleRowid;
+ yymsp[-1].minor.yy192 = TF_WithoutRowid | TF_NoVisibleRowid;
}else{
- yymsp[-1].minor.yy32 = 0;
+ yymsp[-1].minor.yy192 = 0;
sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
}
}
@@ -153059,8 +155696,8 @@ static YYACTIONTYPE yy_reduce(
{sqlite3AddColumn(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
break;
case 24: /* typetoken ::= */
- case 61: /* conslist_opt ::= */ yytestcase(yyruleno==61);
- case 100: /* as ::= */ yytestcase(yyruleno==100);
+ case 63: /* conslist_opt ::= */ yytestcase(yyruleno==63);
+ case 102: /* as ::= */ yytestcase(yyruleno==102);
{yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;}
break;
case 25: /* typetoken ::= typename LP signed RP */
@@ -153079,7 +155716,7 @@ static YYACTIONTYPE yy_reduce(
case 28: /* scanpt ::= */
{
assert( yyLookahead!=YYNOCODE );
- yymsp[1].minor.yy8 = yyLookaheadToken.z;
+ yymsp[1].minor.yy436 = yyLookaheadToken.z;
}
break;
case 29: /* scantok ::= */
@@ -153089,21 +155726,21 @@ static YYACTIONTYPE yy_reduce(
}
break;
case 30: /* ccons ::= CONSTRAINT nm */
- case 63: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==63);
+ case 65: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==65);
{pParse->constraintName = yymsp[0].minor.yy0;}
break;
case 31: /* ccons ::= DEFAULT scantok term */
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy46,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy202,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
break;
case 32: /* ccons ::= DEFAULT LP expr RP */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy46,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy202,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
break;
case 33: /* ccons ::= DEFAULT PLUS scantok term */
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy46,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy202,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
break;
case 34: /* ccons ::= DEFAULT MINUS scantok term */
{
- Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy46, 0);
+ Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy202, 0);
sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);
}
break;
@@ -153118,170 +155755,176 @@ static YYACTIONTYPE yy_reduce(
}
break;
case 36: /* ccons ::= NOT NULL onconf */
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy32);}
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy192);}
break;
case 37: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy32,yymsp[0].minor.yy32,yymsp[-2].minor.yy32);}
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy192,yymsp[0].minor.yy192,yymsp[-2].minor.yy192);}
break;
case 38: /* ccons ::= UNIQUE onconf */
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy32,0,0,0,0,
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy192,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
case 39: /* ccons ::= CHECK LP expr RP */
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy46);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy202);}
break;
case 40: /* ccons ::= REFERENCES nm eidlist_opt refargs */
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy138,yymsp[0].minor.yy32);}
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy242,yymsp[0].minor.yy192);}
break;
case 41: /* ccons ::= defer_subclause */
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy32);}
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy192);}
break;
case 42: /* ccons ::= COLLATE ID|STRING */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
break;
- case 45: /* refargs ::= */
-{ yymsp[1].minor.yy32 = OE_None*0x0101; /* EV: R-19803-45884 */}
+ case 43: /* generated ::= LP expr RP */
+{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy202,0);}
+ break;
+ case 44: /* generated ::= LP expr RP ID */
+{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy202,&yymsp[0].minor.yy0);}
break;
- case 46: /* refargs ::= refargs refarg */
-{ yymsp[-1].minor.yy32 = (yymsp[-1].minor.yy32 & ~yymsp[0].minor.yy495.mask) | yymsp[0].minor.yy495.value; }
+ case 47: /* refargs ::= */
+{ yymsp[1].minor.yy192 = OE_None*0x0101; /* EV: R-19803-45884 */}
break;
- case 47: /* refarg ::= MATCH nm */
-{ yymsp[-1].minor.yy495.value = 0; yymsp[-1].minor.yy495.mask = 0x000000; }
+ case 48: /* refargs ::= refargs refarg */
+{ yymsp[-1].minor.yy192 = (yymsp[-1].minor.yy192 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; }
break;
- case 48: /* refarg ::= ON INSERT refact */
-{ yymsp[-2].minor.yy495.value = 0; yymsp[-2].minor.yy495.mask = 0x000000; }
+ case 49: /* refarg ::= MATCH nm */
+{ yymsp[-1].minor.yy207.value = 0; yymsp[-1].minor.yy207.mask = 0x000000; }
break;
- case 49: /* refarg ::= ON DELETE refact */
-{ yymsp[-2].minor.yy495.value = yymsp[0].minor.yy32; yymsp[-2].minor.yy495.mask = 0x0000ff; }
+ case 50: /* refarg ::= ON INSERT refact */
+{ yymsp[-2].minor.yy207.value = 0; yymsp[-2].minor.yy207.mask = 0x000000; }
break;
- case 50: /* refarg ::= ON UPDATE refact */
-{ yymsp[-2].minor.yy495.value = yymsp[0].minor.yy32<<8; yymsp[-2].minor.yy495.mask = 0x00ff00; }
+ case 51: /* refarg ::= ON DELETE refact */
+{ yymsp[-2].minor.yy207.value = yymsp[0].minor.yy192; yymsp[-2].minor.yy207.mask = 0x0000ff; }
break;
- case 51: /* refact ::= SET NULL */
-{ yymsp[-1].minor.yy32 = OE_SetNull; /* EV: R-33326-45252 */}
+ case 52: /* refarg ::= ON UPDATE refact */
+{ yymsp[-2].minor.yy207.value = yymsp[0].minor.yy192<<8; yymsp[-2].minor.yy207.mask = 0x00ff00; }
break;
- case 52: /* refact ::= SET DEFAULT */
-{ yymsp[-1].minor.yy32 = OE_SetDflt; /* EV: R-33326-45252 */}
+ case 53: /* refact ::= SET NULL */
+{ yymsp[-1].minor.yy192 = OE_SetNull; /* EV: R-33326-45252 */}
break;
- case 53: /* refact ::= CASCADE */
-{ yymsp[0].minor.yy32 = OE_Cascade; /* EV: R-33326-45252 */}
+ case 54: /* refact ::= SET DEFAULT */
+{ yymsp[-1].minor.yy192 = OE_SetDflt; /* EV: R-33326-45252 */}
break;
- case 54: /* refact ::= RESTRICT */
-{ yymsp[0].minor.yy32 = OE_Restrict; /* EV: R-33326-45252 */}
+ case 55: /* refact ::= CASCADE */
+{ yymsp[0].minor.yy192 = OE_Cascade; /* EV: R-33326-45252 */}
break;
- case 55: /* refact ::= NO ACTION */
-{ yymsp[-1].minor.yy32 = OE_None; /* EV: R-33326-45252 */}
+ case 56: /* refact ::= RESTRICT */
+{ yymsp[0].minor.yy192 = OE_Restrict; /* EV: R-33326-45252 */}
break;
- case 56: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
-{yymsp[-2].minor.yy32 = 0;}
+ case 57: /* refact ::= NO ACTION */
+{ yymsp[-1].minor.yy192 = OE_None; /* EV: R-33326-45252 */}
break;
- case 57: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
- case 72: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==72);
- case 160: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==160);
-{yymsp[-1].minor.yy32 = yymsp[0].minor.yy32;}
+ case 58: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
+{yymsp[-2].minor.yy192 = 0;}
break;
- case 59: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
- case 76: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==76);
- case 202: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==202);
- case 205: /* in_op ::= NOT IN */ yytestcase(yyruleno==205);
- case 231: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==231);
-{yymsp[-1].minor.yy32 = 1;}
+ case 59: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+ case 74: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==74);
+ case 162: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==162);
+{yymsp[-1].minor.yy192 = yymsp[0].minor.yy192;}
break;
- case 60: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
-{yymsp[-1].minor.yy32 = 0;}
+ case 61: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
+ case 78: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==78);
+ case 204: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==204);
+ case 207: /* in_op ::= NOT IN */ yytestcase(yyruleno==207);
+ case 233: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==233);
+{yymsp[-1].minor.yy192 = 1;}
break;
- case 62: /* tconscomma ::= COMMA */
+ case 62: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
+{yymsp[-1].minor.yy192 = 0;}
+ break;
+ case 64: /* tconscomma ::= COMMA */
{pParse->constraintName.n = 0;}
break;
- case 64: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy138,yymsp[0].minor.yy32,yymsp[-2].minor.yy32,0);}
+ case 66: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy242,yymsp[0].minor.yy192,yymsp[-2].minor.yy192,0);}
break;
- case 65: /* tcons ::= UNIQUE LP sortlist RP onconf */
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy138,yymsp[0].minor.yy32,0,0,0,0,
+ case 67: /* tcons ::= UNIQUE LP sortlist RP onconf */
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy242,yymsp[0].minor.yy192,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
- case 66: /* tcons ::= CHECK LP expr RP onconf */
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy46);}
+ case 68: /* tcons ::= CHECK LP expr RP onconf */
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy202);}
break;
- case 67: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
+ case 69: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
{
- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy138, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy138, yymsp[-1].minor.yy32);
- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy32);
+ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy242, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy242, yymsp[-1].minor.yy192);
+ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy192);
}
break;
- case 69: /* onconf ::= */
- case 71: /* orconf ::= */ yytestcase(yyruleno==71);
-{yymsp[1].minor.yy32 = OE_Default;}
+ case 71: /* onconf ::= */
+ case 73: /* orconf ::= */ yytestcase(yyruleno==73);
+{yymsp[1].minor.yy192 = OE_Default;}
break;
- case 70: /* onconf ::= ON CONFLICT resolvetype */
-{yymsp[-2].minor.yy32 = yymsp[0].minor.yy32;}
+ case 72: /* onconf ::= ON CONFLICT resolvetype */
+{yymsp[-2].minor.yy192 = yymsp[0].minor.yy192;}
break;
- case 73: /* resolvetype ::= IGNORE */
-{yymsp[0].minor.yy32 = OE_Ignore;}
+ case 75: /* resolvetype ::= IGNORE */
+{yymsp[0].minor.yy192 = OE_Ignore;}
break;
- case 74: /* resolvetype ::= REPLACE */
- case 161: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==161);
-{yymsp[0].minor.yy32 = OE_Replace;}
+ case 76: /* resolvetype ::= REPLACE */
+ case 163: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==163);
+{yymsp[0].minor.yy192 = OE_Replace;}
break;
- case 75: /* cmd ::= DROP TABLE ifexists fullname */
+ case 77: /* cmd ::= DROP TABLE ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy609, 0, yymsp[-1].minor.yy32);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy47, 0, yymsp[-1].minor.yy192);
}
break;
- case 78: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
+ case 80: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
{
- sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy138, yymsp[0].minor.yy25, yymsp[-7].minor.yy32, yymsp[-5].minor.yy32);
+ sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy242, yymsp[0].minor.yy539, yymsp[-7].minor.yy192, yymsp[-5].minor.yy192);
}
break;
- case 79: /* cmd ::= DROP VIEW ifexists fullname */
+ case 81: /* cmd ::= DROP VIEW ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy609, 1, yymsp[-1].minor.yy32);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy47, 1, yymsp[-1].minor.yy192);
}
break;
- case 80: /* cmd ::= select */
+ case 82: /* cmd ::= select */
{
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
- sqlite3Select(pParse, yymsp[0].minor.yy25, &dest);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy25);
+ sqlite3Select(pParse, yymsp[0].minor.yy539, &dest);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy539);
}
break;
- case 81: /* select ::= WITH wqlist selectnowith */
+ case 83: /* select ::= WITH wqlist selectnowith */
{
- Select *p = yymsp[0].minor.yy25;
+ Select *p = yymsp[0].minor.yy539;
if( p ){
- p->pWith = yymsp[-1].minor.yy297;
+ p->pWith = yymsp[-1].minor.yy131;
parserDoubleLinkSelect(pParse, p);
}else{
- sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy297);
+ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy131);
}
- yymsp[-2].minor.yy25 = p;
+ yymsp[-2].minor.yy539 = p;
}
break;
- case 82: /* select ::= WITH RECURSIVE wqlist selectnowith */
+ case 84: /* select ::= WITH RECURSIVE wqlist selectnowith */
{
- Select *p = yymsp[0].minor.yy25;
+ Select *p = yymsp[0].minor.yy539;
if( p ){
- p->pWith = yymsp[-1].minor.yy297;
+ p->pWith = yymsp[-1].minor.yy131;
parserDoubleLinkSelect(pParse, p);
}else{
- sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy297);
+ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy131);
}
- yymsp[-3].minor.yy25 = p;
+ yymsp[-3].minor.yy539 = p;
}
break;
- case 83: /* select ::= selectnowith */
+ case 85: /* select ::= selectnowith */
{
- Select *p = yymsp[0].minor.yy25;
+ Select *p = yymsp[0].minor.yy539;
if( p ){
parserDoubleLinkSelect(pParse, p);
}
- yymsp[0].minor.yy25 = p; /*A-overwrites-X*/
+ yymsp[0].minor.yy539 = p; /*A-overwrites-X*/
}
break;
- case 84: /* selectnowith ::= selectnowith multiselect_op oneselect */
+ case 86: /* selectnowith ::= selectnowith multiselect_op oneselect */
{
- Select *pRhs = yymsp[0].minor.yy25;
- Select *pLhs = yymsp[-2].minor.yy25;
+ Select *pRhs = yymsp[0].minor.yy539;
+ Select *pLhs = yymsp[-2].minor.yy539;
if( pRhs && pRhs->pPrior ){
SrcList *pFrom;
Token x;
@@ -153291,142 +155934,142 @@ static YYACTIONTYPE yy_reduce(
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
}
if( pRhs ){
- pRhs->op = (u8)yymsp[-1].minor.yy32;
+ pRhs->op = (u8)yymsp[-1].minor.yy192;
pRhs->pPrior = pLhs;
if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
pRhs->selFlags &= ~SF_MultiValue;
- if( yymsp[-1].minor.yy32!=TK_ALL ) pParse->hasCompound = 1;
+ if( yymsp[-1].minor.yy192!=TK_ALL ) pParse->hasCompound = 1;
}else{
sqlite3SelectDelete(pParse->db, pLhs);
}
- yymsp[-2].minor.yy25 = pRhs;
+ yymsp[-2].minor.yy539 = pRhs;
}
break;
- case 85: /* multiselect_op ::= UNION */
- case 87: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==87);
-{yymsp[0].minor.yy32 = yymsp[0].major; /*A-overwrites-OP*/}
+ case 87: /* multiselect_op ::= UNION */
+ case 89: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==89);
+{yymsp[0].minor.yy192 = yymsp[0].major; /*A-overwrites-OP*/}
break;
- case 86: /* multiselect_op ::= UNION ALL */
-{yymsp[-1].minor.yy32 = TK_ALL;}
+ case 88: /* multiselect_op ::= UNION ALL */
+{yymsp[-1].minor.yy192 = TK_ALL;}
break;
- case 88: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ case 90: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
- yymsp[-8].minor.yy25 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy138,yymsp[-5].minor.yy609,yymsp[-4].minor.yy46,yymsp[-3].minor.yy138,yymsp[-2].minor.yy46,yymsp[-1].minor.yy138,yymsp[-7].minor.yy32,yymsp[0].minor.yy46);
+ yymsp[-8].minor.yy539 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy242,yymsp[-5].minor.yy47,yymsp[-4].minor.yy202,yymsp[-3].minor.yy242,yymsp[-2].minor.yy202,yymsp[-1].minor.yy242,yymsp[-7].minor.yy192,yymsp[0].minor.yy202);
}
break;
- case 89: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
+ case 91: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
{
- yymsp[-9].minor.yy25 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy138,yymsp[-6].minor.yy609,yymsp[-5].minor.yy46,yymsp[-4].minor.yy138,yymsp[-3].minor.yy46,yymsp[-1].minor.yy138,yymsp[-8].minor.yy32,yymsp[0].minor.yy46);
- if( yymsp[-9].minor.yy25 ){
- yymsp[-9].minor.yy25->pWinDefn = yymsp[-2].minor.yy455;
+ yymsp[-9].minor.yy539 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy242,yymsp[-6].minor.yy47,yymsp[-5].minor.yy202,yymsp[-4].minor.yy242,yymsp[-3].minor.yy202,yymsp[-1].minor.yy242,yymsp[-8].minor.yy192,yymsp[0].minor.yy202);
+ if( yymsp[-9].minor.yy539 ){
+ yymsp[-9].minor.yy539->pWinDefn = yymsp[-2].minor.yy303;
}else{
- sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy455);
+ sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy303);
}
}
break;
- case 90: /* values ::= VALUES LP nexprlist RP */
+ case 92: /* values ::= VALUES LP nexprlist RP */
{
- yymsp[-3].minor.yy25 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy138,0,0,0,0,0,SF_Values,0);
+ yymsp[-3].minor.yy539 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy242,0,0,0,0,0,SF_Values,0);
}
break;
- case 91: /* values ::= values COMMA LP nexprlist RP */
+ case 93: /* values ::= values COMMA LP nexprlist RP */
{
- Select *pRight, *pLeft = yymsp[-4].minor.yy25;
- pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy138,0,0,0,0,0,SF_Values|SF_MultiValue,0);
+ Select *pRight, *pLeft = yymsp[-4].minor.yy539;
+ pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy242,0,0,0,0,0,SF_Values|SF_MultiValue,0);
if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
if( pRight ){
pRight->op = TK_ALL;
pRight->pPrior = pLeft;
- yymsp[-4].minor.yy25 = pRight;
+ yymsp[-4].minor.yy539 = pRight;
}else{
- yymsp[-4].minor.yy25 = pLeft;
+ yymsp[-4].minor.yy539 = pLeft;
}
}
break;
- case 92: /* distinct ::= DISTINCT */
-{yymsp[0].minor.yy32 = SF_Distinct;}
+ case 94: /* distinct ::= DISTINCT */
+{yymsp[0].minor.yy192 = SF_Distinct;}
break;
- case 93: /* distinct ::= ALL */
-{yymsp[0].minor.yy32 = SF_All;}
+ case 95: /* distinct ::= ALL */
+{yymsp[0].minor.yy192 = SF_All;}
break;
- case 95: /* sclp ::= */
- case 128: /* orderby_opt ::= */ yytestcase(yyruleno==128);
- case 138: /* groupby_opt ::= */ yytestcase(yyruleno==138);
- case 218: /* exprlist ::= */ yytestcase(yyruleno==218);
- case 221: /* paren_exprlist ::= */ yytestcase(yyruleno==221);
- case 226: /* eidlist_opt ::= */ yytestcase(yyruleno==226);
-{yymsp[1].minor.yy138 = 0;}
+ case 97: /* sclp ::= */
+ case 130: /* orderby_opt ::= */ yytestcase(yyruleno==130);
+ case 140: /* groupby_opt ::= */ yytestcase(yyruleno==140);
+ case 220: /* exprlist ::= */ yytestcase(yyruleno==220);
+ case 223: /* paren_exprlist ::= */ yytestcase(yyruleno==223);
+ case 228: /* eidlist_opt ::= */ yytestcase(yyruleno==228);
+{yymsp[1].minor.yy242 = 0;}
break;
- case 96: /* selcollist ::= sclp scanpt expr scanpt as */
+ case 98: /* selcollist ::= sclp scanpt expr scanpt as */
{
- yymsp[-4].minor.yy138 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy138, yymsp[-2].minor.yy46);
- if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy138, &yymsp[0].minor.yy0, 1);
- sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy138,yymsp[-3].minor.yy8,yymsp[-1].minor.yy8);
+ yymsp[-4].minor.yy242 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy242, yymsp[-2].minor.yy202);
+ if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy242, &yymsp[0].minor.yy0, 1);
+ sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy242,yymsp[-3].minor.yy436,yymsp[-1].minor.yy436);
}
break;
- case 97: /* selcollist ::= sclp scanpt STAR */
+ case 99: /* selcollist ::= sclp scanpt STAR */
{
Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
- yymsp[-2].minor.yy138 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy138, p);
+ yymsp[-2].minor.yy242 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy242, p);
}
break;
- case 98: /* selcollist ::= sclp scanpt nm DOT STAR */
+ case 100: /* selcollist ::= sclp scanpt nm DOT STAR */
{
Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
- yymsp[-4].minor.yy138 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy138, pDot);
+ yymsp[-4].minor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, pDot);
}
break;
- case 99: /* as ::= AS nm */
- case 110: /* dbnm ::= DOT nm */ yytestcase(yyruleno==110);
- case 242: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==242);
- case 243: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==243);
+ case 101: /* as ::= AS nm */
+ case 112: /* dbnm ::= DOT nm */ yytestcase(yyruleno==112);
+ case 244: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==244);
+ case 245: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==245);
{yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;}
break;
- case 101: /* from ::= */
-{yymsp[1].minor.yy609 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy609));}
+ case 103: /* from ::= */
+{yymsp[1].minor.yy47 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy47));}
break;
- case 102: /* from ::= FROM seltablist */
+ case 104: /* from ::= FROM seltablist */
{
- yymsp[-1].minor.yy609 = yymsp[0].minor.yy609;
- sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy609);
+ yymsp[-1].minor.yy47 = yymsp[0].minor.yy47;
+ sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy47);
}
break;
- case 103: /* stl_prefix ::= seltablist joinop */
+ case 105: /* stl_prefix ::= seltablist joinop */
{
- if( ALWAYS(yymsp[-1].minor.yy609 && yymsp[-1].minor.yy609->nSrc>0) ) yymsp[-1].minor.yy609->a[yymsp[-1].minor.yy609->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy32;
+ if( ALWAYS(yymsp[-1].minor.yy47 && yymsp[-1].minor.yy47->nSrc>0) ) yymsp[-1].minor.yy47->a[yymsp[-1].minor.yy47->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy192;
}
break;
- case 104: /* stl_prefix ::= */
-{yymsp[1].minor.yy609 = 0;}
+ case 106: /* stl_prefix ::= */
+{yymsp[1].minor.yy47 = 0;}
break;
- case 105: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+ case 107: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
{
- yymsp[-6].minor.yy609 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy609,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy46,yymsp[0].minor.yy406);
- sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy609, &yymsp[-2].minor.yy0);
+ yymsp[-6].minor.yy47 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy47,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy47, &yymsp[-2].minor.yy0);
}
break;
- case 106: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
+ case 108: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
{
- yymsp[-8].minor.yy609 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy609,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy46,yymsp[0].minor.yy406);
- sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy609, yymsp[-4].minor.yy138);
+ yymsp[-8].minor.yy47 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy47,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
+ sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy47, yymsp[-4].minor.yy242);
}
break;
- case 107: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+ case 109: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
{
- yymsp[-6].minor.yy609 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy609,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy25,yymsp[-1].minor.yy46,yymsp[0].minor.yy406);
+ yymsp[-6].minor.yy47 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy47,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy539,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
}
break;
- case 108: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+ case 110: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
{
- if( yymsp[-6].minor.yy609==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy46==0 && yymsp[0].minor.yy406==0 ){
- yymsp[-6].minor.yy609 = yymsp[-4].minor.yy609;
- }else if( yymsp[-4].minor.yy609->nSrc==1 ){
- yymsp[-6].minor.yy609 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy609,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy46,yymsp[0].minor.yy406);
- if( yymsp[-6].minor.yy609 ){
- struct SrcList_item *pNew = &yymsp[-6].minor.yy609->a[yymsp[-6].minor.yy609->nSrc-1];
- struct SrcList_item *pOld = yymsp[-4].minor.yy609->a;
+ if( yymsp[-6].minor.yy47==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy202==0 && yymsp[0].minor.yy600==0 ){
+ yymsp[-6].minor.yy47 = yymsp[-4].minor.yy47;
+ }else if( yymsp[-4].minor.yy47->nSrc==1 ){
+ yymsp[-6].minor.yy47 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy47,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
+ if( yymsp[-6].minor.yy47 ){
+ struct SrcList_item *pNew = &yymsp[-6].minor.yy47->a[yymsp[-6].minor.yy47->nSrc-1];
+ struct SrcList_item *pOld = yymsp[-4].minor.yy47->a;
pNew->zName = pOld->zName;
pNew->zDatabase = pOld->zDatabase;
pNew->pSelect = pOld->pSelect;
@@ -153439,208 +156082,208 @@ static YYACTIONTYPE yy_reduce(
pOld->zName = pOld->zDatabase = 0;
pOld->pSelect = 0;
}
- sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy609);
+ sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy47);
}else{
Select *pSubquery;
- sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy609);
- pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy609,0,0,0,0,SF_NestedFrom,0);
- yymsp[-6].minor.yy609 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy609,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy46,yymsp[0].minor.yy406);
+ sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy47);
+ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy47,0,0,0,0,SF_NestedFrom,0);
+ yymsp[-6].minor.yy47 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy47,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
}
}
break;
- case 109: /* dbnm ::= */
- case 123: /* indexed_opt ::= */ yytestcase(yyruleno==123);
+ case 111: /* dbnm ::= */
+ case 125: /* indexed_opt ::= */ yytestcase(yyruleno==125);
{yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;}
break;
- case 111: /* fullname ::= nm */
+ case 113: /* fullname ::= nm */
{
- yylhsminor.yy609 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
- if( IN_RENAME_OBJECT && yylhsminor.yy609 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy609->a[0].zName, &yymsp[0].minor.yy0);
+ yylhsminor.yy47 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
+ if( IN_RENAME_OBJECT && yylhsminor.yy47 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy47->a[0].zName, &yymsp[0].minor.yy0);
}
- yymsp[0].minor.yy609 = yylhsminor.yy609;
+ yymsp[0].minor.yy47 = yylhsminor.yy47;
break;
- case 112: /* fullname ::= nm DOT nm */
+ case 114: /* fullname ::= nm DOT nm */
{
- yylhsminor.yy609 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
- if( IN_RENAME_OBJECT && yylhsminor.yy609 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy609->a[0].zName, &yymsp[0].minor.yy0);
+ yylhsminor.yy47 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ if( IN_RENAME_OBJECT && yylhsminor.yy47 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy47->a[0].zName, &yymsp[0].minor.yy0);
}
- yymsp[-2].minor.yy609 = yylhsminor.yy609;
+ yymsp[-2].minor.yy47 = yylhsminor.yy47;
break;
- case 113: /* xfullname ::= nm */
-{yymsp[0].minor.yy609 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
+ case 115: /* xfullname ::= nm */
+{yymsp[0].minor.yy47 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
break;
- case 114: /* xfullname ::= nm DOT nm */
-{yymsp[-2].minor.yy609 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
+ case 116: /* xfullname ::= nm DOT nm */
+{yymsp[-2].minor.yy47 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 115: /* xfullname ::= nm DOT nm AS nm */
+ case 117: /* xfullname ::= nm DOT nm AS nm */
{
- yymsp[-4].minor.yy609 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
- if( yymsp[-4].minor.yy609 ) yymsp[-4].minor.yy609->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ yymsp[-4].minor.yy47 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
+ if( yymsp[-4].minor.yy47 ) yymsp[-4].minor.yy47->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
- case 116: /* xfullname ::= nm AS nm */
+ case 118: /* xfullname ::= nm AS nm */
{
- yymsp[-2].minor.yy609 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
- if( yymsp[-2].minor.yy609 ) yymsp[-2].minor.yy609->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ yymsp[-2].minor.yy47 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
+ if( yymsp[-2].minor.yy47 ) yymsp[-2].minor.yy47->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
- case 117: /* joinop ::= COMMA|JOIN */
-{ yymsp[0].minor.yy32 = JT_INNER; }
+ case 119: /* joinop ::= COMMA|JOIN */
+{ yymsp[0].minor.yy192 = JT_INNER; }
break;
- case 118: /* joinop ::= JOIN_KW JOIN */
-{yymsp[-1].minor.yy32 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
+ case 120: /* joinop ::= JOIN_KW JOIN */
+{yymsp[-1].minor.yy192 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
break;
- case 119: /* joinop ::= JOIN_KW nm JOIN */
-{yymsp[-2].minor.yy32 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
+ case 121: /* joinop ::= JOIN_KW nm JOIN */
+{yymsp[-2].minor.yy192 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
break;
- case 120: /* joinop ::= JOIN_KW nm nm JOIN */
-{yymsp[-3].minor.yy32 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
+ case 122: /* joinop ::= JOIN_KW nm nm JOIN */
+{yymsp[-3].minor.yy192 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
break;
- case 121: /* on_opt ::= ON expr */
- case 141: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==141);
- case 148: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==148);
- case 214: /* case_else ::= ELSE expr */ yytestcase(yyruleno==214);
- case 235: /* vinto ::= INTO expr */ yytestcase(yyruleno==235);
-{yymsp[-1].minor.yy46 = yymsp[0].minor.yy46;}
+ case 123: /* on_opt ::= ON expr */
+ case 143: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==143);
+ case 150: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==150);
+ case 216: /* case_else ::= ELSE expr */ yytestcase(yyruleno==216);
+ case 237: /* vinto ::= INTO expr */ yytestcase(yyruleno==237);
+{yymsp[-1].minor.yy202 = yymsp[0].minor.yy202;}
break;
- case 122: /* on_opt ::= */
- case 140: /* having_opt ::= */ yytestcase(yyruleno==140);
- case 142: /* limit_opt ::= */ yytestcase(yyruleno==142);
- case 147: /* where_opt ::= */ yytestcase(yyruleno==147);
- case 215: /* case_else ::= */ yytestcase(yyruleno==215);
- case 217: /* case_operand ::= */ yytestcase(yyruleno==217);
- case 236: /* vinto ::= */ yytestcase(yyruleno==236);
-{yymsp[1].minor.yy46 = 0;}
+ case 124: /* on_opt ::= */
+ case 142: /* having_opt ::= */ yytestcase(yyruleno==142);
+ case 144: /* limit_opt ::= */ yytestcase(yyruleno==144);
+ case 149: /* where_opt ::= */ yytestcase(yyruleno==149);
+ case 217: /* case_else ::= */ yytestcase(yyruleno==217);
+ case 219: /* case_operand ::= */ yytestcase(yyruleno==219);
+ case 238: /* vinto ::= */ yytestcase(yyruleno==238);
+{yymsp[1].minor.yy202 = 0;}
break;
- case 124: /* indexed_opt ::= INDEXED BY nm */
+ case 126: /* indexed_opt ::= INDEXED BY nm */
{yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
break;
- case 125: /* indexed_opt ::= NOT INDEXED */
+ case 127: /* indexed_opt ::= NOT INDEXED */
{yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;}
break;
- case 126: /* using_opt ::= USING LP idlist RP */
-{yymsp[-3].minor.yy406 = yymsp[-1].minor.yy406;}
+ case 128: /* using_opt ::= USING LP idlist RP */
+{yymsp[-3].minor.yy600 = yymsp[-1].minor.yy600;}
break;
- case 127: /* using_opt ::= */
- case 162: /* idlist_opt ::= */ yytestcase(yyruleno==162);
-{yymsp[1].minor.yy406 = 0;}
+ case 129: /* using_opt ::= */
+ case 164: /* idlist_opt ::= */ yytestcase(yyruleno==164);
+{yymsp[1].minor.yy600 = 0;}
break;
- case 129: /* orderby_opt ::= ORDER BY sortlist */
- case 139: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==139);
-{yymsp[-2].minor.yy138 = yymsp[0].minor.yy138;}
+ case 131: /* orderby_opt ::= ORDER BY sortlist */
+ case 141: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==141);
+{yymsp[-2].minor.yy242 = yymsp[0].minor.yy242;}
break;
- case 130: /* sortlist ::= sortlist COMMA expr sortorder nulls */
+ case 132: /* sortlist ::= sortlist COMMA expr sortorder nulls */
{
- yymsp[-4].minor.yy138 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy138,yymsp[-2].minor.yy46);
- sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy138,yymsp[-1].minor.yy32,yymsp[0].minor.yy32);
+ yymsp[-4].minor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242,yymsp[-2].minor.yy202);
+ sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy242,yymsp[-1].minor.yy192,yymsp[0].minor.yy192);
}
break;
- case 131: /* sortlist ::= expr sortorder nulls */
+ case 133: /* sortlist ::= expr sortorder nulls */
{
- yymsp[-2].minor.yy138 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy46); /*A-overwrites-Y*/
- sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy138,yymsp[-1].minor.yy32,yymsp[0].minor.yy32);
+ yymsp[-2].minor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy202); /*A-overwrites-Y*/
+ sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy242,yymsp[-1].minor.yy192,yymsp[0].minor.yy192);
}
break;
- case 132: /* sortorder ::= ASC */
-{yymsp[0].minor.yy32 = SQLITE_SO_ASC;}
+ case 134: /* sortorder ::= ASC */
+{yymsp[0].minor.yy192 = SQLITE_SO_ASC;}
break;
- case 133: /* sortorder ::= DESC */
-{yymsp[0].minor.yy32 = SQLITE_SO_DESC;}
+ case 135: /* sortorder ::= DESC */
+{yymsp[0].minor.yy192 = SQLITE_SO_DESC;}
break;
- case 134: /* sortorder ::= */
- case 137: /* nulls ::= */ yytestcase(yyruleno==137);
-{yymsp[1].minor.yy32 = SQLITE_SO_UNDEFINED;}
+ case 136: /* sortorder ::= */
+ case 139: /* nulls ::= */ yytestcase(yyruleno==139);
+{yymsp[1].minor.yy192 = SQLITE_SO_UNDEFINED;}
break;
- case 135: /* nulls ::= NULLS FIRST */
-{yymsp[-1].minor.yy32 = SQLITE_SO_ASC;}
+ case 137: /* nulls ::= NULLS FIRST */
+{yymsp[-1].minor.yy192 = SQLITE_SO_ASC;}
break;
- case 136: /* nulls ::= NULLS LAST */
-{yymsp[-1].minor.yy32 = SQLITE_SO_DESC;}
+ case 138: /* nulls ::= NULLS LAST */
+{yymsp[-1].minor.yy192 = SQLITE_SO_DESC;}
break;
- case 143: /* limit_opt ::= LIMIT expr */
-{yymsp[-1].minor.yy46 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy46,0);}
+ case 145: /* limit_opt ::= LIMIT expr */
+{yymsp[-1].minor.yy202 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy202,0);}
break;
- case 144: /* limit_opt ::= LIMIT expr OFFSET expr */
-{yymsp[-3].minor.yy46 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy46,yymsp[0].minor.yy46);}
+ case 146: /* limit_opt ::= LIMIT expr OFFSET expr */
+{yymsp[-3].minor.yy202 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy202,yymsp[0].minor.yy202);}
break;
- case 145: /* limit_opt ::= LIMIT expr COMMA expr */
-{yymsp[-3].minor.yy46 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy46,yymsp[-2].minor.yy46);}
+ case 147: /* limit_opt ::= LIMIT expr COMMA expr */
+{yymsp[-3].minor.yy202 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy202,yymsp[-2].minor.yy202);}
break;
- case 146: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
+ case 148: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy609, &yymsp[-1].minor.yy0);
- sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy609,yymsp[0].minor.yy46,0,0);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy47, &yymsp[-1].minor.yy0);
+ sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy47,yymsp[0].minor.yy202,0,0);
}
break;
- case 149: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
+ case 151: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy609, &yymsp[-3].minor.yy0);
- sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy138,"set list");
- sqlite3Update(pParse,yymsp[-4].minor.yy609,yymsp[-1].minor.yy138,yymsp[0].minor.yy46,yymsp[-5].minor.yy32,0,0,0);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy47, &yymsp[-3].minor.yy0);
+ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy242,"set list");
+ sqlite3Update(pParse,yymsp[-4].minor.yy47,yymsp[-1].minor.yy242,yymsp[0].minor.yy202,yymsp[-5].minor.yy192,0,0,0);
}
break;
- case 150: /* setlist ::= setlist COMMA nm EQ expr */
+ case 152: /* setlist ::= setlist COMMA nm EQ expr */
{
- yymsp[-4].minor.yy138 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy138, yymsp[0].minor.yy46);
- sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy138, &yymsp[-2].minor.yy0, 1);
+ yymsp[-4].minor.yy242 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy242, yymsp[0].minor.yy202);
+ sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy242, &yymsp[-2].minor.yy0, 1);
}
break;
- case 151: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
+ case 153: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
{
- yymsp[-6].minor.yy138 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy138, yymsp[-3].minor.yy406, yymsp[0].minor.yy46);
+ yymsp[-6].minor.yy242 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy242, yymsp[-3].minor.yy600, yymsp[0].minor.yy202);
}
break;
- case 152: /* setlist ::= nm EQ expr */
+ case 154: /* setlist ::= nm EQ expr */
{
- yylhsminor.yy138 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy46);
- sqlite3ExprListSetName(pParse, yylhsminor.yy138, &yymsp[-2].minor.yy0, 1);
+ yylhsminor.yy242 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy202);
+ sqlite3ExprListSetName(pParse, yylhsminor.yy242, &yymsp[-2].minor.yy0, 1);
}
- yymsp[-2].minor.yy138 = yylhsminor.yy138;
+ yymsp[-2].minor.yy242 = yylhsminor.yy242;
break;
- case 153: /* setlist ::= LP idlist RP EQ expr */
+ case 155: /* setlist ::= LP idlist RP EQ expr */
{
- yymsp[-4].minor.yy138 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy406, yymsp[0].minor.yy46);
+ yymsp[-4].minor.yy242 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy600, yymsp[0].minor.yy202);
}
break;
- case 154: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+ case 156: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
{
- sqlite3Insert(pParse, yymsp[-3].minor.yy609, yymsp[-1].minor.yy25, yymsp[-2].minor.yy406, yymsp[-5].minor.yy32, yymsp[0].minor.yy288);
+ sqlite3Insert(pParse, yymsp[-3].minor.yy47, yymsp[-1].minor.yy539, yymsp[-2].minor.yy600, yymsp[-5].minor.yy192, yymsp[0].minor.yy318);
}
break;
- case 155: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
+ case 157: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
{
- sqlite3Insert(pParse, yymsp[-3].minor.yy609, 0, yymsp[-2].minor.yy406, yymsp[-5].minor.yy32, 0);
+ sqlite3Insert(pParse, yymsp[-3].minor.yy47, 0, yymsp[-2].minor.yy600, yymsp[-5].minor.yy192, 0);
}
break;
- case 156: /* upsert ::= */
-{ yymsp[1].minor.yy288 = 0; }
+ case 158: /* upsert ::= */
+{ yymsp[1].minor.yy318 = 0; }
break;
- case 157: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
-{ yymsp[-10].minor.yy288 = sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy138,yymsp[-5].minor.yy46,yymsp[-1].minor.yy138,yymsp[0].minor.yy46);}
+ case 159: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
+{ yymsp[-10].minor.yy318 = sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy242,yymsp[-5].minor.yy202,yymsp[-1].minor.yy242,yymsp[0].minor.yy202);}
break;
- case 158: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
-{ yymsp[-7].minor.yy288 = sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy138,yymsp[-2].minor.yy46,0,0); }
+ case 160: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
+{ yymsp[-7].minor.yy318 = sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy242,yymsp[-2].minor.yy202,0,0); }
break;
- case 159: /* upsert ::= ON CONFLICT DO NOTHING */
-{ yymsp[-3].minor.yy288 = sqlite3UpsertNew(pParse->db,0,0,0,0); }
+ case 161: /* upsert ::= ON CONFLICT DO NOTHING */
+{ yymsp[-3].minor.yy318 = sqlite3UpsertNew(pParse->db,0,0,0,0); }
break;
- case 163: /* idlist_opt ::= LP idlist RP */
-{yymsp[-2].minor.yy406 = yymsp[-1].minor.yy406;}
+ case 165: /* idlist_opt ::= LP idlist RP */
+{yymsp[-2].minor.yy600 = yymsp[-1].minor.yy600;}
break;
- case 164: /* idlist ::= idlist COMMA nm */
-{yymsp[-2].minor.yy406 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy406,&yymsp[0].minor.yy0);}
+ case 166: /* idlist ::= idlist COMMA nm */
+{yymsp[-2].minor.yy600 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy600,&yymsp[0].minor.yy0);}
break;
- case 165: /* idlist ::= nm */
-{yymsp[0].minor.yy406 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
+ case 167: /* idlist ::= nm */
+{yymsp[0].minor.yy600 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
break;
- case 166: /* expr ::= LP expr RP */
-{yymsp[-2].minor.yy46 = yymsp[-1].minor.yy46;}
+ case 168: /* expr ::= LP expr RP */
+{yymsp[-2].minor.yy202 = yymsp[-1].minor.yy202;}
break;
- case 167: /* expr ::= ID|INDEXED */
- case 168: /* expr ::= JOIN_KW */ yytestcase(yyruleno==168);
-{yymsp[0].minor.yy46=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+ case 169: /* expr ::= ID|INDEXED */
+ case 170: /* expr ::= JOIN_KW */ yytestcase(yyruleno==170);
+{yymsp[0].minor.yy202=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 169: /* expr ::= nm DOT nm */
+ case 171: /* expr ::= nm DOT nm */
{
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
@@ -153648,11 +156291,11 @@ static YYACTIONTYPE yy_reduce(
sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[0].minor.yy0);
sqlite3RenameTokenMap(pParse, (void*)temp1, &yymsp[-2].minor.yy0);
}
- yylhsminor.yy46 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
+ yylhsminor.yy202 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
}
- yymsp[-2].minor.yy46 = yylhsminor.yy46;
+ yymsp[-2].minor.yy202 = yylhsminor.yy202;
break;
- case 170: /* expr ::= nm DOT nm DOT nm */
+ case 172: /* expr ::= nm DOT nm DOT nm */
{
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1);
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
@@ -153662,26 +156305,26 @@ static YYACTIONTYPE yy_reduce(
sqlite3RenameTokenMap(pParse, (void*)temp3, &yymsp[0].minor.yy0);
sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[-2].minor.yy0);
}
- yylhsminor.yy46 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
+ yylhsminor.yy202 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
}
- yymsp[-4].minor.yy46 = yylhsminor.yy46;
+ yymsp[-4].minor.yy202 = yylhsminor.yy202;
break;
- case 171: /* term ::= NULL|FLOAT|BLOB */
- case 172: /* term ::= STRING */ yytestcase(yyruleno==172);
-{yymsp[0].minor.yy46=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+ case 173: /* term ::= NULL|FLOAT|BLOB */
+ case 174: /* term ::= STRING */ yytestcase(yyruleno==174);
+{yymsp[0].minor.yy202=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 173: /* term ::= INTEGER */
+ case 175: /* term ::= INTEGER */
{
- yylhsminor.yy46 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
+ yylhsminor.yy202 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
}
- yymsp[0].minor.yy46 = yylhsminor.yy46;
+ yymsp[0].minor.yy202 = yylhsminor.yy202;
break;
- case 174: /* expr ::= VARIABLE */
+ case 176: /* expr ::= VARIABLE */
{
if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
u32 n = yymsp[0].minor.yy0.n;
- yymsp[0].minor.yy46 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
- sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy46, n);
+ yymsp[0].minor.yy202 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
+ sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy202, n);
}else{
/* When doing a nested parse, one can include terms in an expression
** that look like this: #1 #2 ... These terms refer to registers
@@ -153690,156 +156333,159 @@ static YYACTIONTYPE yy_reduce(
assert( t.n>=2 );
if( pParse->nested==0 ){
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
- yymsp[0].minor.yy46 = 0;
+ yymsp[0].minor.yy202 = 0;
}else{
- yymsp[0].minor.yy46 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
- if( yymsp[0].minor.yy46 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy46->iTable);
+ yymsp[0].minor.yy202 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
+ if( yymsp[0].minor.yy202 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy202->iTable);
}
}
}
break;
- case 175: /* expr ::= expr COLLATE ID|STRING */
+ case 177: /* expr ::= expr COLLATE ID|STRING */
{
- yymsp[-2].minor.yy46 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy46, &yymsp[0].minor.yy0, 1);
+ yymsp[-2].minor.yy202 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy202, &yymsp[0].minor.yy0, 1);
}
break;
- case 176: /* expr ::= CAST LP expr AS typetoken RP */
+ case 178: /* expr ::= CAST LP expr AS typetoken RP */
{
- yymsp[-5].minor.yy46 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
- sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy46, yymsp[-3].minor.yy46, 0);
+ yymsp[-5].minor.yy202 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
+ sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy202, yymsp[-3].minor.yy202, 0);
}
break;
- case 177: /* expr ::= ID|INDEXED LP distinct exprlist RP */
+ case 179: /* expr ::= ID|INDEXED LP distinct exprlist RP */
{
- yylhsminor.yy46 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy138, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy32);
+ yylhsminor.yy202 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy242, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy192);
}
- yymsp[-4].minor.yy46 = yylhsminor.yy46;
+ yymsp[-4].minor.yy202 = yylhsminor.yy202;
break;
- case 178: /* expr ::= ID|INDEXED LP STAR RP */
+ case 180: /* expr ::= ID|INDEXED LP STAR RP */
{
- yylhsminor.yy46 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
+ yylhsminor.yy202 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
}
- yymsp[-3].minor.yy46 = yylhsminor.yy46;
+ yymsp[-3].minor.yy202 = yylhsminor.yy202;
break;
- case 179: /* expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
+ case 181: /* expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
{
- yylhsminor.yy46 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy138, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy32);
- sqlite3WindowAttach(pParse, yylhsminor.yy46, yymsp[0].minor.yy455);
+ yylhsminor.yy202 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy242, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy192);
+ sqlite3WindowAttach(pParse, yylhsminor.yy202, yymsp[0].minor.yy303);
}
- yymsp[-5].minor.yy46 = yylhsminor.yy46;
+ yymsp[-5].minor.yy202 = yylhsminor.yy202;
break;
- case 180: /* expr ::= ID|INDEXED LP STAR RP filter_over */
+ case 182: /* expr ::= ID|INDEXED LP STAR RP filter_over */
{
- yylhsminor.yy46 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0);
- sqlite3WindowAttach(pParse, yylhsminor.yy46, yymsp[0].minor.yy455);
+ yylhsminor.yy202 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0);
+ sqlite3WindowAttach(pParse, yylhsminor.yy202, yymsp[0].minor.yy303);
}
- yymsp[-4].minor.yy46 = yylhsminor.yy46;
+ yymsp[-4].minor.yy202 = yylhsminor.yy202;
break;
- case 181: /* term ::= CTIME_KW */
+ case 183: /* term ::= CTIME_KW */
{
- yylhsminor.yy46 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
+ yylhsminor.yy202 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
}
- yymsp[0].minor.yy46 = yylhsminor.yy46;
+ yymsp[0].minor.yy202 = yylhsminor.yy202;
break;
- case 182: /* expr ::= LP nexprlist COMMA expr RP */
+ case 184: /* expr ::= LP nexprlist COMMA expr RP */
{
- ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy138, yymsp[-1].minor.yy46);
- yymsp[-4].minor.yy46 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
- if( yymsp[-4].minor.yy46 ){
- yymsp[-4].minor.yy46->x.pList = pList;
+ ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy242, yymsp[-1].minor.yy202);
+ yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
+ if( yymsp[-4].minor.yy202 ){
+ yymsp[-4].minor.yy202->x.pList = pList;
+ if( ALWAYS(pList->nExpr) ){
+ yymsp[-4].minor.yy202->flags |= pList->a[0].pExpr->flags & EP_Propagate;
+ }
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
}
break;
- case 183: /* expr ::= expr AND expr */
-{yymsp[-2].minor.yy46=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy46,yymsp[0].minor.yy46);}
+ case 185: /* expr ::= expr AND expr */
+{yymsp[-2].minor.yy202=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy202,yymsp[0].minor.yy202);}
break;
- case 184: /* expr ::= expr OR expr */
- case 185: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==185);
- case 186: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==186);
- case 187: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==187);
- case 188: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==188);
- case 189: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==189);
- case 190: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==190);
-{yymsp[-2].minor.yy46=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy46,yymsp[0].minor.yy46);}
+ case 186: /* expr ::= expr OR expr */
+ case 187: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==187);
+ case 188: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==188);
+ case 189: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==189);
+ case 190: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==190);
+ case 191: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==191);
+ case 192: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==192);
+{yymsp[-2].minor.yy202=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy202,yymsp[0].minor.yy202);}
break;
- case 191: /* likeop ::= NOT LIKE_KW|MATCH */
+ case 193: /* likeop ::= NOT LIKE_KW|MATCH */
{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/}
break;
- case 192: /* expr ::= expr likeop expr */
+ case 194: /* expr ::= expr likeop expr */
{
ExprList *pList;
int bNot = yymsp[-1].minor.yy0.n & 0x80000000;
yymsp[-1].minor.yy0.n &= 0x7fffffff;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy46);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy46);
- yymsp[-2].minor.yy46 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
- if( bNot ) yymsp[-2].minor.yy46 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy46, 0);
- if( yymsp[-2].minor.yy46 ) yymsp[-2].minor.yy46->flags |= EP_InfixFunc;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy202);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy202);
+ yymsp[-2].minor.yy202 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
+ if( bNot ) yymsp[-2].minor.yy202 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy202, 0);
+ if( yymsp[-2].minor.yy202 ) yymsp[-2].minor.yy202->flags |= EP_InfixFunc;
}
break;
- case 193: /* expr ::= expr likeop expr ESCAPE expr */
+ case 195: /* expr ::= expr likeop expr ESCAPE expr */
{
ExprList *pList;
int bNot = yymsp[-3].minor.yy0.n & 0x80000000;
yymsp[-3].minor.yy0.n &= 0x7fffffff;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy46);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy46);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy46);
- yymsp[-4].minor.yy46 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
- if( bNot ) yymsp[-4].minor.yy46 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy46, 0);
- if( yymsp[-4].minor.yy46 ) yymsp[-4].minor.yy46->flags |= EP_InfixFunc;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy202);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy202);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy202);
+ yymsp[-4].minor.yy202 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
+ if( bNot ) yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
+ if( yymsp[-4].minor.yy202 ) yymsp[-4].minor.yy202->flags |= EP_InfixFunc;
}
break;
- case 194: /* expr ::= expr ISNULL|NOTNULL */
-{yymsp[-1].minor.yy46 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy46,0);}
+ case 196: /* expr ::= expr ISNULL|NOTNULL */
+{yymsp[-1].minor.yy202 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy202,0);}
break;
- case 195: /* expr ::= expr NOT NULL */
-{yymsp[-2].minor.yy46 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy46,0);}
+ case 197: /* expr ::= expr NOT NULL */
+{yymsp[-2].minor.yy202 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy202,0);}
break;
- case 196: /* expr ::= expr IS expr */
+ case 198: /* expr ::= expr IS expr */
{
- yymsp[-2].minor.yy46 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy46,yymsp[0].minor.yy46);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy46, yymsp[-2].minor.yy46, TK_ISNULL);
+ yymsp[-2].minor.yy202 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy202,yymsp[0].minor.yy202);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy202, yymsp[-2].minor.yy202, TK_ISNULL);
}
break;
- case 197: /* expr ::= expr IS NOT expr */
+ case 199: /* expr ::= expr IS NOT expr */
{
- yymsp[-3].minor.yy46 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy46,yymsp[0].minor.yy46);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy46, yymsp[-3].minor.yy46, TK_NOTNULL);
+ yymsp[-3].minor.yy202 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy202,yymsp[0].minor.yy202);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy202, yymsp[-3].minor.yy202, TK_NOTNULL);
}
break;
- case 198: /* expr ::= NOT expr */
- case 199: /* expr ::= BITNOT expr */ yytestcase(yyruleno==199);
-{yymsp[-1].minor.yy46 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy46, 0);/*A-overwrites-B*/}
+ case 200: /* expr ::= NOT expr */
+ case 201: /* expr ::= BITNOT expr */ yytestcase(yyruleno==201);
+{yymsp[-1].minor.yy202 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy202, 0);/*A-overwrites-B*/}
break;
- case 200: /* expr ::= PLUS|MINUS expr */
+ case 202: /* expr ::= PLUS|MINUS expr */
{
- yymsp[-1].minor.yy46 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy46, 0);
+ yymsp[-1].minor.yy202 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy202, 0);
/*A-overwrites-B*/
}
break;
- case 201: /* between_op ::= BETWEEN */
- case 204: /* in_op ::= IN */ yytestcase(yyruleno==204);
-{yymsp[0].minor.yy32 = 0;}
+ case 203: /* between_op ::= BETWEEN */
+ case 206: /* in_op ::= IN */ yytestcase(yyruleno==206);
+{yymsp[0].minor.yy192 = 0;}
break;
- case 203: /* expr ::= expr between_op expr AND expr */
+ case 205: /* expr ::= expr between_op expr AND expr */
{
- ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy46);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy46);
- yymsp[-4].minor.yy46 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy46, 0);
- if( yymsp[-4].minor.yy46 ){
- yymsp[-4].minor.yy46->x.pList = pList;
+ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy202);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy202);
+ yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy202, 0);
+ if( yymsp[-4].minor.yy202 ){
+ yymsp[-4].minor.yy202->x.pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
- if( yymsp[-3].minor.yy32 ) yymsp[-4].minor.yy46 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy46, 0);
+ if( yymsp[-3].minor.yy192 ) yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
}
break;
- case 206: /* expr ::= expr in_op LP exprlist RP */
+ case 208: /* expr ::= expr in_op LP exprlist RP */
{
- if( yymsp[-1].minor.yy138==0 ){
+ if( yymsp[-1].minor.yy242==0 ){
/* Expressions of the form
**
** expr1 IN ()
@@ -153848,190 +156494,190 @@ static YYACTIONTYPE yy_reduce(
** simplify to constants 0 (false) and 1 (true), respectively,
** regardless of the value of expr1.
*/
- sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy46);
- yymsp[-4].minor.yy46 = sqlite3Expr(pParse->db, TK_INTEGER, yymsp[-3].minor.yy32 ? "1" : "0");
+ sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy202);
+ yymsp[-4].minor.yy202 = sqlite3Expr(pParse->db, TK_INTEGER, yymsp[-3].minor.yy192 ? "1" : "0");
}else{
- yymsp[-4].minor.yy46 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy46, 0);
- if( yymsp[-4].minor.yy46 ){
- yymsp[-4].minor.yy46->x.pList = yymsp[-1].minor.yy138;
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy46);
+ yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy202, 0);
+ if( yymsp[-4].minor.yy202 ){
+ yymsp[-4].minor.yy202->x.pList = yymsp[-1].minor.yy242;
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy202);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy138);
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy242);
}
- if( yymsp[-3].minor.yy32 ) yymsp[-4].minor.yy46 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy46, 0);
+ if( yymsp[-3].minor.yy192 ) yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
}
}
break;
- case 207: /* expr ::= LP select RP */
+ case 209: /* expr ::= LP select RP */
{
- yymsp[-2].minor.yy46 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy46, yymsp[-1].minor.yy25);
+ yymsp[-2].minor.yy202 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy202, yymsp[-1].minor.yy539);
}
break;
- case 208: /* expr ::= expr in_op LP select RP */
+ case 210: /* expr ::= expr in_op LP select RP */
{
- yymsp[-4].minor.yy46 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy46, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy46, yymsp[-1].minor.yy25);
- if( yymsp[-3].minor.yy32 ) yymsp[-4].minor.yy46 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy46, 0);
+ yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy202, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy202, yymsp[-1].minor.yy539);
+ if( yymsp[-3].minor.yy192 ) yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
}
break;
- case 209: /* expr ::= expr in_op nm dbnm paren_exprlist */
+ case 211: /* expr ::= expr in_op nm dbnm paren_exprlist */
{
SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);
Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
- if( yymsp[0].minor.yy138 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy138);
- yymsp[-4].minor.yy46 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy46, 0);
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy46, pSelect);
- if( yymsp[-3].minor.yy32 ) yymsp[-4].minor.yy46 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy46, 0);
+ if( yymsp[0].minor.yy242 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy242);
+ yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy202, 0);
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy202, pSelect);
+ if( yymsp[-3].minor.yy192 ) yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
}
break;
- case 210: /* expr ::= EXISTS LP select RP */
+ case 212: /* expr ::= EXISTS LP select RP */
{
Expr *p;
- p = yymsp[-3].minor.yy46 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
- sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy25);
+ p = yymsp[-3].minor.yy202 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
+ sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy539);
}
break;
- case 211: /* expr ::= CASE case_operand case_exprlist case_else END */
+ case 213: /* expr ::= CASE case_operand case_exprlist case_else END */
{
- yymsp[-4].minor.yy46 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy46, 0);
- if( yymsp[-4].minor.yy46 ){
- yymsp[-4].minor.yy46->x.pList = yymsp[-1].minor.yy46 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy138,yymsp[-1].minor.yy46) : yymsp[-2].minor.yy138;
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy46);
+ yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy202, 0);
+ if( yymsp[-4].minor.yy202 ){
+ yymsp[-4].minor.yy202->x.pList = yymsp[-1].minor.yy202 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy242,yymsp[-1].minor.yy202) : yymsp[-2].minor.yy242;
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy202);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy138);
- sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy46);
+ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy242);
+ sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy202);
}
}
break;
- case 212: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ case 214: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
- yymsp[-4].minor.yy138 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy138, yymsp[-2].minor.yy46);
- yymsp[-4].minor.yy138 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy138, yymsp[0].minor.yy46);
+ yymsp[-4].minor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, yymsp[-2].minor.yy202);
+ yymsp[-4].minor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, yymsp[0].minor.yy202);
}
break;
- case 213: /* case_exprlist ::= WHEN expr THEN expr */
+ case 215: /* case_exprlist ::= WHEN expr THEN expr */
{
- yymsp[-3].minor.yy138 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy46);
- yymsp[-3].minor.yy138 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy138, yymsp[0].minor.yy46);
+ yymsp[-3].minor.yy242 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy202);
+ yymsp[-3].minor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy242, yymsp[0].minor.yy202);
}
break;
- case 216: /* case_operand ::= expr */
-{yymsp[0].minor.yy46 = yymsp[0].minor.yy46; /*A-overwrites-X*/}
+ case 218: /* case_operand ::= expr */
+{yymsp[0].minor.yy202 = yymsp[0].minor.yy202; /*A-overwrites-X*/}
break;
- case 219: /* nexprlist ::= nexprlist COMMA expr */
-{yymsp[-2].minor.yy138 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy138,yymsp[0].minor.yy46);}
+ case 221: /* nexprlist ::= nexprlist COMMA expr */
+{yymsp[-2].minor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy242,yymsp[0].minor.yy202);}
break;
- case 220: /* nexprlist ::= expr */
-{yymsp[0].minor.yy138 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy46); /*A-overwrites-Y*/}
+ case 222: /* nexprlist ::= expr */
+{yymsp[0].minor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy202); /*A-overwrites-Y*/}
break;
- case 222: /* paren_exprlist ::= LP exprlist RP */
- case 227: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==227);
-{yymsp[-2].minor.yy138 = yymsp[-1].minor.yy138;}
+ case 224: /* paren_exprlist ::= LP exprlist RP */
+ case 229: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==229);
+{yymsp[-2].minor.yy242 = yymsp[-1].minor.yy242;}
break;
- case 223: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ case 225: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
{
sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0,
- sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy138, yymsp[-10].minor.yy32,
- &yymsp[-11].minor.yy0, yymsp[0].minor.yy46, SQLITE_SO_ASC, yymsp[-8].minor.yy32, SQLITE_IDXTYPE_APPDEF);
+ sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy242, yymsp[-10].minor.yy192,
+ &yymsp[-11].minor.yy0, yymsp[0].minor.yy202, SQLITE_SO_ASC, yymsp[-8].minor.yy192, SQLITE_IDXTYPE_APPDEF);
if( IN_RENAME_OBJECT && pParse->pNewIndex ){
sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0);
}
}
break;
- case 224: /* uniqueflag ::= UNIQUE */
- case 266: /* raisetype ::= ABORT */ yytestcase(yyruleno==266);
-{yymsp[0].minor.yy32 = OE_Abort;}
+ case 226: /* uniqueflag ::= UNIQUE */
+ case 268: /* raisetype ::= ABORT */ yytestcase(yyruleno==268);
+{yymsp[0].minor.yy192 = OE_Abort;}
break;
- case 225: /* uniqueflag ::= */
-{yymsp[1].minor.yy32 = OE_None;}
+ case 227: /* uniqueflag ::= */
+{yymsp[1].minor.yy192 = OE_None;}
break;
- case 228: /* eidlist ::= eidlist COMMA nm collate sortorder */
+ case 230: /* eidlist ::= eidlist COMMA nm collate sortorder */
{
- yymsp[-4].minor.yy138 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy138, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy32, yymsp[0].minor.yy32);
+ yymsp[-4].minor.yy242 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy242, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy192, yymsp[0].minor.yy192);
}
break;
- case 229: /* eidlist ::= nm collate sortorder */
+ case 231: /* eidlist ::= nm collate sortorder */
{
- yymsp[-2].minor.yy138 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy32, yymsp[0].minor.yy32); /*A-overwrites-Y*/
+ yymsp[-2].minor.yy242 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy192, yymsp[0].minor.yy192); /*A-overwrites-Y*/
}
break;
- case 232: /* cmd ::= DROP INDEX ifexists fullname */
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy609, yymsp[-1].minor.yy32);}
+ case 234: /* cmd ::= DROP INDEX ifexists fullname */
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy47, yymsp[-1].minor.yy192);}
break;
- case 233: /* cmd ::= VACUUM vinto */
-{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy46);}
+ case 235: /* cmd ::= VACUUM vinto */
+{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy202);}
break;
- case 234: /* cmd ::= VACUUM nm vinto */
-{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy46);}
+ case 236: /* cmd ::= VACUUM nm vinto */
+{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy202);}
break;
- case 237: /* cmd ::= PRAGMA nm dbnm */
+ case 239: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
break;
- case 238: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
+ case 240: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
break;
- case 239: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ case 241: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
break;
- case 240: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
+ case 242: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
break;
- case 241: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ case 243: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
break;
- case 244: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ case 246: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
{
Token all;
all.z = yymsp[-3].minor.yy0.z;
all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
- sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy527, &all);
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy447, &all);
}
break;
- case 245: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ case 247: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
- sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy32, yymsp[-4].minor.yy572.a, yymsp[-4].minor.yy572.b, yymsp[-2].minor.yy609, yymsp[0].minor.yy46, yymsp[-10].minor.yy32, yymsp[-8].minor.yy32);
+ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy192, yymsp[-4].minor.yy230.a, yymsp[-4].minor.yy230.b, yymsp[-2].minor.yy47, yymsp[0].minor.yy202, yymsp[-10].minor.yy192, yymsp[-8].minor.yy192);
yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/
}
break;
- case 246: /* trigger_time ::= BEFORE|AFTER */
-{ yymsp[0].minor.yy32 = yymsp[0].major; /*A-overwrites-X*/ }
+ case 248: /* trigger_time ::= BEFORE|AFTER */
+{ yymsp[0].minor.yy192 = yymsp[0].major; /*A-overwrites-X*/ }
break;
- case 247: /* trigger_time ::= INSTEAD OF */
-{ yymsp[-1].minor.yy32 = TK_INSTEAD;}
+ case 249: /* trigger_time ::= INSTEAD OF */
+{ yymsp[-1].minor.yy192 = TK_INSTEAD;}
break;
- case 248: /* trigger_time ::= */
-{ yymsp[1].minor.yy32 = TK_BEFORE; }
+ case 250: /* trigger_time ::= */
+{ yymsp[1].minor.yy192 = TK_BEFORE; }
break;
- case 249: /* trigger_event ::= DELETE|INSERT */
- case 250: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==250);
-{yymsp[0].minor.yy572.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy572.b = 0;}
+ case 251: /* trigger_event ::= DELETE|INSERT */
+ case 252: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==252);
+{yymsp[0].minor.yy230.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy230.b = 0;}
break;
- case 251: /* trigger_event ::= UPDATE OF idlist */
-{yymsp[-2].minor.yy572.a = TK_UPDATE; yymsp[-2].minor.yy572.b = yymsp[0].minor.yy406;}
+ case 253: /* trigger_event ::= UPDATE OF idlist */
+{yymsp[-2].minor.yy230.a = TK_UPDATE; yymsp[-2].minor.yy230.b = yymsp[0].minor.yy600;}
break;
- case 252: /* when_clause ::= */
- case 271: /* key_opt ::= */ yytestcase(yyruleno==271);
-{ yymsp[1].minor.yy46 = 0; }
+ case 254: /* when_clause ::= */
+ case 273: /* key_opt ::= */ yytestcase(yyruleno==273);
+{ yymsp[1].minor.yy202 = 0; }
break;
- case 253: /* when_clause ::= WHEN expr */
- case 272: /* key_opt ::= KEY expr */ yytestcase(yyruleno==272);
-{ yymsp[-1].minor.yy46 = yymsp[0].minor.yy46; }
+ case 255: /* when_clause ::= WHEN expr */
+ case 274: /* key_opt ::= KEY expr */ yytestcase(yyruleno==274);
+{ yymsp[-1].minor.yy202 = yymsp[0].minor.yy202; }
break;
- case 254: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ case 256: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
- assert( yymsp[-2].minor.yy527!=0 );
- yymsp[-2].minor.yy527->pLast->pNext = yymsp[-1].minor.yy527;
- yymsp[-2].minor.yy527->pLast = yymsp[-1].minor.yy527;
+ assert( yymsp[-2].minor.yy447!=0 );
+ yymsp[-2].minor.yy447->pLast->pNext = yymsp[-1].minor.yy447;
+ yymsp[-2].minor.yy447->pLast = yymsp[-1].minor.yy447;
}
break;
- case 255: /* trigger_cmd_list ::= trigger_cmd SEMI */
+ case 257: /* trigger_cmd_list ::= trigger_cmd SEMI */
{
- assert( yymsp[-1].minor.yy527!=0 );
- yymsp[-1].minor.yy527->pLast = yymsp[-1].minor.yy527;
+ assert( yymsp[-1].minor.yy447!=0 );
+ yymsp[-1].minor.yy447->pLast = yymsp[-1].minor.yy447;
}
break;
- case 256: /* trnm ::= nm DOT nm */
+ case 258: /* trnm ::= nm DOT nm */
{
yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;
sqlite3ErrorMsg(pParse,
@@ -154039,342 +156685,344 @@ static YYACTIONTYPE yy_reduce(
"statements within triggers");
}
break;
- case 257: /* tridxby ::= INDEXED BY nm */
+ case 259: /* tridxby ::= INDEXED BY nm */
{
sqlite3ErrorMsg(pParse,
"the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 258: /* tridxby ::= NOT INDEXED */
+ case 260: /* tridxby ::= NOT INDEXED */
{
sqlite3ErrorMsg(pParse,
"the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 259: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
-{yylhsminor.yy527 = sqlite3TriggerUpdateStep(pParse, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy138, yymsp[-1].minor.yy46, yymsp[-6].minor.yy32, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy8);}
- yymsp[-7].minor.yy527 = yylhsminor.yy527;
+ case 261: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
+{yylhsminor.yy447 = sqlite3TriggerUpdateStep(pParse, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy242, yymsp[-1].minor.yy202, yymsp[-6].minor.yy192, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy436);}
+ yymsp[-7].minor.yy447 = yylhsminor.yy447;
break;
- case 260: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ case 262: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
{
- yylhsminor.yy527 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy406,yymsp[-2].minor.yy25,yymsp[-6].minor.yy32,yymsp[-1].minor.yy288,yymsp[-7].minor.yy8,yymsp[0].minor.yy8);/*yylhsminor.yy527-overwrites-yymsp[-6].minor.yy32*/
+ yylhsminor.yy447 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy600,yymsp[-2].minor.yy539,yymsp[-6].minor.yy192,yymsp[-1].minor.yy318,yymsp[-7].minor.yy436,yymsp[0].minor.yy436);/*yylhsminor.yy447-overwrites-yymsp[-6].minor.yy192*/
}
- yymsp[-7].minor.yy527 = yylhsminor.yy527;
+ yymsp[-7].minor.yy447 = yylhsminor.yy447;
break;
- case 261: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
-{yylhsminor.yy527 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy46, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy8);}
- yymsp[-5].minor.yy527 = yylhsminor.yy527;
+ case 263: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+{yylhsminor.yy447 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy202, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy436);}
+ yymsp[-5].minor.yy447 = yylhsminor.yy447;
break;
- case 262: /* trigger_cmd ::= scanpt select scanpt */
-{yylhsminor.yy527 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy25, yymsp[-2].minor.yy8, yymsp[0].minor.yy8); /*yylhsminor.yy527-overwrites-yymsp[-1].minor.yy25*/}
- yymsp[-2].minor.yy527 = yylhsminor.yy527;
+ case 264: /* trigger_cmd ::= scanpt select scanpt */
+{yylhsminor.yy447 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy539, yymsp[-2].minor.yy436, yymsp[0].minor.yy436); /*yylhsminor.yy447-overwrites-yymsp[-1].minor.yy539*/}
+ yymsp[-2].minor.yy447 = yylhsminor.yy447;
break;
- case 263: /* expr ::= RAISE LP IGNORE RP */
+ case 265: /* expr ::= RAISE LP IGNORE RP */
{
- yymsp[-3].minor.yy46 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
- if( yymsp[-3].minor.yy46 ){
- yymsp[-3].minor.yy46->affExpr = OE_Ignore;
+ yymsp[-3].minor.yy202 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
+ if( yymsp[-3].minor.yy202 ){
+ yymsp[-3].minor.yy202->affExpr = OE_Ignore;
}
}
break;
- case 264: /* expr ::= RAISE LP raisetype COMMA nm RP */
+ case 266: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
- yymsp[-5].minor.yy46 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
- if( yymsp[-5].minor.yy46 ) {
- yymsp[-5].minor.yy46->affExpr = (char)yymsp[-3].minor.yy32;
+ yymsp[-5].minor.yy202 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
+ if( yymsp[-5].minor.yy202 ) {
+ yymsp[-5].minor.yy202->affExpr = (char)yymsp[-3].minor.yy192;
}
}
break;
- case 265: /* raisetype ::= ROLLBACK */
-{yymsp[0].minor.yy32 = OE_Rollback;}
+ case 267: /* raisetype ::= ROLLBACK */
+{yymsp[0].minor.yy192 = OE_Rollback;}
break;
- case 267: /* raisetype ::= FAIL */
-{yymsp[0].minor.yy32 = OE_Fail;}
+ case 269: /* raisetype ::= FAIL */
+{yymsp[0].minor.yy192 = OE_Fail;}
break;
- case 268: /* cmd ::= DROP TRIGGER ifexists fullname */
+ case 270: /* cmd ::= DROP TRIGGER ifexists fullname */
{
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy609,yymsp[-1].minor.yy32);
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy47,yymsp[-1].minor.yy192);
}
break;
- case 269: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ case 271: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
- sqlite3Attach(pParse, yymsp[-3].minor.yy46, yymsp[-1].minor.yy46, yymsp[0].minor.yy46);
+ sqlite3Attach(pParse, yymsp[-3].minor.yy202, yymsp[-1].minor.yy202, yymsp[0].minor.yy202);
}
break;
- case 270: /* cmd ::= DETACH database_kw_opt expr */
+ case 272: /* cmd ::= DETACH database_kw_opt expr */
{
- sqlite3Detach(pParse, yymsp[0].minor.yy46);
+ sqlite3Detach(pParse, yymsp[0].minor.yy202);
}
break;
- case 273: /* cmd ::= REINDEX */
+ case 275: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
break;
- case 274: /* cmd ::= REINDEX nm dbnm */
+ case 276: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 275: /* cmd ::= ANALYZE */
+ case 277: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
break;
- case 276: /* cmd ::= ANALYZE nm dbnm */
+ case 278: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 277: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+ case 279: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy609,&yymsp[0].minor.yy0);
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy47,&yymsp[0].minor.yy0);
}
break;
- case 278: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ case 280: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
{
yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n;
sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0);
}
break;
- case 279: /* add_column_fullname ::= fullname */
+ case 281: /* add_column_fullname ::= fullname */
{
disableLookaside(pParse);
- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy609);
+ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy47);
}
break;
- case 280: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ case 282: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
{
- sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy609, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
+ sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy47, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
}
break;
- case 281: /* cmd ::= create_vtab */
+ case 283: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
- case 282: /* cmd ::= create_vtab LP vtabarglist RP */
+ case 284: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
- case 283: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ case 285: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
{
- sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy32);
+ sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy192);
}
break;
- case 284: /* vtabarg ::= */
+ case 286: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
- case 285: /* vtabargtoken ::= ANY */
- case 286: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==286);
- case 287: /* lp ::= LP */ yytestcase(yyruleno==287);
+ case 287: /* vtabargtoken ::= ANY */
+ case 288: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==288);
+ case 289: /* lp ::= LP */ yytestcase(yyruleno==289);
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
- case 288: /* with ::= WITH wqlist */
- case 289: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==289);
-{ sqlite3WithPush(pParse, yymsp[0].minor.yy297, 1); }
+ case 290: /* with ::= WITH wqlist */
+ case 291: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==291);
+{ sqlite3WithPush(pParse, yymsp[0].minor.yy131, 1); }
break;
- case 290: /* wqlist ::= nm eidlist_opt AS LP select RP */
+ case 292: /* wqlist ::= nm eidlist_opt AS LP select RP */
{
- yymsp[-5].minor.yy297 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy138, yymsp[-1].minor.yy25); /*A-overwrites-X*/
+ yymsp[-5].minor.yy131 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy242, yymsp[-1].minor.yy539); /*A-overwrites-X*/
}
break;
- case 291: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
+ case 293: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
{
- yymsp[-7].minor.yy297 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy297, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy138, yymsp[-1].minor.yy25);
+ yymsp[-7].minor.yy131 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy131, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy242, yymsp[-1].minor.yy539);
}
break;
- case 292: /* windowdefn_list ::= windowdefn */
-{ yylhsminor.yy455 = yymsp[0].minor.yy455; }
- yymsp[0].minor.yy455 = yylhsminor.yy455;
+ case 294: /* windowdefn_list ::= windowdefn */
+{ yylhsminor.yy303 = yymsp[0].minor.yy303; }
+ yymsp[0].minor.yy303 = yylhsminor.yy303;
break;
- case 293: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */
+ case 295: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */
{
- assert( yymsp[0].minor.yy455!=0 );
- sqlite3WindowChain(pParse, yymsp[0].minor.yy455, yymsp[-2].minor.yy455);
- yymsp[0].minor.yy455->pNextWin = yymsp[-2].minor.yy455;
- yylhsminor.yy455 = yymsp[0].minor.yy455;
+ assert( yymsp[0].minor.yy303!=0 );
+ sqlite3WindowChain(pParse, yymsp[0].minor.yy303, yymsp[-2].minor.yy303);
+ yymsp[0].minor.yy303->pNextWin = yymsp[-2].minor.yy303;
+ yylhsminor.yy303 = yymsp[0].minor.yy303;
}
- yymsp[-2].minor.yy455 = yylhsminor.yy455;
+ yymsp[-2].minor.yy303 = yylhsminor.yy303;
break;
- case 294: /* windowdefn ::= nm AS LP window RP */
+ case 296: /* windowdefn ::= nm AS LP window RP */
{
- if( ALWAYS(yymsp[-1].minor.yy455) ){
- yymsp[-1].minor.yy455->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n);
+ if( ALWAYS(yymsp[-1].minor.yy303) ){
+ yymsp[-1].minor.yy303->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n);
}
- yylhsminor.yy455 = yymsp[-1].minor.yy455;
+ yylhsminor.yy303 = yymsp[-1].minor.yy303;
}
- yymsp[-4].minor.yy455 = yylhsminor.yy455;
+ yymsp[-4].minor.yy303 = yylhsminor.yy303;
break;
- case 295: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */
+ case 297: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */
{
- yymsp[-4].minor.yy455 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy455, yymsp[-2].minor.yy138, yymsp[-1].minor.yy138, 0);
+ yymsp[-4].minor.yy303 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, yymsp[-2].minor.yy242, yymsp[-1].minor.yy242, 0);
}
break;
- case 296: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
+ case 298: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
{
- yylhsminor.yy455 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy455, yymsp[-2].minor.yy138, yymsp[-1].minor.yy138, &yymsp[-5].minor.yy0);
+ yylhsminor.yy303 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, yymsp[-2].minor.yy242, yymsp[-1].minor.yy242, &yymsp[-5].minor.yy0);
}
- yymsp[-5].minor.yy455 = yylhsminor.yy455;
+ yymsp[-5].minor.yy303 = yylhsminor.yy303;
break;
- case 297: /* window ::= ORDER BY sortlist frame_opt */
+ case 299: /* window ::= ORDER BY sortlist frame_opt */
{
- yymsp[-3].minor.yy455 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy455, 0, yymsp[-1].minor.yy138, 0);
+ yymsp[-3].minor.yy303 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, 0, yymsp[-1].minor.yy242, 0);
}
break;
- case 298: /* window ::= nm ORDER BY sortlist frame_opt */
+ case 300: /* window ::= nm ORDER BY sortlist frame_opt */
{
- yylhsminor.yy455 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy455, 0, yymsp[-1].minor.yy138, &yymsp[-4].minor.yy0);
+ yylhsminor.yy303 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, 0, yymsp[-1].minor.yy242, &yymsp[-4].minor.yy0);
}
- yymsp[-4].minor.yy455 = yylhsminor.yy455;
+ yymsp[-4].minor.yy303 = yylhsminor.yy303;
break;
- case 299: /* window ::= frame_opt */
- case 318: /* filter_over ::= over_clause */ yytestcase(yyruleno==318);
+ case 301: /* window ::= frame_opt */
+ case 320: /* filter_over ::= over_clause */ yytestcase(yyruleno==320);
{
- yylhsminor.yy455 = yymsp[0].minor.yy455;
+ yylhsminor.yy303 = yymsp[0].minor.yy303;
}
- yymsp[0].minor.yy455 = yylhsminor.yy455;
+ yymsp[0].minor.yy303 = yylhsminor.yy303;
break;
- case 300: /* window ::= nm frame_opt */
+ case 302: /* window ::= nm frame_opt */
{
- yylhsminor.yy455 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy455, 0, 0, &yymsp[-1].minor.yy0);
+ yylhsminor.yy303 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, 0, 0, &yymsp[-1].minor.yy0);
}
- yymsp[-1].minor.yy455 = yylhsminor.yy455;
+ yymsp[-1].minor.yy303 = yylhsminor.yy303;
break;
- case 301: /* frame_opt ::= */
+ case 303: /* frame_opt ::= */
{
- yymsp[1].minor.yy455 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0);
+ yymsp[1].minor.yy303 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0);
}
break;
- case 302: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
+ case 304: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
{
- yylhsminor.yy455 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy32, yymsp[-1].minor.yy57.eType, yymsp[-1].minor.yy57.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy118);
+ yylhsminor.yy303 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy192, yymsp[-1].minor.yy77.eType, yymsp[-1].minor.yy77.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy58);
}
- yymsp[-2].minor.yy455 = yylhsminor.yy455;
+ yymsp[-2].minor.yy303 = yylhsminor.yy303;
break;
- case 303: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
+ case 305: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
{
- yylhsminor.yy455 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy32, yymsp[-3].minor.yy57.eType, yymsp[-3].minor.yy57.pExpr, yymsp[-1].minor.yy57.eType, yymsp[-1].minor.yy57.pExpr, yymsp[0].minor.yy118);
+ yylhsminor.yy303 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy192, yymsp[-3].minor.yy77.eType, yymsp[-3].minor.yy77.pExpr, yymsp[-1].minor.yy77.eType, yymsp[-1].minor.yy77.pExpr, yymsp[0].minor.yy58);
}
- yymsp[-5].minor.yy455 = yylhsminor.yy455;
+ yymsp[-5].minor.yy303 = yylhsminor.yy303;
break;
- case 305: /* frame_bound_s ::= frame_bound */
- case 307: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==307);
-{yylhsminor.yy57 = yymsp[0].minor.yy57;}
- yymsp[0].minor.yy57 = yylhsminor.yy57;
+ case 307: /* frame_bound_s ::= frame_bound */
+ case 309: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==309);
+{yylhsminor.yy77 = yymsp[0].minor.yy77;}
+ yymsp[0].minor.yy77 = yylhsminor.yy77;
break;
- case 306: /* frame_bound_s ::= UNBOUNDED PRECEDING */
- case 308: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==308);
- case 310: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==310);
-{yylhsminor.yy57.eType = yymsp[-1].major; yylhsminor.yy57.pExpr = 0;}
- yymsp[-1].minor.yy57 = yylhsminor.yy57;
+ case 308: /* frame_bound_s ::= UNBOUNDED PRECEDING */
+ case 310: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==310);
+ case 312: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==312);
+{yylhsminor.yy77.eType = yymsp[-1].major; yylhsminor.yy77.pExpr = 0;}
+ yymsp[-1].minor.yy77 = yylhsminor.yy77;
break;
- case 309: /* frame_bound ::= expr PRECEDING|FOLLOWING */
-{yylhsminor.yy57.eType = yymsp[0].major; yylhsminor.yy57.pExpr = yymsp[-1].minor.yy46;}
- yymsp[-1].minor.yy57 = yylhsminor.yy57;
+ case 311: /* frame_bound ::= expr PRECEDING|FOLLOWING */
+{yylhsminor.yy77.eType = yymsp[0].major; yylhsminor.yy77.pExpr = yymsp[-1].minor.yy202;}
+ yymsp[-1].minor.yy77 = yylhsminor.yy77;
break;
- case 311: /* frame_exclude_opt ::= */
-{yymsp[1].minor.yy118 = 0;}
+ case 313: /* frame_exclude_opt ::= */
+{yymsp[1].minor.yy58 = 0;}
break;
- case 312: /* frame_exclude_opt ::= EXCLUDE frame_exclude */
-{yymsp[-1].minor.yy118 = yymsp[0].minor.yy118;}
+ case 314: /* frame_exclude_opt ::= EXCLUDE frame_exclude */
+{yymsp[-1].minor.yy58 = yymsp[0].minor.yy58;}
break;
- case 313: /* frame_exclude ::= NO OTHERS */
- case 314: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==314);
-{yymsp[-1].minor.yy118 = yymsp[-1].major; /*A-overwrites-X*/}
+ case 315: /* frame_exclude ::= NO OTHERS */
+ case 316: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==316);
+{yymsp[-1].minor.yy58 = yymsp[-1].major; /*A-overwrites-X*/}
break;
- case 315: /* frame_exclude ::= GROUP|TIES */
-{yymsp[0].minor.yy118 = yymsp[0].major; /*A-overwrites-X*/}
+ case 317: /* frame_exclude ::= GROUP|TIES */
+{yymsp[0].minor.yy58 = yymsp[0].major; /*A-overwrites-X*/}
break;
- case 316: /* window_clause ::= WINDOW windowdefn_list */
-{ yymsp[-1].minor.yy455 = yymsp[0].minor.yy455; }
+ case 318: /* window_clause ::= WINDOW windowdefn_list */
+{ yymsp[-1].minor.yy303 = yymsp[0].minor.yy303; }
break;
- case 317: /* filter_over ::= filter_clause over_clause */
+ case 319: /* filter_over ::= filter_clause over_clause */
{
- yymsp[0].minor.yy455->pFilter = yymsp[-1].minor.yy46;
- yylhsminor.yy455 = yymsp[0].minor.yy455;
+ yymsp[0].minor.yy303->pFilter = yymsp[-1].minor.yy202;
+ yylhsminor.yy303 = yymsp[0].minor.yy303;
}
- yymsp[-1].minor.yy455 = yylhsminor.yy455;
+ yymsp[-1].minor.yy303 = yylhsminor.yy303;
break;
- case 319: /* filter_over ::= filter_clause */
+ case 321: /* filter_over ::= filter_clause */
{
- yylhsminor.yy455 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
- if( yylhsminor.yy455 ){
- yylhsminor.yy455->eFrmType = TK_FILTER;
- yylhsminor.yy455->pFilter = yymsp[0].minor.yy46;
+ yylhsminor.yy303 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
+ if( yylhsminor.yy303 ){
+ yylhsminor.yy303->eFrmType = TK_FILTER;
+ yylhsminor.yy303->pFilter = yymsp[0].minor.yy202;
}else{
- sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy46);
+ sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy202);
}
}
- yymsp[0].minor.yy455 = yylhsminor.yy455;
+ yymsp[0].minor.yy303 = yylhsminor.yy303;
break;
- case 320: /* over_clause ::= OVER LP window RP */
+ case 322: /* over_clause ::= OVER LP window RP */
{
- yymsp[-3].minor.yy455 = yymsp[-1].minor.yy455;
- assert( yymsp[-3].minor.yy455!=0 );
+ yymsp[-3].minor.yy303 = yymsp[-1].minor.yy303;
+ assert( yymsp[-3].minor.yy303!=0 );
}
break;
- case 321: /* over_clause ::= OVER nm */
+ case 323: /* over_clause ::= OVER nm */
{
- yymsp[-1].minor.yy455 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
- if( yymsp[-1].minor.yy455 ){
- yymsp[-1].minor.yy455->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n);
+ yymsp[-1].minor.yy303 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
+ if( yymsp[-1].minor.yy303 ){
+ yymsp[-1].minor.yy303->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n);
}
}
break;
- case 322: /* filter_clause ::= FILTER LP WHERE expr RP */
-{ yymsp[-4].minor.yy46 = yymsp[-1].minor.yy46; }
+ case 324: /* filter_clause ::= FILTER LP WHERE expr RP */
+{ yymsp[-4].minor.yy202 = yymsp[-1].minor.yy202; }
break;
default:
- /* (323) input ::= cmdlist */ yytestcase(yyruleno==323);
- /* (324) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==324);
- /* (325) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=325);
- /* (326) ecmd ::= SEMI */ yytestcase(yyruleno==326);
- /* (327) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==327);
- /* (328) ecmd ::= explain cmdx */ yytestcase(yyruleno==328);
- /* (329) trans_opt ::= */ yytestcase(yyruleno==329);
- /* (330) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==330);
- /* (331) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==331);
- /* (332) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==332);
- /* (333) savepoint_opt ::= */ yytestcase(yyruleno==333);
- /* (334) cmd ::= create_table create_table_args */ yytestcase(yyruleno==334);
- /* (335) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==335);
- /* (336) columnlist ::= columnname carglist */ yytestcase(yyruleno==336);
- /* (337) nm ::= ID|INDEXED */ yytestcase(yyruleno==337);
- /* (338) nm ::= STRING */ yytestcase(yyruleno==338);
- /* (339) nm ::= JOIN_KW */ yytestcase(yyruleno==339);
- /* (340) typetoken ::= typename */ yytestcase(yyruleno==340);
- /* (341) typename ::= ID|STRING */ yytestcase(yyruleno==341);
- /* (342) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=342);
- /* (343) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=343);
- /* (344) carglist ::= carglist ccons */ yytestcase(yyruleno==344);
- /* (345) carglist ::= */ yytestcase(yyruleno==345);
- /* (346) ccons ::= NULL onconf */ yytestcase(yyruleno==346);
- /* (347) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==347);
- /* (348) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==348);
- /* (349) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=349);
- /* (350) tconscomma ::= */ yytestcase(yyruleno==350);
- /* (351) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=351);
- /* (352) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=352);
- /* (353) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=353);
- /* (354) oneselect ::= values */ yytestcase(yyruleno==354);
- /* (355) sclp ::= selcollist COMMA */ yytestcase(yyruleno==355);
- /* (356) as ::= ID|STRING */ yytestcase(yyruleno==356);
- /* (357) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=357);
- /* (358) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==358);
- /* (359) exprlist ::= nexprlist */ yytestcase(yyruleno==359);
- /* (360) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=360);
- /* (361) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=361);
- /* (362) nmnum ::= ON */ yytestcase(yyruleno==362);
- /* (363) nmnum ::= DELETE */ yytestcase(yyruleno==363);
- /* (364) nmnum ::= DEFAULT */ yytestcase(yyruleno==364);
- /* (365) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==365);
- /* (366) foreach_clause ::= */ yytestcase(yyruleno==366);
- /* (367) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==367);
- /* (368) trnm ::= nm */ yytestcase(yyruleno==368);
- /* (369) tridxby ::= */ yytestcase(yyruleno==369);
- /* (370) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==370);
- /* (371) database_kw_opt ::= */ yytestcase(yyruleno==371);
- /* (372) kwcolumn_opt ::= */ yytestcase(yyruleno==372);
- /* (373) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==373);
- /* (374) vtabarglist ::= vtabarg */ yytestcase(yyruleno==374);
- /* (375) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==375);
- /* (376) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==376);
- /* (377) anylist ::= */ yytestcase(yyruleno==377);
- /* (378) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==378);
- /* (379) anylist ::= anylist ANY */ yytestcase(yyruleno==379);
- /* (380) with ::= */ yytestcase(yyruleno==380);
+ /* (325) input ::= cmdlist */ yytestcase(yyruleno==325);
+ /* (326) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==326);
+ /* (327) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=327);
+ /* (328) ecmd ::= SEMI */ yytestcase(yyruleno==328);
+ /* (329) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==329);
+ /* (330) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=330);
+ /* (331) trans_opt ::= */ yytestcase(yyruleno==331);
+ /* (332) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==332);
+ /* (333) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==333);
+ /* (334) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==334);
+ /* (335) savepoint_opt ::= */ yytestcase(yyruleno==335);
+ /* (336) cmd ::= create_table create_table_args */ yytestcase(yyruleno==336);
+ /* (337) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==337);
+ /* (338) columnlist ::= columnname carglist */ yytestcase(yyruleno==338);
+ /* (339) nm ::= ID|INDEXED */ yytestcase(yyruleno==339);
+ /* (340) nm ::= STRING */ yytestcase(yyruleno==340);
+ /* (341) nm ::= JOIN_KW */ yytestcase(yyruleno==341);
+ /* (342) typetoken ::= typename */ yytestcase(yyruleno==342);
+ /* (343) typename ::= ID|STRING */ yytestcase(yyruleno==343);
+ /* (344) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=344);
+ /* (345) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=345);
+ /* (346) carglist ::= carglist ccons */ yytestcase(yyruleno==346);
+ /* (347) carglist ::= */ yytestcase(yyruleno==347);
+ /* (348) ccons ::= NULL onconf */ yytestcase(yyruleno==348);
+ /* (349) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==349);
+ /* (350) ccons ::= AS generated */ yytestcase(yyruleno==350);
+ /* (351) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==351);
+ /* (352) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==352);
+ /* (353) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=353);
+ /* (354) tconscomma ::= */ yytestcase(yyruleno==354);
+ /* (355) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=355);
+ /* (356) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=356);
+ /* (357) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=357);
+ /* (358) oneselect ::= values */ yytestcase(yyruleno==358);
+ /* (359) sclp ::= selcollist COMMA */ yytestcase(yyruleno==359);
+ /* (360) as ::= ID|STRING */ yytestcase(yyruleno==360);
+ /* (361) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=361);
+ /* (362) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==362);
+ /* (363) exprlist ::= nexprlist */ yytestcase(yyruleno==363);
+ /* (364) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=364);
+ /* (365) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=365);
+ /* (366) nmnum ::= ON */ yytestcase(yyruleno==366);
+ /* (367) nmnum ::= DELETE */ yytestcase(yyruleno==367);
+ /* (368) nmnum ::= DEFAULT */ yytestcase(yyruleno==368);
+ /* (369) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==369);
+ /* (370) foreach_clause ::= */ yytestcase(yyruleno==370);
+ /* (371) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==371);
+ /* (372) trnm ::= nm */ yytestcase(yyruleno==372);
+ /* (373) tridxby ::= */ yytestcase(yyruleno==373);
+ /* (374) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==374);
+ /* (375) database_kw_opt ::= */ yytestcase(yyruleno==375);
+ /* (376) kwcolumn_opt ::= */ yytestcase(yyruleno==376);
+ /* (377) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==377);
+ /* (378) vtabarglist ::= vtabarg */ yytestcase(yyruleno==378);
+ /* (379) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==379);
+ /* (380) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==380);
+ /* (381) anylist ::= */ yytestcase(yyruleno==381);
+ /* (382) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==382);
+ /* (383) anylist ::= anylist ANY */ yytestcase(yyruleno==383);
+ /* (384) with ::= */ yytestcase(yyruleno==384);
break;
/********** End reduce actions ************************************************/
};
@@ -154670,8 +157318,8 @@ SQLITE_PRIVATE int sqlite3ParserFallback(int iToken){
return yyFallback[iToken];
#else
(void)iToken;
-#endif
return 0;
+#endif
}
/************** End of parse.c ***********************************************/
@@ -154836,20 +157484,20 @@ const unsigned char ebcdicToAscii[] = {
** is substantially reduced. This is important for embedded applications
** on platforms with limited memory.
*/
-/* Hash score: 221 */
-/* zKWText[] encodes 967 bytes of keyword text in 638 bytes */
+/* Hash score: 227 */
+/* zKWText[] encodes 984 bytes of keyword text in 648 bytes */
/* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */
/* ABLEFTHENDEFERRABLELSEXCLUDELETEMPORARYISNULLSAVEPOINTERSECT */
/* IESNOTNULLIKEXCEPTRANSACTIONATURALTERAISEXCLUSIVEXISTS */
-/* CONSTRAINTOFFSETRIGGEREFERENCESUNIQUERYWITHOUTERELEASEATTACH */
-/* AVINGLOBEGINNERANGEBETWEENOTHINGROUPSCASCADETACHCASECOLLATE */
-/* CREATECURRENT_DATEIMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORT */
-/* UPDATEVALUESVIRTUALASTWHENWHERECURSIVEAFTERENAMEANDEFAULT */
-/* AUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSSCURRENT_TIMESTAMP */
-/* ARTITIONDEFERREDISTINCTDROPRECEDINGFAILIMITFILTEREPLACEFIRST */
-/* FOLLOWINGFROMFULLIFORDERESTRICTOTHERSOVERIGHTROLLBACKROWS */
+/* CONSTRAINTOFFSETRIGGERANGENERATEDETACHAVINGLOBEGINNEREFERENCES */
+/* UNIQUERYWITHOUTERELEASEATTACHBETWEENOTHINGROUPSCASCADEFAULT */
+/* CASECOLLATECREATECURRENT_DATEIMMEDIATEJOINSERTMATCHPLANALYZE */
+/* PRAGMABORTUPDATEVALUESVIRTUALWAYSWHENWHERECURSIVEAFTERENAMEAND */
+/* EFERREDISTINCTAUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSS */
+/* CURRENT_TIMESTAMPARTITIONDROPRECEDINGFAILASTFILTEREPLACEFIRST */
+/* FOLLOWINGFROMFULLIMITIFORDERESTRICTOTHERSOVERIGHTROLLBACKROWS */
/* UNBOUNDEDUNIONUSINGVACUUMVIEWINDOWBYINITIALLYPRIMARY */
-static const char zKWText[637] = {
+static const char zKWText[647] = {
'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H',
'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G',
'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A',
@@ -154860,93 +157508,96 @@ static const char zKWText[637] = {
'N','U','L','L','I','K','E','X','C','E','P','T','R','A','N','S','A','C',
'T','I','O','N','A','T','U','R','A','L','T','E','R','A','I','S','E','X',
'C','L','U','S','I','V','E','X','I','S','T','S','C','O','N','S','T','R',
- 'A','I','N','T','O','F','F','S','E','T','R','I','G','G','E','R','E','F',
- 'E','R','E','N','C','E','S','U','N','I','Q','U','E','R','Y','W','I','T',
- 'H','O','U','T','E','R','E','L','E','A','S','E','A','T','T','A','C','H',
- 'A','V','I','N','G','L','O','B','E','G','I','N','N','E','R','A','N','G',
- 'E','B','E','T','W','E','E','N','O','T','H','I','N','G','R','O','U','P',
- 'S','C','A','S','C','A','D','E','T','A','C','H','C','A','S','E','C','O',
- 'L','L','A','T','E','C','R','E','A','T','E','C','U','R','R','E','N','T',
- '_','D','A','T','E','I','M','M','E','D','I','A','T','E','J','O','I','N',
- 'S','E','R','T','M','A','T','C','H','P','L','A','N','A','L','Y','Z','E',
- 'P','R','A','G','M','A','B','O','R','T','U','P','D','A','T','E','V','A',
- 'L','U','E','S','V','I','R','T','U','A','L','A','S','T','W','H','E','N',
- 'W','H','E','R','E','C','U','R','S','I','V','E','A','F','T','E','R','E',
- 'N','A','M','E','A','N','D','E','F','A','U','L','T','A','U','T','O','I',
- 'N','C','R','E','M','E','N','T','C','A','S','T','C','O','L','U','M','N',
- 'C','O','M','M','I','T','C','O','N','F','L','I','C','T','C','R','O','S',
- 'S','C','U','R','R','E','N','T','_','T','I','M','E','S','T','A','M','P',
- 'A','R','T','I','T','I','O','N','D','E','F','E','R','R','E','D','I','S',
- 'T','I','N','C','T','D','R','O','P','R','E','C','E','D','I','N','G','F',
- 'A','I','L','I','M','I','T','F','I','L','T','E','R','E','P','L','A','C',
- 'E','F','I','R','S','T','F','O','L','L','O','W','I','N','G','F','R','O',
- 'M','F','U','L','L','I','F','O','R','D','E','R','E','S','T','R','I','C',
- 'T','O','T','H','E','R','S','O','V','E','R','I','G','H','T','R','O','L',
- 'L','B','A','C','K','R','O','W','S','U','N','B','O','U','N','D','E','D',
- 'U','N','I','O','N','U','S','I','N','G','V','A','C','U','U','M','V','I',
- 'E','W','I','N','D','O','W','B','Y','I','N','I','T','I','A','L','L','Y',
- 'P','R','I','M','A','R','Y',
+ 'A','I','N','T','O','F','F','S','E','T','R','I','G','G','E','R','A','N',
+ 'G','E','N','E','R','A','T','E','D','E','T','A','C','H','A','V','I','N',
+ 'G','L','O','B','E','G','I','N','N','E','R','E','F','E','R','E','N','C',
+ 'E','S','U','N','I','Q','U','E','R','Y','W','I','T','H','O','U','T','E',
+ 'R','E','L','E','A','S','E','A','T','T','A','C','H','B','E','T','W','E',
+ 'E','N','O','T','H','I','N','G','R','O','U','P','S','C','A','S','C','A',
+ 'D','E','F','A','U','L','T','C','A','S','E','C','O','L','L','A','T','E',
+ 'C','R','E','A','T','E','C','U','R','R','E','N','T','_','D','A','T','E',
+ 'I','M','M','E','D','I','A','T','E','J','O','I','N','S','E','R','T','M',
+ 'A','T','C','H','P','L','A','N','A','L','Y','Z','E','P','R','A','G','M',
+ 'A','B','O','R','T','U','P','D','A','T','E','V','A','L','U','E','S','V',
+ 'I','R','T','U','A','L','W','A','Y','S','W','H','E','N','W','H','E','R',
+ 'E','C','U','R','S','I','V','E','A','F','T','E','R','E','N','A','M','E',
+ 'A','N','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','A',
+ 'U','T','O','I','N','C','R','E','M','E','N','T','C','A','S','T','C','O',
+ 'L','U','M','N','C','O','M','M','I','T','C','O','N','F','L','I','C','T',
+ 'C','R','O','S','S','C','U','R','R','E','N','T','_','T','I','M','E','S',
+ 'T','A','M','P','A','R','T','I','T','I','O','N','D','R','O','P','R','E',
+ 'C','E','D','I','N','G','F','A','I','L','A','S','T','F','I','L','T','E',
+ 'R','E','P','L','A','C','E','F','I','R','S','T','F','O','L','L','O','W',
+ 'I','N','G','F','R','O','M','F','U','L','L','I','M','I','T','I','F','O',
+ 'R','D','E','R','E','S','T','R','I','C','T','O','T','H','E','R','S','O',
+ 'V','E','R','I','G','H','T','R','O','L','L','B','A','C','K','R','O','W',
+ 'S','U','N','B','O','U','N','D','E','D','U','N','I','O','N','U','S','I',
+ 'N','G','V','A','C','U','U','M','V','I','E','W','I','N','D','O','W','B',
+ 'Y','I','N','I','T','I','A','L','L','Y','P','R','I','M','A','R','Y',
};
/* aKWHash[i] is the hash value for the i-th keyword */
static const unsigned char aKWHash[127] = {
- 82, 113, 130, 80, 110, 29, 0, 0, 89, 0, 83, 70, 0,
- 53, 35, 84, 15, 0, 129, 92, 64, 124, 131, 19, 0, 0,
- 136, 0, 134, 126, 0, 22, 100, 0, 9, 0, 0, 121, 78,
- 0, 76, 6, 0, 58, 97, 143, 0, 132, 108, 0, 0, 48,
- 0, 111, 24, 0, 17, 0, 137, 63, 23, 26, 5, 65, 138,
- 103, 120, 0, 142, 114, 69, 141, 66, 118, 72, 0, 98, 0,
- 107, 41, 0, 106, 0, 0, 0, 102, 99, 104, 109, 123, 14,
- 50, 122, 0, 87, 0, 139, 119, 140, 68, 127, 135, 86, 81,
- 37, 91, 117, 0, 0, 101, 51, 128, 125, 0, 133, 0, 0,
- 44, 0, 93, 67, 39, 0, 20, 45, 115, 88,
+ 84, 102, 132, 82, 114, 29, 0, 0, 91, 0, 85, 72, 0,
+ 53, 35, 86, 15, 0, 42, 94, 54, 126, 133, 19, 0, 0,
+ 138, 0, 40, 128, 0, 22, 104, 0, 9, 0, 0, 122, 80,
+ 0, 78, 6, 0, 65, 99, 145, 0, 134, 112, 0, 0, 48,
+ 0, 100, 24, 0, 17, 0, 27, 70, 23, 26, 5, 60, 140,
+ 107, 121, 0, 73, 101, 71, 143, 61, 119, 74, 0, 49, 0,
+ 11, 41, 0, 110, 0, 0, 0, 106, 10, 108, 113, 124, 14,
+ 50, 123, 0, 89, 0, 18, 120, 142, 56, 129, 137, 88, 83,
+ 37, 30, 125, 0, 0, 105, 51, 130, 127, 0, 34, 0, 0,
+ 44, 0, 95, 38, 39, 0, 20, 45, 116, 90,
};
/* aKWNext[] forms the hash collision chain. If aKWHash[i]==0
** then the i-th keyword has no more hash collisions. Otherwise,
** the next keyword with the same hash is aKWHash[i]-1. */
-static const unsigned char aKWNext[143] = {
- 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 21, 0, 0, 0, 0, 12, 0, 0, 0, 0,
- 0, 0, 0, 7, 0, 36, 0, 0, 28, 0, 0, 0, 31,
- 0, 0, 0, 40, 0, 0, 0, 0, 0, 60, 0, 54, 0,
- 0, 38, 47, 0, 0, 0, 3, 0, 0, 74, 1, 73, 0,
- 0, 0, 52, 0, 0, 0, 0, 0, 0, 57, 59, 56, 30,
- 0, 0, 0, 46, 0, 16, 49, 10, 0, 0, 0, 0, 0,
- 0, 0, 11, 79, 95, 0, 0, 8, 0, 112, 0, 105, 0,
- 43, 62, 0, 77, 0, 116, 0, 61, 0, 0, 94, 42, 55,
- 0, 75, 34, 90, 32, 33, 27, 25, 18, 96, 0, 71, 85,
+static const unsigned char aKWNext[145] = {
+ 0, 0, 0, 0, 4, 0, 43, 0, 0, 103, 111, 0, 0,
+ 0, 2, 0, 0, 141, 0, 0, 0, 13, 0, 0, 0, 0,
+ 139, 0, 0, 118, 52, 0, 0, 135, 12, 0, 0, 62, 0,
+ 136, 0, 131, 0, 0, 36, 0, 0, 28, 77, 0, 0, 0,
+ 0, 59, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 69, 0, 0, 0, 0, 0, 144, 3, 0, 58, 0, 1,
+ 75, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 64, 66,
+ 63, 0, 0, 0, 0, 46, 0, 16, 0, 115, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 81, 97, 0, 8, 0, 109,
+ 21, 7, 67, 0, 79, 93, 117, 0, 0, 68, 0, 0, 96,
+ 0, 55, 0, 76, 0, 92, 32, 33, 57, 25, 0, 98, 0,
+ 0, 87,
};
/* aKWLen[i] is the length (in bytes) of the i-th keyword */
-static const unsigned char aKWLen[143] = {
+static const unsigned char aKWLen[145] = {
7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6,
7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 7,
6, 9, 4, 2, 6, 5, 9, 9, 4, 7, 3, 2, 4,
4, 6, 11, 6, 2, 7, 5, 5, 9, 6, 10, 4, 6,
- 2, 3, 7, 10, 6, 5, 7, 4, 5, 7, 6, 6, 4,
- 5, 5, 5, 7, 7, 6, 5, 7, 3, 6, 4, 7, 6,
- 12, 9, 4, 6, 5, 4, 7, 6, 5, 6, 6, 7, 4,
- 4, 5, 9, 5, 6, 3, 7, 13, 2, 2, 4, 6, 6,
- 8, 5, 17, 12, 7, 9, 8, 8, 2, 4, 9, 4, 5,
- 6, 7, 5, 9, 4, 4, 2, 5, 8, 6, 4, 5, 8,
- 4, 3, 9, 5, 5, 6, 4, 6, 2, 2, 9, 3, 7,
+ 2, 3, 7, 5, 9, 6, 6, 4, 5, 5, 10, 6, 5,
+ 7, 4, 5, 7, 6, 7, 7, 6, 5, 7, 3, 7, 4,
+ 7, 6, 12, 9, 4, 6, 5, 4, 7, 6, 5, 6, 6,
+ 7, 6, 4, 5, 9, 5, 6, 3, 8, 8, 2, 13, 2,
+ 2, 4, 6, 6, 8, 5, 17, 12, 7, 9, 4, 9, 4,
+ 4, 6, 7, 5, 9, 4, 4, 5, 2, 5, 8, 6, 4,
+ 5, 8, 4, 3, 9, 5, 5, 6, 4, 6, 2, 2, 9,
+ 3, 7,
};
/* aKWOffset[i] is the index into zKWText[] of the start of
** the text for the i-th keyword. */
-static const unsigned short int aKWOffset[143] = {
+static const unsigned short int aKWOffset[145] = {
0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33,
36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81,
86, 90, 90, 94, 99, 101, 105, 111, 119, 123, 123, 123, 126,
129, 132, 137, 142, 146, 147, 152, 156, 160, 168, 174, 181, 184,
- 184, 187, 189, 195, 205, 208, 213, 213, 217, 221, 228, 233, 238,
- 241, 244, 248, 253, 259, 265, 265, 271, 272, 276, 282, 286, 293,
- 299, 311, 320, 322, 328, 333, 335, 342, 347, 352, 358, 364, 370,
- 374, 378, 381, 390, 394, 400, 402, 409, 411, 413, 422, 426, 432,
- 438, 446, 451, 451, 451, 467, 476, 483, 484, 491, 494, 503, 506,
- 511, 516, 523, 528, 537, 541, 545, 547, 551, 559, 565, 568, 573,
- 581, 581, 585, 594, 599, 604, 610, 613, 616, 619, 621, 626, 630,
+ 184, 187, 189, 195, 198, 206, 211, 216, 219, 222, 226, 236, 239,
+ 244, 244, 248, 252, 259, 265, 271, 277, 277, 283, 284, 288, 295,
+ 299, 306, 312, 324, 333, 335, 341, 346, 348, 355, 360, 365, 371,
+ 377, 382, 388, 392, 395, 404, 408, 414, 416, 423, 424, 431, 433,
+ 435, 444, 448, 454, 460, 468, 473, 473, 473, 489, 498, 501, 510,
+ 513, 517, 522, 529, 534, 543, 547, 550, 555, 557, 561, 569, 575,
+ 578, 583, 591, 591, 595, 604, 609, 614, 620, 623, 626, 629, 631,
+ 636, 640,
};
/* aKWCode[i] is the parser symbol code for the i-th keyword */
-static const unsigned char aKWCode[143] = {
+static const unsigned char aKWCode[145] = {
TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE,
TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN,
TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD,
@@ -154958,25 +157609,154 @@ static const unsigned char aKWCode[143] = {
TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW,
TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_CONSTRAINT,
TK_INTO, TK_OFFSET, TK_OF, TK_SET, TK_TRIGGER,
- TK_REFERENCES, TK_UNIQUE, TK_QUERY, TK_WITHOUT, TK_WITH,
- TK_JOIN_KW, TK_RELEASE, TK_ATTACH, TK_HAVING, TK_LIKE_KW,
- TK_BEGIN, TK_JOIN_KW, TK_RANGE, TK_BETWEEN, TK_NOTHING,
- TK_GROUPS, TK_GROUP, TK_CASCADE, TK_ASC, TK_DETACH,
- TK_CASE, TK_COLLATE, TK_CREATE, TK_CTIME_KW, TK_IMMEDIATE,
- TK_JOIN, TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE,
- TK_PRAGMA, TK_ABORT, TK_UPDATE, TK_VALUES, TK_VIRTUAL,
- TK_LAST, TK_WHEN, TK_WHERE, TK_RECURSIVE, TK_AFTER,
- TK_RENAME, TK_AND, TK_DEFAULT, TK_AUTOINCR, TK_TO,
- TK_IN, TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT,
- TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_CURRENT, TK_PARTITION,
- TK_DEFERRED, TK_DISTINCT, TK_IS, TK_DROP, TK_PRECEDING,
- TK_FAIL, TK_LIMIT, TK_FILTER, TK_REPLACE, TK_FIRST,
- TK_FOLLOWING, TK_FROM, TK_JOIN_KW, TK_IF, TK_ORDER,
- TK_RESTRICT, TK_OTHERS, TK_OVER, TK_JOIN_KW, TK_ROLLBACK,
- TK_ROWS, TK_ROW, TK_UNBOUNDED, TK_UNION, TK_USING,
- TK_VACUUM, TK_VIEW, TK_WINDOW, TK_DO, TK_BY,
- TK_INITIALLY, TK_ALL, TK_PRIMARY,
+ TK_RANGE, TK_GENERATED, TK_DETACH, TK_HAVING, TK_LIKE_KW,
+ TK_BEGIN, TK_JOIN_KW, TK_REFERENCES, TK_UNIQUE, TK_QUERY,
+ TK_WITHOUT, TK_WITH, TK_JOIN_KW, TK_RELEASE, TK_ATTACH,
+ TK_BETWEEN, TK_NOTHING, TK_GROUPS, TK_GROUP, TK_CASCADE,
+ TK_ASC, TK_DEFAULT, TK_CASE, TK_COLLATE, TK_CREATE,
+ TK_CTIME_KW, TK_IMMEDIATE, TK_JOIN, TK_INSERT, TK_MATCH,
+ TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_ABORT, TK_UPDATE,
+ TK_VALUES, TK_VIRTUAL, TK_ALWAYS, TK_WHEN, TK_WHERE,
+ TK_RECURSIVE, TK_AFTER, TK_RENAME, TK_AND, TK_DEFERRED,
+ TK_DISTINCT, TK_IS, TK_AUTOINCR, TK_TO, TK_IN,
+ TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW,
+ TK_CTIME_KW, TK_CTIME_KW, TK_CURRENT, TK_PARTITION, TK_DROP,
+ TK_PRECEDING, TK_FAIL, TK_LAST, TK_FILTER, TK_REPLACE,
+ TK_FIRST, TK_FOLLOWING, TK_FROM, TK_JOIN_KW, TK_LIMIT,
+ TK_IF, TK_ORDER, TK_RESTRICT, TK_OTHERS, TK_OVER,
+ TK_JOIN_KW, TK_ROLLBACK, TK_ROWS, TK_ROW, TK_UNBOUNDED,
+ TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_WINDOW,
+ TK_DO, TK_BY, TK_INITIALLY, TK_ALL, TK_PRIMARY,
};
+/* Hash table decoded:
+** 0: INSERT
+** 1: IS
+** 2: ROLLBACK TRIGGER
+** 3: IMMEDIATE
+** 4: PARTITION
+** 5: TEMP
+** 6:
+** 7:
+** 8: VALUES WITHOUT
+** 9:
+** 10: MATCH
+** 11: NOTHING
+** 12:
+** 13: OF
+** 14: TIES IGNORE
+** 15: PLAN
+** 16: INSTEAD INDEXED
+** 17:
+** 18: TRANSACTION RIGHT
+** 19: WHEN
+** 20: SET HAVING
+** 21: IF
+** 22: ROWS
+** 23: SELECT
+** 24:
+** 25:
+** 26: VACUUM SAVEPOINT
+** 27:
+** 28: LIKE UNION VIRTUAL REFERENCES
+** 29: RESTRICT
+** 30:
+** 31: THEN REGEXP
+** 32: TO
+** 33:
+** 34: BEFORE
+** 35:
+** 36:
+** 37: FOLLOWING COLLATE CASCADE
+** 38: CREATE
+** 39:
+** 40: CASE REINDEX
+** 41: EACH
+** 42:
+** 43: QUERY
+** 44: AND ADD
+** 45: PRIMARY ANALYZE
+** 46:
+** 47: ROW ASC DETACH
+** 48: CURRENT_TIME CURRENT_DATE
+** 49:
+** 50:
+** 51: EXCLUSIVE TEMPORARY
+** 52:
+** 53: DEFERRED
+** 54: DEFERRABLE
+** 55:
+** 56: DATABASE
+** 57:
+** 58: DELETE VIEW GENERATED
+** 59: ATTACH
+** 60: END
+** 61: EXCLUDE
+** 62: ESCAPE DESC
+** 63: GLOB
+** 64: WINDOW ELSE
+** 65: COLUMN
+** 66: FIRST
+** 67:
+** 68: GROUPS ALL
+** 69: DISTINCT DROP KEY
+** 70: BETWEEN
+** 71: INITIALLY
+** 72: BEGIN
+** 73: FILTER CHECK ACTION
+** 74: GROUP INDEX
+** 75:
+** 76: EXISTS DEFAULT
+** 77:
+** 78: FOR CURRENT_TIMESTAMP
+** 79: EXCEPT
+** 80:
+** 81: CROSS
+** 82:
+** 83:
+** 84:
+** 85: CAST
+** 86: FOREIGN AUTOINCREMENT
+** 87: COMMIT
+** 88: CURRENT AFTER ALTER
+** 89: FULL FAIL CONFLICT
+** 90: EXPLAIN
+** 91: CONSTRAINT
+** 92: FROM ALWAYS
+** 93:
+** 94: ABORT
+** 95:
+** 96: AS DO
+** 97: REPLACE WITH RELEASE
+** 98: BY RENAME
+** 99: RANGE RAISE
+** 100: OTHERS
+** 101: USING NULLS
+** 102: PRAGMA
+** 103: JOIN ISNULL OFFSET
+** 104: NOT
+** 105: OR LAST LEFT
+** 106: LIMIT
+** 107:
+** 108:
+** 109: IN
+** 110: INTO
+** 111: OVER RECURSIVE
+** 112: ORDER OUTER
+** 113:
+** 114: INTERSECT UNBOUNDED
+** 115:
+** 116:
+** 117: ON
+** 118:
+** 119: WHERE
+** 120: NO INNER
+** 121: NULL
+** 122:
+** 123: TABLE
+** 124: NATURAL NOTNULL
+** 125: PRECEDING
+** 126: UPDATE UNIQUE
+*/
/* Check to see if z[0..n-1] is a keyword. If it is, write the
** parser symbol code for that keyword into *pType. Always
** return the integer n (the length of the token). */
@@ -155051,94 +157831,96 @@ static int keywordCode(const char *z, int n, int *pType){
testcase( i==52 ); /* OF */
testcase( i==53 ); /* SET */
testcase( i==54 ); /* TRIGGER */
- testcase( i==55 ); /* REFERENCES */
- testcase( i==56 ); /* UNIQUE */
- testcase( i==57 ); /* QUERY */
- testcase( i==58 ); /* WITHOUT */
- testcase( i==59 ); /* WITH */
- testcase( i==60 ); /* OUTER */
- testcase( i==61 ); /* RELEASE */
- testcase( i==62 ); /* ATTACH */
- testcase( i==63 ); /* HAVING */
- testcase( i==64 ); /* GLOB */
- testcase( i==65 ); /* BEGIN */
- testcase( i==66 ); /* INNER */
- testcase( i==67 ); /* RANGE */
- testcase( i==68 ); /* BETWEEN */
- testcase( i==69 ); /* NOTHING */
- testcase( i==70 ); /* GROUPS */
- testcase( i==71 ); /* GROUP */
- testcase( i==72 ); /* CASCADE */
- testcase( i==73 ); /* ASC */
- testcase( i==74 ); /* DETACH */
- testcase( i==75 ); /* CASE */
- testcase( i==76 ); /* COLLATE */
- testcase( i==77 ); /* CREATE */
- testcase( i==78 ); /* CURRENT_DATE */
- testcase( i==79 ); /* IMMEDIATE */
- testcase( i==80 ); /* JOIN */
- testcase( i==81 ); /* INSERT */
- testcase( i==82 ); /* MATCH */
- testcase( i==83 ); /* PLAN */
- testcase( i==84 ); /* ANALYZE */
- testcase( i==85 ); /* PRAGMA */
- testcase( i==86 ); /* ABORT */
- testcase( i==87 ); /* UPDATE */
- testcase( i==88 ); /* VALUES */
- testcase( i==89 ); /* VIRTUAL */
- testcase( i==90 ); /* LAST */
- testcase( i==91 ); /* WHEN */
- testcase( i==92 ); /* WHERE */
- testcase( i==93 ); /* RECURSIVE */
- testcase( i==94 ); /* AFTER */
- testcase( i==95 ); /* RENAME */
- testcase( i==96 ); /* AND */
- testcase( i==97 ); /* DEFAULT */
- testcase( i==98 ); /* AUTOINCREMENT */
- testcase( i==99 ); /* TO */
- testcase( i==100 ); /* IN */
- testcase( i==101 ); /* CAST */
- testcase( i==102 ); /* COLUMN */
- testcase( i==103 ); /* COMMIT */
- testcase( i==104 ); /* CONFLICT */
- testcase( i==105 ); /* CROSS */
- testcase( i==106 ); /* CURRENT_TIMESTAMP */
- testcase( i==107 ); /* CURRENT_TIME */
- testcase( i==108 ); /* CURRENT */
- testcase( i==109 ); /* PARTITION */
- testcase( i==110 ); /* DEFERRED */
- testcase( i==111 ); /* DISTINCT */
- testcase( i==112 ); /* IS */
- testcase( i==113 ); /* DROP */
- testcase( i==114 ); /* PRECEDING */
- testcase( i==115 ); /* FAIL */
- testcase( i==116 ); /* LIMIT */
- testcase( i==117 ); /* FILTER */
- testcase( i==118 ); /* REPLACE */
- testcase( i==119 ); /* FIRST */
- testcase( i==120 ); /* FOLLOWING */
- testcase( i==121 ); /* FROM */
- testcase( i==122 ); /* FULL */
- testcase( i==123 ); /* IF */
- testcase( i==124 ); /* ORDER */
- testcase( i==125 ); /* RESTRICT */
- testcase( i==126 ); /* OTHERS */
- testcase( i==127 ); /* OVER */
- testcase( i==128 ); /* RIGHT */
- testcase( i==129 ); /* ROLLBACK */
- testcase( i==130 ); /* ROWS */
- testcase( i==131 ); /* ROW */
- testcase( i==132 ); /* UNBOUNDED */
- testcase( i==133 ); /* UNION */
- testcase( i==134 ); /* USING */
- testcase( i==135 ); /* VACUUM */
- testcase( i==136 ); /* VIEW */
- testcase( i==137 ); /* WINDOW */
- testcase( i==138 ); /* DO */
- testcase( i==139 ); /* BY */
- testcase( i==140 ); /* INITIALLY */
- testcase( i==141 ); /* ALL */
- testcase( i==142 ); /* PRIMARY */
+ testcase( i==55 ); /* RANGE */
+ testcase( i==56 ); /* GENERATED */
+ testcase( i==57 ); /* DETACH */
+ testcase( i==58 ); /* HAVING */
+ testcase( i==59 ); /* GLOB */
+ testcase( i==60 ); /* BEGIN */
+ testcase( i==61 ); /* INNER */
+ testcase( i==62 ); /* REFERENCES */
+ testcase( i==63 ); /* UNIQUE */
+ testcase( i==64 ); /* QUERY */
+ testcase( i==65 ); /* WITHOUT */
+ testcase( i==66 ); /* WITH */
+ testcase( i==67 ); /* OUTER */
+ testcase( i==68 ); /* RELEASE */
+ testcase( i==69 ); /* ATTACH */
+ testcase( i==70 ); /* BETWEEN */
+ testcase( i==71 ); /* NOTHING */
+ testcase( i==72 ); /* GROUPS */
+ testcase( i==73 ); /* GROUP */
+ testcase( i==74 ); /* CASCADE */
+ testcase( i==75 ); /* ASC */
+ testcase( i==76 ); /* DEFAULT */
+ testcase( i==77 ); /* CASE */
+ testcase( i==78 ); /* COLLATE */
+ testcase( i==79 ); /* CREATE */
+ testcase( i==80 ); /* CURRENT_DATE */
+ testcase( i==81 ); /* IMMEDIATE */
+ testcase( i==82 ); /* JOIN */
+ testcase( i==83 ); /* INSERT */
+ testcase( i==84 ); /* MATCH */
+ testcase( i==85 ); /* PLAN */
+ testcase( i==86 ); /* ANALYZE */
+ testcase( i==87 ); /* PRAGMA */
+ testcase( i==88 ); /* ABORT */
+ testcase( i==89 ); /* UPDATE */
+ testcase( i==90 ); /* VALUES */
+ testcase( i==91 ); /* VIRTUAL */
+ testcase( i==92 ); /* ALWAYS */
+ testcase( i==93 ); /* WHEN */
+ testcase( i==94 ); /* WHERE */
+ testcase( i==95 ); /* RECURSIVE */
+ testcase( i==96 ); /* AFTER */
+ testcase( i==97 ); /* RENAME */
+ testcase( i==98 ); /* AND */
+ testcase( i==99 ); /* DEFERRED */
+ testcase( i==100 ); /* DISTINCT */
+ testcase( i==101 ); /* IS */
+ testcase( i==102 ); /* AUTOINCREMENT */
+ testcase( i==103 ); /* TO */
+ testcase( i==104 ); /* IN */
+ testcase( i==105 ); /* CAST */
+ testcase( i==106 ); /* COLUMN */
+ testcase( i==107 ); /* COMMIT */
+ testcase( i==108 ); /* CONFLICT */
+ testcase( i==109 ); /* CROSS */
+ testcase( i==110 ); /* CURRENT_TIMESTAMP */
+ testcase( i==111 ); /* CURRENT_TIME */
+ testcase( i==112 ); /* CURRENT */
+ testcase( i==113 ); /* PARTITION */
+ testcase( i==114 ); /* DROP */
+ testcase( i==115 ); /* PRECEDING */
+ testcase( i==116 ); /* FAIL */
+ testcase( i==117 ); /* LAST */
+ testcase( i==118 ); /* FILTER */
+ testcase( i==119 ); /* REPLACE */
+ testcase( i==120 ); /* FIRST */
+ testcase( i==121 ); /* FOLLOWING */
+ testcase( i==122 ); /* FROM */
+ testcase( i==123 ); /* FULL */
+ testcase( i==124 ); /* LIMIT */
+ testcase( i==125 ); /* IF */
+ testcase( i==126 ); /* ORDER */
+ testcase( i==127 ); /* RESTRICT */
+ testcase( i==128 ); /* OTHERS */
+ testcase( i==129 ); /* OVER */
+ testcase( i==130 ); /* RIGHT */
+ testcase( i==131 ); /* ROLLBACK */
+ testcase( i==132 ); /* ROWS */
+ testcase( i==133 ); /* ROW */
+ testcase( i==134 ); /* UNBOUNDED */
+ testcase( i==135 ); /* UNION */
+ testcase( i==136 ); /* USING */
+ testcase( i==137 ); /* VACUUM */
+ testcase( i==138 ); /* VIEW */
+ testcase( i==139 ); /* WINDOW */
+ testcase( i==140 ); /* DO */
+ testcase( i==141 ); /* BY */
+ testcase( i==142 ); /* INITIALLY */
+ testcase( i==143 ); /* ALL */
+ testcase( i==144 ); /* PRIMARY */
*pType = aKWCode[i];
break;
}
@@ -155150,7 +157932,7 @@ SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){
keywordCode((char*)z, n, &id);
return id;
}
-#define SQLITE_N_KEYWORD 143
+#define SQLITE_N_KEYWORD 145
SQLITE_API int sqlite3_keyword_name(int i,const char **pzName,int *pnName){
if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR;
*pzName = zKWText + aKWOffset[i];
@@ -155777,7 +158559,7 @@ SQLITE_PRIVATE char *sqlite3Normalize(
int nParen; /* Number of nested levels of parentheses */
int iStartIN; /* Start of RHS of IN operator in z[] */
int nParenAtIN; /* Value of nParent at start of RHS of IN operator */
- int j; /* Bytes of normalized SQL generated so far */
+ u32 j; /* Bytes of normalized SQL generated so far */
sqlite3_str *pStr; /* The normalized SQL string under construction */
db = sqlite3VdbeDb(pVdbe);
@@ -155821,7 +158603,7 @@ SQLITE_PRIVATE char *sqlite3Normalize(
}
case TK_RP: {
if( iStartIN>0 && nParen==nParenAtIN ){
- assert( pStr->nChar>=iStartIN );
+ assert( pStr->nChar>=(u32)iStartIN );
pStr->nChar = iStartIN+1;
sqlite3_str_append(pStr, "?,?,?", 5);
iStartIN = 0;
@@ -156958,6 +159740,9 @@ SQLITE_API int sqlite3_config(int op, ...){
static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
#ifndef SQLITE_OMIT_LOOKASIDE
void *pStart;
+ sqlite3_int64 szAlloc = sz*(sqlite3_int64)cnt;
+ int nBig; /* Number of full-size slots */
+ int nSm; /* Number smaller LOOKASIDE_SMALL-byte slots */
if( sqlite3LookasideUsed(db,0)>0 ){
return SQLITE_BUSY;
@@ -156980,37 +159765,71 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
pStart = 0;
}else if( pBuf==0 ){
sqlite3BeginBenignMalloc();
- pStart = sqlite3Malloc( sz*(sqlite3_int64)cnt ); /* IMP: R-61949-35727 */
+ pStart = sqlite3Malloc( szAlloc ); /* IMP: R-61949-35727 */
sqlite3EndBenignMalloc();
- if( pStart ) cnt = sqlite3MallocSize(pStart)/sz;
+ if( pStart ) szAlloc = sqlite3MallocSize(pStart);
}else{
pStart = pBuf;
}
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ if( sz>=LOOKASIDE_SMALL*3 ){
+ nBig = szAlloc/(3*LOOKASIDE_SMALL+sz);
+ nSm = (szAlloc - sz*nBig)/LOOKASIDE_SMALL;
+ }else if( sz>=LOOKASIDE_SMALL*2 ){
+ nBig = szAlloc/(LOOKASIDE_SMALL+sz);
+ nSm = (szAlloc - sz*nBig)/LOOKASIDE_SMALL;
+ }else
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
+ if( sz>0 ){
+ nBig = szAlloc/sz;
+ nSm = 0;
+ }else{
+ nBig = nSm = 0;
+ }
db->lookaside.pStart = pStart;
db->lookaside.pInit = 0;
db->lookaside.pFree = 0;
db->lookaside.sz = (u16)sz;
+ db->lookaside.szTrue = (u16)sz;
if( pStart ){
int i;
LookasideSlot *p;
assert( sz > (int)sizeof(LookasideSlot*) );
- db->lookaside.nSlot = cnt;
p = (LookasideSlot*)pStart;
- for(i=cnt-1; i>=0; i--){
+ for(i=0; i<nBig; i++){
p->pNext = db->lookaside.pInit;
db->lookaside.pInit = p;
p = (LookasideSlot*)&((u8*)p)[sz];
}
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ db->lookaside.pSmallInit = 0;
+ db->lookaside.pSmallFree = 0;
+ db->lookaside.pMiddle = p;
+ for(i=0; i<nSm; i++){
+ p->pNext = db->lookaside.pSmallInit;
+ db->lookaside.pSmallInit = p;
+ p = (LookasideSlot*)&((u8*)p)[LOOKASIDE_SMALL];
+ }
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
+ assert( ((uptr)p)<=szAlloc + (uptr)pStart );
db->lookaside.pEnd = p;
db->lookaside.bDisable = 0;
db->lookaside.bMalloced = pBuf==0 ?1:0;
+ db->lookaside.nSlot = nBig+nSm;
}else{
db->lookaside.pStart = db;
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+ db->lookaside.pSmallInit = 0;
+ db->lookaside.pSmallFree = 0;
+ db->lookaside.pMiddle = db;
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
db->lookaside.pEnd = db;
db->lookaside.bDisable = 1;
+ db->lookaside.sz = 0;
db->lookaside.bMalloced = 0;
db->lookaside.nSlot = 0;
}
+ assert( sqlite3LookasideUsed(db,0)==0 );
#endif /* SQLITE_OMIT_LOOKASIDE */
return SQLITE_OK;
}
@@ -157124,6 +159943,8 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
{ SQLITE_DBCONFIG_LEGACY_ALTER_TABLE, SQLITE_LegacyAlter },
{ SQLITE_DBCONFIG_DQS_DDL, SQLITE_DqsDDL },
{ SQLITE_DBCONFIG_DQS_DML, SQLITE_DqsDML },
+ { SQLITE_DBCONFIG_LEGACY_FILE_FORMAT, SQLITE_LegacyFileFmt },
+ { SQLITE_DBCONFIG_TRUSTED_SCHEMA, SQLITE_TrustedSchema },
};
unsigned int i;
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
@@ -157662,6 +160483,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
case SQLITE_CANTOPEN_ISDIR: zName = "SQLITE_CANTOPEN_ISDIR"; break;
case SQLITE_CANTOPEN_FULLPATH: zName = "SQLITE_CANTOPEN_FULLPATH"; break;
case SQLITE_CANTOPEN_CONVPATH: zName = "SQLITE_CANTOPEN_CONVPATH"; break;
+ case SQLITE_CANTOPEN_SYMLINK: zName = "SQLITE_CANTOPEN_SYMLINK"; break;
case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
@@ -157994,8 +160816,15 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY );
- extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|SQLITE_SUBTYPE);
+ extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|
+ SQLITE_SUBTYPE|SQLITE_INNOCUOUS);
enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
+
+ /* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But
+ ** the meaning is inverted. So flip the bit. */
+ assert( SQLITE_FUNC_UNSAFE==SQLITE_INNOCUOUS );
+ extraFlags ^= SQLITE_FUNC_UNSAFE;
+
#ifndef SQLITE_OMIT_UTF16
/* If SQLITE_UTF16 is specified as the encoding type, transform this
@@ -158009,11 +160838,13 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
enc = SQLITE_UTF16NATIVE;
}else if( enc==SQLITE_ANY ){
int rc;
- rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags,
+ rc = sqlite3CreateFunc(db, zFunctionName, nArg,
+ (SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE,
pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
if( rc==SQLITE_OK ){
- rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags,
- pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
+ rc = sqlite3CreateFunc(db, zFunctionName, nArg,
+ (SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE,
+ pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
}
if( rc!=SQLITE_OK ){
return rc;
@@ -159339,6 +162170,7 @@ static int openDatabase(
db->magic = SQLITE_MAGIC_BUSY;
db->aDb = db->aDbStatic;
db->lookaside.bDisable = 1;
+ db->lookaside.sz = 0;
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
@@ -159352,7 +162184,9 @@ static int openDatabase(
| SQLITE_EnableTrigger
| SQLITE_EnableView
| SQLITE_CacheSpill
-
+#if !defined(SQLITE_TRUSTED_SCHEMA) || SQLITE_TRUSTED_SCHEMA+0!=0
+ | SQLITE_TrustedSchema
+#endif
/* The SQLITE_DQS compile-time option determines the default settings
** for SQLITE_DBCONFIG_DQS_DDL and SQLITE_DBCONFIG_DQS_DML.
**
@@ -159582,6 +162416,13 @@ static int openDatabase(
}
#endif
+#ifdef SQLITE_ENABLE_INTERNAL_FUNCTIONS
+ /* Testing use only!!! The -DSQLITE_ENABLE_INTERNAL_FUNCTIONS=1 compile-time
+ ** option gives access to internal functions by default.
+ ** Testing use only!!! */
+ db->mDbFlags |= DBFLAG_InternalFunc;
+#endif
+
/* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking
** mode. Doing nothing at all also makes NORMAL the default.
@@ -160120,6 +162961,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){
** This test-control also resets the PRNG so that the new seed will
** be used for the next call to sqlite3_randomness().
*/
+#ifndef SQLITE_OMIT_WSD
case SQLITE_TESTCTRL_PRNG_SEED: {
int x = va_arg(ap, int);
int y;
@@ -160130,6 +162972,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){
sqlite3_randomness(0,0);
break;
}
+#endif
/*
** sqlite3_test_control(BITVEC_TEST, size, program)
@@ -160314,15 +163157,14 @@ SQLITE_API int sqlite3_test_control(int op, ...){
break;
}
- /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCS, int onoff);
+ /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, sqlite3*);
**
- ** If parameter onoff is non-zero, internal-use-only SQL functions
- ** are visible to ordinary SQL. This is useful for testing but is
- ** unsafe because invalid parameters to those internal-use-only functions
- ** can result in crashes or segfaults.
+ ** Toggle the ability to use internal functions on or off for
+ ** the database connection given in the argument.
*/
case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: {
- sqlite3GlobalConfig.bInternalFunctions = va_arg(ap, int);
+ sqlite3 *db = va_arg(ap, sqlite3*);
+ db->mDbFlags ^= DBFLAG_InternalFunc;
break;
}
@@ -160459,6 +163301,21 @@ SQLITE_API int sqlite3_test_control(int op, ...){
}
/*
+** The Pager stores the Database filename, Journal filename, and WAL filename
+** consecutively in memory, in that order. The database filename is prefixed
+** by four zero bytes. Locate the start of the database filename by searching
+** backwards for the first byte following four consecutive zero bytes.
+**
+** This only works if the filename passed in was obtained from the Pager.
+*/
+static const char *databaseName(const char *zName){
+ while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
+ zName--;
+ }
+ return zName;
+}
+
+/*
** This is a utility routine, useful to VFS implementations, that checks
** to see if a database file was a URI that contained a specific query
** parameter, and if so obtains the value of the query parameter.
@@ -160471,6 +163328,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){
*/
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
if( zFilename==0 || zParam==0 ) return 0;
+ zFilename = databaseName(zFilename);
zFilename += sqlite3Strlen30(zFilename) + 1;
while( zFilename[0] ){
int x = strcmp(zFilename, zParam);
@@ -160482,6 +163340,20 @@ SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *
}
/*
+** Return a pointer to the name of Nth query parameter of the filename.
+*/
+SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N){
+ if( zFilename==0 || N<0 ) return 0;
+ zFilename = databaseName(zFilename);
+ zFilename += sqlite3Strlen30(zFilename) + 1;
+ while( zFilename[0] && (N--)>0 ){
+ zFilename += sqlite3Strlen30(zFilename) + 1;
+ zFilename += sqlite3Strlen30(zFilename) + 1;
+ }
+ return zFilename[0] ? zFilename : 0;
+}
+
+/*
** Return a boolean value for a query parameter.
*/
SQLITE_API int sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){
@@ -160507,6 +163379,39 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(
}
/*
+** Translate a filename that was handed to a VFS routine into the corresponding
+** database, journal, or WAL file.
+**
+** It is an error to pass this routine a filename string that was not
+** passed into the VFS from the SQLite core. Doing so is similar to
+** passing free() a pointer that was not obtained from malloc() - it is
+** an error that we cannot easily detect but that will likely cause memory
+** corruption.
+*/
+SQLITE_API const char *sqlite3_filename_database(const char *zFilename){
+ return databaseName(zFilename);
+ return sqlite3_uri_parameter(zFilename - 3, "\003");
+}
+SQLITE_API const char *sqlite3_filename_journal(const char *zFilename){
+ zFilename = databaseName(zFilename);
+ zFilename += sqlite3Strlen30(zFilename) + 1;
+ while( zFilename[0] ){
+ zFilename += sqlite3Strlen30(zFilename) + 1;
+ zFilename += sqlite3Strlen30(zFilename) + 1;
+ }
+ return zFilename + 1;
+}
+SQLITE_API const char *sqlite3_filename_wal(const char *zFilename){
+#ifdef SQLITE_OMIT_WAL
+ return 0;
+#else
+ zFilename = sqlite3_filename_journal(zFilename);
+ zFilename += sqlite3Strlen30(zFilename) + 1;
+ return zFilename;
+#endif
+}
+
+/*
** Return the Btree pointer identified by zDbName. Return NULL if not found.
*/
SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
@@ -161839,6 +164744,9 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */
# define TESTONLY(X)
#endif
+#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
+#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
+
#endif /* SQLITE_AMALGAMATION */
#ifdef SQLITE_DEBUG
@@ -161882,6 +164790,7 @@ struct Fts3Table {
char *zLanguageid; /* languageid=xxx option, or NULL */
int nAutoincrmerge; /* Value configured by 'automerge' */
u32 nLeafAdd; /* Number of leaf blocks added this trans */
+ int bLock; /* Used to prevent recursive content= tbls */
/* Precompiled statements used by the implementation. Each of these
** statements is run and reset within a single virtual table API call.
@@ -161940,13 +164849,23 @@ struct Fts3Table {
int mxSavepoint; /* Largest valid xSavepoint integer */
#endif
-#ifdef SQLITE_TEST
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/* True to disable the incremental doclist optimization. This is controled
** by special insert command 'test-no-incr-doclist'. */
int bNoIncrDoclist;
+
+ /* Number of segments in a level */
+ int nMergeCount;
#endif
};
+/* Macro to find the number of segments to merge */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
+# define MergeCount(P) ((P)->nMergeCount)
+#else
+# define MergeCount(P) FTS3_MERGE_COUNT
+#endif
+
/*
** When the core wants to read from the virtual table, it creates a
** virtual table cursor (an instance of the following structure) using
@@ -162210,6 +165129,8 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...);
SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
+SQLITE_PRIVATE int sqlite3Fts3GetVarintU(const char *, sqlite_uint64 *);
+SQLITE_PRIVATE int sqlite3Fts3GetVarintBounded(const char*,const char*,sqlite3_int64*);
SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64);
SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
@@ -162296,18 +165217,6 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int);
SQLITE_EXTENSION_INIT1
#endif
-/*
-** The following are copied from sqliteInt.h.
-**
-** Constants for the largest and smallest possible 64-bit signed integers.
-** These macros are designed to work correctly on both 32-bit and 64-bit
-** compilers.
-*/
-#ifndef SQLITE_AMALGAMATION
-# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
-# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
-#endif
-
static int fts3EvalNext(Fts3Cursor *pCsr);
static int fts3EvalStart(Fts3Cursor *pCsr);
static int fts3TermSegReaderCursor(
@@ -162352,12 +165261,7 @@ SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
v = (*ptr++); \
if( (v & mask2)==0 ){ var = v; return ret; }
-/*
-** Read a 64-bit variable-length integer from memory starting at p[0].
-** Return the number of bytes read, or 0 on error.
-** The value is stored in *v.
-*/
-SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
+SQLITE_PRIVATE int sqlite3Fts3GetVarintU(const char *pBuf, sqlite_uint64 *v){
const unsigned char *p = (const unsigned char*)pBuf;
const unsigned char *pStart = p;
u32 a;
@@ -162379,6 +165283,41 @@ SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
return (int)(p - pStart);
}
+/*
+** Read a 64-bit variable-length integer from memory starting at p[0].
+** Return the number of bytes read, or 0 on error.
+** The value is stored in *v.
+*/
+SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
+ return sqlite3Fts3GetVarintU(pBuf, (sqlite3_uint64*)v);
+}
+
+/*
+** Read a 64-bit variable-length integer from memory starting at p[0] and
+** not extending past pEnd[-1].
+** Return the number of bytes read, or 0 on error.
+** The value is stored in *v.
+*/
+SQLITE_PRIVATE int sqlite3Fts3GetVarintBounded(
+ const char *pBuf,
+ const char *pEnd,
+ sqlite_int64 *v
+){
+ const unsigned char *p = (const unsigned char*)pBuf;
+ const unsigned char *pStart = p;
+ const unsigned char *pX = (const unsigned char*)pEnd;
+ u64 b = 0;
+ int shift;
+ for(shift=0; shift<=63; shift+=7){
+ u64 c = p<pX ? *p : 0;
+ p++;
+ b += (c&0x7F) << shift;
+ if( (c & 0x80)==0 ) break;
+ }
+ *v = b;
+ return (int)(p - pStart);
+}
+
/*
** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to
** a non-negative 32-bit integer before it is returned.
@@ -163474,6 +166413,10 @@ static int fts3InitVtab(
fts3DatabasePageSize(&rc, p);
p->nNodeSize = p->nPgsz-35;
+#if defined(SQLITE_DEBUG)||defined(SQLITE_TEST)
+ p->nMergeCount = FTS3_MERGE_COUNT;
+#endif
+
/* Declare the table schema to SQLite. */
fts3DeclareVtab(&rc, p);
@@ -163569,6 +166512,10 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
int iDocidLe = -1; /* Index of docid<=x constraint, if present */
int iIdx;
+ if( p->bLock ){
+ return SQLITE_ERROR;
+ }
+
/* By default use a full table scan. This is an expensive option,
** so search through the constraints to see if a more efficient
** strategy is possible.
@@ -163767,7 +166714,11 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
}else{
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
if( !zSql ) return SQLITE_NOMEM;
- rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
+ p->bLock++;
+ rc = sqlite3_prepare_v3(
+ p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
+ );
+ p->bLock--;
sqlite3_free(zSql);
}
if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
@@ -163785,11 +166736,15 @@ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
if( pCsr->isRequireSeek ){
rc = fts3CursorSeekStmt(pCsr);
if( rc==SQLITE_OK ){
+ Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab;
+ pTab->bLock++;
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
pCsr->isRequireSeek = 0;
if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
+ pTab->bLock--;
return SQLITE_OK;
}else{
+ pTab->bLock--;
rc = sqlite3_reset(pCsr->pStmt);
if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
/* If no row was found and no error has occurred, then the %_content
@@ -163961,7 +166916,7 @@ static int fts3SelectLeaf(
fts3GetVarint32(zNode, &iHeight);
rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
- assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
+ assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
if( rc==SQLITE_OK && iHeight>1 ){
char *zBlob = 0; /* Blob read from %_segments table */
@@ -163981,7 +166936,13 @@ static int fts3SelectLeaf(
rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0);
}
if( rc==SQLITE_OK ){
- rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
+ int iNewHeight = 0;
+ fts3GetVarint32(zBlob, &iNewHeight);
+ if( iNewHeight>=iHeight ){
+ rc = FTS_CORRUPT_VTAB;
+ }else{
+ rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
+ }
}
sqlite3_free(zBlob);
}
@@ -164436,12 +167397,12 @@ static void fts3GetDeltaVarint3(
if( *pp>=pEnd ){
*pp = 0;
}else{
- sqlite3_int64 iVal;
- *pp += sqlite3Fts3GetVarint(*pp, &iVal);
+ u64 iVal;
+ *pp += sqlite3Fts3GetVarintU(*pp, &iVal);
if( bDescIdx ){
- *pVal -= iVal;
+ *pVal = (i64)((u64)*pVal - iVal);
}else{
- *pVal += iVal;
+ *pVal = (i64)((u64)*pVal + iVal);
}
}
}
@@ -164468,15 +167429,16 @@ static void fts3PutDeltaVarint3(
int *pbFirst, /* IN/OUT: True after first int written */
sqlite3_int64 iVal /* Write this value to the list */
){
- sqlite3_int64 iWrite;
+ sqlite3_uint64 iWrite;
if( bDescIdx==0 || *pbFirst==0 ){
- iWrite = iVal - *piPrev;
+ assert_fts3_nc( *pbFirst==0 || iVal>=*piPrev );
+ iWrite = (u64)iVal - (u64)*piPrev;
}else{
- iWrite = *piPrev - iVal;
+ assert_fts3_nc( *piPrev>=iVal );
+ iWrite = (u64)*piPrev - (u64)iVal;
}
assert( *pbFirst || *piPrev==0 );
assert_fts3_nc( *pbFirst==0 || iWrite>0 );
- assert( *pbFirst==0 || iWrite>=0 );
*pp += sqlite3Fts3PutVarint(*pp, iWrite);
*piPrev = iVal;
*pbFirst = 1;
@@ -164492,7 +167454,8 @@ static void fts3PutDeltaVarint3(
** Using this makes it easier to write code that can merge doclists that are
** sorted in either ascending or descending order.
*/
-#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
+/* #define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i64)((u64)i1-i2)) */
+#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1>i2?1:((i1==i2)?0:-1)))
/*
** This function does an "OR" merge of two doclists (output contains all
@@ -164906,7 +167869,7 @@ static int fts3SegReaderCursor(
** Fts3SegReaderPending might segfault, as the data structures used by
** fts4aux are not completely populated. So it's easiest to filter these
** calls out here. */
- if( iLevel<0 && p->aIndex ){
+ if( iLevel<0 && p->aIndex && p->iPrevLangid==iLangid ){
Fts3SegReader *pSeg = 0;
rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg);
if( rc==SQLITE_OK && pSeg ){
@@ -165169,6 +168132,8 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
int rc;
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
if( pCsr->eSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){
+ Fts3Table *pTab = (Fts3Table*)pCursor->pVtab;
+ pTab->bLock++;
if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
pCsr->isEof = 1;
rc = sqlite3_reset(pCsr->pStmt);
@@ -165176,6 +168141,7 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
rc = SQLITE_OK;
}
+ pTab->bLock--;
}else{
rc = fts3EvalNext((Fts3Cursor *)pCursor);
}
@@ -165236,6 +168202,10 @@ static int fts3FilterMethod(
UNUSED_PARAMETER(idxStr);
UNUSED_PARAMETER(nVal);
+ if( p->bLock ){
+ return SQLITE_ERROR;
+ }
+
eSearch = (idxNum & 0x0000FFFF);
assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
assert( p->pSegments==0 );
@@ -165307,7 +168277,11 @@ static int fts3FilterMethod(
);
}
if( zSql ){
- rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
+ p->bLock++;
+ rc = sqlite3_prepare_v3(
+ p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
+ );
+ p->bLock--;
sqlite3_free(zSql);
}else{
rc = SQLITE_NOMEM;
@@ -166324,7 +169298,7 @@ static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
int bIncrOk = (bOptOk
&& pCsr->bDesc==pTab->bDescIdx
&& p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
-#ifdef SQLITE_TEST
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
&& pTab->bNoIncrDoclist==0
#endif
);
@@ -166466,15 +169440,16 @@ static void fts3EvalDlPhraseNext(
u8 *pbEof
){
char *pIter; /* Used to iterate through aAll */
- char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
+ char *pEnd; /* 1 byte past end of aAll */
if( pDL->pNextDocid ){
pIter = pDL->pNextDocid;
+ assert( pDL->aAll!=0 || pIter==0 );
}else{
pIter = pDL->aAll;
}
- if( pIter>=pEnd ){
+ if( pIter==0 || pIter>=(pEnd = pDL->aAll + pDL->nAll) ){
/* We have already reached the end of this doclist. EOF. */
*pbEof = 1;
}else{
@@ -166846,12 +169821,13 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
if( rc!=SQLITE_OK ) return rc;
a = sqlite3_column_blob(pStmt, 0);
- assert( a );
-
- pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
- a += sqlite3Fts3GetVarint(a, &nDoc);
- while( a<pEnd ){
- a += sqlite3Fts3GetVarint(a, &nByte);
+ testcase( a==0 ); /* If %_stat.value set to X'' */
+ if( a ){
+ pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
+ a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc);
+ while( a<pEnd ){
+ a += sqlite3Fts3GetVarintBounded(a, pEnd, &nByte);
+ }
}
if( nDoc==0 || nByte==0 ){
sqlite3_reset(pStmt);
@@ -171289,7 +174265,9 @@ int queryTokenizer(
sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
if( SQLITE_ROW==sqlite3_step(pStmt) ){
- if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
+ if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB
+ && sqlite3_column_bytes(pStmt, 0)==sizeof(*pp)
+ ){
memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
}
}
@@ -171378,7 +174356,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitHashTable(
){
int rc = SQLITE_OK;
void *p = (void *)pHash;
- const int any = SQLITE_ANY;
+ const int any = SQLITE_UTF8|SQLITE_DIRECTONLY;
#ifdef SQLITE_TEST
char *zTest = 0;
@@ -172138,7 +175116,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){
/* #include <string.h> */
/* #include <assert.h> */
/* #include <stdlib.h> */
-
+/* #include <stdio.h> */
#define FTS_MAX_APPENDABLE_HEIGHT 16
@@ -172182,7 +175160,7 @@ int test_fts3_node_chunk_threshold = (4*1024)*4;
#endif
/*
-** The two values that may be meaningfully bound to the :1 parameter in
+** The values that may be meaningfully bound to the :1 parameter in
** statements SQL_REPLACE_STAT and SQL_SELECT_STAT.
*/
#define FTS_STAT_DOCTOTAL 0
@@ -172450,7 +175428,7 @@ static int fts3SqlStmt(
** returns zero rows. */
/* 28 */ "SELECT level, count(*) AS cnt FROM %Q.'%q_segdir' "
" GROUP BY level HAVING cnt>=?"
- " ORDER BY (level %% 1024) ASC LIMIT 1",
+ " ORDER BY (level %% 1024) ASC, 2 DESC LIMIT 1",
/* Estimate the upper limit on the number of leaf nodes in a new segment
** created by merging the oldest :2 segments from absolute level :1. See
@@ -172811,7 +175789,7 @@ static int fts3PendingListAppend(
assert( !p || p->iLastDocid<=iDocid );
if( !p || p->iLastDocid!=iDocid ){
- sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0);
+ u64 iDelta = (u64)iDocid - (u64)(p ? p->iLastDocid : 0);
if( p ){
assert( p->nData<p->nSpace );
assert( p->aData[p->nData]==0 );
@@ -173268,7 +176246,7 @@ static int fts3AllocateSegdirIdx(
** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
*/
- if( iNext>=FTS3_MERGE_COUNT ){
+ if( iNext>=MergeCount(p) ){
fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel));
rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel);
*piIdx = 0;
@@ -173352,6 +176330,8 @@ SQLITE_PRIVATE int sqlite3Fts3ReadBlock(
}
*paBlob = aByte;
}
+ }else if( rc==SQLITE_ERROR ){
+ rc = FTS_CORRUPT_VTAB;
}
return rc;
@@ -173494,7 +176474,7 @@ static int fts3SegReaderNext(
pNext += fts3GetVarint32(pNext, &nSuffix);
if( nSuffix<=0
|| (&pReader->aNode[pReader->nNode] - pNext)<nSuffix
- || nPrefix>pReader->nTermAlloc
+ || nPrefix>pReader->nTerm
){
return FTS_CORRUPT_VTAB;
}
@@ -173644,18 +176624,18 @@ static int fts3SegReaderNextDocid(
}else{
rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
if( rc==SQLITE_OK ){
- sqlite3_int64 iDelta;
- pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
+ u64 iDelta;
+ pReader->pOffsetList = p + sqlite3Fts3GetVarintU(p, &iDelta);
if( pTab->bDescIdx ){
- pReader->iDocid -= iDelta;
+ pReader->iDocid = (i64)((u64)pReader->iDocid - iDelta);
}else{
- pReader->iDocid += iDelta;
+ pReader->iDocid = (i64)((u64)pReader->iDocid + iDelta);
}
}
}
}
- return SQLITE_OK;
+ return rc;
}
@@ -174145,6 +177125,11 @@ static int fts3NodeAddTerm(
nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm);
nSuffix = nTerm-nPrefix;
+ /* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of
+ ** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when
+ ** compared with BINARY collation. This indicates corruption. */
+ if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
+
nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix;
if( nReq<=p->nNodeSize || !pTree->zTerm ){
@@ -174389,6 +177374,7 @@ static int fts3SegWriterAdd(
int rc;
/* The current leaf node is full. Write it out to the database. */
+ if( pWriter->iFree==LARGEST_INT64 ) return FTS_CORRUPT_VTAB;
rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData);
if( rc!=SQLITE_OK ) return rc;
p->nLeafAdd++;
@@ -174438,9 +177424,11 @@ static int fts3SegWriterAdd(
/* Append the prefix-compressed term and doclist to the buffer. */
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nPrefix);
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nSuffix);
+ assert( nSuffix>0 );
memcpy(&pWriter->aData[nData], &zTerm[nPrefix], nSuffix);
nData += nSuffix;
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nDoclist);
+ assert( nDoclist>0 );
memcpy(&pWriter->aData[nData], aDoclist, nDoclist);
pWriter->nData = nData + nDoclist;
@@ -174460,6 +177448,7 @@ static int fts3SegWriterAdd(
pWriter->zTerm = zNew;
}
assert( pWriter->zTerm==pWriter->zMalloc );
+ assert( nTerm>0 );
memcpy(pWriter->zTerm, zTerm, nTerm);
}else{
pWriter->zTerm = (char *)zTerm;
@@ -174768,6 +177757,7 @@ static int fts3MsrBufferData(
pMsr->aBuffer = pNew;
}
+ assert( nList>0 );
memcpy(pMsr->aBuffer, pList, nList);
return SQLITE_OK;
}
@@ -175081,14 +178071,12 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
** doclist. */
sqlite3_int64 iDelta;
if( p->bDescIdx && nDoclist>0 ){
- iDelta = iPrev - iDocid;
+ if( iPrev<=iDocid ) return FTS_CORRUPT_VTAB;
+ iDelta = (i64)((u64)iPrev - (u64)iDocid);
}else{
- iDelta = iDocid - iPrev;
- }
- if( iDelta<=0 && (nDoclist>0 || iDelta!=iDocid) ){
- return FTS_CORRUPT_VTAB;
+ if( nDoclist>0 && iPrev>=iDocid ) return FTS_CORRUPT_VTAB;
+ iDelta = (i64)((u64)iDocid - (u64)iPrev);
}
- assert( nDoclist>0 || iDelta==iDocid );
nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
if( nDoclist+nByte>pCsr->nBuffer ){
@@ -175370,7 +178358,7 @@ static int fts3SegmentMerge(
csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
}
if( rc!=SQLITE_OK ) goto finished;
- assert( pWriter || bIgnoreEmpty );
+ assert_fts3_nc( pWriter || bIgnoreEmpty );
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
rc = fts3DeleteSegdir(
@@ -175597,7 +178585,10 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
int rc;
sqlite3_stmt *pAllLangid = 0;
- rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
+ rc = sqlite3Fts3PendingTermsFlush(p);
+ if( rc==SQLITE_OK ){
+ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
+ }
if( rc==SQLITE_OK ){
int rc2;
sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
@@ -175618,7 +178609,6 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
}
sqlite3Fts3SegmentsClose(p);
- sqlite3Fts3PendingTermsClear(p);
return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
}
@@ -175956,6 +178946,7 @@ static int fts3IncrmergePush(
** be added to. */
nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm);
nSuffix = nTerm - nPrefix;
+ if(nSuffix<=0 ) return FTS_CORRUPT_VTAB;
nSpace = sqlite3Fts3VarintLen(nPrefix);
nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
@@ -176350,6 +179341,10 @@ static int fts3IncrmergeLoad(
pWriter->bNoLeafData = (pWriter->nLeafData==0);
nRoot = sqlite3_column_bytes(pSelect, 4);
aRoot = sqlite3_column_blob(pSelect, 4);
+ if( aRoot==0 ){
+ sqlite3_reset(pSelect);
+ return nRoot ? SQLITE_NOMEM : FTS_CORRUPT_VTAB;
+ }
}else{
return sqlite3_reset(pSelect);
}
@@ -176385,6 +179380,10 @@ static int fts3IncrmergeLoad(
int i;
int nHeight = (int)aRoot[0];
NodeWriter *pNode;
+ if( nHeight<1 || nHeight>FTS_MAX_APPENDABLE_HEIGHT ){
+ sqlite3_reset(pSelect);
+ return FTS_CORRUPT_VTAB;
+ }
pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT;
pWriter->iStart = iStart;
@@ -176945,13 +179944,17 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
const int nHint = pHint->n;
int i;
- i = pHint->n-2;
+ i = pHint->n-1;
+ if( (pHint->a[i] & 0x80) ) return FTS_CORRUPT_VTAB;
while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
+ if( i==0 ) return FTS_CORRUPT_VTAB;
+ i--;
while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
pHint->n = i;
i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
i += fts3GetVarint32(&pHint->a[i], pnInput);
+ assert( i<=nHint );
if( i!=nHint ) return FTS_CORRUPT_VTAB;
return SQLITE_OK;
@@ -177021,8 +180024,14 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg);
if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){
+ /* Based on the scan in the block above, it is known that there
+ ** are no levels with a relative level smaller than that of
+ ** iAbsLevel with more than nSeg segments, or if nSeg is -1,
+ ** no levels with more than nMin segments. Use this to limit the
+ ** value of nHintSeg to avoid a large memory allocation in case the
+ ** merge-hint is corrupt*/
iAbsLevel = iHintAbsLevel;
- nSeg = nHintSeg;
+ nSeg = MIN(MAX(nMin,nSeg), nHintSeg);
bUseHint = 1;
bDirtyHint = 1;
}else{
@@ -177035,7 +180044,7 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
/* If nSeg is less that zero, then there is no level with at least
** nMin segments and no hint in the %_stat table. No work to do.
** Exit early in this case. */
- if( nSeg<0 ) break;
+ if( nSeg<=0 ) break;
/* Open a cursor to iterate through the contents of the oldest nSeg
** indexes of absolute level iAbsLevel. If this cursor is opened using
@@ -177063,8 +180072,15 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
}
if( SQLITE_OK==rc && pCsr->nSegment==nSeg
&& SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
- && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
){
+ int bEmpty = 0;
+ rc = sqlite3Fts3SegReaderStep(p, pCsr);
+ if( rc==SQLITE_OK ){
+ bEmpty = 1;
+ }else if( rc!=SQLITE_ROW ){
+ sqlite3Fts3SegReaderFinish(pCsr);
+ break;
+ }
if( bUseHint && iIdx>0 ){
const char *zKey = pCsr->zTerm;
int nKey = pCsr->nTerm;
@@ -177075,11 +180091,13 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
if( rc==SQLITE_OK && pWriter->nLeafEst ){
fts3LogMerge(nSeg, iAbsLevel);
- do {
- rc = fts3IncrmergeAppend(p, pWriter, pCsr);
- if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
- if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
- }while( rc==SQLITE_ROW );
+ if( bEmpty==0 ){
+ do {
+ rc = fts3IncrmergeAppend(p, pWriter, pCsr);
+ if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
+ if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
+ }while( rc==SQLITE_ROW );
+ }
/* Update or delete the input segments */
if( rc==SQLITE_OK ){
@@ -177144,7 +180162,7 @@ static int fts3DoIncrmerge(
const char *zParam /* Nul-terminated string containing "A,B" */
){
int rc;
- int nMin = (FTS3_MERGE_COUNT / 2);
+ int nMin = (MergeCount(p) / 2);
int nMerge = 0;
const char *z = zParam;
@@ -177189,7 +180207,7 @@ static int fts3DoAutoincrmerge(
int rc = SQLITE_OK;
sqlite3_stmt *pStmt = 0;
p->nAutoincrmerge = fts3Getint(&zParam);
- if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){
+ if( p->nAutoincrmerge==1 || p->nAutoincrmerge>MergeCount(p) ){
p->nAutoincrmerge = 8;
}
if( !p->bHasStat ){
@@ -177272,12 +180290,12 @@ static u64 fts3ChecksumIndex(
i64 iDocid = 0;
i64 iCol = 0;
- i64 iPos = 0;
+ u64 iPos = 0;
pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid);
while( pCsr<pEnd ){
- i64 iVal = 0;
- pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
+ u64 iVal = 0;
+ pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
if( pCsr<pEnd ){
if( iVal==0 || iVal==1 ){
iCol = 0;
@@ -177285,8 +180303,12 @@ static u64 fts3ChecksumIndex(
if( iVal ){
pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
}else{
- pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
- iDocid += iVal;
+ pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
+ if( p->bDescIdx ){
+ iDocid = (i64)((u64)iDocid - iVal);
+ }else{
+ iDocid = (i64)((u64)iDocid + iVal);
+ }
}
}else{
iPos += (iVal - 2);
@@ -177359,10 +180381,9 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
if( p->abNotindexed[iCol]==0 ){
const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
- int nText = sqlite3_column_bytes(pStmt, iCol+1);
sqlite3_tokenizer_cursor *pT = 0;
- rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText,&pT);
+ rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, -1, &pT);
while( rc==SQLITE_OK ){
char const *zToken; /* Buffer containing token */
int nToken = 0; /* Number of bytes in token */
@@ -177447,7 +180468,7 @@ static int fts3DoIntegrityCheck(
** meaningful value to insert is the text 'optimize'.
*/
static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
- int rc; /* Return Code */
+ int rc = SQLITE_ERROR; /* Return Code */
const char *zVal = (const char *)sqlite3_value_text(pVal);
int nVal = sqlite3_value_bytes(pVal);
@@ -177463,21 +180484,27 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
rc = fts3DoIncrmerge(p, &zVal[6]);
}else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){
rc = fts3DoAutoincrmerge(p, &zVal[10]);
-#ifdef SQLITE_TEST
- }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
- p->nNodeSize = atoi(&zVal[9]);
- rc = SQLITE_OK;
- }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
- p->nMaxPendingData = atoi(&zVal[11]);
- rc = SQLITE_OK;
- }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){
- p->bNoIncrDoclist = atoi(&zVal[21]);
- rc = SQLITE_OK;
-#endif
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
}else{
- rc = SQLITE_ERROR;
+ int v;
+ if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
+ v = atoi(&zVal[9]);
+ if( v>=24 && v<=p->nPgsz-35 ) p->nNodeSize = v;
+ rc = SQLITE_OK;
+ }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
+ v = atoi(&zVal[11]);
+ if( v>=64 && v<=FTS3_MAX_PENDING_DATA ) p->nMaxPendingData = v;
+ rc = SQLITE_OK;
+ }else if( nVal>21 && 0==sqlite3_strnicmp(zVal,"test-no-incr-doclist=",21) ){
+ p->bNoIncrDoclist = atoi(&zVal[21]);
+ rc = SQLITE_OK;
+ }else if( nVal>11 && 0==sqlite3_strnicmp(zVal,"mergecount=",11) ){
+ v = atoi(&zVal[11]);
+ if( v>=4 && v<=FTS3_MERGE_COUNT && (v&1)==0 ) p->nMergeCount = v;
+ rc = SQLITE_OK;
+ }
+#endif
}
-
return rc;
}
@@ -178404,7 +181431,7 @@ static int fts3BestSnippet(
/* Set the *pmSeen output variable. */
for(i=0; i<nList; i++){
if( sIter.aPhrase[i].pHead ){
- *pmSeen |= (u64)1 << i;
+ *pmSeen |= (u64)1 << (i%64);
}
}
@@ -178882,11 +181909,15 @@ static int fts3MatchinfoSelectDoctotal(
Fts3Table *pTab,
sqlite3_stmt **ppStmt,
sqlite3_int64 *pnDoc,
- const char **paLen
+ const char **paLen,
+ const char **ppEnd
){
sqlite3_stmt *pStmt;
const char *a;
+ const char *pEnd;
sqlite3_int64 nDoc;
+ int n;
+
if( !*ppStmt ){
int rc = sqlite3Fts3SelectDoctotal(pTab, ppStmt);
@@ -178895,12 +181926,20 @@ static int fts3MatchinfoSelectDoctotal(
pStmt = *ppStmt;
assert( sqlite3_data_count(pStmt)==1 );
+ n = sqlite3_column_bytes(pStmt, 0);
a = sqlite3_column_blob(pStmt, 0);
- a += sqlite3Fts3GetVarint(a, &nDoc);
- if( nDoc==0 ) return FTS_CORRUPT_VTAB;
- *pnDoc = (u32)nDoc;
+ if( a==0 ){
+ return FTS_CORRUPT_VTAB;
+ }
+ pEnd = a + n;
+ a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc);
+ if( nDoc<=0 || a>pEnd ){
+ return FTS_CORRUPT_VTAB;
+ }
+ *pnDoc = nDoc;
if( paLen ) *paLen = a;
+ if( ppEnd ) *ppEnd = pEnd;
return SQLITE_OK;
}
@@ -179081,7 +182120,7 @@ static int fts3MatchinfoValues(
case FTS3_MATCHINFO_NDOC:
if( bGlobal ){
sqlite3_int64 nDoc = 0;
- rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0);
+ rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0, 0);
pInfo->aMatchinfo[0] = (u32)nDoc;
}
break;
@@ -179090,14 +182129,19 @@ static int fts3MatchinfoValues(
if( bGlobal ){
sqlite3_int64 nDoc; /* Number of rows in table */
const char *a; /* Aggregate column length array */
+ const char *pEnd; /* First byte past end of length array */
- rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a);
+ rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a, &pEnd);
if( rc==SQLITE_OK ){
int iCol;
for(iCol=0; iCol<pInfo->nCol; iCol++){
u32 iVal;
sqlite3_int64 nToken;
a += sqlite3Fts3GetVarint(a, &nToken);
+ if( a>pEnd ){
+ rc = SQLITE_CORRUPT_VTAB;
+ break;
+ }
iVal = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc);
pInfo->aMatchinfo[iCol] = iVal;
}
@@ -179111,9 +182155,14 @@ static int fts3MatchinfoValues(
if( rc==SQLITE_OK ){
int iCol;
const char *a = sqlite3_column_blob(pSelectDocsize, 0);
+ const char *pEnd = a + sqlite3_column_bytes(pSelectDocsize, 0);
for(iCol=0; iCol<pInfo->nCol; iCol++){
sqlite3_int64 nToken;
- a += sqlite3Fts3GetVarint(a, &nToken);
+ a += sqlite3Fts3GetVarintBounded(a, pEnd, &nToken);
+ if( a>pEnd ){
+ rc = SQLITE_CORRUPT_VTAB;
+ break;
+ }
pInfo->aMatchinfo[iCol] = (u32)nToken;
}
}
@@ -179144,7 +182193,7 @@ static int fts3MatchinfoValues(
if( rc!=SQLITE_OK ) break;
if( bGlobal ){
if( pCsr->pDeferred ){
- rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc, 0);
+ rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc,0,0);
if( rc!=SQLITE_OK ) break;
}
rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo);
@@ -180881,6 +183930,37 @@ static void jsonReturnJson(
}
/*
+** Translate a single byte of Hex into an integer.
+** This routine only works if h really is a valid hexadecimal
+** character: 0..9a..fA..F
+*/
+static u8 jsonHexToInt(int h){
+ assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
+#ifdef SQLITE_EBCDIC
+ h += 9*(1&~(h>>4));
+#else
+ h += 9*(1&(h>>6));
+#endif
+ return (u8)(h & 0xf);
+}
+
+/*
+** Convert a 4-byte hex string into an integer
+*/
+static u32 jsonHexToInt4(const char *z){
+ u32 v;
+ assert( safe_isxdigit(z[0]) );
+ assert( safe_isxdigit(z[1]) );
+ assert( safe_isxdigit(z[2]) );
+ assert( safe_isxdigit(z[3]) );
+ v = (jsonHexToInt(z[0])<<12)
+ + (jsonHexToInt(z[1])<<8)
+ + (jsonHexToInt(z[2])<<4)
+ + jsonHexToInt(z[3]);
+ return v;
+}
+
+/*
** Make the JsonNode the return value of the function.
*/
static void jsonReturn(
@@ -180973,15 +184053,8 @@ static void jsonReturn(
}else{
c = z[++i];
if( c=='u' ){
- u32 v = 0, k;
- for(k=0; k<4; i++, k++){
- assert( i<n-2 );
- c = z[i+1];
- assert( safe_isxdigit(c) );
- if( c<='9' ) v = v*16 + c - '0';
- else if( c<='F' ) v = v*16 + c - 'A' + 10;
- else v = v*16 + c - 'a' + 10;
- }
+ u32 v = jsonHexToInt4(z+i+1);
+ i += 4;
if( v==0 ) break;
if( v<=0x7f ){
zOut[j++] = (char)v;
@@ -180989,9 +184062,25 @@ static void jsonReturn(
zOut[j++] = (char)(0xc0 | (v>>6));
zOut[j++] = 0x80 | (v&0x3f);
}else{
- zOut[j++] = (char)(0xe0 | (v>>12));
- zOut[j++] = 0x80 | ((v>>6)&0x3f);
- zOut[j++] = 0x80 | (v&0x3f);
+ u32 vlo;
+ if( (v&0xfc00)==0xd800
+ && i<n-6
+ && z[i+1]=='\\'
+ && z[i+2]=='u'
+ && ((vlo = jsonHexToInt4(z+i+3))&0xfc00)==0xdc00
+ ){
+ /* We have a surrogate pair */
+ v = ((v&0x3ff)<<10) + (vlo&0x3ff) + 0x10000;
+ i += 6;
+ zOut[j++] = 0xf0 | (v>>18);
+ zOut[j++] = 0x80 | ((v>>12)&0x3f);
+ zOut[j++] = 0x80 | ((v>>6)&0x3f);
+ zOut[j++] = 0x80 | (v&0x3f);
+ }else{
+ zOut[j++] = 0xe0 | (v>>12);
+ zOut[j++] = 0x80 | ((v>>6)&0x3f);
+ zOut[j++] = 0x80 | (v&0x3f);
+ }
}
}else{
if( c=='b' ){
@@ -181494,18 +184583,49 @@ static JsonNode *jsonLookupStep(
}
return pNode;
}
- }else if( zPath[0]=='[' && safe_isdigit(zPath[1]) ){
- if( pRoot->eType!=JSON_ARRAY ) return 0;
+ }else if( zPath[0]=='[' ){
i = 0;
j = 1;
while( safe_isdigit(zPath[j]) ){
i = i*10 + zPath[j] - '0';
j++;
}
- if( zPath[j]!=']' ){
- *pzErr = zPath;
- return 0;
+ if( j<2 || zPath[j]!=']' ){
+ if( zPath[1]=='#' ){
+ JsonNode *pBase = pRoot;
+ int iBase = iRoot;
+ if( pRoot->eType!=JSON_ARRAY ) return 0;
+ for(;;){
+ while( j<=pBase->n ){
+ if( (pBase[j].jnFlags & JNODE_REMOVE)==0 ) i++;
+ j += jsonNodeSize(&pBase[j]);
+ }
+ if( (pBase->jnFlags & JNODE_APPEND)==0 ) break;
+ iBase += pBase->u.iAppend;
+ pBase = &pParse->aNode[iBase];
+ j = 1;
+ }
+ j = 2;
+ if( zPath[2]=='-' && safe_isdigit(zPath[3]) ){
+ unsigned int x = 0;
+ j = 3;
+ do{
+ x = x*10 + zPath[j] - '0';
+ j++;
+ }while( safe_isdigit(zPath[j]) );
+ if( x>i ) return 0;
+ i -= x;
+ }
+ if( zPath[j]!=']' ){
+ *pzErr = zPath;
+ return 0;
+ }
+ }else{
+ *pzErr = zPath;
+ return 0;
+ }
}
+ if( pRoot->eType!=JSON_ARRAY ) return 0;
zPath += j + 1;
j = 1;
for(;;){
@@ -182378,6 +185498,7 @@ static int jsonEachConnect(
pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(*pNew));
+ sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
}
return rc;
}
@@ -182868,16 +185989,19 @@ SQLITE_PRIVATE int sqlite3Json1Init(sqlite3 *db){
{ "json_tree", &jsonTreeModule },
};
#endif
+ static const int enc =
+ SQLITE_UTF8 |
+ SQLITE_DETERMINISTIC |
+ SQLITE_INNOCUOUS;
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
- rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
- SQLITE_UTF8 | SQLITE_DETERMINISTIC,
+ rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, enc,
(void*)&aFunc[i].flag,
aFunc[i].xFunc, 0, 0);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
rc = sqlite3_create_window_function(db, aAgg[i].zName, aAgg[i].nArg,
- SQLITE_SUBTYPE | SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
+ SQLITE_SUBTYPE | enc, 0,
aAgg[i].xStep, aAgg[i].xFinal,
aAgg[i].xValue, jsonGroupInverse, 0);
}
@@ -182973,6 +186097,7 @@ SQLITE_API int sqlite3_json_init(
#else
/* #include "sqlite3.h" */
#endif
+SQLITE_PRIVATE int sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */
#ifndef SQLITE_AMALGAMATION
#include "sqlite3rtree.h"
@@ -183236,6 +186361,12 @@ struct RtreeConstraint {
#define RTREE_MATCH 0x46 /* F: Old-style sqlite3_rtree_geometry_callback() */
#define RTREE_QUERY 0x47 /* G: New-style sqlite3_rtree_query_callback() */
+/* Special operators available only on cursors. Needs to be consecutive
+** with the normal values above, but must be less than RTREE_MATCH. These
+** are used in the cursor for contraints such as x=NULL (RTREE_FALSE) or
+** x<'xyz' (RTREE_TRUE) */
+#define RTREE_TRUE 0x3f /* ? */
+#define RTREE_FALSE 0x40 /* @ */
/*
** An rtree structure node.
@@ -183969,9 +187100,12 @@ static int rtreeOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
/*
-** Free the RtreeCursor.aConstraint[] array and its contents.
+** Reset a cursor back to its initial state.
*/
-static void freeCursorConstraints(RtreeCursor *pCsr){
+static void resetCursor(RtreeCursor *pCsr){
+ Rtree *pRtree = (Rtree *)(pCsr->base.pVtab);
+ int ii;
+ sqlite3_stmt *pStmt;
if( pCsr->aConstraint ){
int i; /* Used to iterate through constraint array */
for(i=0; i<pCsr->nConstraint; i++){
@@ -183984,6 +187118,13 @@ static void freeCursorConstraints(RtreeCursor *pCsr){
sqlite3_free(pCsr->aConstraint);
pCsr->aConstraint = 0;
}
+ for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
+ sqlite3_free(pCsr->aPoint);
+ pStmt = pCsr->pReadAux;
+ memset(pCsr, 0, sizeof(RtreeCursor));
+ pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
+ pCsr->pReadAux = pStmt;
+
}
/*
@@ -183991,13 +187132,10 @@ static void freeCursorConstraints(RtreeCursor *pCsr){
*/
static int rtreeClose(sqlite3_vtab_cursor *cur){
Rtree *pRtree = (Rtree *)(cur->pVtab);
- int ii;
RtreeCursor *pCsr = (RtreeCursor *)cur;
assert( pRtree->nCursor>0 );
- freeCursorConstraints(pCsr);
+ resetCursor(pCsr);
sqlite3_finalize(pCsr->pReadAux);
- sqlite3_free(pCsr->aPoint);
- for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
sqlite3_free(pCsr);
pRtree->nCursor--;
nodeBlobReset(pRtree);
@@ -184155,9 +187293,12 @@ static void rtreeNonleafConstraint(
pCellData += 8 + 4*(p->iCoord&0xfe);
assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
- || p->op==RTREE_GT || p->op==RTREE_EQ );
+ || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE
+ || p->op==RTREE_FALSE );
assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */
switch( p->op ){
+ case RTREE_TRUE: return; /* Always satisfied */
+ case RTREE_FALSE: break; /* Never satisfied */
case RTREE_LE:
case RTREE_LT:
case RTREE_EQ:
@@ -184195,16 +187336,19 @@ static void rtreeLeafConstraint(
RtreeDValue xN; /* Coordinate value converted to a double */
assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
- || p->op==RTREE_GT || p->op==RTREE_EQ );
+ || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE
+ || p->op==RTREE_FALSE );
pCellData += 8 + p->iCoord*4;
assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */
RTREE_DECODE_COORD(eInt, pCellData, xN);
switch( p->op ){
- case RTREE_LE: if( xN <= p->u.rValue ) return; break;
- case RTREE_LT: if( xN < p->u.rValue ) return; break;
- case RTREE_GE: if( xN >= p->u.rValue ) return; break;
- case RTREE_GT: if( xN > p->u.rValue ) return; break;
- default: if( xN == p->u.rValue ) return; break;
+ case RTREE_TRUE: return; /* Always satisfied */
+ case RTREE_FALSE: break; /* Never satisfied */
+ case RTREE_LE: if( xN <= p->u.rValue ) return; break;
+ case RTREE_LT: if( xN < p->u.rValue ) return; break;
+ case RTREE_GE: if( xN >= p->u.rValue ) return; break;
+ case RTREE_GT: if( xN > p->u.rValue ) return; break;
+ default: if( xN == p->u.rValue ) return; break;
}
*peWithin = NOT_WITHIN;
}
@@ -184697,17 +187841,11 @@ static int rtreeFilter(
int ii;
int rc = SQLITE_OK;
int iCell = 0;
- sqlite3_stmt *pStmt;
rtreeReference(pRtree);
/* Reset the cursor to the same state as rtreeOpen() leaves it in. */
- freeCursorConstraints(pCsr);
- sqlite3_free(pCsr->aPoint);
- pStmt = pCsr->pReadAux;
- memset(pCsr, 0, sizeof(RtreeCursor));
- pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
- pCsr->pReadAux = pStmt;
+ resetCursor(pCsr);
pCsr->iStrategy = idxNum;
if( idxNum==1 ){
@@ -184716,7 +187854,15 @@ static int rtreeFilter(
RtreeSearchPoint *p; /* Search point for the leaf */
i64 iRowid = sqlite3_value_int64(argv[0]);
i64 iNode = 0;
- rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode);
+ int eType = sqlite3_value_numeric_type(argv[0]);
+ if( eType==SQLITE_INTEGER
+ || (eType==SQLITE_FLOAT && sqlite3_value_double(argv[0])==iRowid)
+ ){
+ rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode);
+ }else{
+ rc = SQLITE_OK;
+ pLeaf = 0;
+ }
if( rc==SQLITE_OK && pLeaf!=0 ){
p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0);
assert( p!=0 ); /* Always returns pCsr->sPoint */
@@ -184746,6 +187892,7 @@ static int rtreeFilter(
|| (idxStr && (int)strlen(idxStr)==argc*2) );
for(ii=0; ii<argc; ii++){
RtreeConstraint *p = &pCsr->aConstraint[ii];
+ int eType = sqlite3_value_numeric_type(argv[ii]);
p->op = idxStr[ii*2];
p->iCoord = idxStr[ii*2+1]-'0';
if( p->op>=RTREE_MATCH ){
@@ -184760,12 +187907,21 @@ static int rtreeFilter(
p->pInfo->nCoord = pRtree->nDim2;
p->pInfo->anQueue = pCsr->anQueue;
p->pInfo->mxLevel = pRtree->iDepth + 1;
- }else{
+ }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
#ifdef SQLITE_RTREE_INT_ONLY
p->u.rValue = sqlite3_value_int64(argv[ii]);
#else
p->u.rValue = sqlite3_value_double(argv[ii]);
#endif
+ }else{
+ p->u.rValue = RTREE_ZERO;
+ if( eType==SQLITE_NULL ){
+ p->op = RTREE_FALSE;
+ }else if( p->op==RTREE_LT || p->op==RTREE_LE ){
+ p->op = RTREE_TRUE;
+ }else{
+ p->op = RTREE_FALSE;
+ }
}
}
}
@@ -186542,6 +189698,14 @@ static int getNodeSize(
return rc;
}
+/*
+** Return the length of a token
+*/
+static int rtreeTokenLength(const char *z){
+ int dummy = 0;
+ return sqlite3GetToken((const unsigned char*)z,&dummy);
+}
+
/*
** This function is the implementation of both the xConnect and xCreate
** methods of the r-tree virtual table.
@@ -186578,8 +189742,8 @@ static int rtreeInit(
};
assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
- if( argc>RTREE_MAX_AUX_COLUMN+3 ){
- *pzErr = sqlite3_mprintf("%s", aErrMsg[3]);
+ if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){
+ *pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]);
return SQLITE_ERROR;
}
@@ -186607,16 +189771,18 @@ static int rtreeInit(
** the r-tree table schema.
*/
pSql = sqlite3_str_new(db);
- sqlite3_str_appendf(pSql, "CREATE TABLE x(%s", argv[3]);
+ sqlite3_str_appendf(pSql, "CREATE TABLE x(%.*s INT",
+ rtreeTokenLength(argv[3]), argv[3]);
for(ii=4; ii<argc; ii++){
- if( argv[ii][0]=='+' ){
+ const char *zArg = argv[ii];
+ if( zArg[0]=='+' ){
pRtree->nAux++;
- sqlite3_str_appendf(pSql, ",%s", argv[ii]+1);
+ sqlite3_str_appendf(pSql, ",%.*s", rtreeTokenLength(zArg+1), zArg+1);
}else if( pRtree->nAux>0 ){
break;
}else{
pRtree->nDim2++;
- sqlite3_str_appendf(pSql, ",%s", argv[ii]);
+ sqlite3_str_appendf(pSql, ",%.*s NUM", rtreeTokenLength(zArg), zArg);
}
}
sqlite3_str_appendf(pSql, ");");
@@ -188564,17 +191730,11 @@ static int geopolyFilter(
RtreeNode *pRoot = 0;
int rc = SQLITE_OK;
int iCell = 0;
- sqlite3_stmt *pStmt;
rtreeReference(pRtree);
/* Reset the cursor to the same state as rtreeOpen() leaves it in. */
- freeCursorConstraints(pCsr);
- sqlite3_free(pCsr->aPoint);
- pStmt = pCsr->pReadAux;
- memset(pCsr, 0, sizeof(RtreeCursor));
- pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
- pCsr->pReadAux = pStmt;
+ resetCursor(pCsr);
pCsr->iStrategy = idxNum;
if( idxNum==1 ){
@@ -189011,14 +192171,20 @@ static int sqlite3_geopoly_init(sqlite3 *db){
};
int i;
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
- int enc = aFunc[i].bPure ? SQLITE_UTF8|SQLITE_DETERMINISTIC : SQLITE_UTF8;
+ int enc;
+ if( aFunc[i].bPure ){
+ enc = SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS;
+ }else{
+ enc = SQLITE_UTF8|SQLITE_DIRECTONLY;
+ }
rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
enc, 0,
aFunc[i].xFunc, 0, 0);
}
for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
- rc = sqlite3_create_function(db, aAgg[i].zName, 1, SQLITE_UTF8, 0,
- 0, aAgg[i].xStep, aAgg[i].xFinal);
+ rc = sqlite3_create_function(db, aAgg[i].zName, 1,
+ SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS, 0,
+ 0, aAgg[i].xStep, aAgg[i].xFinal);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_module_v2(db, "geopoly", &geopolyModule, 0, 0);
@@ -189708,26 +192874,27 @@ static void icuLoadCollation(
** Register the ICU extension functions with database db.
*/
SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){
+# define SQLITEICU_EXTRAFLAGS (SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS)
static const struct IcuScalar {
const char *zName; /* Function name */
unsigned char nArg; /* Number of arguments */
- unsigned short enc; /* Optimal text encoding */
+ unsigned int enc; /* Optimal text encoding */
unsigned char iContext; /* sqlite3_user_data() context */
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} scalars[] = {
- {"icu_load_collation", 2, SQLITE_UTF8, 1, icuLoadCollation},
+ {"icu_load_collation",2,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
- {"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc},
- {"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
- {"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
- {"upper", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
- {"upper", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
- {"lower", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
- {"lower", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
- {"upper", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
- {"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
- {"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
- {"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
+ {"regexp", 2, SQLITE_ANY|SQLITEICU_EXTRAFLAGS, 0, icuRegexpFunc},
+ {"lower", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
+ {"lower", 2, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
+ {"upper", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
+ {"upper", 2, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
+ {"lower", 1, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
+ {"lower", 2, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
+ {"upper", 1, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
+ {"upper", 2, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
+ {"like", 2, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 0, icuLikeFunc},
+ {"like", 3, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 0, icuLikeFunc},
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */
};
int rc = SQLITE_OK;
@@ -195575,33 +198742,6 @@ static int rbuVfsShmUnmap(sqlite3_file *pFile, int delFlag){
return rc;
}
-/*
-** A main database named zName has just been opened. The following
-** function returns a pointer to a buffer owned by SQLite that contains
-** the name of the *-wal file this db connection will use. SQLite
-** happens to pass a pointer to this buffer when using xAccess()
-** or xOpen() to operate on the *-wal file.
-*/
-static const char *rbuMainToWal(const char *zName, int flags){
- int n = (int)strlen(zName);
- const char *z = &zName[n];
- if( flags & SQLITE_OPEN_URI ){
- int odd = 0;
- while( 1 ){
- if( z[0]==0 ){
- odd = 1 - odd;
- if( odd && z[1]==0 ) break;
- }
- z++;
- }
- z += 2;
- }else{
- while( *z==0 ) z++;
- }
- z += (n + 8 + 1);
- return z;
-}
-
/*
** Open an rbu file handle.
*/
@@ -195650,7 +198790,7 @@ static int rbuVfsOpen(
** the name of the *-wal file this db connection will use. SQLite
** happens to pass a pointer to this buffer when using xAccess()
** or xOpen() to operate on the *-wal file. */
- pFd->zWal = rbuMainToWal(zName, flags);
+ pFd->zWal = sqlite3_filename_wal(zName);
}
else if( flags & SQLITE_OPEN_WAL ){
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
@@ -195665,7 +198805,7 @@ static int rbuVfsOpen(
char *zCopy;
if( rbuIsVacuum(pDb->pRbu) ){
zBase = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
- zBase = rbuMainToWal(zBase, SQLITE_OPEN_URI);
+ zBase = sqlite3_filename_wal(zBase);
}
nCopy = strlen(zBase);
zCopy = sqlite3_malloc64(nCopy+2);
@@ -195985,7 +199125,7 @@ SQLITE_API sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu *pRbu){
**
** This file contains an implementation of the "dbstat" virtual table.
**
-** The dbstat virtual table is used to extract low-level formatting
+** The dbstat virtual table is used to extract low-level storage
** information from an SQLite database in order to implement the
** "sqlite3_analyzer" utility. See the ../tool/spaceanal.tcl script
** for an example implementation.
@@ -196029,27 +199169,30 @@ SQLITE_API sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu *pRbu){
**
** '/1c2/000/' // Left-most child of 451st child of root
*/
-#define VTAB_SCHEMA \
- "CREATE TABLE xx( " \
- " name TEXT, /* Name of table or index */" \
- " path TEXT, /* Path to page from root */" \
- " pageno INTEGER, /* Page number */" \
- " pagetype TEXT, /* 'internal', 'leaf' or 'overflow' */" \
- " ncell INTEGER, /* Cells on page (0 for overflow) */" \
- " payload INTEGER, /* Bytes of payload on this page */" \
- " unused INTEGER, /* Bytes of unused space on this page */" \
- " mx_payload INTEGER, /* Largest payload size of all cells */" \
- " pgoffset INTEGER, /* Offset of page in file */" \
- " pgsize INTEGER, /* Size of the page */" \
- " schema TEXT HIDDEN /* Database schema being analyzed */" \
- ");"
-
-
+static const char zDbstatSchema[] =
+ "CREATE TABLE x("
+ " name TEXT," /* 0 Name of table or index */
+ " path TEXT," /* 1 Path to page from root (NULL for agg) */
+ " pageno INTEGER," /* 2 Page number (page count for aggregates) */
+ " pagetype TEXT," /* 3 'internal', 'leaf', 'overflow', or NULL */
+ " ncell INTEGER," /* 4 Cells on page (0 for overflow) */
+ " payload INTEGER," /* 5 Bytes of payload on this page */
+ " unused INTEGER," /* 6 Bytes of unused space on this page */
+ " mx_payload INTEGER," /* 7 Largest payload size of all cells */
+ " pgoffset INTEGER," /* 8 Offset of page in file (NULL for agg) */
+ " pgsize INTEGER," /* 9 Size of the page (sum for aggregate) */
+ " schema TEXT HIDDEN," /* 10 Database schema being analyzed */
+ " aggregate BOOLEAN HIDDEN" /* 11 aggregate info for each table */
+ ")"
+;
+
+/* Forward reference to data structured used in this module */
typedef struct StatTable StatTable;
typedef struct StatCursor StatCursor;
typedef struct StatPage StatPage;
typedef struct StatCell StatCell;
+/* Size information for a single cell within a btree page */
struct StatCell {
int nLocal; /* Bytes of local payload */
u32 iChildPg; /* Child node (or 0 if this is a leaf) */
@@ -196059,10 +199202,11 @@ struct StatCell {
int iOvfl; /* Iterates through aOvfl[] */
};
+/* Size information for a single btree page */
struct StatPage {
- u32 iPgno;
- DbPage *pPg;
- int iCell;
+ u32 iPgno; /* Page number */
+ DbPage *pPg; /* Page content */
+ int iCell; /* Current cell */
char *zPath; /* Path to this page */
@@ -196072,34 +199216,38 @@ struct StatPage {
int nUnused; /* Number of unused bytes on page */
StatCell *aCell; /* Array of parsed cells */
u32 iRightChildPg; /* Right-child page number (or 0) */
- int nMxPayload; /* Largest payload of any cell on this page */
+ int nMxPayload; /* Largest payload of any cell on the page */
};
+/* The cursor for scanning the dbstat virtual table */
struct StatCursor {
- sqlite3_vtab_cursor base;
+ sqlite3_vtab_cursor base; /* base class. MUST BE FIRST! */
sqlite3_stmt *pStmt; /* Iterates through set of root pages */
- int isEof; /* After pStmt has returned SQLITE_DONE */
+ u8 isEof; /* After pStmt has returned SQLITE_DONE */
+ u8 isAgg; /* Aggregate results for each table */
int iDb; /* Schema used for this query */
- StatPage aPage[32];
+ StatPage aPage[32]; /* Pages in path to current page */
int iPage; /* Current entry in aPage[] */
/* Values to return. */
+ u32 iPageno; /* Value of 'pageno' column */
char *zName; /* Value of 'name' column */
char *zPath; /* Value of 'path' column */
- u32 iPageno; /* Value of 'pageno' column */
char *zPagetype; /* Value of 'pagetype' column */
+ int nPage; /* Number of pages in current btree */
int nCell; /* Value of 'ncell' column */
- int nPayload; /* Value of 'payload' column */
- int nUnused; /* Value of 'unused' column */
int nMxPayload; /* Value of 'mx_payload' column */
+ i64 nUnused; /* Value of 'unused' column */
+ i64 nPayload; /* Value of 'payload' column */
i64 iOffset; /* Value of 'pgOffset' column */
- int szPage; /* Value of 'pgSize' column */
+ i64 szPage; /* Value of 'pgSize' column */
};
+/* An instance of the DBSTAT virtual table */
struct StatTable {
- sqlite3_vtab base;
- sqlite3 *db;
+ sqlite3_vtab base; /* base class. MUST BE FIRST! */
+ sqlite3 *db; /* Database connection that owns this vtab */
int iDb; /* Index of database to analyze */
};
@@ -196108,7 +199256,7 @@ struct StatTable {
#endif
/*
-** Connect to or create a statvfs virtual table.
+** Connect to or create a new DBSTAT virtual table.
*/
static int statConnect(
sqlite3 *db,
@@ -196132,7 +199280,8 @@ static int statConnect(
}else{
iDb = 0;
}
- rc = sqlite3_declare_vtab(db, VTAB_SCHEMA);
+ sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
+ rc = sqlite3_declare_vtab(db, zDbstatSchema);
if( rc==SQLITE_OK ){
pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable));
if( pTab==0 ) rc = SQLITE_NOMEM_BKPT;
@@ -196150,7 +199299,7 @@ static int statConnect(
}
/*
-** Disconnect from or destroy a statvfs virtual table.
+** Disconnect from or destroy the DBSTAT virtual table.
*/
static int statDisconnect(sqlite3_vtab *pVtab){
sqlite3_free(pVtab);
@@ -196158,14 +199307,20 @@ static int statDisconnect(sqlite3_vtab *pVtab){
}
/*
-** There is no "best-index". This virtual table always does a linear
-** scan. However, a schema=? constraint should cause this table to
-** operate on a different database schema, so check for it.
+** Compute the best query strategy and return the result in idxNum.
**
-** idxNum is normally 0, but will be 1 if a schema=? constraint exists.
+** idxNum-Bit Meaning
+** ---------- ----------------------------------------------
+** 0x01 There is a schema=? term in the WHERE clause
+** 0x02 There is a name=? term in the WHERE clause
+** 0x04 There is an aggregate=? term in the WHERE clause
+** 0x08 Output should be ordered by name and path
*/
static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
int i;
+ int iSchema = -1;
+ int iName = -1;
+ int iAgg = -1;
/* Look for a valid schema=? constraint. If found, change the idxNum to
** 1 and request the value of that constraint be sent to xFilter. And
@@ -196173,16 +199328,40 @@ static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
** used.
*/
for(i=0; i<pIdxInfo->nConstraint; i++){
- if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue;
- if( pIdxInfo->aConstraint[i].usable==0 ) return SQLITE_CONSTRAINT;
if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- pIdxInfo->idxNum = 1;
- pIdxInfo->estimatedCost = 1.0;
- pIdxInfo->aConstraintUsage[i].argvIndex = 1;
- pIdxInfo->aConstraintUsage[i].omit = 1;
- break;
+ if( pIdxInfo->aConstraint[i].usable==0 ){
+ /* Force DBSTAT table should always be the right-most table in a join */
+ return SQLITE_CONSTRAINT;
+ }
+ switch( pIdxInfo->aConstraint[i].iColumn ){
+ case 0: { /* name */
+ iName = i;
+ break;
+ }
+ case 10: { /* schema */
+ iSchema = i;
+ break;
+ }
+ case 11: { /* aggregate */
+ iAgg = i;
+ break;
+ }
+ }
}
-
+ i = 0;
+ if( iSchema>=0 ){
+ pIdxInfo->aConstraintUsage[iSchema].argvIndex = ++i;
+ pIdxInfo->idxNum |= 0x01;
+ }
+ if( iName>=0 ){
+ pIdxInfo->aConstraintUsage[iName].argvIndex = ++i;
+ pIdxInfo->idxNum |= 0x02;
+ }
+ if( iAgg>=0 ){
+ pIdxInfo->aConstraintUsage[iAgg].argvIndex = ++i;
+ pIdxInfo->idxNum |= 0x04;
+ }
+ pIdxInfo->estimatedCost = 1.0;
/* Records are always returned in ascending order of (name, path).
** If this will satisfy the client, set the orderByConsumed flag so that
@@ -196200,13 +199379,14 @@ static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
)
){
pIdxInfo->orderByConsumed = 1;
+ pIdxInfo->idxNum |= 0x08;
}
return SQLITE_OK;
}
/*
-** Open a new statvfs cursor.
+** Open a new DBSTAT cursor.
*/
static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
StatTable *pTab = (StatTable *)pVTab;
@@ -196256,8 +199436,18 @@ static void statResetCsr(StatCursor *pCsr){
pCsr->isEof = 0;
}
+/* Resize the space-used counters inside of the cursor */
+static void statResetCounts(StatCursor *pCsr){
+ pCsr->nCell = 0;
+ pCsr->nMxPayload = 0;
+ pCsr->nUnused = 0;
+ pCsr->nPayload = 0;
+ pCsr->szPage = 0;
+ pCsr->nPage = 0;
+}
+
/*
-** Close a statvfs cursor.
+** Close a DBSTAT cursor.
*/
static int statClose(sqlite3_vtab_cursor *pCursor){
StatCursor *pCsr = (StatCursor *)pCursor;
@@ -196267,11 +199457,15 @@ static int statClose(sqlite3_vtab_cursor *pCursor){
return SQLITE_OK;
}
-static void getLocalPayload(
+/*
+** For a single cell on a btree page, compute the number of bytes of
+** content (payload) stored on that page. That is to say, compute the
+** number of bytes of content not found on overflow pages.
+*/
+static int getLocalPayload(
int nUsable, /* Usable bytes per page */
u8 flags, /* Page flags */
- int nTotal, /* Total record (payload) size */
- int *pnLocal /* OUT: Bytes stored locally */
+ int nTotal /* Total record (payload) size */
){
int nLocal;
int nMinLocal;
@@ -196287,9 +199481,12 @@ static void getLocalPayload(
nLocal = nMinLocal + (nTotal - nMinLocal) % (nUsable - 4);
if( nLocal>nMaxLocal ) nLocal = nMinLocal;
- *pnLocal = nLocal;
+ return nLocal;
}
+/* Populate the StatPage object with information about the all
+** cells found on the page currently under analysis.
+*/
static int statDecodePage(Btree *pBt, StatPage *p){
int nUnused;
int iOff;
@@ -196360,7 +199557,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
iOff += sqlite3GetVarint(&aData[iOff], &dummy);
}
if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload;
- getLocalPayload(nUsable, p->flags, nPayload, &nLocal);
+ nLocal = getLocalPayload(nUsable, p->flags, nPayload);
if( nLocal<0 ) goto statPageIsCorrupt;
pCell->nLocal = nLocal;
assert( nPayload>=(u32)nLocal );
@@ -196410,23 +199607,25 @@ static void statSizeAndOffset(StatCursor *pCsr){
sqlite3_file *fd;
sqlite3_int64 x[2];
- /* The default page size and offset */
- pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
- pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1);
-
- /* If connected to a ZIPVFS backend, override the page size and
- ** offset with actual values obtained from ZIPVFS.
+ /* If connected to a ZIPVFS backend, find the page size and
+ ** offset from ZIPVFS.
*/
fd = sqlite3PagerFile(pPager);
x[0] = pCsr->iPageno;
if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){
pCsr->iOffset = x[0];
- pCsr->szPage = (int)x[1];
+ pCsr->szPage += x[1];
+ }else{
+ /* Not ZIPVFS: The default page size and offset */
+ pCsr->szPage += sqlite3BtreeGetPageSize(pBt);
+ pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1);
}
}
/*
-** Move a statvfs cursor to the next entry in the file.
+** Move a DBSTAT cursor to the next entry. Normally, the next
+** entry will be the next page, but in aggregated mode (pCsr->isAgg!=0),
+** the next entry is the next btree.
*/
static int statNext(sqlite3_vtab_cursor *pCursor){
int rc;
@@ -196442,6 +199641,8 @@ static int statNext(sqlite3_vtab_cursor *pCursor){
statNextRestart:
if( pCsr->aPage[0].pPg==0 ){
+ /* Start measuring space on the next btree */
+ statResetCounts(pCsr);
rc = sqlite3_step(pCsr->pStmt);
if( rc==SQLITE_ROW ){
int nPage;
@@ -196454,44 +199655,47 @@ statNextRestart:
rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg, 0);
pCsr->aPage[0].iPgno = iRoot;
pCsr->aPage[0].iCell = 0;
- pCsr->aPage[0].zPath = z = sqlite3_mprintf("/");
+ if( !pCsr->isAgg ){
+ pCsr->aPage[0].zPath = z = sqlite3_mprintf("/");
+ if( z==0 ) rc = SQLITE_NOMEM_BKPT;
+ }
pCsr->iPage = 0;
- if( z==0 ) rc = SQLITE_NOMEM_BKPT;
+ pCsr->nPage = 1;
}else{
pCsr->isEof = 1;
return sqlite3_reset(pCsr->pStmt);
}
}else{
-
- /* Page p itself has already been visited. */
+ /* Continue analyzing the btree previously started */
StatPage *p = &pCsr->aPage[pCsr->iPage];
-
+ if( !pCsr->isAgg ) statResetCounts(pCsr);
while( p->iCell<p->nCell ){
StatCell *pCell = &p->aCell[p->iCell];
- if( pCell->iOvfl<pCell->nOvfl ){
- int nUsable;
+ while( pCell->iOvfl<pCell->nOvfl ){
+ int nUsable, iOvfl;
sqlite3BtreeEnter(pBt);
nUsable = sqlite3BtreeGetPageSize(pBt) -
sqlite3BtreeGetReserveNoMutex(pBt);
sqlite3BtreeLeave(pBt);
- pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
- pCsr->iPageno = pCell->aOvfl[pCell->iOvfl];
- pCsr->zPagetype = "overflow";
- pCsr->nCell = 0;
- pCsr->nMxPayload = 0;
- pCsr->zPath = z = sqlite3_mprintf(
- "%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl
- );
+ pCsr->nPage++;
+ statSizeAndOffset(pCsr);
if( pCell->iOvfl<pCell->nOvfl-1 ){
- pCsr->nUnused = 0;
- pCsr->nPayload = nUsable - 4;
+ pCsr->nPayload += nUsable - 4;
}else{
- pCsr->nPayload = pCell->nLastOvfl;
- pCsr->nUnused = nUsable - 4 - pCsr->nPayload;
+ pCsr->nPayload += pCell->nLastOvfl;
+ pCsr->nUnused += nUsable - 4 - pCell->nLastOvfl;
}
+ iOvfl = pCell->iOvfl;
pCell->iOvfl++;
- statSizeAndOffset(pCsr);
- return z==0 ? SQLITE_NOMEM_BKPT : SQLITE_OK;
+ if( !pCsr->isAgg ){
+ pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
+ pCsr->iPageno = pCell->aOvfl[iOvfl];
+ pCsr->zPagetype = "overflow";
+ pCsr->zPath = z = sqlite3_mprintf(
+ "%s%.3x+%.6x", p->zPath, p->iCell, iOvfl
+ );
+ return z==0 ? SQLITE_NOMEM_BKPT : SQLITE_OK;
+ }
}
if( p->iRightChildPg ) break;
p->iCell++;
@@ -196499,8 +199703,13 @@ statNextRestart:
if( !p->iRightChildPg || p->iCell>p->nCell ){
statClearPage(p);
- if( pCsr->iPage==0 ) return statNext(pCursor);
- pCsr->iPage--;
+ if( pCsr->iPage>0 ){
+ pCsr->iPage--;
+ }else if( pCsr->isAgg ){
+ /* label-statNext-done: When computing aggregate space usage over
+ ** an entire btree, this is the exit point from this function */
+ return SQLITE_OK;
+ }
goto statNextRestart; /* Tail recursion */
}
pCsr->iPage++;
@@ -196516,10 +199725,13 @@ statNextRestart:
p[1].iPgno = p->aCell[p->iCell].iChildPg;
}
rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg, 0);
+ pCsr->nPage++;
p[1].iCell = 0;
- p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell);
+ if( !pCsr->isAgg ){
+ p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell);
+ if( z==0 ) rc = SQLITE_NOMEM_BKPT;
+ }
p->iCell++;
- if( z==0 ) rc = SQLITE_NOMEM_BKPT;
}
@@ -196549,16 +199761,23 @@ statNextRestart:
pCsr->zPagetype = "corrupted";
break;
}
- pCsr->nCell = p->nCell;
- pCsr->nUnused = p->nUnused;
- pCsr->nMxPayload = p->nMxPayload;
- pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath);
- if( z==0 ) rc = SQLITE_NOMEM_BKPT;
+ pCsr->nCell += p->nCell;
+ pCsr->nUnused += p->nUnused;
+ if( p->nMxPayload>pCsr->nMxPayload ) pCsr->nMxPayload = p->nMxPayload;
+ if( !pCsr->isAgg ){
+ pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath);
+ if( z==0 ) rc = SQLITE_NOMEM_BKPT;
+ }
nPayload = 0;
for(i=0; i<p->nCell; i++){
nPayload += p->aCell[i].nLocal;
}
- pCsr->nPayload = nPayload;
+ pCsr->nPayload += nPayload;
+
+ /* If computing aggregate space usage by btree, continue with the
+ ** next page. The loop will exit via the return at label-statNext-done
+ */
+ if( pCsr->isAgg ) goto statNextRestart;
}
}
@@ -196570,6 +199789,10 @@ static int statEof(sqlite3_vtab_cursor *pCursor){
return pCsr->isEof;
}
+/* Initialize a cursor according to the query plan idxNum using the
+** arguments in argv[0]. See statBestIndex() for a description of the
+** meaning of the bits in idxNum.
+*/
static int statFilter(
sqlite3_vtab_cursor *pCursor,
int idxNum, const char *idxStr,
@@ -196577,29 +199800,52 @@ static int statFilter(
){
StatCursor *pCsr = (StatCursor *)pCursor;
StatTable *pTab = (StatTable*)(pCursor->pVtab);
- char *zSql;
- int rc = SQLITE_OK;
+ sqlite3_str *pSql; /* Query of btrees to analyze */
+ char *zSql; /* String value of pSql */
+ int iArg = 0; /* Count of argv[] parameters used so far */
+ int rc = SQLITE_OK; /* Result of this operation */
+ const char *zName = 0; /* Only provide analysis of this table */
- if( idxNum==1 ){
- const char *zDbase = (const char*)sqlite3_value_text(argv[0]);
+ statResetCsr(pCsr);
+ sqlite3_finalize(pCsr->pStmt);
+ pCsr->pStmt = 0;
+ if( idxNum & 0x01 ){
+ /* schema=? constraint is present. Get its value */
+ const char *zDbase = (const char*)sqlite3_value_text(argv[iArg++]);
pCsr->iDb = sqlite3FindDbName(pTab->db, zDbase);
if( pCsr->iDb<0 ){
- sqlite3_free(pCursor->pVtab->zErrMsg);
- pCursor->pVtab->zErrMsg = sqlite3_mprintf("no such schema: %s", zDbase);
- return pCursor->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM_BKPT;
+ pCsr->iDb = 0;
+ pCsr->isEof = 1;
+ return SQLITE_OK;
}
}else{
pCsr->iDb = pTab->iDb;
}
- statResetCsr(pCsr);
- sqlite3_finalize(pCsr->pStmt);
- pCsr->pStmt = 0;
- zSql = sqlite3_mprintf(
- "SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
- " UNION ALL "
- "SELECT name, rootpage, type"
- " FROM \"%w\".sqlite_master WHERE rootpage!=0"
- " ORDER BY name", pTab->db->aDb[pCsr->iDb].zDbSName);
+ if( idxNum & 0x02 ){
+ /* name=? constraint is present */
+ zName = (const char*)sqlite3_value_text(argv[iArg++]);
+ }
+ if( idxNum & 0x04 ){
+ /* aggregate=? constraint is present */
+ pCsr->isAgg = sqlite3_value_double(argv[iArg++])!=0.0;
+ }else{
+ pCsr->isAgg = 0;
+ }
+ pSql = sqlite3_str_new(pTab->db);
+ sqlite3_str_appendf(pSql,
+ "SELECT * FROM ("
+ "SELECT 'sqlite_master' AS name,1 AS rootpage,'table' AS type"
+ " UNION ALL "
+ "SELECT name,rootpage,type"
+ " FROM \"%w\".sqlite_master WHERE rootpage!=0)",
+ pTab->db->aDb[pCsr->iDb].zDbSName);
+ if( zName ){
+ sqlite3_str_appendf(pSql, "WHERE name=%Q", zName);
+ }
+ if( idxNum & 0x08 ){
+ sqlite3_str_appendf(pSql, " ORDER BY name");
+ }
+ zSql = sqlite3_str_finish(pSql);
if( zSql==0 ){
return SQLITE_NOMEM_BKPT;
}else{
@@ -196624,13 +199870,21 @@ static int statColumn(
sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_TRANSIENT);
break;
case 1: /* path */
- sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT);
+ if( !pCsr->isAgg ){
+ sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT);
+ }
break;
case 2: /* pageno */
- sqlite3_result_int64(ctx, pCsr->iPageno);
+ if( pCsr->isAgg ){
+ sqlite3_result_int64(ctx, pCsr->nPage);
+ }else{
+ sqlite3_result_int64(ctx, pCsr->iPageno);
+ }
break;
case 3: /* pagetype */
- sqlite3_result_text(ctx, pCsr->zPagetype, -1, SQLITE_STATIC);
+ if( !pCsr->isAgg ){
+ sqlite3_result_text(ctx, pCsr->zPagetype, -1, SQLITE_STATIC);
+ }
break;
case 4: /* ncell */
sqlite3_result_int(ctx, pCsr->nCell);
@@ -196645,17 +199899,23 @@ static int statColumn(
sqlite3_result_int(ctx, pCsr->nMxPayload);
break;
case 8: /* pgoffset */
- sqlite3_result_int64(ctx, pCsr->iOffset);
+ if( !pCsr->isAgg ){
+ sqlite3_result_int64(ctx, pCsr->iOffset);
+ }
break;
case 9: /* pgsize */
sqlite3_result_int(ctx, pCsr->szPage);
break;
- default: { /* schema */
+ case 10: { /* schema */
sqlite3 *db = sqlite3_context_db_handle(ctx);
int iDb = pCsr->iDb;
sqlite3_result_text(ctx, db->aDb[iDb].zDbSName, -1, SQLITE_STATIC);
break;
}
+ default: { /* aggregate */
+ sqlite3_result_int(ctx, pCsr->isAgg);
+ break;
+ }
}
return SQLITE_OK;
}
@@ -196779,6 +200039,7 @@ static int dbpageConnect(
DbpageTable *pTab = 0;
int rc = SQLITE_OK;
+ sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
rc = sqlite3_declare_vtab(db,
"CREATE TABLE x(pgno INTEGER PRIMARY KEY, data BLOB, schema HIDDEN)");
if( rc==SQLITE_OK ){
@@ -202767,7 +206028,7 @@ struct Fts5PhraseIter {
**
** xSetAuxdata(pFts5, pAux, xDelete)
**
-** Save the pointer passed as the second argument as the extension functions
+** Save the pointer passed as the second argument as the extension function's
** "auxiliary data". The pointer may then be retrieved by the current or any
** future invocation of the same fts5 extension function made as part of
** the same MATCH query using the xGetAuxdata() API.
@@ -203009,8 +206270,8 @@ struct Fts5ExtensionApi {
**
** There are several ways to approach this in FTS5:
**
-** <ol><li> By mapping all synonyms to a single token. In this case, the
-** In the above example, this means that the tokenizer returns the
+** <ol><li> By mapping all synonyms to a single token. In this case, using
+** the above example, this means that the tokenizer returns the
** same token for inputs "first" and "1st". Say that token is in
** fact "first", so that when the user inserts the document "I won
** 1st place" entries are added to the index for tokens "i", "won",
@@ -203245,6 +206506,11 @@ typedef sqlite3_uint64 u64;
*/
#define FTS5_MAX_PREFIX_INDEXES 31
+/*
+** Maximum segments permitted in a single index
+*/
+#define FTS5_MAX_SEGMENT 2000
+
#define FTS5_DEFAULT_NEARDIST 10
#define FTS5_DEFAULT_RANK "bm25"
@@ -203602,6 +206868,11 @@ static int sqlite3Fts5IterNextFrom(Fts5IndexIter*, i64 iMatch);
static void sqlite3Fts5IterClose(Fts5IndexIter*);
/*
+** Close the reader blob handle, if it is open.
+*/
+static void sqlite3Fts5IndexCloseReader(Fts5Index*);
+
+/*
** This interface is used by the fts5vocab module.
*/
static const char *sqlite3Fts5IterTerm(Fts5IndexIter*, int*);
@@ -204161,6 +207432,7 @@ typedef union {
#define sqlite3Fts5ParserCTX_STORE
#define fts5YYNSTATE 35
#define fts5YYNRULE 28
+#define fts5YYNRULE_WITH_ACTION 28
#define fts5YYNFTS5TOKEN 16
#define fts5YY_MAX_SHIFT 34
#define fts5YY_MIN_SHIFTREDUCE 52
@@ -204990,12 +208262,15 @@ static fts5YYACTIONTYPE fts5yy_reduce(
if( fts5yyTraceFILE && fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) ){
fts5yysize = fts5yyRuleInfoNRhs[fts5yyruleno];
if( fts5yysize ){
- fprintf(fts5yyTraceFILE, "%sReduce %d [%s], go to state %d.\n",
+ fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
fts5yyTracePrompt,
- fts5yyruleno, fts5yyRuleName[fts5yyruleno], fts5yymsp[fts5yysize].stateno);
+ fts5yyruleno, fts5yyRuleName[fts5yyruleno],
+ fts5yyruleno<fts5YYNRULE_WITH_ACTION ? "" : " without external action",
+ fts5yymsp[fts5yysize].stateno);
}else{
- fprintf(fts5yyTraceFILE, "%sReduce %d [%s].\n",
- fts5yyTracePrompt, fts5yyruleno, fts5yyRuleName[fts5yyruleno]);
+ fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s.\n",
+ fts5yyTracePrompt, fts5yyruleno, fts5yyRuleName[fts5yyruleno],
+ fts5yyruleno<fts5YYNRULE_WITH_ACTION ? "" : " without external action");
}
}
#endif /* NDEBUG */
@@ -205477,8 +208752,8 @@ static int sqlite3Fts5ParserFallback(int iToken){
return fts5yyFallback[iToken];
#else
(void)iToken;
-#endif
return 0;
+#endif
}
/*
@@ -206627,7 +209902,7 @@ static void sqlite3Fts5TermsetFree(Fts5Termset *p){
#define FTS5_DEFAULT_HASHSIZE (1024*1024)
/* Maximum allowed page size */
-#define FTS5_MAX_PAGE_SIZE (128*1024)
+#define FTS5_MAX_PAGE_SIZE (64*1024)
static int fts5_iswhitespace(char x){
return (x==' ');
@@ -206754,7 +210029,7 @@ static int fts5Dequote(char *z){
assert( q=='[' || q=='\'' || q=='"' || q=='`' );
if( q=='[' ) q = ']';
- while( ALWAYS(z[iIn]) ){
+ while( z[iIn] ){
if( z[iIn]==q ){
if( z[iIn+1]!=q ){
/* Character iIn was the close quote. */
@@ -207432,7 +210707,7 @@ static int sqlite3Fts5ConfigSetValue(
if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
pgsz = sqlite3_value_int(pVal);
}
- if( pgsz<=0 || pgsz>FTS5_MAX_PAGE_SIZE ){
+ if( pgsz<32 || pgsz>FTS5_MAX_PAGE_SIZE ){
*pbBadkey = 1;
}else{
pConfig->pgsz = pgsz;
@@ -207485,6 +210760,7 @@ static int sqlite3Fts5ConfigSetValue(
*pbBadkey = 1;
}else{
if( nCrisisMerge<=1 ) nCrisisMerge = FTS5_DEFAULT_CRISISMERGE;
+ if( nCrisisMerge>=FTS5_MAX_SEGMENT ) nCrisisMerge = FTS5_MAX_SEGMENT-1;
pConfig->nCrisisMerge = nCrisisMerge;
}
}
@@ -210082,10 +213358,12 @@ static void fts5ExprFunction(
azConfig[1] = "main";
azConfig[2] = "tbl";
for(i=3; iArg<nArg; iArg++){
- azConfig[i++] = (const char*)sqlite3_value_text(apVal[iArg]);
+ const char *z = (const char*)sqlite3_value_text(apVal[iArg]);
+ azConfig[i++] = (z ? z : "");
}
zExpr = (const char*)sqlite3_value_text(apVal[0]);
+ if( zExpr==0 ) zExpr = "";
rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
if( rc==SQLITE_OK ){
@@ -211256,11 +214534,6 @@ static void sqlite3Fts5HashScanEntry(
#define FTS5_SEGMENT_ROWID(segid, pgno) fts5_dri(segid, 0, 0, pgno)
#define FTS5_DLIDX_ROWID(segid, height, pgno) fts5_dri(segid, 1, height, pgno)
-/*
-** Maximum segments permitted in a single index
-*/
-#define FTS5_MAX_SEGMENT 2000
-
#ifdef SQLITE_DEBUG
static int sqlite3Fts5Corrupt() { return SQLITE_CORRUPT_VTAB; }
#endif
@@ -211636,7 +214909,7 @@ static int fts5LeafFirstTermOff(Fts5Data *pLeaf){
/*
** Close the read-only blob handle, if it is open.
*/
-static void fts5CloseReader(Fts5Index *p){
+static void sqlite3Fts5IndexCloseReader(Fts5Index *p){
if( p->pReader ){
sqlite3_blob *pReader = p->pReader;
p->pReader = 0;
@@ -211665,7 +214938,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
assert( p->pReader==0 );
p->pReader = pBlob;
if( rc!=SQLITE_OK ){
- fts5CloseReader(p);
+ sqlite3Fts5IndexCloseReader(p);
}
if( rc==SQLITE_ABORT ) rc = SQLITE_OK;
}
@@ -216226,7 +219499,7 @@ static int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
static int sqlite3Fts5IndexSync(Fts5Index *p){
assert( p->rc==SQLITE_OK );
fts5IndexFlush(p);
- fts5CloseReader(p);
+ sqlite3Fts5IndexCloseReader(p);
return fts5IndexReturn(p);
}
@@ -216237,7 +219510,7 @@ static int sqlite3Fts5IndexSync(Fts5Index *p){
** records must be invalidated.
*/
static int sqlite3Fts5IndexRollback(Fts5Index *p){
- fts5CloseReader(p);
+ sqlite3Fts5IndexCloseReader(p);
fts5IndexDiscardData(p);
fts5StructureInvalidate(p);
/* assert( p->rc==SQLITE_OK ); */
@@ -216252,6 +219525,7 @@ static int sqlite3Fts5IndexRollback(Fts5Index *p){
static int sqlite3Fts5IndexReinit(Fts5Index *p){
Fts5Structure s;
fts5StructureInvalidate(p);
+ fts5IndexDiscardData(p);
memset(&s, 0, sizeof(Fts5Structure));
fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
fts5StructureWrite(p, &s);
@@ -216339,9 +219613,13 @@ static int sqlite3Fts5IndexCharlenToBytelen(
for(i=0; i<nChar; i++){
if( n>=nByte ) return 0; /* Input contains fewer than nChar chars */
if( (unsigned char)p[n++]>=0xc0 ){
+ if( n>=nByte ) return 0;
while( (p[n] & 0xc0)==0x80 ){
n++;
- if( n>=nByte ) break;
+ if( n>=nByte ){
+ if( i+1==nChar ) break;
+ return 0;
+ }
}
}
}
@@ -216477,7 +219755,7 @@ static int sqlite3Fts5IndexQuery(
if( p->rc ){
sqlite3Fts5IterClose((Fts5IndexIter*)pRet);
pRet = 0;
- fts5CloseReader(p);
+ sqlite3Fts5IndexCloseReader(p);
}
*ppIter = (Fts5IndexIter*)pRet;
@@ -216550,7 +219828,7 @@ static void sqlite3Fts5IterClose(Fts5IndexIter *pIndexIter){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
Fts5Index *pIndex = pIter->pIndex;
fts5MultiIterFree(pIter);
- fts5CloseReader(pIndex);
+ sqlite3Fts5IndexCloseReader(pIndex);
}
}
@@ -216743,6 +220021,37 @@ static int fts5QueryCksum(
return rc;
}
+/*
+** Check if buffer z[], size n bytes, contains as series of valid utf-8
+** encoded codepoints. If so, return 0. Otherwise, if the buffer does not
+** contain valid utf-8, return non-zero.
+*/
+static int fts5TestUtf8(const char *z, int n){
+ int i = 0;
+ assert_nc( n>0 );
+ while( i<n ){
+ if( (z[i] & 0x80)==0x00 ){
+ i++;
+ }else
+ if( (z[i] & 0xE0)==0xC0 ){
+ if( i+1>=n || (z[i+1] & 0xC0)!=0x80 ) return 1;
+ i += 2;
+ }else
+ if( (z[i] & 0xF0)==0xE0 ){
+ if( i+2>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1;
+ i += 3;
+ }else
+ if( (z[i] & 0xF8)==0xF0 ){
+ if( i+3>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1;
+ if( (z[i+2] & 0xC0)!=0x80 ) return 1;
+ i += 3;
+ }else{
+ return 1;
+ }
+ }
+
+ return 0;
+}
/*
** This function is also purely an internal test. It does not contribute to
@@ -216783,8 +220092,14 @@ static void fts5TestTerm(
** This check may only be performed if the hash table is empty. This
** is because the hash table only supports a single scan query at
** a time, and the multi-iter loop from which this function is called
- ** is already performing such a scan. */
- if( p->nPendingData==0 ){
+ ** is already performing such a scan.
+ **
+ ** Also only do this if buffer zTerm contains nTerm bytes of valid
+ ** utf-8. Otherwise, the last part of the buffer contents might contain
+ ** a non-utf-8 sequence that happens to be a prefix of a valid utf-8
+ ** character stored in the main fts index, which will cause the
+ ** test to fail. */
+ if( p->nPendingData==0 && 0==fts5TestUtf8(zTerm, nTerm) ){
if( iIdx>0 && rc==SQLITE_OK ){
int f = flags|FTS5INDEX_QUERY_TEST_NOIDX;
ck2 = 0;
@@ -216907,7 +220222,8 @@ static void fts5IndexIntegrityCheckSegment(
if( pSeg->pgnoFirst==0 ) return;
fts5IndexPrepareStmt(p, &pStmt, sqlite3_mprintf(
- "SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d",
+ "SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d "
+ "ORDER BY 1, 2",
pConfig->zDb, pConfig->zName, pSeg->iSegid
));
@@ -216916,8 +220232,8 @@ static void fts5IndexIntegrityCheckSegment(
i64 iRow; /* Rowid for this leaf */
Fts5Data *pLeaf; /* Data for this leaf */
+ const char *zIdxTerm = (const char*)sqlite3_column_blob(pStmt, 1);
int nIdxTerm = sqlite3_column_bytes(pStmt, 1);
- const char *zIdxTerm = (const char*)sqlite3_column_text(pStmt, 1);
int iIdxLeaf = sqlite3_column_int(pStmt, 2);
int bIdxDlidx = sqlite3_column_int(pStmt, 3);
@@ -217898,7 +221214,10 @@ static void fts5CheckTransactionState(Fts5FullTable *p, int op, int iSavepoint){
case FTS5_ROLLBACKTO:
assert( p->ts.eState==1 );
assert( iSavepoint>=-1 );
- assert( iSavepoint<=p->ts.iSavepoint );
+ /* The following assert() can fail if another vtab strikes an error
+ ** within an xSavepoint() call then SQLite calls xRollbackTo() - without
+ ** having called xSavepoint() on this vtab. */
+ /* assert( iSavepoint<=p->ts.iSavepoint ); */
p->ts.iSavepoint = iSavepoint;
break;
}
@@ -218353,6 +221672,7 @@ static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
sqlite3_free(pCsr->zRankArgs);
}
+ sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan - (u8*)pCsr));
}
@@ -218503,15 +221823,24 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
break;
}
- default:
+ default: {
+ Fts5Config *pConfig = ((Fts5Table*)pCursor->pVtab)->pConfig;
+ pConfig->bLock++;
rc = sqlite3_step(pCsr->pStmt);
+ pConfig->bLock--;
if( rc!=SQLITE_ROW ){
CsrFlagSet(pCsr, FTS5CSR_EOF);
rc = sqlite3_reset(pCsr->pStmt);
+ if( rc!=SQLITE_OK ){
+ pCursor->pVtab->zErrMsg = sqlite3_mprintf(
+ "%s", sqlite3_errmsg(pConfig->db)
+ );
+ }
}else{
rc = SQLITE_OK;
}
break;
+ }
}
}
@@ -218796,6 +222125,13 @@ static int fts5FilterMethod(
int iIdxStr = 0;
Fts5Expr *pExpr = 0;
+ if( pConfig->bLock ){
+ pTab->p.base.zErrMsg = sqlite3_mprintf(
+ "recursively defined fts5 content table"
+ );
+ return SQLITE_ERROR;
+ }
+
if( pCsr->ePlan ){
fts5FreeCursorComponents(pCsr);
memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan-(u8*)pCsr));
@@ -219016,10 +222352,13 @@ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
}
if( rc==SQLITE_OK && CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) ){
+ Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
assert( pCsr->pExpr );
sqlite3_reset(pCsr->pStmt);
sqlite3_bind_int64(pCsr->pStmt, 1, fts5CursorRowid(pCsr));
+ pTab->pConfig->bLock++;
rc = sqlite3_step(pCsr->pStmt);
+ pTab->pConfig->bLock--;
if( rc==SQLITE_ROW ){
rc = SQLITE_OK;
CsrFlagClear(pCsr, FTS5CSR_REQUIRE_CONTENT);
@@ -219027,6 +222366,10 @@ static int fts5SeekCursor(Fts5Cursor *pCsr, int bErrormsg){
rc = sqlite3_reset(pCsr->pStmt);
if( rc==SQLITE_OK ){
rc = FTS5_CORRUPT;
+ }else if( pTab->pConfig->pzErrmsg ){
+ *pTab->pConfig->pzErrmsg = sqlite3_mprintf(
+ "%s", sqlite3_errmsg(pTab->pConfig->db)
+ );
}
}
}
@@ -220042,10 +223385,12 @@ static int fts5ColumnMethod(
}
}
}else if( !fts5IsContentless(pTab) ){
+ pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
rc = fts5SeekCursor(pCsr, 1);
if( rc==SQLITE_OK ){
sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
}
+ pConfig->pzErrmsg = 0;
}
return rc;
}
@@ -220322,7 +223667,7 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
- sqlite3_result_text(pCtx, "fts5: 2019-10-10 20:19:45 18db032d058f1436ce3dea84081f4ee5a0f2259ad97301d43c426bc7f3df1b0b", -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(pCtx, "fts5: 2020-01-27 19:55:54 3bfa9cc97da10598521b342961df8f5f68c7388fa117345eeb516eaa837bb4d6", -1, SQLITE_TRANSIENT);
}
/*
@@ -221016,6 +224361,8 @@ static int sqlite3Fts5StorageDeleteAll(Fts5Storage *p){
Fts5Config *pConfig = p->pConfig;
int rc;
+ p->bTotalsValid = 0;
+
/* Delete the contents of the %_data and %_docsize tables. */
rc = fts5ExecPrintf(pConfig->db, 0,
"DELETE FROM %Q.'%q_data';"
@@ -221067,10 +224414,11 @@ static int sqlite3Fts5StorageRebuild(Fts5Storage *p){
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
ctx.szCol = 0;
if( pConfig->abUnindexed[ctx.iCol]==0 ){
+ const char *zText = (const char*)sqlite3_column_text(pScan, ctx.iCol+1);
+ int nText = sqlite3_column_bytes(pScan, ctx.iCol+1);
rc = sqlite3Fts5Tokenize(pConfig,
FTS5_TOKENIZE_DOCUMENT,
- (const char*)sqlite3_column_text(pScan, ctx.iCol+1),
- sqlite3_column_bytes(pScan, ctx.iCol+1),
+ zText, nText,
(void*)&ctx,
fts5StorageInsertCallback
);
@@ -221192,10 +224540,11 @@ static int sqlite3Fts5StorageIndexInsert(
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
ctx.szCol = 0;
if( pConfig->abUnindexed[ctx.iCol]==0 ){
+ const char *zText = (const char*)sqlite3_value_text(apVal[ctx.iCol+2]);
+ int nText = sqlite3_value_bytes(apVal[ctx.iCol+2]);
rc = sqlite3Fts5Tokenize(pConfig,
FTS5_TOKENIZE_DOCUMENT,
- (const char*)sqlite3_value_text(apVal[ctx.iCol+2]),
- sqlite3_value_bytes(apVal[ctx.iCol+2]),
+ zText, nText,
(void*)&ctx,
fts5StorageInsertCallback
);
@@ -221364,10 +224713,11 @@ static int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
}
if( rc==SQLITE_OK ){
+ const char *zText = (const char*)sqlite3_column_text(pScan, i+1);
+ int nText = sqlite3_column_bytes(pScan, i+1);
rc = sqlite3Fts5Tokenize(pConfig,
FTS5_TOKENIZE_DOCUMENT,
- (const char*)sqlite3_column_text(pScan, i+1),
- sqlite3_column_bytes(pScan, i+1),
+ zText, nText,
(void*)&ctx,
fts5StorageIntegrityCallback
);
@@ -225090,9 +228440,9 @@ SQLITE_API int sqlite3_stmt_init(
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
-#if __LINE__!=225056
+#if __LINE__!=228443
#undef SQLITE_SOURCE_ID
-#define SQLITE_SOURCE_ID "2019-10-10 20:19:45 18db032d058f1436ce3dea84081f4ee5a0f2259ad97301d43c426bc7f3dfalt2"
+#define SQLITE_SOURCE_ID "2020-01-27 19:55:54 3bfa9cc97da10598521b342961df8f5f68c7388fa117345eeb516eaa837balt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
diff --git a/src/3rdparty/sqlite/sqlite3.h b/src/3rdparty/sqlite/sqlite3.h
index 37bfac5289..cef6eea18c 100644
--- a/src/3rdparty/sqlite/sqlite3.h
+++ b/src/3rdparty/sqlite/sqlite3.h
@@ -123,9 +123,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.30.1"
-#define SQLITE_VERSION_NUMBER 3030001
-#define SQLITE_SOURCE_ID "2019-10-10 20:19:45 18db032d058f1436ce3dea84081f4ee5a0f2259ad97301d43c426bc7f3df1b0b"
+#define SQLITE_VERSION "3.31.1"
+#define SQLITE_VERSION_NUMBER 3031001
+#define SQLITE_SOURCE_ID "2020-01-27 19:55:54 3bfa9cc97da10598521b342961df8f5f68c7388fa117345eeb516eaa837bb4d6"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -516,6 +516,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
+#define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
@@ -535,11 +536,13 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8))
#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8))
+#define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8))
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8))
+#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8))
/*
** CAPI3REF: Flags For File Open Operations
@@ -568,6 +571,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
+#define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */
/* Reserved: 0x00F00000 */
@@ -979,16 +983,16 @@ struct sqlite3_io_methods {
** ^The [SQLITE_FCNTL_BUSYHANDLER]
** file-control may be invoked by SQLite on the database file handle
** shortly after it is opened in order to provide a custom VFS with access
-** to the connections busy-handler callback. The argument is of type (void **)
+** to the connection's busy-handler callback. The argument is of type (void**)
** - an array of two (void *) values. The first (void *) actually points
-** to a function of type (int (*)(void *)). In order to invoke the connections
+** to a function of type (int (*)(void *)). In order to invoke the connection's
** busy-handler, this function should be invoked with the second (void *) in
** the array as the only argument. If it returns non-zero, then the operation
** should be retried. If it returns zero, the custom VFS should abandon the
** current operation.
**
** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
-** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
+** ^Applications can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
** to have SQLite generate a
** temporary filename using the same algorithm that is followed to generate
** temporary filenames for TEMP tables and other internal uses. The
@@ -1101,12 +1105,18 @@ struct sqlite3_io_methods {
** not provide a mechanism to detect changes to MAIN only. Also, the
** [sqlite3_total_changes()] interface responds to internal changes only and
** omits changes made by other database connections. The
-** [PRAGMA data_version] command provide a mechanism to detect changes to
+** [PRAGMA data_version] command provides a mechanism to detect changes to
** a single attached database that occur due to other database connections,
** but omits changes implemented by the database connection on which it is
** called. This file control is the only mechanism to detect changes that
** happen either internally or externally and that are associated with
** a particular attached database.
+**
+** <li>[[SQLITE_FCNTL_CKPT_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
@@ -1144,6 +1154,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_LOCK_TIMEOUT 34
#define SQLITE_FCNTL_DATA_VERSION 35
#define SQLITE_FCNTL_SIZE_LIMIT 36
+#define SQLITE_FCNTL_CKPT_DONE 37
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -1189,10 +1200,10 @@ typedef struct sqlite3_api_routines sqlite3_api_routines;
** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields
** may be appended to the sqlite3_vfs object and the iVersion value
** may increase again in future versions of SQLite.
-** Note that the structure
-** of the sqlite3_vfs object changes in the transition from
+** Note that due to an oversight, the structure
+** of the sqlite3_vfs object changed in the transition from
** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0]
-** and yet the iVersion field was not modified.
+** and yet the iVersion field was not increased.
**
** The szOsFile field is the size of the subclassed [sqlite3_file]
** structure used by this VFS. mxPathname is the maximum length of
@@ -1283,7 +1294,7 @@ typedef struct sqlite3_api_routines sqlite3_api_routines;
** for exclusive access.
**
** ^At least szOsFile bytes of memory are allocated by SQLite
-** to hold the [sqlite3_file] structure passed as the third
+** to hold the [sqlite3_file] structure passed as the third
** argument to xOpen. The xOpen method does not have to
** allocate the structure; it should just fill it in. Note that
** the xOpen method must set the sqlite3_file.pMethods to either
@@ -1620,7 +1631,7 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
** that causes the corresponding memory allocation to fail.
**
** The xInit method initializes the memory allocator. For example,
-** it might allocate any require mutexes or initialize internal data
+** it might allocate any required mutexes or initialize internal data
** structures. The xShutdown method is invoked (indirectly) by
** [sqlite3_shutdown()] and should deallocate any resources acquired
** by xInit. The pAppData pointer is used as the only parameter to
@@ -1742,6 +1753,7 @@ struct sqlite3_mem_methods {
** memory allocation statistics. ^(When memory allocation statistics are
** disabled, the following SQLite interfaces become non-operational:
** <ul>
+** <li> [sqlite3_hard_heap_limit64()]
** <li> [sqlite3_memory_used()]
** <li> [sqlite3_memory_highwater()]
** <li> [sqlite3_soft_heap_limit64()]
@@ -1760,7 +1772,7 @@ struct sqlite3_mem_methods {
** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool
** that SQLite can use for the database page cache with the default page
** cache implementation.
-** This configuration option is a no-op if an application-define page
+** This configuration option is a no-op if an application-defined page
** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2].
** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
** 8-byte aligned memory (pMem), the size of each page cache line (sz),
@@ -2245,7 +2257,7 @@ struct sqlite3_mem_methods {
** [[SQLITE_DBCONFIG_DQS_DML]]
** <dt>SQLITE_DBCONFIG_DQS_DML</td>
** <dd>The SQLITE_DBCONFIG_DQS_DML option activates or deactivates
-** the legacy [double-quoted string literal] misfeature for DML statement
+** the legacy [double-quoted string literal] misfeature for DML statements
** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The
** default value of this setting is determined by the [-DSQLITE_DQS]
** compile-time option.
@@ -2259,6 +2271,49 @@ struct sqlite3_mem_methods {
** default value of this setting is determined by the [-DSQLITE_DQS]
** compile-time option.
** </dd>
+**
+** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]]
+** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</td>
+** <dd>The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to
+** assume that database schemas (the contents of the [sqlite_master] tables)
+** are untainted by malicious content.
+** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite
+** takes additional defensive steps to protect the application from harm
+** including:
+** <ul>
+** <li> Prohibit the use of SQL functions inside triggers, views,
+** CHECK constraints, DEFAULT clauses, expression indexes,
+** partial indexes, or generated columns
+** unless those functions are tagged with [SQLITE_INNOCUOUS].
+** <li> Prohibit the use of virtual tables inside of triggers or views
+** unless those virtual tables are tagged with [SQLITE_VTAB_INNOCUOUS].
+** </ul>
+** This setting defaults to "on" for legacy compatibility, however
+** all applications are advised to turn it off if possible. This setting
+** can also be controlled using the [PRAGMA trusted_schema] statement.
+** </dd>
+**
+** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]]
+** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</td>
+** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates
+** the legacy file format flag. When activated, this flag causes all newly
+** created database file to have a schema format version number (the 4-byte
+** integer found at offset 44 into the database header) of 1. This in turn
+** means that the resulting database file will be readable and writable by
+** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting,
+** newly created databases are generally not understandable by SQLite versions
+** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there
+** is now scarcely any need to generated database files that are compatible
+** all the way back to version 3.0.0, and so this setting is of little
+** practical use, but is provided so that SQLite can continue to claim the
+** ability to generate new database files that are compatible with version
+** 3.0.0.
+** <p>Note that when the SQLITE_DBCONFIG_LEGACY_FILE_FORMAT setting is on,
+** the [VACUUM] command will fail with an obscure error when attempting to
+** process a table with generated columns and a descending index. This is
+** not considered a bug since SQLite versions 3.3.0 and earlier do not support
+** either generated columns or decending indexes.
+** </dd>
** </dl>
*/
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
@@ -2277,7 +2332,9 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */
#define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */
-#define SQLITE_DBCONFIG_MAX 1015 /* Largest DBCONFIG */
+#define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */
+#define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */
+#define SQLITE_DBCONFIG_MAX 1017 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
@@ -2483,7 +2540,7 @@ SQLITE_API int sqlite3_total_changes(sqlite3*);
** ^The sqlite3_interrupt(D) call is in effect until all currently running
** SQL statements on [database connection] D complete. ^Any new SQL statements
** that are started after the sqlite3_interrupt() call and before the
-** running statements reaches zero are interrupted as if they had been
+** running statement count reaches zero are interrupted as if they had been
** running prior to the sqlite3_interrupt() call. ^New SQL statements
** that are started after the running statement count reaches zero are
** not effected by the sqlite3_interrupt().
@@ -2651,9 +2708,9 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
** Cindy | 21
** </pre></blockquote>
**
-** There are two column (M==2) and three rows (N==3). Thus the
+** There are two columns (M==2) and three rows (N==3). Thus the
** result table has 8 entries. Suppose the result table is stored
-** in an array names azResult. Then azResult holds this content:
+** in an array named azResult. Then azResult holds this content:
**
** <blockquote><pre>
** azResult&#91;0] = "Name";
@@ -2746,7 +2803,7 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
**
** The SQLite core uses these three routines for all of its own
** internal memory allocation needs. "Core" in the previous sentence
-** does not include operating-system specific VFS implementation. The
+** does not include operating-system specific [VFS] implementation. The
** Windows VFS uses native malloc() and free() for some operations.
**
** ^The sqlite3_malloc() routine returns a pointer to a block
@@ -2807,19 +2864,6 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time
** option is used.
**
-** In SQLite version 3.5.0 and 3.5.1, it was possible to define
-** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in
-** implementation of these routines to be omitted. That capability
-** is no longer provided. Only built-in memory allocators can be used.
-**
-** Prior to SQLite version 3.7.10, the Windows OS interface layer called
-** the system malloc() and free() directly when converting
-** filenames between the UTF-8 encoding used by SQLite
-** and whatever filename encoding is used by the particular Windows
-** installation. Memory allocation errors were detected, but
-** they were reported back as [SQLITE_CANTOPEN] or
-** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
-**
** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
** must be either NULL or else pointers obtained from a prior
** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have
@@ -2868,7 +2912,7 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
** SQLite contains a high-quality pseudo-random number generator (PRNG) used to
** select random [ROWID | ROWIDs] when inserting new records into a table that
** already uses the largest possible [ROWID]. The PRNG is also used for
-** the build-in random() and randomblob() SQL functions. This interface allows
+** the built-in random() and randomblob() SQL functions. This interface allows
** applications to access the same PRNG for other purposes.
**
** ^A call to this routine stores N bytes of randomness into buffer P.
@@ -3242,10 +3286,8 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** The sqlite3_open_v2() interface works like sqlite3_open()
** except that it accepts two additional parameters for additional control
** over the new database connection. ^(The flags parameter to
-** sqlite3_open_v2() can take one of
-** the following three values, optionally combined with the
-** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
-** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
+** sqlite3_open_v2() must include, at a minimum, one of the following
+** three flag combinations:)^
**
** <dl>
** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
@@ -3263,23 +3305,51 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** sqlite3_open() and sqlite3_open16().</dd>)^
** </dl>
**
+** In addition to the required flags, the following optional flags are
+** also supported:
+**
+** <dl>
+** ^(<dt>[SQLITE_OPEN_URI]</dt>
+** <dd>The filename can be interpreted as a URI if this flag is set.</dd>)^
+**
+** ^(<dt>[SQLITE_OPEN_MEMORY]</dt>
+** <dd>The database will be opened as an in-memory database. The database
+** is named by the "filename" argument for the purposes of cache-sharing,
+** if shared cache mode is enabled, but the "filename" is otherwise ignored.
+** </dd>)^
+**
+** ^(<dt>[SQLITE_OPEN_NOMUTEX]</dt>
+** <dd>The new database connection will use the "multi-thread"
+** [threading mode].)^ This means that separate threads are allowed
+** to use SQLite at the same time, as long as each thread is using
+** a different [database connection].
+**
+** ^(<dt>[SQLITE_OPEN_FULLMUTEX]</dt>
+** <dd>The new database connection will use the "serialized"
+** [threading mode].)^ This means the multiple threads can safely
+** attempt to use the same database connection at the same time.
+** (Mutexes will block any actual concurrency, but in this mode
+** there is no harm in trying.)
+**
+** ^(<dt>[SQLITE_OPEN_SHAREDCACHE]</dt>
+** <dd>The database is opened [shared cache] enabled, overriding
+** the default shared cache setting provided by
+** [sqlite3_enable_shared_cache()].)^
+**
+** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt>
+** <dd>The database is opened [shared cache] disabled, overriding
+** the default shared cache setting provided by
+** [sqlite3_enable_shared_cache()].)^
+**
+** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
+** <dd>The database filename is not allowed to be a symbolic link</dd>
+** </dl>)^
+**
** If the 3rd parameter to sqlite3_open_v2() is not one of the
-** combinations shown above optionally combined with other
+** required combinations shown above optionally combined with other
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
** then the behavior is undefined.
**
-** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
-** opens in the multi-thread [threading mode] as long as the single-thread
-** mode has not been set at compile-time or start-time. ^If the
-** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens
-** in the serialized [threading mode] unless single-thread was
-** previously selected at compile-time or start-time.
-** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
-** eligible to use [shared cache mode], regardless of whether or not shared
-** cache is enabled using [sqlite3_enable_shared_cache()]. ^The
-** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
-** participate in [shared cache mode] even if it is enabled.
-**
** ^The fourth parameter to sqlite3_open_v2() is the name of the
** [sqlite3_vfs] object that defines the operating system interface that
** the new database connection should use. ^If the fourth parameter is
@@ -3459,17 +3529,16 @@ SQLITE_API int sqlite3_open_v2(
/*
** CAPI3REF: Obtain Values For URI Parameters
**
-** These are utility routines, useful to VFS implementations, that check
-** to see if a database file was a URI that contained a specific query
+** These are utility routines, useful to [VFS|custom VFS implementations],
+** that check if a database file was a URI that contained a specific query
** parameter, and if so obtains the value of that query parameter.
**
** If F is the database filename pointer passed into the xOpen() method of
-** a VFS implementation when the flags parameter to xOpen() has one or
-** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
-** P is the name of the query parameter, then
+** a VFS implementation or it is the return value of [sqlite3_db_filename()]
+** and if P is the name of the query parameter, then
** sqlite3_uri_parameter(F,P) returns the value of the P
** parameter if it exists or a NULL pointer if P does not appear as a
-** query parameter on F. If P is a query parameter of F
+** query parameter on F. If P is a query parameter of F and it
** has no explicit value, then sqlite3_uri_parameter(F,P) returns
** a pointer to an empty string.
**
@@ -3481,25 +3550,72 @@ SQLITE_API int sqlite3_open_v2(
** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of
** query parameter P is one of "no", "false", or "off" in any case or
** if the value begins with a numeric zero. If P is not a query
-** parameter on F or if the value of P is does not match any of the
+** parameter on F or if the value of P does not match any of the
** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0).
**
** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
** 64-bit signed integer and returns that integer, or D if P does not
** exist. If the value of P is something other than an integer, then
** zero is returned.
+**
+** The sqlite3_uri_key(F,N) returns a pointer to the name (not
+** the value) of the N-th query parameter for filename F, or a NULL
+** pointer if N is less than zero or greater than the number of query
+** parameters minus 1. The N value is zero-based so N should be 0 to obtain
+** the name of the first query parameter, 1 for the second parameter, and
+** so forth.
**
** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and
-** is not a database file pathname pointer that SQLite passed into the xOpen
-** VFS method, then the behavior of this routine is undefined and probably
-** undesirable.
+** is not a database file pathname pointer that the SQLite core passed
+** into the xOpen VFS method, then the behavior of this routine is undefined
+** and probably undesirable.
+**
+** Beginning with SQLite [version 3.31.0] ([dateof:3.31.0]) the input F
+** parameter can also be the name of a rollback journal file or WAL file
+** in addition to the main database file. Prior to version 3.31.0, these
+** routines would only work if F was the name of the main database file.
+** When the F parameter is the name of the rollback journal or WAL file,
+** it has access to all the same query parameters as were found on the
+** main database file.
**
** See the [URI filename] documentation for additional information.
*/
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
+SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N);
+
+/*
+** CAPI3REF: Translate filenames
+**
+** These routines are available to [VFS|custom VFS implementations] for
+** translating filenames between the main database file, the journal file,
+** and the WAL file.
+**
+** If F is the name of an sqlite database file, journal file, or WAL file
+** passed by the SQLite core into the VFS, then sqlite3_filename_database(F)
+** returns the name of the corresponding database file.
+**
+** If F is the name of an sqlite database file, journal file, or WAL file
+** passed by the SQLite core into the VFS, or if F is a database filename
+** obtained from [sqlite3_db_filename()], then sqlite3_filename_journal(F)
+** returns the name of the corresponding rollback journal file.
+**
+** If F is the name of an sqlite database file, journal file, or WAL file
+** that was passed by the SQLite core into the VFS, or if F is a database
+** filename obtained from [sqlite3_db_filename()], then
+** sqlite3_filename_wal(F) returns the name of the corresponding
+** WAL file.
+**
+** In all of the above, if F is not the name of a database, journal or WAL
+** filename passed into the VFS from the SQLite core and F is not the
+** return value from [sqlite3_db_filename()], then the result is
+** undefined and is likely a memory access violation.
+*/
+SQLITE_API const char *sqlite3_filename_database(const char*);
+SQLITE_API const char *sqlite3_filename_journal(const char*);
+SQLITE_API const char *sqlite3_filename_wal(const char*);
/*
@@ -3818,12 +3934,12 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** </li>
**
** <li>
-** ^If the specific value bound to [parameter | host parameter] in the
+** ^If the specific value bound to a [parameter | host parameter] in the
** WHERE clause might influence the choice of query plan for a statement,
** then the statement will be automatically recompiled, as if there had been
-** a schema change, on the first [sqlite3_step()] call following any change
+** a schema change, on the first [sqlite3_step()] call following any change
** to the [sqlite3_bind_text | bindings] of that [parameter].
-** ^The specific value of WHERE-clause [parameter] might influence the
+** ^The specific value of a WHERE-clause [parameter] might influence the
** choice of query plan if the parameter is the left-hand side of a [LIKE]
** or [GLOB] operator or if the parameter is compared to an indexed column
** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled.
@@ -4332,7 +4448,7 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
**
** ^If the Nth column returned by the statement is an expression or
** subquery and is not a column value, then all of these functions return
-** NULL. ^These routine might also return NULL if a memory allocation error
+** NULL. ^These routines might also return NULL if a memory allocation error
** occurs. ^Otherwise, they return the name of the attached database, table,
** or column that query result column was extracted from.
**
@@ -4342,10 +4458,6 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
** ^These APIs are only available if the library was compiled with the
** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol.
**
-** If two or more threads call one or more of these routines against the same
-** prepared statement and column at the same time then the results are
-** undefined.
-**
** If two or more threads call one or more
** [sqlite3_column_database_name | column metadata interfaces]
** for the same [prepared statement] and result column
@@ -4482,7 +4594,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt*);
** ^The sqlite3_data_count(P) interface returns the number of columns in the
** current row of the result set of [prepared statement] P.
** ^If prepared statement P does not have results ready to return
-** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
+** (via calls to the [sqlite3_column_int | sqlite3_column()] family of
** interfaces) then sqlite3_data_count(P) returns 0.
** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
@@ -4806,8 +4918,6 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Create Or Redefine SQL Functions
** KEYWORDS: {function creation routines}
-** KEYWORDS: {application-defined SQL function}
-** KEYWORDS: {application-defined SQL functions}
** METHOD: sqlite3
**
** ^These functions (collectively known as "function creation routines")
@@ -4863,9 +4973,20 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
**
** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY]
** flag, which if present prevents the function from being invoked from
-** within VIEWs or TRIGGERs. For security reasons, the [SQLITE_DIRECTONLY]
-** flag is recommended for any application-defined SQL function that has
-** side-effects.
+** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions,
+** index expressions, or the WHERE clause of partial indexes.
+**
+** <span style="background-color:#ffff90;">
+** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
+** all application-defined SQL functions that do not need to be
+** used inside of triggers, view, CHECK constraints, or other elements of
+** the database schema. This flags is especially recommended for SQL
+** functions that have side effects or reveal internal application state.
+** Without this flag, an attacker might be able to modify the schema of
+** a database file to include invocations of the function with parameters
+** chosen by the attacker, which the application will then execute when
+** the database file is opened and read.
+** </span>
**
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
** function can gain access to this pointer using [sqlite3_user_data()].)^
@@ -4984,18 +5105,53 @@ SQLITE_API int sqlite3_create_window_function(
** to [sqlite3_create_function()], [sqlite3_create_function16()], or
** [sqlite3_create_function_v2()].
**
-** The SQLITE_DETERMINISTIC flag means that the new function will always
-** maps the same inputs into the same output. The abs() function is
-** deterministic, for example, but randomblob() is not.
-**
+** <dl>
+** [[SQLITE_DETERMINISTIC]] <dt>SQLITE_DETERMINISTIC</dt><dd>
+** The SQLITE_DETERMINISTIC flag means that the new function always gives
+** the same output when the input parameters are the same.
+** The [abs|abs() function] is deterministic, for example, but
+** [randomblob|randomblob()] is not. Functions must
+** be deterministic in order to be used in certain contexts such as
+** with the WHERE clause of [partial indexes] or in [generated columns].
+** SQLite might also optimize deterministic functions by factoring them
+** out of inner loops.
+** </dd>
+**
+** [[SQLITE_DIRECTONLY]] <dt>SQLITE_DIRECTONLY</dt><dd>
** The SQLITE_DIRECTONLY flag means that the function may only be invoked
-** from top-level SQL, and cannot be used in VIEWs or TRIGGERs. This is
-** a security feature which is recommended for all
-** [application-defined SQL functions] that have side-effects. This flag
-** prevents an attacker from adding triggers and views to a schema then
-** tricking a high-privilege application into causing unintended side-effects
-** while performing ordinary queries.
+** from top-level SQL, and cannot be used in VIEWs or TRIGGERs nor in
+** schema structures such as [CHECK constraints], [DEFAULT clauses],
+** [expression indexes], [partial indexes], or [generated columns].
+** The SQLITE_DIRECTONLY flags is a security feature which is recommended
+** for all [application-defined SQL functions], and especially for functions
+** that have side-effects or that could potentially leak sensitive
+** information.
+** </dd>
**
+** [[SQLITE_INNOCUOUS]] <dt>SQLITE_INNOCUOUS</dt><dd>
+** The SQLITE_INNOCUOUS flag means that the function is unlikely
+** to cause problems even if misused. An innocuous function should have
+** no side effects and should not depend on any values other than its
+** input parameters. The [abs|abs() function] is an example of an
+** innocuous function.
+** The [load_extension() SQL function] is not innocuous because of its
+** side effects.
+** <p> SQLITE_INNOCUOUS is similar to SQLITE_DETERMINISTIC, but is not
+** exactly the same. The [random|random() function] is an example of a
+** function that is innocuous but not deterministic.
+** <p>Some heightened security settings
+** ([SQLITE_DBCONFIG_TRUSTED_SCHEMA] and [PRAGMA trusted_schema=OFF])
+** disable the use of SQL functions inside views and triggers and in
+** schema structures such as [CHECK constraints], [DEFAULT clauses],
+** [expression indexes], [partial indexes], and [generated columns] unless
+** the function is tagged with SQLITE_INNOCUOUS. Most built-in functions
+** are innocuous. Developers are advised to avoid using the
+** SQLITE_INNOCUOUS flag for application-defined functions unless the
+** function has been carefully audited and found to be free of potentially
+** security-adverse side-effects and information-leaks.
+** </dd>
+**
+** [[SQLITE_SUBTYPE]] <dt>SQLITE_SUBTYPE</dt><dd>
** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call
** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
** Specifying this flag makes no difference for scalar or aggregate user
@@ -5003,10 +5159,13 @@ SQLITE_API int sqlite3_create_window_function(
** function, then any sub-types belonging to arguments passed to the window
** function may be discarded before the window function is called (i.e.
** sqlite3_value_subtype() will always return 0).
+** </dd>
+** </dl>
*/
#define SQLITE_DETERMINISTIC 0x000000800
#define SQLITE_DIRECTONLY 0x000080000
#define SQLITE_SUBTYPE 0x000100000
+#define SQLITE_INNOCUOUS 0x000200000
/*
** CAPI3REF: Deprecated Functions
@@ -5065,8 +5224,8 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
**
** These routines extract type, size, and content information from
** [protected sqlite3_value] objects. Protected sqlite3_value objects
-** are used to pass parameter information into implementation of
-** [application-defined SQL functions] and [virtual tables].
+** are used to pass parameter information into the functions that
+** implement [application-defined SQL functions] and [virtual tables].
**
** These routines work only with [protected sqlite3_value] objects.
** Any attempt to use these routines on an [unprotected sqlite3_value]
@@ -5123,7 +5282,7 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** ^The sqlite3_value_frombind(X) interface returns non-zero if the
** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()]
** interfaces. ^If X comes from an SQL literal value, or a table column,
-** and expression, then sqlite3_value_frombind(X) returns zero.
+** or an expression, then sqlite3_value_frombind(X) returns zero.
**
** Please pay particular attention to the fact that the pointer returned
** from [sqlite3_value_blob()], [sqlite3_value_text()], or
@@ -5209,8 +5368,8 @@ SQLITE_API void sqlite3_value_free(sqlite3_value*);
** routine to allocate memory for storing their state.
**
** ^The first time the sqlite3_aggregate_context(C,N) routine is called
-** for a particular aggregate function, SQLite
-** allocates N of memory, zeroes out that memory, and returns a pointer
+** for a particular aggregate function, SQLite allocates
+** N bytes of memory, zeroes out that memory, and returns a pointer
** to the new memory. ^On second and subsequent calls to
** sqlite3_aggregate_context() for the same aggregate function instance,
** the same buffer is returned. Sqlite3_aggregate_context() is normally
@@ -5227,7 +5386,7 @@ SQLITE_API void sqlite3_value_free(sqlite3_value*);
**
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
** determined by the N parameter on first successful call. Changing the
-** value of N in subsequent call to sqlite3_aggregate_context() within
+** value of N in any subsequents call to sqlite3_aggregate_context() within
** the same aggregate function instance will not resize the memory
** allocation.)^ Within the xFinal callback, it is customary to set
** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
@@ -5538,7 +5697,7 @@ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);
** <li> [SQLITE_UTF16_ALIGNED].
** </ul>)^
** ^The eTextRep argument determines the encoding of strings passed
-** to the collating function callback, xCallback.
+** to the collating function callback, xCompare.
** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep
** force strings to be UTF16 with native byte order.
** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin
@@ -5547,18 +5706,19 @@ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);
** ^The fourth argument, pArg, is an application data pointer that is passed
** through as the first argument to the collating function callback.
**
-** ^The fifth argument, xCallback, is a pointer to the collating function.
+** ^The fifth argument, xCompare, is a pointer to the collating function.
** ^Multiple collating functions can be registered using the same name but
** with different eTextRep parameters and SQLite will use whichever
** function requires the least amount of data transformation.
-** ^If the xCallback argument is NULL then the collating function is
+** ^If the xCompare argument is NULL then the collating function is
** deleted. ^When all collating functions having the same name are deleted,
** that collation is no longer usable.
**
** ^The collating function callback is invoked with a copy of the pArg
** application data pointer and with two strings in the encoding specified
-** by the eTextRep argument. The collating function must return an
-** integer that is negative, zero, or positive
+** by the eTextRep argument. The two integer parameters to the collating
+** function callback are the length of the two strings, in bytes. The collating
+** function must return an integer that is negative, zero, or positive
** if the first string is less than, equal to, or greater than the second,
** respectively. A collating function must always return the same answer
** given the same inputs. If two or more collating functions are registered
@@ -5575,7 +5735,7 @@ SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);
** </ol>
**
** If a collating function fails any of the above constraints and that
-** collating function is registered and used, then the behavior of SQLite
+** collating function is registered and used, then the behavior of SQLite
** is undefined.
**
** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation()
@@ -5902,16 +6062,31 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
** CAPI3REF: Return The Filename For A Database Connection
** METHOD: sqlite3
**
-** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
-** associated with database N of connection D. ^The main database file
-** has the name "main". If there is no attached database N on the database
+** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename
+** associated with database N of connection D.
+** ^If there is no attached database N on the database
** connection D, or if database N is a temporary or in-memory database, then
** this function will return either a NULL pointer or an empty string.
**
+** ^The string value returned by this routine is owned and managed by
+** the database connection. ^The value will be valid until the database N
+** is [DETACH]-ed or until the database connection closes.
+**
** ^The filename returned by this function is the output of the
** xFullPathname method of the [VFS]. ^In other words, the filename
** will be an absolute pathname, even if the filename used
** to open the database originally was a URI or relative pathname.
+**
+** If the filename pointer returned by this routine is not NULL, then it
+** can be used as the filename input parameter to these routines:
+** <ul>
+** <li> [sqlite3_uri_parameter()]
+** <li> [sqlite3_uri_boolean()]
+** <li> [sqlite3_uri_int64()]
+** <li> [sqlite3_filename_database()]
+** <li> [sqlite3_filename_journal()]
+** <li> [sqlite3_filename_wal()]
+** </ul>
*/
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
@@ -6061,15 +6236,19 @@ SQLITE_API void *sqlite3_update_hook(
**
** ^(The cache sharing mode set by this interface effects all subsequent
** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()].
-** Existing database connections continue use the sharing mode
+** Existing database connections continue to use the sharing mode
** that was in effect at the time they were opened.)^
**
** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled
** successfully. An [error code] is returned otherwise.)^
**
-** ^Shared cache is disabled by default. But this might change in
-** future releases of SQLite. Applications that care about shared
-** cache setting should set it explicitly.
+** ^Shared cache is disabled by default. It is recommended that it stay
+** that way. In other words, do not use this routine. This interface
+** continues to be provided for historical compatibility, but its use is
+** discouraged. Any use of shared cache is discouraged. If shared cache
+** must be used, it is recommended that shared cache only be enabled for
+** individual database connections using the [sqlite3_open_v2()] interface
+** with the [SQLITE_OPEN_SHAREDCACHE] flag.
**
** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0
** and will always return SQLITE_MISUSE. On those systems,
@@ -6116,6 +6295,9 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
/*
** CAPI3REF: Impose A Limit On Heap Size
**
+** These interfaces impose limits on the amount of heap memory that will be
+** by all database connections within a single process.
+**
** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
** soft limit on the amount of heap memory that may be allocated by SQLite.
** ^SQLite strives to keep heap memory utilization below the soft heap
@@ -6126,20 +6308,41 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** an [SQLITE_NOMEM] error. In other words, the soft heap limit
** is advisory only.
**
-** ^The return value from sqlite3_soft_heap_limit64() is the size of
-** the soft heap limit prior to the call, or negative in the case of an
-** error. ^If the argument N is negative
-** then no change is made to the soft heap limit. Hence, the current
-** size of the soft heap limit can be determined by invoking
-** sqlite3_soft_heap_limit64() with a negative argument.
-**
-** ^If the argument N is zero then the soft heap limit is disabled.
+** ^The sqlite3_hard_heap_limit64(N) interface sets a hard upper bound of
+** N bytes on the amount of memory that will be allocated. ^The
+** sqlite3_hard_heap_limit64(N) interface is similar to
+** sqlite3_soft_heap_limit64(N) except that memory allocations will fail
+** when the hard heap limit is reached.
**
-** ^(The soft heap limit is not enforced in the current implementation
+** ^The return value from both sqlite3_soft_heap_limit64() and
+** sqlite3_hard_heap_limit64() is the size of
+** the heap limit prior to the call, or negative in the case of an
+** error. ^If the argument N is negative
+** then no change is made to the heap limit. Hence, the current
+** size of heap limits can be determined by invoking
+** sqlite3_soft_heap_limit64(-1) or sqlite3_hard_heap_limit(-1).
+**
+** ^Setting the heap limits to zero disables the heap limiter mechanism.
+**
+** ^The soft heap limit may not be greater than the hard heap limit.
+** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N)
+** is invoked with a value of N that is greater than the hard heap limit,
+** the the soft heap limit is set to the value of the hard heap limit.
+** ^The soft heap limit is automatically enabled whenever the hard heap
+** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and
+** the soft heap limit is outside the range of 1..N, then the soft heap
+** limit is set to N. ^Invoking sqlite3_soft_heap_limit64(0) when the
+** hard heap limit is enabled makes the soft heap limit equal to the
+** hard heap limit.
+**
+** The memory allocation limits can also be adjusted using
+** [PRAGMA soft_heap_limit] and [PRAGMA hard_heap_limit].
+**
+** ^(The heap limits are not enforced in the current implementation
** if one or more of following conditions are true:
**
** <ul>
-** <li> The soft heap limit is set to zero.
+** <li> The limit value is set to zero.
** <li> Memory accounting is disabled using a combination of the
** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
@@ -6150,21 +6353,11 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** from the heap.
** </ul>)^
**
-** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]),
-** the soft heap limit is enforced
-** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT]
-** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT],
-** the soft heap limit is enforced on every memory allocation. Without
-** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced
-** when memory is allocated by the page cache. Testing suggests that because
-** the page cache is the predominate memory user in SQLite, most
-** applications will achieve adequate soft heap limit enforcement without
-** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT].
-**
-** The circumstances under which SQLite will enforce the soft heap limit may
+** The circumstances under which SQLite will enforce the heap limits may
** changes in future releases of SQLite.
*/
SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
+SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N);
/*
** CAPI3REF: Deprecated Soft Heap Limit Interface
@@ -6188,7 +6381,7 @@ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
** interface returns SQLITE_OK and fills in the non-NULL pointers in
** the final five arguments with appropriate values if the specified
** column exists. ^The sqlite3_table_column_metadata() interface returns
-** SQLITE_ERROR and if the specified column does not exist.
+** SQLITE_ERROR if the specified column does not exist.
** ^If the column-name parameter to sqlite3_table_column_metadata() is a
** NULL pointer, then this routine simply checks for the existence of the
** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
@@ -6330,7 +6523,7 @@ SQLITE_API int sqlite3_load_extension(
** to enable or disable only the C-API.)^
**
** <b>Security warning:</b> It is recommended that extension loading
-** be disabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
+** be enabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
** rather than this interface, so the [load_extension()] SQL function
** remains disabled. This will prevent SQL injections from giving attackers
** access to extension loading capabilities.
@@ -6417,7 +6610,7 @@ typedef struct sqlite3_module sqlite3_module;
** KEYWORDS: sqlite3_module {virtual table module}
**
** This structure, sometimes called a "virtual table module",
-** defines the implementation of a [virtual tables].
+** defines the implementation of a [virtual table].
** This structure consists mostly of methods for the module.
**
** ^A virtual table module is created by filling in a persistent
@@ -6514,7 +6707,13 @@ struct sqlite3_module {
** the right-hand side of the corresponding aConstraint[] is evaluated
** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit
** is true, then the constraint is assumed to be fully handled by the
-** virtual table and is not checked again by SQLite.)^
+** virtual table and might not be checked again by the byte code.)^ ^(The
+** aConstraintUsage[].omit flag is an optimization hint. When the omit flag
+** is left in its default setting of false, the constraint will always be
+** checked separately in byte code. If the omit flag is change to true, then
+** the constraint may or may not be checked in byte code. In other words,
+** when the omit flag is true there is no guarantee that the constraint will
+** not be checked again using byte code.)^
**
** ^The idxNum and idxPtr values are recorded and passed into the
** [xFilter] method.
@@ -6554,7 +6753,7 @@ struct sqlite3_module {
** If a virtual table extension is
** used with an SQLite version earlier than 3.8.2, the results of attempting
** to read or write the estimatedRows field are undefined (but are likely
-** to included crashing the application). The estimatedRows field should
+** to include crashing the application). The estimatedRows field should
** therefore only be used if [sqlite3_libversion_number()] returns a
** value greater than or equal to 3008002. Similarly, the idxFlags field
** was added for [version 3.9.0] ([dateof:3.9.0]).
@@ -6606,7 +6805,7 @@ struct sqlite3_index_info {
/*
** CAPI3REF: Virtual Table Constraint Operator Codes
**
-** These macros defined the allowed values for the
+** These macros define the allowed values for the
** [sqlite3_index_info].aConstraint[].op field. Each value represents
** an operator that is part of a constraint term in the wHERE clause of
** a query that uses a [virtual table].
@@ -7216,7 +7415,7 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
** The only difference is that the public sqlite3_XXX functions enumerated
** above silently ignore any invocations that pass a NULL pointer instead
** of a valid mutex handle. The implementations of the methods defined
-** by this structure are not required to handle this case, the results
+** by this structure are not required to handle this case. The results
** of passing a NULL pointer instead of a valid mutex handle are undefined
** (i.e. it is acceptable to provide an implementation that segfaults if
** it is passed a NULL pointer).
@@ -7689,7 +7888,7 @@ SQLITE_API int sqlite3_status64(
**
** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
-** handed to [pagecache memory allocator]. Only the value returned in the
+** handed to the [pagecache memory allocator]. Only the value returned in the
** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
@@ -7765,7 +7964,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** checked out.</dd>)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
-** <dd>This parameter returns the number malloc attempts that were
+** <dd>This parameter returns the number of malloc attempts that were
** satisfied using lookaside memory. Only the high-water value is meaningful;
** the current value is always zero.)^
**
@@ -7847,7 +8046,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** cache overflowing. Transactions are more efficient if they are written
** to disk all at once. When pages spill mid-transaction, that introduces
** additional overhead. This parameter can be used help identify
-** inefficiencies that can be resolve by increasing the cache size.
+** inefficiencies that can be resolved by increasing the cache size.
** </dd>
**
** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
@@ -7936,7 +8135,7 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
**
** [[SQLITE_STMTSTATUS_REPREPARE]] <dt>SQLITE_STMTSTATUS_REPREPARE</dt>
** <dd>^This is the number of times that the prepare statement has been
-** automatically regenerated due to schema changes or change to
+** automatically regenerated due to schema changes or changes to
** [bound parameters] that might affect the query plan.
**
** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt>
@@ -8107,7 +8306,7 @@ struct sqlite3_pcache_page {
**
** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite
** will only use a createFlag of 2 after a prior call with a createFlag of 1
-** failed.)^ In between the to xFetch() calls, SQLite may
+** failed.)^ In between the xFetch() calls, SQLite may
** attempt to unpin one or more cache pages by spilling the content of
** pinned pages to disk and synching the operating system disk cache.
**
@@ -8425,7 +8624,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
** the first argument to register for a callback that will be invoked
** when the blocking connections current transaction is concluded. ^The
** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
-** call that concludes the blocking connections transaction.
+** call that concludes the blocking connection's transaction.
**
** ^(If sqlite3_unlock_notify() is called in a multi-threaded application,
** there is a chance that the blocking connection will have already
@@ -8463,7 +8662,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
** an unlock-notify callback is a pointer to an array of void* pointers,
** and the second is the number of entries in the array.
**
-** When a blocking connections transaction is concluded, there may be
+** When a blocking connection's transaction is concluded, there may be
** more than one blocked connection that has registered for an unlock-notify
** callback. ^If two or more such blocked connections have specified the
** same callback function, then instead of invoking the callback function
@@ -8811,14 +9010,20 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
** If this interface is invoked outside the context of an xConnect or
** xCreate virtual table method then the behavior is undefined.
**
-** At present, there is only one option that may be configured using
-** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
-** may be added in the future.
+** In the call sqlite3_vtab_config(D,C,...) the D parameter is the
+** [database connection] in which the virtual table is being created and
+** which is passed in as the first argument to the [xConnect] or [xCreate]
+** method that is invoking sqlite3_vtab_config(). The C parameter is one
+** of the [virtual table configuration options]. The presence and meaning
+** of parameters after C depend on which [virtual table configuration option]
+** is used.
*/
SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
/*
** CAPI3REF: Virtual Table Configuration Options
+** KEYWORDS: {virtual table configuration options}
+** KEYWORDS: {virtual table configuration option}
**
** These macros define the various options to the
** [sqlite3_vtab_config()] interface that [virtual table] implementations
@@ -8826,7 +9031,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
**
** <dl>
** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]]
-** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
+** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT</dt>
** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
** where X is an integer. If X is zero, then the [virtual table] whose
@@ -8855,9 +9060,31 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
** return SQLITE_OK. Or, if this is not possible, it may return
** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
** constraint handling.
+** </dd>
+**
+** [[SQLITE_VTAB_DIRECTONLY]]<dt>SQLITE_VTAB_DIRECTONLY</dt>
+** <dd>Calls of the form
+** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the
+** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
+** prohibits that virtual table from being used from within triggers and
+** views.
+** </dd>
+**
+** [[SQLITE_VTAB_INNOCUOUS]]<dt>SQLITE_VTAB_INNOCUOUS</dt>
+** <dd>Calls of the form
+** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the
+** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
+** identify that virtual table as being safe to use from within triggers
+** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the
+** virtual table can do no serious harm even if it is controlled by a
+** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS
+** flag unless absolutely necessary.
+** </dd>
** </dl>
*/
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
+#define SQLITE_VTAB_INNOCUOUS 2
+#define SQLITE_VTAB_DIRECTONLY 3
/*
** CAPI3REF: Determine The Virtual Table Conflict Policy
@@ -8937,15 +9164,15 @@ SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_
**
** <dl>
** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt>
-** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be
+** <dd>^The [sqlite3_int64] variable pointed to by the V parameter will be
** set to the total number of times that the X-th loop has run.</dd>
**
** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt>
-** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set
+** <dd>^The [sqlite3_int64] variable pointed to by the V parameter will be set
** to the total number of rows examined by all iterations of the X-th loop.</dd>
**
** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt>
-** <dd>^The "double" variable pointed to by the T parameter will be set to the
+** <dd>^The "double" variable pointed to by the V parameter will be set to the
** query planner's estimate for the average number of rows output from each
** iteration of the X-th loop. If the query planner's estimates was accurate,
** then this value will approximate the quotient NVISIT/NLOOP and the
@@ -8953,17 +9180,17 @@ SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_
** be the NLOOP value for the current loop.
**
** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt>
-** <dd>^The "const char *" variable pointed to by the T parameter will be set
+** <dd>^The "const char *" variable pointed to by the V parameter will be set
** to a zero-terminated UTF-8 string containing the name of the index or table
** used for the X-th loop.
**
** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt>
-** <dd>^The "const char *" variable pointed to by the T parameter will be set
+** <dd>^The "const char *" variable pointed to by the V parameter will be set
** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN]
** description for the X-th loop.
**
** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt>
-** <dd>^The "int" variable pointed to by the T parameter will be set to the
+** <dd>^The "int" variable pointed to by the V parameter will be set to the
** "select-id" for the X-th loop. The select-id identifies which query or
** subquery the loop is part of. The main query has a select-id of zero.
** The select-id is the same value as is output in the first column
@@ -9818,7 +10045,7 @@ SQLITE_API int sqlite3session_attach(
** The second argument (xFilter) is the "filter callback". For changes to rows
** in tables that are not attached to the Session object, the filter is called
** to determine whether changes to the table's rows should be tracked or not.
-** If xFilter returns 0, changes is not tracked. Note that once a table is
+** If xFilter returns 0, changes are not tracked. Note that once a table is
** attached, xFilter will not be called again.
*/
SQLITE_API void sqlite3session_table_filter(
@@ -9992,7 +10219,7 @@ SQLITE_API int sqlite3session_changeset(
** It an error if database zFrom does not exist or does not contain the
** required compatible table.
**
-** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite
+** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite
** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg
** may be set to point to a buffer containing an English language error
** message. It is the responsibility of the caller to free this buffer using
@@ -10129,7 +10356,7 @@ SQLITE_API int sqlite3changeset_start_v2(
** CAPI3REF: Advance A Changeset Iterator
** METHOD: sqlite3_changeset_iter
**
-** This function may only be used with iterators created by function
+** This function may only be used with iterators created by the function
** [sqlite3changeset_start()]. If it is called on an iterator passed to
** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE
** is returned and the call has no effect.
@@ -10545,8 +10772,8 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
** case, this function fails with SQLITE_SCHEMA. If the input changeset
** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is
** returned. Or, if an out-of-memory condition occurs during processing, this
-** function returns SQLITE_NOMEM. In all cases, if an error occurs the
-** final contents of the changegroup is undefined.
+** function returns SQLITE_NOMEM. In all cases, if an error occurs the state
+** of the final contents of the changegroup is undefined.
**
** If no error occurs, SQLITE_OK is returned.
*/
@@ -10721,7 +10948,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
**
** It is safe to execute SQL statements, including those that write to the
** table that the callback related to, from within the xConflict callback.
-** This can be used to further customize the applications conflict
+** This can be used to further customize the application's conflict
** resolution strategy.
**
** All changes made by these functions are enclosed in a savepoint transaction.
@@ -11031,7 +11258,7 @@ SQLITE_API int sqlite3rebaser_configure(
**
** Argument pIn must point to a buffer containing a changeset nIn bytes
** in size. This function allocates and populates a buffer with a copy
-** of the changeset rebased rebased according to the configuration of the
+** of the changeset rebased according to the configuration of the
** rebaser object passed as the first argument. If successful, (*ppOut)
** is set to point to the new buffer containing the rebased changeset and
** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the
@@ -11439,7 +11666,7 @@ struct Fts5PhraseIter {
**
** xSetAuxdata(pFts5, pAux, xDelete)
**
-** Save the pointer passed as the second argument as the extension functions
+** Save the pointer passed as the second argument as the extension function's
** "auxiliary data". The pointer may then be retrieved by the current or any
** future invocation of the same fts5 extension function made as part of
** the same MATCH query using the xGetAuxdata() API.
@@ -11681,8 +11908,8 @@ struct Fts5ExtensionApi {
**
** There are several ways to approach this in FTS5:
**
-** <ol><li> By mapping all synonyms to a single token. In this case, the
-** In the above example, this means that the tokenizer returns the
+** <ol><li> By mapping all synonyms to a single token. In this case, using
+** the above example, this means that the tokenizer returns the
** same token for inputs "first" and "1st". Say that token is in
** fact "first", so that when the user inserts the document "I won
** 1st place" entries are added to the index for tokens "i", "won",
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
index 7db16002ff..c1c4d5559d 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -740,54 +740,66 @@ public class QtNative
public static boolean hasClipboardText()
{
- if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
- ClipData primaryClip = m_clipboardManager.getPrimaryClip();
- for (int i = 0; i < primaryClip.getItemCount(); ++i)
- if (primaryClip.getItemAt(i).getText() != null)
- return true;
+ try {
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getText() != null)
+ return true;
+ }
+ } catch (Exception e) {
+ Log.e(QtTAG, "Failed to get clipboard data", e);
}
return false;
}
private static String getClipboardText()
{
- if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
- ClipData primaryClip = m_clipboardManager.getPrimaryClip();
- for (int i = 0; i < primaryClip.getItemCount(); ++i)
- if (primaryClip.getItemAt(i).getText() != null)
- return primaryClip.getItemAt(i).getText().toString();
+ try {
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getText() != null)
+ return primaryClip.getItemAt(i).getText().toString();
+ }
+ } catch (Exception e) {
+ Log.e(QtTAG, "Failed to get clipboard data", e);
}
return "";
}
private static void updatePrimaryClip(ClipData clipData)
{
- if (m_usePrimaryClip) {
- ClipData clip = m_clipboardManager.getPrimaryClip();
- if (Build.VERSION.SDK_INT >= 26) {
- if (m_addItemMethod == null) {
- Class[] cArg = new Class[2];
- cArg[0] = ContentResolver.class;
- cArg[1] = ClipData.Item.class;
+ try {
+ if (m_usePrimaryClip) {
+ ClipData clip = m_clipboardManager.getPrimaryClip();
+ if (Build.VERSION.SDK_INT >= 26) {
+ if (m_addItemMethod == null) {
+ Class[] cArg = new Class[2];
+ cArg[0] = ContentResolver.class;
+ cArg[1] = ClipData.Item.class;
+ try {
+ m_addItemMethod = m_clipboardManager.getClass().getMethod("addItem", cArg);
+ } catch (Exception e) {
+ }
+ }
+ }
+ if (m_addItemMethod != null) {
try {
- m_addItemMethod = m_clipboardManager.getClass().getMethod("addItem", cArg);
+ m_addItemMethod.invoke(m_activity.getContentResolver(), clipData.getItemAt(0));
} catch (Exception e) {
+ e.printStackTrace();
}
+ } else {
+ clip.addItem(clipData.getItemAt(0));
}
- }
- if (m_addItemMethod != null) {
- try {
- m_addItemMethod.invoke(m_activity.getContentResolver(), clipData.getItemAt(0));
- } catch (Exception e) {
- e.printStackTrace();
- }
+ m_clipboardManager.setPrimaryClip(clip);
} else {
- clip.addItem(clipData.getItemAt(0));
+ m_clipboardManager.setPrimaryClip(clipData);
+ m_usePrimaryClip = true;
}
- m_clipboardManager.setPrimaryClip(clip);
- } else {
- m_clipboardManager.setPrimaryClip(clipData);
- m_usePrimaryClip = true;
+ } catch (Exception e) {
+ Log.e(QtTAG, "Failed to set clipboard data", e);
}
}
@@ -801,22 +813,30 @@ public class QtNative
public static boolean hasClipboardHtml()
{
- if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
- ClipData primaryClip = m_clipboardManager.getPrimaryClip();
- for (int i = 0; i < primaryClip.getItemCount(); ++i)
- if (primaryClip.getItemAt(i).getHtmlText() != null)
- return true;
+ try {
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getHtmlText() != null)
+ return true;
+ }
+ } catch (Exception e) {
+ Log.e(QtTAG, "Failed to get clipboard data", e);
}
return false;
}
private static String getClipboardHtml()
{
- if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
- ClipData primaryClip = m_clipboardManager.getPrimaryClip();
- for (int i = 0; i < primaryClip.getItemCount(); ++i)
- if (primaryClip.getItemAt(i).getHtmlText() != null)
- return primaryClip.getItemAt(i).getHtmlText().toString();
+ try {
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getHtmlText() != null)
+ return primaryClip.getItemAt(i).getHtmlText().toString();
+ }
+ } catch (Exception e) {
+ Log.e(QtTAG, "Failed to get clipboard data", e);
}
return "";
}
@@ -832,11 +852,15 @@ public class QtNative
public static boolean hasClipboardUri()
{
- if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
- ClipData primaryClip = m_clipboardManager.getPrimaryClip();
- for (int i = 0; i < primaryClip.getItemCount(); ++i)
- if (primaryClip.getItemAt(i).getUri() != null)
- return true;
+ try {
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getUri() != null)
+ return true;
+ }
+ } catch (Exception e) {
+ Log.e(QtTAG, "Failed to get clipboard data", e);
}
return false;
}
@@ -844,11 +868,15 @@ public class QtNative
private static String[] getClipboardUris()
{
ArrayList<String> uris = new ArrayList<String>();
- if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
- ClipData primaryClip = m_clipboardManager.getPrimaryClip();
- for (int i = 0; i < primaryClip.getItemCount(); ++i)
- if (primaryClip.getItemAt(i).getUri() != null)
- uris.add(primaryClip.getItemAt(i).getUri().toString());
+ try {
+ if (m_clipboardManager != null && m_clipboardManager.hasPrimaryClip()) {
+ ClipData primaryClip = m_clipboardManager.getPrimaryClip();
+ for (int i = 0; i < primaryClip.getItemCount(); ++i)
+ if (primaryClip.getItemAt(i).getUri() != null)
+ uris.add(primaryClip.getItemAt(i).getUri().toString());
+ }
+ } catch (Exception e) {
+ Log.e(QtTAG, "Failed to get clipboard data", e);
}
String[] strings = new String[uris.size()];
strings = uris.toArray(strings);
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java
index fad9588425..c3074c353e 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivityLoader.java
@@ -62,7 +62,7 @@ public class QtActivityLoader extends QtLoader {
protected void downloadUpgradeMinistro(String msg) {
AlertDialog.Builder downloadDialog = new AlertDialog.Builder(m_activity);
downloadDialog.setMessage(msg);
- downloadDialog.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
+ downloadDialog.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
try {
@@ -76,7 +76,7 @@ public class QtActivityLoader extends QtLoader {
}
});
- downloadDialog.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
+ downloadDialog.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
m_activity.finish();
diff --git a/src/corelib/.prev_CMakeLists.txt b/src/corelib/.prev_CMakeLists.txt
index a6e862e1de..78b9c17b3f 100644
--- a/src/corelib/.prev_CMakeLists.txt
+++ b/src/corelib/.prev_CMakeLists.txt
@@ -385,6 +385,7 @@ qt_extend_target(Core CONDITION WIN32 AND NOT WINRT
qt_extend_target(Core CONDITION APPLE
SOURCES
global/qoperatingsystemversion_darwin.mm
+ io/qfilesystemengine_mac.mm
io/qstandardpaths_mac.mm
io/qstorageinfo_mac.cpp
kernel/qcfsocketnotifier.cpp kernel/qcfsocketnotifier_p.h
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index 64c993fe9f..45b0033abe 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -492,6 +492,7 @@ qt_extend_target(Core CONDITION WIN32 AND NOT WINRT
qt_extend_target(Core CONDITION APPLE
SOURCES
global/qoperatingsystemversion_darwin.mm
+ io/qfilesystemengine_mac.mm
io/qstandardpaths_mac.mm
io/qstorageinfo_mac.cpp
kernel/qcfsocketnotifier.cpp kernel/qcfsocketnotifier_p.h
diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake
index 2bc97c6d12..94d270b739 100644
--- a/src/corelib/Qt6CoreMacros.cmake
+++ b/src/corelib/Qt6CoreMacros.cmake
@@ -59,7 +59,14 @@ macro(qt6_make_output_file infile prefix ext outfile )
set(_outfile "${CMAKE_CURRENT_BINARY_DIR}/${rel}")
string(REPLACE ".." "__" _outfile ${_outfile})
get_filename_component(outpath ${_outfile} PATH)
- get_filename_component(_outfile ${_outfile} NAME_WE)
+ if(CMAKE_VERSION VERSION_LESS "3.14")
+ get_filename_component(_outfile_ext ${_outfile} EXT)
+ get_filename_component(_outfile_ext ${_outfile_ext} NAME_WE)
+ get_filename_component(_outfile ${_outfile} NAME_WE)
+ string(APPEND _outfile ${_outfile_ext})
+ else()
+ get_filename_component(_outfile ${_outfile} NAME_WLE)
+ endif()
file(MAKE_DIRECTORY ${outpath})
set(${outfile} ${outpath}/${prefix}${_outfile}.${ext})
endmacro()
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
index a140175956..d30ad50ffc 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -135,7 +135,7 @@ class Employee
{
public:
Employee() {}
- Employee(const QString &name, const QDate &dateOfBirth);
+ Employee(const QString &name, QDate dateOfBirth);
...
private:
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp
index 506022f082..145cd10d84 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp
@@ -151,7 +151,7 @@ class Employee
{
public:
Employee() {}
- Employee(const QString &name, const QDate &dateOfBirth);
+ Employee(const QString &name, QDate dateOfBirth);
...
private:
diff --git a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
index 84a156bb6d..879cdbe329 100644
--- a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
+++ b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
@@ -61,14 +61,13 @@ ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
QGridLayout *gridLayout = new QGridLayout;
for (int i = 0; i < texts.size(); ++i) {
QPushButton *button = new QPushButton(texts[i]);
- connect(button, &QPushButton::clicked,
- signalMapper, &QSignalMapper::map);
+ connect(button, &QPushButton::clicked, signalMapper, &QSignalMapper::map);
//! [0] //! [1]
signalMapper->setMapping(button, texts[i]);
gridLayout->addWidget(button, i / 3, i % 3);
}
- connect(signalMapper, QOverload<const QString &>::of(&QSignalMapper::mapped),
+ connect(signalMapper, &QSignalMapper::mappedString,
//! [1] //! [2]
this, &ButtonWidget::clicked);
diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp
index 51766c9760..80a851e4e4 100644
--- a/src/corelib/global/qfloat16.cpp
+++ b/src/corelib/global/qfloat16.cpp
@@ -213,7 +213,7 @@ f16cextern void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype
#undef f16cextern
}
-#elif defined(__ARM_FP16_FORMAT_IEEE) && defined(__ARM_NEON__)
+#elif defined(__ARM_FP16_FORMAT_IEEE) && defined(__ARM_NEON__) && (__ARM_FP & 2)
static inline bool hasFastF16()
{
return true;
diff --git a/src/corelib/global/qfloat16tables.cpp b/src/corelib/global/qfloat16tables.cpp
index 3d764937d7..b87986d6b8 100644
--- a/src/corelib/global/qfloat16tables.cpp
+++ b/src/corelib/global/qfloat16tables.cpp
@@ -44,7 +44,7 @@
QT_BEGIN_NAMESPACE
-#if !defined(__F16C__) && !defined(__ARM_FP16_FORMAT_IEEE)
+#if !defined(__ARM_FP16_FORMAT_IEEE)
const quint32 qfloat16::mantissatable[2048] = {
0,
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index ca4d8dbd11..123cc88ad6 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -1669,14 +1669,34 @@ static bool android_default_message_handler(QtMsgType type,
#endif //Q_OS_ANDROID
#ifdef Q_OS_WIN
+static void win_outputDebugString_helper(QStringView message)
+{
+ const int maxOutputStringLength = 32766;
+ static QBasicMutex m;
+ auto locker = qt_unique_lock(m);
+ // fast path: Avoid string copies if one output is enough
+ if (message.length() <= maxOutputStringLength) {
+ OutputDebugString(reinterpret_cast<const wchar_t *>(message.utf16()));
+ } else {
+ wchar_t *messagePart = new wchar_t[maxOutputStringLength + 1];
+ for (int i = 0; i < message.length(); i += maxOutputStringLength ) {
+ const int length = std::min(message.length() - i, maxOutputStringLength );
+ const int len = message.mid(i, length).toWCharArray(messagePart);
+ Q_ASSERT(len == length);
+ messagePart[len] = 0;
+ OutputDebugString(messagePart);
+ }
+ delete[] messagePart;
+ }
+}
+
static bool win_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &message)
{
if (shouldLogToStderr())
return false; // Leave logging up to stderr handler
- QString formattedMessage = qFormatLogMessage(type, context, message);
- formattedMessage.append(QLatin1Char('\n'));
- OutputDebugString(reinterpret_cast<const wchar_t *>(formattedMessage.utf16()));
+ const QString formattedMessage = qFormatLogMessage(type, context, message).append('\n');
+ win_outputDebugString_helper(formattedMessage);
return true; // Prevent further output to stderr
}
@@ -1832,11 +1852,11 @@ static void qt_message_print(QtMsgType msgType, const QMessageLogContext &contex
static void qt_message_print(const QString &message)
{
#if defined(Q_OS_WINRT)
- OutputDebugString(reinterpret_cast<const wchar_t*>(message.utf16()));
+ win_outputDebugString_helper(message);
return;
#elif defined(Q_OS_WIN) && !defined(QT_BOOTSTRAPPED)
if (!shouldLogToStderr()) {
- OutputDebugString(reinterpret_cast<const wchar_t*>(message.utf16()));
+ win_outputDebugString_helper(message);
return;
}
#endif
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index f278850ccf..57ccd308d7 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -1249,14 +1249,16 @@ namespace Qt {
enum DateFormat {
TextDate, // default Qt
ISODate, // ISO 8601
- SystemLocaleDate, // deprecated
- LocalDate = SystemLocaleDate, // deprecated
- LocaleDate, // deprecated
- SystemLocaleShortDate,
- SystemLocaleLongDate,
- DefaultLocaleShortDate,
- DefaultLocaleLongDate,
- RFC2822Date, // RFC 2822 (+ 850 and 1036 during parsing)
+#if QT_DEPRECATED_SINCE(5, 15)
+ SystemLocaleDate Q_DECL_ENUMERATOR_DEPRECATED_X("Use QLocale"),
+ LocalDate Q_DECL_ENUMERATOR_DEPRECATED_X("Use QLocale") = 2, // i.e. SystemLocaleDate
+ LocaleDate Q_DECL_ENUMERATOR_DEPRECATED_X("Use QLocale"),
+ SystemLocaleShortDate Q_DECL_ENUMERATOR_DEPRECATED_X("Use QLocale"),
+ SystemLocaleLongDate Q_DECL_ENUMERATOR_DEPRECATED_X("Use QLocale"),
+ DefaultLocaleShortDate Q_DECL_ENUMERATOR_DEPRECATED_X("Use QLocale"),
+ DefaultLocaleLongDate Q_DECL_ENUMERATOR_DEPRECATED_X("Use QLocale"),
+#endif
+ RFC2822Date = 8, // RFC 2822 (+ 850 and 1036 during parsing)
ISODateWithMs
};
@@ -1750,7 +1752,7 @@ namespace Qt {
};
// QTBUG-48701
- enum ReturnByValue_t { ReturnByValue }; // ### Qt 7: Remove me
+ enum ReturnByValueConstant { ReturnByValue }; // ### Qt 7: Remove me
#ifndef Q_QDOC
// NOTE: Generally, do not add Q_ENUM_NS if a corresponding Q_FLAG_NS exists.
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index 9acb978efc..708ecb11ab 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -709,26 +709,38 @@
\value ISODateWithMs \l{ISO 8601} extended format, including milliseconds if applicable.
- \value SystemLocaleShortDate The \l{QLocale::ShortFormat}{short format} used
- by the \l{QLocale::system()}{operating system}.
+ \value SystemLocaleShortDate \e{This enum value is deprecated and
+ shall be removed in Qt 6.} Use QLocale's methods for converting
+ dates and times to and from strings, with the
+ \l{QLocale::ShortFormat}{short format} of
+ \l{QLocale::system()}{the locale used by the operating system}.
- \value SystemLocaleLongDate The \l{QLocale::LongFormat}{long format} used
- by the \l{QLocale::system()}{operating system}.
+ \value SystemLocaleLongDate \e{This enum value is deprecated and
+ shall be removed in Qt 6.} Use QLocale's methods for converting
+ dates and times to and from strings, with the
+ \l{QLocale::LongFormat}{long format} of \l{QLocale::system()}{the
+ locale used by the operating system}.
- \value DefaultLocaleShortDate The \l{QLocale::ShortFormat}{short format} specified
- by the \l{QLocale::setDefault()}{application's locale}.
+ \value DefaultLocaleShortDate \e{This enum value is deprecated and
+ shall be removed in Qt 6.} Use QLocale's methods for converting
+ dates and times to and from strings, with the
+ \l{QLocale::ShortFormat}{short format} of
+ \l{QLocale::setDefault()}{the application's locale}.
- \value DefaultLocaleLongDate The \l{QLocale::LongFormat}{long format} used
- by the \l{QLocale::setDefault()}{application's locale}.
+ \value DefaultLocaleLongDate \e{This enum value is deprecated and
+ shall be removed in Qt 6.} Use QLocale's methods for converting
+ dates and times to and from strings, with the
+ \l{QLocale::LongFormat}{long format} \l{QLocale::setDefault()}{the
+ application's locale}.
- \value SystemLocaleDate \e{This enum value is deprecated.} Use Qt::SystemLocaleShortDate
- instead (or Qt::SystemLocaleLongDate if you want long dates).
+ \value SystemLocaleDate \e{This enum value is deprecated and shall
+ be removed in Qt 6.} It is equivalent to SystemLocaleShortDate.
- \value LocaleDate \e{This enum value is deprecated.} Use Qt::DefaultLocaleShortDate
- instead (or Qt::DefaultLocaleLongDate if you want long dates).
+ \value LocaleDate \e{This enum value is deprecated and shall be
+ removed in Qt 6.} It is equivalent to DefaultLocaleShortDate.
- \value LocalDate \e{This enum value is deprecated.} Use Qt::SystemLocaleShortDate
- instead (or Qt::SystemLocaleLongDate if you want long dates).
+ \value LocalDate \e{This enum value is deprecated and shall be
+ removed in Qt 6.} It is equivalent to SystemLocaleShortDate.
\value RFC2822Date \l{RFC 2822}, \l{RFC 850} and \l{RFC 1036} format:
either \c{[ddd,] dd MMM yyyy [hh:mm[:ss]][ ±tzoff]}
@@ -1187,6 +1199,7 @@
\value WA_StyleSheetTarget Indicates that the widget appearance was modified
by a \l{Qt Style Sheets}{style sheet}. WA_StyleSheet will also be set.
+ This value was introduced in Qt 5.12.
\value WA_TabletTracking Indicates that the widget has tablet
tracking enabled. See QWidget::tabletTracking.
@@ -3321,7 +3334,7 @@
*/
/*!
- \enum Qt::ReturnByValue_t
+ \enum Qt::ReturnByValueConstant
\since 5.15
This is a dummy type, designed to help users transition from certain deprecated APIs to their replacement APIs.
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index c4c6f41387..a33ffe75f2 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -183,7 +183,9 @@ win32 {
SOURCES += io/qstorageinfo_mac.cpp
qtConfig(processenvironment): \
OBJECTIVE_SOURCES += io/qprocess_darwin.mm
- OBJECTIVE_SOURCES += io/qstandardpaths_mac.mm
+ OBJECTIVE_SOURCES += \
+ io/qstandardpaths_mac.mm \
+ io/qfilesystemengine_mac.mm
osx {
LIBS += -framework DiskArbitration -framework IOKit
} else {
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 5320ae2986..0cdc5bd6d3 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -552,6 +552,66 @@ QFile::remove(const QString &fileName)
}
/*!
+ \since 5.15
+
+ Moves the file specified by fileName() to the trash. Returns \c true if successful,
+ and sets the fileName() to the path at which the file can be found within the trash;
+ otherwise returns \c false.
+
+ \note On systems where the system API doesn't report the location of the file in the
+ trash, fileName() will be set to the null string once the file has been moved. On
+ systems that don't have a trash can, this function always returns false.
+*/
+bool
+QFile::moveToTrash()
+{
+ Q_D(QFile);
+ if (d->fileName.isEmpty() &&
+ !static_cast<QFSFileEngine *>(d->engine())->isUnnamedFile()) {
+ qWarning("QFile::remove: Empty or null file name");
+ return false;
+ }
+ unsetError();
+ close();
+ if (error() == QFile::NoError) {
+ QFileSystemEntry fileEntry(d->fileName);
+ QFileSystemEntry trashEntry;
+ QSystemError error;
+ if (QFileSystemEngine::moveFileToTrash(fileEntry, trashEntry, error)) {
+ setFileName(trashEntry.filePath());
+ unsetError();
+ return true;
+ }
+ d->setError(QFile::RenameError, error.toString());
+ }
+ return false;
+}
+
+/*!
+ \since 5.15
+ \overload
+
+ Moves the file specified by fileName() to the trash. Returns \c true if successful,
+ and sets \a pathInTrash (if provided) to the path at which the file can be found within
+ the trash; otherwise returns \c false.
+
+ \note On systems where the system API doesn't report the path of the file in the
+ trash, \a pathInTrash will be set to the null string once the file has been moved.
+ On systems that don't have a trash can, this function always returns false.
+*/
+bool
+QFile::moveToTrash(const QString &fileName, QString *pathInTrash)
+{
+ QFile file(fileName);
+ if (file.moveToTrash()) {
+ if (pathInTrash)
+ *pathInTrash = file.fileName();
+ return true;
+ }
+ return false;
+}
+
+/*!
Renames the file currently specified by fileName() to \a newName.
Returns \c true if successful; otherwise returns \c false.
diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h
index 2099b2852f..917fec4e1a 100644
--- a/src/corelib/io/qfile.h
+++ b/src/corelib/io/qfile.h
@@ -125,6 +125,9 @@ public:
bool remove();
static bool remove(const QString &fileName);
+ bool moveToTrash();
+ static bool moveToTrash(const QString &fileName, QString *pathInTrash = nullptr);
+
bool rename(const QString &newName);
static bool rename(const QString &oldName, const QString &newName);
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index 3fe1aec41f..64b1557231 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -1147,6 +1147,8 @@ bool QFileInfo::isShortcut() const
/*!
+ \since 5.15
+
Returns \c true if the object points to a junction;
otherwise returns \c false.
diff --git a/src/corelib/io/qfilesystemengine_mac.mm b/src/corelib/io/qfilesystemengine_mac.mm
new file mode 100644
index 0000000000..258ae2e8e0
--- /dev/null
+++ b/src/corelib/io/qfilesystemengine_mac.mm
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qfilesystemengine_p.h"
+#include "qfile.h"
+#include "qurl.h"
+
+#include <QtCore/private/qcore_mac_p.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ This implementation does not enable the "put back" option in Finder
+ for the trashed object. The only way to get this is to use Finder automation,
+ which would query the user for permission to access Finder using a modal,
+ blocking dialog - which we definitely can't have in a console application.
+
+ Using Finder would also play the trash sound, which we don't want either in
+ such a core API; applications that want that can play the sound themselves.
+*/
+//static
+bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source,
+ QFileSystemEntry &newLocation, QSystemError &error)
+{
+#ifdef Q_OS_MACOS // desktop macOS has a trash can
+ QMacAutoReleasePool pool;
+
+ QFileInfo info(source.filePath());
+ NSString *filepath = info.filePath().toNSString();
+ NSURL *fileurl = [NSURL fileURLWithPath:filepath isDirectory:info.isDir()];
+ NSURL *resultingUrl = nil;
+ NSError *nserror = nil;
+ NSFileManager *fm = [NSFileManager defaultManager];
+ if ([fm trashItemAtURL:fileurl resultingItemURL:&resultingUrl error:&nserror] != YES) {
+ error = QSystemError(nserror.code, QSystemError::NativeError);
+ return false;
+ }
+ newLocation = QFileSystemEntry(QUrl::fromNSURL(resultingUrl).path());
+ return true;
+#else // watch, tv, iOS don't have a trash can
+ return false;
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h
index ecfdc03743..555483a972 100644
--- a/src/corelib/io/qfilesystemengine_p.h
+++ b/src/corelib/io/qfilesystemengine_p.h
@@ -88,7 +88,7 @@ inline bool qIsFilenameBroken(const QFileSystemEntry &entry)
Q_RETURN_ON_INVALID_FILENAME("Broken filename passed to function", (result)); \
} while (false)
-class QFileSystemEngine
+class Q_AUTOTEST_EXPORT QFileSystemEngine
{
public:
static bool isCaseSensitive()
@@ -155,6 +155,7 @@ public:
static bool createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
static bool copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
+ static bool moveFileToTrash(const QFileSystemEntry &source, QFileSystemEntry &newLocation, QSystemError &error);
static bool renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
static bool renameOverwriteFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
static bool removeFile(const QFileSystemEntry &entry, QSystemError &error);
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 3bbebc7fe9..eaf4e2d9af 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -42,6 +42,8 @@
#include "qplatformdefs.h"
#include "qfilesystemengine_p.h"
#include "qfile.h"
+#include "qstorageinfo.h"
+#include "qtextstream.h"
#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/private/qcore_unix_p.h>
@@ -1197,6 +1199,216 @@ bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSy
return false;
}
+#ifndef Q_OS_DARWIN
+/*
+ Implementing as per https://specifications.freedesktop.org/trash-spec/trashspec-1.0.html
+*/
+
+// bootstrapped tools don't need this, and we don't want QStorageInfo
+#ifndef QT_BOOTSTRAPPED
+static QString freeDesktopTrashLocation(const QString &sourcePath)
+{
+ auto makeTrashDir = [](const QDir &topDir, const QString &trashDir) -> QString {
+ auto ownerPerms = QFileDevice::ReadOwner
+ | QFileDevice::WriteOwner
+ | QFileDevice::ExeOwner;
+ QString targetDir = topDir.filePath(trashDir);
+ if (topDir.mkdir(trashDir))
+ QFile::setPermissions(targetDir, ownerPerms);
+ if (QFileInfo(targetDir).isDir())
+ return targetDir;
+ return QString();
+ };
+ auto isSticky = [](const QFileInfo &fileInfo) -> bool {
+ struct stat st;
+ if (stat(QFile::encodeName(fileInfo.absoluteFilePath()).constData(), &st) == 0)
+ return st.st_mode & S_ISVTX;
+
+ return false;
+ };
+
+ QString trash;
+ const QLatin1String dotTrash(".Trash");
+ const QStorageInfo sourceStorage(sourcePath);
+ const QStorageInfo homeStorage(QDir::home());
+ // We support trashing of files outside the users home partition
+ if (sourceStorage != homeStorage) {
+ QDir topDir(sourceStorage.rootPath());
+ /*
+ Method 1:
+ "An administrator can create an $topdir/.Trash directory. The permissions on this
+ directories should permit all users who can trash files at all to write in it;
+ and the “sticky bit” in the permissions must be set, if the file system supports
+ it.
+ When trashing a file from a non-home partition/device, an implementation
+ (if it supports trashing in top directories) MUST check for the presence
+ of $topdir/.Trash."
+ */
+ const QString userID = QString::number(::getuid());
+ if (topDir.cd(dotTrash)) {
+ const QFileInfo trashInfo(topDir.path());
+
+ // we MUST check that the sticky bit is set, and that it is not a symlink
+ if (trashInfo.isSymLink()) {
+ // we SHOULD report the failed check to the administrator
+ qCritical("Warning: '%s' is a symlink to '%s'",
+ trashInfo.absoluteFilePath().toLocal8Bit().constData(),
+ trashInfo.symLinkTarget().toLatin1().constData());
+ } else if (!isSticky(trashInfo)) {
+ // we SHOULD report the failed check to the administrator
+ qCritical("Warning: '%s' doesn't have sticky bit set!",
+ trashInfo.absoluteFilePath().toLocal8Bit().constData());
+ } else if (trashInfo.isDir()) {
+ /*
+ "If the directory exists and passes the checks, a subdirectory of the
+ $topdir/.Trash directory is to be used as the user's trash directory
+ for this partition/device. The name of this subdirectory is the numeric
+ identifier of the current user ($topdir/.Trash/$uid).
+ When trashing a file, if this directory does not exist for the current user,
+ the implementation MUST immediately create it, without any warnings or
+ delays for the user."
+ */
+ trash = makeTrashDir(topDir, userID);
+ }
+ }
+ /*
+ Method 2:
+ "If an $topdir/.Trash directory is absent, an $topdir/.Trash-$uid directory is to be
+ used as the user's trash directory for this device/partition. [...] When trashing a
+ file, if an $topdir/.Trash-$uid directory does not exist, the implementation MUST
+ immediately create it, without any warnings or delays for the user."
+ */
+ if (trash.isEmpty()) {
+ topDir = QDir(sourceStorage.rootPath());
+ const QString userTrashDir = dotTrash + QLatin1Char('-') + userID;
+ trash = makeTrashDir(topDir, userTrashDir);
+ }
+ }
+ /*
+ "If both (1) and (2) fail [...], the implementation MUST either trash the
+ file into the user's “home trash” or refuse to trash it."
+
+ We trash the file into the user's home trash.
+ */
+ if (trash.isEmpty()) {
+ QDir topDir = QDir::home();
+ trash = makeTrashDir(topDir, dotTrash);
+ if (!QFileInfo(trash).isDir()) {
+ qWarning("Unable to establish trash directory %s in %s",
+ dotTrash.latin1(), topDir.path().toLocal8Bit().constData());
+ }
+ }
+
+ return trash;
+}
+#endif // QT_BOOTSTRAPPED
+
+//static
+bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source,
+ QFileSystemEntry &newLocation, QSystemError &error)
+{
+#ifdef QT_BOOTSTRAPPED
+ Q_UNUSED(source);
+ Q_UNUSED(newLocation);
+ error = QSystemError(ENOSYS, QSystemError::StandardLibraryError);
+ return false;
+#else
+ const QFileInfo sourceInfo(source.filePath());
+ if (!sourceInfo.exists()) {
+ error = QSystemError(ENOENT, QSystemError::StandardLibraryError);
+ return false;
+ }
+ const QString sourcePath = sourceInfo.absoluteFilePath();
+
+ QDir trashDir(freeDesktopTrashLocation(sourcePath));
+ if (!trashDir.exists())
+ return false;
+ /*
+ "A trash directory contains two subdirectories, named info and files."
+ */
+ const QLatin1String filesDir("files");
+ const QLatin1String infoDir("info");
+ trashDir.mkdir(filesDir);
+ int savedErrno = errno;
+ trashDir.mkdir(infoDir);
+ if (!savedErrno)
+ savedErrno = errno;
+ if (!trashDir.exists(filesDir) || !trashDir.exists(infoDir)) {
+ error = QSystemError(savedErrno, QSystemError::StandardLibraryError);
+ return false;
+ }
+ /*
+ "The $trash/files directory contains the files and directories that were trashed.
+ The names of files in this directory are to be determined by the implementation;
+ the only limitation is that they must be unique within the directory. Even if a
+ file with the same name and location gets trashed many times, each subsequent
+ trashing must not overwrite a previous copy."
+ */
+ const QString trashedName = sourceInfo.isDir()
+ ? QDir(sourcePath).dirName()
+ : sourceInfo.fileName();
+ QString uniqueTrashedName = QLatin1Char('/') + trashedName;
+ QString infoFileName;
+ int counter = 0;
+ QFile infoFile;
+ auto makeUniqueTrashedName = [trashedName, &counter]() -> QString {
+ ++counter;
+ return QString(QLatin1String("/%1-%2"))
+ .arg(trashedName)
+ .arg(counter, 4, 10, QLatin1Char('0'));
+ };
+ do {
+ while (QFile::exists(trashDir.filePath(filesDir) + uniqueTrashedName))
+ uniqueTrashedName = makeUniqueTrashedName();
+ /*
+ "The $trash/info directory contains an "information file" for every file and directory
+ in $trash/files. This file MUST have exactly the same name as the file or directory in
+ $trash/files, plus the extension ".trashinfo"
+ [...]
+ When trashing a file or directory, the implementation MUST create the corresponding
+ file in $trash/info first. Moreover, it MUST try to do this in an atomic fashion,
+ so that if two processes try to trash files with the same filename this will result
+ in two different trash files. On Unix-like systems this is done by generating a
+ filename, and then opening with O_EXCL. If that succeeds the creation was atomic
+ (at least on the same machine), if it fails you need to pick another filename."
+ */
+ infoFileName = trashDir.filePath(infoDir)
+ + uniqueTrashedName + QLatin1String(".trashinfo");
+ infoFile.setFileName(infoFileName);
+ if (!infoFile.open(QIODevice::NewOnly | QIODevice::WriteOnly | QIODevice::Text))
+ uniqueTrashedName = makeUniqueTrashedName();
+ } while (!infoFile.isOpen());
+
+ const QString targetPath = trashDir.filePath(filesDir) + uniqueTrashedName;
+ const QFileSystemEntry target(targetPath);
+
+ /*
+ We might fail to rename if source and target are on different file systems.
+ In that case, we don't try further, i.e. copying and removing the original
+ is usually not what the user would expect to happen.
+ */
+ if (!renameFile(source, target, error)) {
+ infoFile.close();
+ infoFile.remove();
+ return false;
+ }
+
+ QTextStream out(&infoFile);
+#if QT_CONFIG(textcodec)
+ out.setCodec("UTF-8");
+#endif
+ out << "[Trash Info]" << Qt::endl;
+ out << "Path=" << sourcePath << Qt::endl;
+ out << "DeletionDate="
+ << QDateTime::currentDateTime().toString(QLatin1String("yyyy-MM-ddThh:mm:ss")) << Qt::endl;
+ infoFile.close();
+
+ newLocation = QFileSystemEntry(targetPath);
+ return true;
+#endif // QT_BOOTSTRAPPED
+}
+#endif // Q_OS_DARWIN
+
//static
bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index 0579872f8d..36d43e9cb7 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -41,6 +41,7 @@
#include "qoperatingsystemversion.h"
#include "qplatformdefs.h"
#include "qsysinfo.h"
+#include "qscopeguard.h"
#include "private/qabstractfileengine_p.h"
#include "private/qfsfileengine_p.h"
#include <private/qsystemlibrary_p.h>
@@ -59,6 +60,8 @@
#include <objbase.h>
#ifndef Q_OS_WINRT
# include <shlobj.h>
+# include <shobjidl.h>
+# include <shellapi.h>
# include <lm.h>
# include <accctrl.h>
#endif
@@ -422,6 +425,104 @@ static inline bool getFindData(QString path, WIN32_FIND_DATA &findData)
return false;
}
+#if defined(__IFileOperation_INTERFACE_DEFINED__)
+class FileOperationProgressSink : public IFileOperationProgressSink
+{
+public:
+ FileOperationProgressSink()
+ : ref(1)
+ {}
+ virtual ~FileOperationProgressSink() {}
+
+ ULONG STDMETHODCALLTYPE AddRef()
+ {
+ return ++ref;
+ }
+ ULONG STDMETHODCALLTYPE Release()
+ {
+ if (--ref == 0) {
+ delete this;
+ return 0;
+ }
+ return ref;
+ }
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject)
+ {
+ if (!ppvObject)
+ return E_POINTER;
+
+ *ppvObject = nullptr;
+
+ if (iid == __uuidof(IUnknown)) {
+ *ppvObject = static_cast<IUnknown*>(this);
+ } else if (iid == __uuidof(IFileOperationProgressSink)) {
+ *ppvObject = static_cast<IFileOperationProgressSink*>(this);
+ }
+
+ if (*ppvObject) {
+ AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+ }
+
+ HRESULT STDMETHODCALLTYPE StartOperations()
+ { return S_OK; }
+ HRESULT STDMETHODCALLTYPE FinishOperations(HRESULT)
+ { return S_OK; }
+ HRESULT STDMETHODCALLTYPE PreRenameItem(DWORD, IShellItem *, LPCWSTR)
+ { return S_OK; }
+ HRESULT STDMETHODCALLTYPE PostRenameItem(DWORD, IShellItem *, LPCWSTR, HRESULT, IShellItem *)
+ { return S_OK; }
+ HRESULT STDMETHODCALLTYPE PreMoveItem(DWORD, IShellItem *, IShellItem *, LPCWSTR)
+ { return S_OK; }
+ HRESULT STDMETHODCALLTYPE PostMoveItem(DWORD, IShellItem *, IShellItem *, LPCWSTR, HRESULT,
+ IShellItem *)
+ { return S_OK; }
+ HRESULT STDMETHODCALLTYPE PreCopyItem(DWORD, IShellItem *, IShellItem *, LPCWSTR )
+ { return S_OK; }
+ HRESULT STDMETHODCALLTYPE PostCopyItem(DWORD, IShellItem *, IShellItem *, LPCWSTR, HRESULT,
+ IShellItem *)
+ { return S_OK; }
+ HRESULT STDMETHODCALLTYPE PreDeleteItem(DWORD dwFlags, IShellItem *)
+ {
+ // stop the operation if the file will be deleted rather than trashed
+ return (dwFlags & TSF_DELETE_RECYCLE_IF_POSSIBLE) ? S_OK : E_FAIL;
+ }
+ HRESULT STDMETHODCALLTYPE PostDeleteItem(DWORD /* dwFlags */, IShellItem * /* psiItem */,
+ HRESULT /* hrDelete */, IShellItem *psiNewlyCreated)
+ {
+ if (psiNewlyCreated) {
+ wchar_t *pszName = nullptr;
+ psiNewlyCreated->GetDisplayName(SIGDN_FILESYSPATH, &pszName);
+ if (pszName) {
+ targetPath = QString::fromWCharArray(pszName);
+ CoTaskMemFree(pszName);
+ }
+ }
+ return S_OK;
+ }
+ HRESULT STDMETHODCALLTYPE PreNewItem(DWORD, IShellItem *, LPCWSTR)
+ { return S_OK; }
+ HRESULT STDMETHODCALLTYPE PostNewItem(DWORD, IShellItem *, LPCWSTR, LPCWSTR, DWORD, HRESULT,
+ IShellItem *)
+ { return S_OK; }
+ HRESULT STDMETHODCALLTYPE UpdateProgress(UINT,UINT)
+ { return S_OK; }
+ HRESULT STDMETHODCALLTYPE ResetTimer()
+ { return S_OK; }
+ HRESULT STDMETHODCALLTYPE PauseTimer()
+ { return S_OK; }
+ HRESULT STDMETHODCALLTYPE ResumeTimer()
+ { return S_OK; }
+
+ QString targetPath;
+private:
+ ULONG ref;
+};
+#endif
+
bool QFileSystemEngine::uncListSharesOnServer(const QString &server, QStringList *list)
{
DWORD res = ERROR_NOT_SUPPORTED;
@@ -1431,6 +1532,103 @@ bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &
return ret;
}
+/*
+ If possible, we use the IFileOperation implementation, which allows us to determine
+ the location of the object in the trash.
+ If not (likely on mingw), we fall back to the old API, which won't allow us to know
+ that.
+*/
+//static
+bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source,
+ QFileSystemEntry &newLocation, QSystemError &error)
+{
+#ifndef Q_OS_WINRT
+ // we need the "display name" of the file, so can't use nativeFilePath
+ const QString sourcePath = QDir::toNativeSeparators(source.filePath());
+
+ /*
+ Windows 7 insists on showing confirmation dialogs and ignores the respective
+ flags set on IFileOperation. Fall back to SHFileOperation, even if it doesn't
+ give us the new location of the file.
+ */
+ if (QOperatingSystemVersion::current() > QOperatingSystemVersion::Windows7) {
+# if defined(__IFileOperation_INTERFACE_DEFINED__)
+ CoInitialize(NULL);
+ IFileOperation *pfo = nullptr;
+ IShellItem *deleteItem = nullptr;
+ FileOperationProgressSink *sink = nullptr;
+ HRESULT hres = E_FAIL;
+
+ auto coUninitialize = qScopeGuard([&](){
+ if (sink)
+ sink->Release();
+ if (deleteItem)
+ deleteItem->Release();
+ if (pfo)
+ pfo->Release();
+ CoUninitialize();
+ if (!SUCCEEDED(hres))
+ error = QSystemError(hres, QSystemError::NativeError);
+ });
+
+ hres = CoCreateInstance(CLSID_FileOperation, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&pfo));
+ if (!pfo)
+ return false;
+ pfo->SetOperationFlags(FOF_ALLOWUNDO | FOFX_RECYCLEONDELETE | FOF_NOCONFIRMATION
+ | FOF_SILENT | FOF_NOERRORUI);
+ hres = SHCreateItemFromParsingName(reinterpret_cast<const wchar_t*>(sourcePath.utf16()),
+ nullptr, IID_PPV_ARGS(&deleteItem));
+ if (!deleteItem)
+ return false;
+ sink = new FileOperationProgressSink;
+ hres = pfo->DeleteItem(deleteItem, static_cast<IFileOperationProgressSink*>(sink));
+ if (!SUCCEEDED(hres))
+ return false;
+ hres = pfo->PerformOperations();
+ if (!SUCCEEDED(hres))
+ return false;
+ newLocation = QFileSystemEntry(sink->targetPath);
+
+# endif // no IFileOperation in SDK (mingw, likely) - fall back to SHFileOperation
+ } else {
+ // double null termination needed, so can't use QString::utf16
+ QVarLengthArray<wchar_t, MAX_PATH + 1> winFile(sourcePath.length() + 2);
+ sourcePath.toWCharArray(winFile.data());
+ winFile[sourcePath.length()] = wchar_t{};
+ winFile[sourcePath.length() + 1] = wchar_t{};
+
+ SHFILEOPSTRUCTW operation;
+ operation.hwnd = nullptr;
+ operation.wFunc = FO_DELETE;
+ operation.pFrom = winFile.constData();
+ operation.pTo = nullptr;
+ operation.fFlags = FOF_ALLOWUNDO | FOF_NO_UI;
+ operation.fAnyOperationsAborted = FALSE;
+ operation.hNameMappings = nullptr;
+ operation.lpszProgressTitle = nullptr;
+
+ int result = SHFileOperation(&operation);
+ if (result != 0) {
+ error = QSystemError(result, QSystemError::NativeError);
+ return false;
+ }
+ /*
+ This implementation doesn't let us know where the file ended up, even if
+ we would specify FOF_WANTMAPPINGHANDLE | FOF_RENAMEONCOLLISION, as
+ FOF_RENAMEONCOLLISION has no effect unless files are moved, copied, or renamed.
+ */
+ Q_UNUSED(newLocation);
+ }
+ return true;
+
+#else // Q_OS_WINRT
+ Q_UNUSED(source);
+ Q_UNUSED(newLocation);
+ Q_UNUSED(error);
+ return false;
+#endif
+}
+
//static
bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error,
QFileSystemMetaData *data)
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index f7a86c25cd..cc1d110252 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -714,7 +714,7 @@ void QIODevicePrivate::setReadChannelCount(int count)
/*!
\since 5.7
- Returns the the index of the current write channel.
+ Returns the index of the current write channel.
\sa setCurrentWriteChannel(), writeChannelCount()
*/
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
index b2bf77c0da..ce2b7e8faa 100644
--- a/src/corelib/io/qlockfile_unix.cpp
+++ b/src/corelib/io/qlockfile_unix.cpp
@@ -58,7 +58,8 @@
#include <sys/file.h> // flock
#endif
-#if defined(Q_OS_RTEMS)
+#if defined(Q_OS_RTEMS) || defined(Q_OS_QNX)
+// flock() does not work in these OSes and produce warnings when we try to use
# undef LOCK_EX
# undef LOCK_NB
#endif
diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp
index 37b8a60c37..698c4ddf41 100644
--- a/src/corelib/io/qstorageinfo_unix.cpp
+++ b/src/corelib/io/qstorageinfo_unix.cpp
@@ -60,6 +60,7 @@
#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
# include <mntent.h>
# include <sys/statvfs.h>
+# include <sys/sysmacros.h>
#elif defined(Q_OS_SOLARIS)
# include <sys/mnttab.h>
# include <sys/statvfs.h>
@@ -152,7 +153,7 @@ private:
//(2) parent ID: the ID of the parent mount (or of self for the top of the mount tree).
// int parent_id;
//(3) major:minor: the value of st_dev for files on this filesystem (see stat(2)).
-// dev_t rdev;
+ dev_t rdev;
//(4) root: the pathname of the directory in the filesystem which forms the root of this mount.
char *subvolume;
//(5) mount point: the pathname of the mount point relative to the process's root directory.
@@ -503,8 +504,7 @@ inline bool QStorageIterator::next()
int rdevminor = qstrtoll(ptr + 1, const_cast<const char **>(&ptr), 10, &ok);
if (!ptr || !ok)
return false;
- Q_UNUSED(rdevmajor);
- Q_UNUSED(rdevminor);
+ mnt.rdev = makedev(rdevmajor, rdevminor);
if (*ptr != ' ')
return false;
@@ -566,6 +566,21 @@ inline QByteArray QStorageIterator::fileSystemType() const
inline QByteArray QStorageIterator::device() const
{
+ // check that the device exists
+ if (mnt.mnt_fsname[0] == '/' && access(mnt.mnt_fsname, F_OK) != 0) {
+ // It doesn't, so let's try to resolve the dev_t from /dev/block.
+ // Note how strlen("4294967295") == digits10 + 1, so we need to add 1
+ // for each number, plus the ':'.
+ char buf[sizeof("/dev/block/") + 2 * std::numeric_limits<unsigned>::digits10 + 3];
+ QByteArray dev(PATH_MAX, Qt::Uninitialized);
+ char *devdata = dev.data();
+
+ snprintf(buf, sizeof(buf), "/dev/block/%u:%u", major(mnt.rdev), minor(mnt.rdev));
+ if (realpath(buf, devdata)) {
+ dev.truncate(strlen(devdata));
+ return dev;
+ }
+ }
return QByteArray(mnt.mnt_fsname);
}
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index 0a5f9256eb..1beeb7b2a2 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -415,7 +415,7 @@
#include "qhash.h"
#include "qdir.h" // for QDir::fromNativeSeparators
#include "qdatastream.h"
-#if QT_CONFIG(topleveldomain)
+#if QT_CONFIG(topleveldomain) // ### Qt6: Remove section
#include "qtldurl_p.h"
#endif
#include "private/qipaddress_p.h"
@@ -3149,10 +3149,13 @@ bool QUrl::hasFragment() const
return d->hasFragment();
}
+#if QT_DEPRECATED_SINCE(5, 15)
#if QT_CONFIG(topleveldomain)
/*!
\since 4.8
+ \deprecated
+
Returns the TLD (Top-Level Domain) of the URL, (e.g. .co.uk, .net).
Note that the return value is prefixed with a '.' unless the
URL does not contain a valid TLD, in which case the function returns
@@ -3185,7 +3188,7 @@ QString QUrl::topLevelDomain(ComponentFormattingOptions options) const
return tld;
}
#endif
-
+#endif // QT_DEPRECATED_SINCE(5, 15)
/*!
Returns the result of the merge of this URL with \a relative. This
URL is used as a base to convert \a relative to an absolute URL.
diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h
index 94269e4369..eb7fb8087c 100644
--- a/src/corelib/io/qurl.h
+++ b/src/corelib/io/qurl.h
@@ -233,9 +233,11 @@ public:
void setHost(const QString &host, ParsingMode mode = DecodedMode);
QString host(ComponentFormattingOptions = FullyDecoded) const;
+#if QT_DEPRECATED_SINCE(5, 15)
#if QT_CONFIG(topleveldomain)
- QString topLevelDomain(ComponentFormattingOptions options = FullyDecoded) const;
+ QT_DEPRECATED QString topLevelDomain(ComponentFormattingOptions options = FullyDecoded) const;
#endif
+#endif // QT_DEPRECATED_SINCE(5, 15)
void setPort(int port);
int port(int defaultPort = -1) const;
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index f132cba473..a5df17e386 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -108,6 +108,9 @@ void QPersistentModelIndexData::destroy(QPersistentModelIndexData *data)
It is good practice to check that persistent model indexes are valid
before using them.
+ \note You cannot store a QStandardItemModel's QPersistentModelIndex
+ in one of the model's items.
+
\sa {Model/View Programming}, QModelIndex, QAbstractItemModel
*/
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index b1f3b74cd4..a042361686 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -247,7 +247,7 @@ AppleApplication *qt_apple_sharedApplication()
qWarning() << "accessing the shared" << [AppleApplication class]
<< "is not allowed in application extensions";
- // In practice the application is actually available, but the the App
+ // In practice the application is actually available, but the App
// review process will likely catch uses of it, so we return nil just
// in case, unless we don't care about being App Store compliant.
#if QT_CONFIG(appstore_compliant)
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 927bfb7667..b5a62d1aa0 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -988,6 +988,30 @@ enum IteratorCapability
RandomAccessCapability = 4
};
+enum ContainerCapability
+{
+ ContainerIsAppendable = 1
+};
+
+template<typename Container, typename T = void>
+struct ContainerCapabilitiesImpl
+{
+ enum {ContainerCapabilities = 0};
+ using appendFunction = void(*)(const void *container, const void *newElement);
+ static constexpr const appendFunction appendImpl = nullptr;
+};
+
+template<typename Container>
+struct ContainerCapabilitiesImpl<Container, decltype(std::declval<Container>().push_back(std::declval<typename Container::value_type>()))>
+{
+ enum {ContainerCapabilities = ContainerIsAppendable};
+
+ // The code below invokes undefined behavior if and only if the pointer passed into QSequentialIterableImpl
+ // pointed to a const object to begin with
+ static void appendImpl(const void *container, const void *value)
+ { static_cast<Container *>(const_cast<void *>(container))->push_back(*static_cast<const typename Container::value_type *>(value)); }
+};
+
template<typename T, typename Category = typename std::iterator_traits<typename T::const_iterator>::iterator_category>
struct CapabilitiesImpl;
@@ -1019,6 +1043,12 @@ template<typename T>
struct ContainerAPI<std::list<T> > : CapabilitiesImpl<std::list<T> >
{ static int size(const std::list<T> *t) { return int(t->size()); } };
+/*
+ revision 0: _iteratorCapabilities is simply a uint, where the bits at _revision were never set
+ revision 1: _iteratorCapabilties is treated as a bitfield, the remaining bits are used to introduce
+ _revision, _containerCapabilities and _unused. The latter contains 21 bits that are
+ not used yet
+*/
class QSequentialIterableImpl
{
public:
@@ -1027,19 +1057,37 @@ public:
int _metaType_id;
uint _metaType_flags;
uint _iteratorCapabilities;
+ // Iterator capabilities looks actually like
+ // uint _iteratorCapabilities:4;
+ // uint _revision:3;
+ // uint _containerCapabilities:4;
+ // uint _unused:21;*/
typedef int(*sizeFunc)(const void *p);
typedef const void * (*atFunc)(const void *p, int);
typedef void (*moveIteratorFunc)(const void *p, void **);
+ enum Position { ToBegin, ToEnd };
+ typedef void (*moveIteratorFunc2)(const void *p, void **, Position position);
typedef void (*advanceFunc)(void **p, int);
typedef VariantData (*getFunc)( void * const *p, int metaTypeId, uint flags);
typedef void (*destroyIterFunc)(void **p);
typedef bool (*equalIterFunc)(void * const *p, void * const *other);
typedef void (*copyIterFunc)(void **, void * const *);
+ typedef void(*appendFunction)(const void *container, const void *newElement);
+
+ IteratorCapability iteratorCapabilities() {return static_cast<IteratorCapability>(_iteratorCapabilities & 0xF);}
+ uint revision() {return _iteratorCapabilities >> 4 & 0x7;}
+ uint containerCapabilities() {return _iteratorCapabilities >> 7 & 0xF;}
sizeFunc _size;
atFunc _at;
- moveIteratorFunc _moveToBegin;
- moveIteratorFunc _moveToEnd;
+ union {
+ moveIteratorFunc _moveToBegin;
+ moveIteratorFunc2 _moveTo;
+ };
+ union {
+ moveIteratorFunc _moveToEnd;
+ appendFunction _append;
+ };
advanceFunc _advance;
getFunc _get;
destroyIterFunc _destroyIter;
@@ -1066,6 +1114,15 @@ public:
static void moveToEndImpl(const void *container, void **iterator)
{ IteratorOwner<typename T::const_iterator>::assign(iterator, static_cast<const T*>(container)->end()); }
+ template<class Container>
+ static void moveToImpl(const void *container, void **iterator, Position position)
+ {
+ if (position == ToBegin)
+ moveToBeginImpl<Container>(container, iterator);
+ else
+ moveToEndImpl<Container>(container, iterator);
+ }
+
template<class T>
static VariantData getImpl(void * const *iterator, int metaTypeId, uint flags)
{ return VariantData(metaTypeId, IteratorOwner<typename T::const_iterator>::getData(iterator), flags); }
@@ -1076,11 +1133,11 @@ public:
, _iterator(nullptr)
, _metaType_id(qMetaTypeId<typename T::value_type>())
, _metaType_flags(QTypeInfo<typename T::value_type>::isPointer)
- , _iteratorCapabilities(ContainerAPI<T>::IteratorCapabilities)
+ , _iteratorCapabilities(ContainerAPI<T>::IteratorCapabilities | (1 << 4) | (ContainerCapabilitiesImpl<T>::ContainerCapabilities << (4+3)))
, _size(sizeImpl<T>)
, _at(atImpl<T>)
- , _moveToBegin(moveToBeginImpl<T>)
- , _moveToEnd(moveToEndImpl<T>)
+ , _moveTo(moveToImpl<T>)
+ , _append(ContainerCapabilitiesImpl<T>::appendImpl)
, _advance(IteratorOwner<typename T::const_iterator>::advance)
, _get(getImpl<T>)
, _destroyIter(IteratorOwner<typename T::const_iterator>::destroy)
@@ -1094,7 +1151,7 @@ public:
, _iterator(nullptr)
, _metaType_id(QMetaType::UnknownType)
, _metaType_flags(0)
- , _iteratorCapabilities(0)
+ , _iteratorCapabilities(0 | (1 << 4) ) // no iterator capabilities, revision 1
, _size(nullptr)
, _at(nullptr)
, _moveToBegin(nullptr)
@@ -1107,8 +1164,18 @@ public:
{
}
- inline void moveToBegin() { _moveToBegin(_iterable, &_iterator); }
- inline void moveToEnd() { _moveToEnd(_iterable, &_iterator); }
+ inline void moveToBegin() {
+ if (revision() == 0)
+ _moveToBegin(_iterable, &_iterator);
+ else
+ _moveTo(_iterable, &_iterator, ToBegin);
+ }
+ inline void moveToEnd() {
+ if (revision() == 0)
+ _moveToEnd(_iterable, &_iterator);
+ else
+ _moveTo(_iterable, &_iterator, ToEnd);
+ }
inline bool equal(const QSequentialIterableImpl&other) const { return _equalIter(&_iterator, &other._iterator); }
inline QSequentialIterableImpl &advance(int i) {
Q_ASSERT(i > 0 || _iteratorCapabilities & BiDirectionalCapability);
@@ -1116,6 +1183,11 @@ public:
return *this;
}
+ inline void append(const void *newElement) {
+ if (containerCapabilities() & ContainerIsAppendable)
+ _append(_iterable, newElement);
+ }
+
inline VariantData getCurrent() const { return _get(&_iterator, _metaType_id, _metaType_flags); }
VariantData at(int idx) const
diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp
index fca258c9e3..c38dab3e3f 100644
--- a/src/corelib/kernel/qmimedata.cpp
+++ b/src/corelib/kernel/qmimedata.cpp
@@ -72,40 +72,44 @@ public:
QVariant retrieveTypedData(const QString &format, QMetaType::Type type) const;
- QVector<QMimeDataStruct> dataList;
+ std::vector<QMimeDataStruct>::iterator find(const QString &format) noexcept {
+ const auto formatEquals = [](const QString &format) {
+ return [&format](const QMimeDataStruct &s) { return s.format == format; };
+ };
+ return std::find_if(dataList.begin(), dataList.end(), formatEquals(format));
+ }
+
+ std::vector<QMimeDataStruct>::const_iterator find(const QString &format) const noexcept {
+ return const_cast<QMimeDataPrivate*>(this)->find(format);
+ }
+
+ std::vector<QMimeDataStruct> dataList;
};
void QMimeDataPrivate::removeData(const QString &format)
{
- for (int i=0; i<dataList.size(); i++) {
- if (dataList.at(i).format == format) {
- dataList.removeAt(i);
- return;
- }
- }
+ const auto it = find(format);
+ if (it != dataList.end())
+ dataList.erase(it);
}
void QMimeDataPrivate::setData(const QString &format, const QVariant &data)
{
- // remove it first if the format is already here.
- removeData(format);
- QMimeDataStruct mimeData;
- mimeData.format = format;
- mimeData.data = data;
- dataList += mimeData;
+ const auto it = find(format);
+ if (it == dataList.end())
+ dataList.push_back({format, data});
+ else
+ it->data = data;
}
QVariant QMimeDataPrivate::getData(const QString &format) const
{
- QVariant data;
- for (int i=0; i<dataList.size(); i++) {
- if (dataList.at(i).format == format) {
- data = dataList.at(i).data;
- break;
- }
- }
- return data;
+ const auto it = find(format);
+ if (it == dataList.cend())
+ return {};
+ else
+ return it->data;
}
QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QMetaType::Type type) const
@@ -635,10 +639,9 @@ QStringList QMimeData::formats() const
{
Q_D(const QMimeData);
QStringList list;
- const int size = d->dataList.size();
- list.reserve(size);
- for (int i = 0; i < size; ++i)
- list += d->dataList.at(i).format;
+ list.reserve(static_cast<int>(d->dataList.size()));
+ for (auto &e : d->dataList)
+ list += e.format;
return list;
}
diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp
index 24b174972f..dc0dfe8f40 100644
--- a/src/corelib/kernel/qsignalmapper.cpp
+++ b/src/corelib/kernel/qsignalmapper.cpp
@@ -53,11 +53,36 @@ public:
Q_Q(QSignalMapper);
q->removeMappings(q->sender());
}
+
+ template <class Signal, class Container>
+ void emitMappedValue(QObject *sender, Signal signal, const Container &mappedValues)
+ {
+ Q_Q(QSignalMapper);
+
+ auto it = mappedValues.find(sender);
+ if (it != mappedValues.end()) {
+#if QT_DEPRECATED_SINCE(5, 15)
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+ Q_EMIT q->mapped(*it);
+QT_WARNING_POP
+#endif
+ Q_EMIT (q->*signal)(*it);
+ }
+ }
+
+ void emitMappedValues(QObject *sender)
+ {
+ emitMappedValue(sender, &QSignalMapper::mappedInt, intHash);
+ emitMappedValue(sender, &QSignalMapper::mappedString, stringHash);
+ emitMappedValue(sender, &QSignalMapper::mappedWidget, widgetHash);
+ emitMappedValue(sender, &QSignalMapper::mappedObject, objectHash);
+ }
+
QHash<QObject *, int> intHash;
QHash<QObject *, QString> stringHash;
QHash<QObject *, QWidget*> widgetHash;
QHash<QObject *, QObject*> objectHash;
-
};
/*!
@@ -74,11 +99,12 @@ public:
use lambdas for passing custom parameters to slots. This is less
costly and will simplify the code.
- The class supports the mapping of particular strings or integers
- with particular objects using setMapping(). The objects' signals
- can then be connected to the map() slot which will emit the
- mapped() signal with the string or integer associated with the
- original signalling object. Mappings can be removed later using
+ The class supports the mapping of particular strings, integers,
+ objects and widgets with particular objects using setMapping().
+ The objects' signals can then be connected to the map() slot which
+ will emit a signal (it could be mappedInt(), mappedString(),
+ mappedWidget() and mappedObject()) with a value associated with
+ the original signalling object. Mappings can be removed later using
removeMappings().
Example: Suppose we want to create a custom widget that contains
@@ -106,8 +132,8 @@ public:
created. We connect each button's \c clicked() signal to the
signal mapper's map() slot, and create a mapping in the signal
mapper from each button to the button's text. Finally we connect
- the signal mapper's mapped() signal to the custom widget's \c
- clicked() signal. When the user clicks a button, the custom
+ the signal mapper's mappedString() signal to the custom widget's
+ \c clicked() signal. When the user clicks a button, the custom
widget will emit a single \c clicked() signal whose argument is
the text of the button the user clicked.
@@ -137,7 +163,7 @@ QSignalMapper::~QSignalMapper()
/*!
Adds a mapping so that when map() is signalled from the given \a
- sender, the signal mapped(\a id) is emitted.
+ sender, the signal mappedInt(\a id) is emitted.
There may be at most one integer ID for each sender.
@@ -152,7 +178,7 @@ void QSignalMapper::setMapping(QObject *sender, int id)
/*!
Adds a mapping so that when map() is signalled from the \a sender,
- the signal mapped(\a text ) is emitted.
+ the signal mappedString(\a text ) is emitted.
There may be at most one text for each sender.
*/
@@ -165,7 +191,7 @@ void QSignalMapper::setMapping(QObject *sender, const QString &text)
/*!
Adds a mapping so that when map() is signalled from the \a sender,
- the signal mapped(\a widget ) is emitted.
+ the signal mappedWidget(\a widget ) is emitted.
There may be at most one widget for each sender.
*/
@@ -178,7 +204,7 @@ void QSignalMapper::setMapping(QObject *sender, QWidget *widget)
/*!
Adds a mapping so that when map() is signalled from the \a sender,
- the signal mapped(\a object ) is emitted.
+ the signal mappedObject(\a object ) is emitted.
There may be at most one object for each sender.
*/
@@ -259,20 +285,14 @@ void QSignalMapper::map() { map(sender()); }
*/
void QSignalMapper::map(QObject *sender)
{
- Q_D(QSignalMapper);
- if (d->intHash.contains(sender))
- emit mapped(d->intHash.value(sender));
- if (d->stringHash.contains(sender))
- emit mapped(d->stringHash.value(sender));
- if (d->widgetHash.contains(sender))
- emit mapped(d->widgetHash.value(sender));
- if (d->objectHash.contains(sender))
- emit mapped(d->objectHash.value(sender));
+ d_func()->emitMappedValues(sender);
}
-
+#if QT_DEPRECATED_SINCE(5, 15)
/*!
\fn void QSignalMapper::mapped(int i)
+ \obsolete
+ \overload
This signal is emitted when map() is signalled from an object that
has an integer mapping set. The object's mapped integer is passed
@@ -283,6 +303,8 @@ void QSignalMapper::map(QObject *sender)
/*!
\fn void QSignalMapper::mapped(const QString &text)
+ \obsolete
+ \overload
This signal is emitted when map() is signalled from an object that
has a string mapping set. The object's mapped string is passed in
@@ -293,6 +315,8 @@ void QSignalMapper::map(QObject *sender)
/*!
\fn void QSignalMapper::mapped(QWidget *widget)
+ \obsolete
+ \overload
This signal is emitted when map() is signalled from an object that
has a widget mapping set. The object's mapped widget is passed in
@@ -303,6 +327,53 @@ void QSignalMapper::map(QObject *sender)
/*!
\fn void QSignalMapper::mapped(QObject *object)
+ \obsolete
+ \overload
+
+ This signal is emitted when map() is signalled from an object that
+ has an object mapping set. The object provided by the map is passed in
+ \a object.
+
+ \sa setMapping()
+*/
+#endif
+
+/*!
+ \fn void QSignalMapper::mappedInt(int i)
+ \since 5.15
+
+ This signal is emitted when map() is signalled from an object that
+ has an integer mapping set. The object's mapped integer is passed
+ in \a i.
+
+ \sa setMapping()
+*/
+
+/*!
+ \fn void QSignalMapper::mappedString(const QString &text)
+ \since 5.15
+
+ This signal is emitted when map() is signalled from an object that
+ has a string mapping set. The object's mapped string is passed in
+ \a text.
+
+ \sa setMapping()
+*/
+
+/*!
+ \fn void QSignalMapper::mappedWidget(QWidget *widget)
+ \since 5.15
+
+ This signal is emitted when map() is signalled from an object that
+ has a widget mapping set. The object's mapped widget is passed in
+ \a widget.
+
+ \sa setMapping()
+*/
+
+/*!
+ \fn void QSignalMapper::mappedObject(QObject *object)
+ \since 5.15
This signal is emitted when map() is signalled from an object that
has an object mapping set. The object provided by the map is passed in
diff --git a/src/corelib/kernel/qsignalmapper.h b/src/corelib/kernel/qsignalmapper.h
index 0da1e8f87d..592986e6a5 100644
--- a/src/corelib/kernel/qsignalmapper.h
+++ b/src/corelib/kernel/qsignalmapper.h
@@ -66,10 +66,20 @@ public:
QObject *mapping(QObject *object) const;
Q_SIGNALS:
+#if QT_DEPRECATED_SINCE(5, 15)
+ QT_DEPRECATED_VERSION_X_5_15("Use QSignalMapper::mappedInt(int) instead")
void mapped(int);
+ QT_DEPRECATED_VERSION_X_5_15("Use QSignalMapper::mappedString(const QString&) instead")
void mapped(const QString &);
+ QT_DEPRECATED_VERSION_X_5_15("Use QSignalMapper::mappedWidget(QWidget *) instead")
void mapped(QWidget *);
+ QT_DEPRECATED_VERSION_X_5_15("Use QSignalMapper::mappedObject(QObject *) instead")
void mapped(QObject *);
+#endif
+ void mappedInt(int);
+ void mappedString(const QString &);
+ void mappedWidget(QWidget *);
+ void mappedObject(QObject *);
public Q_SLOTS:
void map();
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index 4bd8874630..5767d52f6a 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -283,7 +283,7 @@ class QTranslatorPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QTranslator)
public:
- enum { Contexts = 0x2f, Hashes = 0x42, Messages = 0x69, NumerusRules = 0x88, Dependencies = 0x96 };
+ enum { Contexts = 0x2f, Hashes = 0x42, Messages = 0x69, NumerusRules = 0x88, Dependencies = 0x96, Language = 0xa7 };
QTranslatorPrivate() :
#if defined(QT_USE_MMAP)
@@ -316,6 +316,9 @@ public:
uint contextLength;
uint numerusRulesLength;
+ QString language;
+ QString filePath;
+
bool do_load(const QString &filename, const QString &directory);
bool do_load(const uchar *data, qsizetype len, const QString &directory);
QString do_translate(const char *context, const char *sourceText, const char *comment,
@@ -597,8 +600,10 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo
}
}
- if (ok && d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength, directory))
+ if (ok && d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength, directory)) {
+ d->filePath = realname;
return true;
+ }
#if defined(QT_USE_MMAP)
if (used_mmap) {
@@ -829,7 +834,9 @@ bool QTranslatorPrivate::do_load(const uchar *data, qsizetype len, const QString
break;
}
- if (tag == QTranslatorPrivate::Contexts) {
+ if (tag == QTranslatorPrivate::Language) {
+ language = QString::fromUtf8((const char*)data, blockLen);
+ } else if (tag == QTranslatorPrivate::Contexts) {
contextArray = data;
contextLength = blockLen;
} else if (tag == QTranslatorPrivate::Hashes) {
@@ -1091,6 +1098,9 @@ void QTranslatorPrivate::clear()
qDeleteAll(subTranslators);
subTranslators.clear();
+ language.clear();
+ filePath.clear();
+
if (QCoreApplicationPrivate::isTranslatorInstalled(q))
QCoreApplication::postEvent(QCoreApplication::instance(),
new QEvent(QEvent::LanguageChange));
@@ -1132,6 +1142,32 @@ bool QTranslator::isEmpty() const
&& d->subTranslators.isEmpty();
}
+/*!
+ \since 5.15
+
+ Returns the target language as stored in the translation file.
+ */
+QString QTranslator::language() const
+{
+ Q_D(const QTranslator);
+ return d->language;
+}
+
+/*!
+ \since 5.15
+
+ Returns the path of the loaded translation file.
+
+ The file path is empty if no translation was loaded yet,
+ the loading failed, or if the translation was not loaded
+ from a file.
+ */
+QString QTranslator::filePath() const
+{
+ Q_D(const QTranslator);
+ return d->filePath;
+}
+
QT_END_NAMESPACE
#include "moc_qtranslator.cpp"
diff --git a/src/corelib/kernel/qtranslator.h b/src/corelib/kernel/qtranslator.h
index e7c39191e7..61a39c4089 100644
--- a/src/corelib/kernel/qtranslator.h
+++ b/src/corelib/kernel/qtranslator.h
@@ -63,6 +63,9 @@ public:
virtual bool isEmpty() const;
+ QString language() const;
+ QString filePath() const;
+
bool load(const QString & filename,
const QString & directory = QString(),
const QString & search_delimiters = QString(),
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 4ac26e3048..e3d565f185 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -662,7 +662,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
# endif
#endif
case QMetaType::QDate:
- *dt = QDateTime(*v_cast<QDate>(d));
+ *dt = v_cast<QDate>(d)->startOfDay();
break;
default:
return false;
@@ -1229,7 +1229,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
*static_cast<QCborValue *>(result) = *v_cast<QByteArray>(d);
break;
case QMetaType::QDate:
- *static_cast<QCborValue *>(result) = QCborValue(QDateTime(*v_cast<QDate>(d)));
+ *static_cast<QCborValue *>(result) = QCborValue(v_cast<QDate>(d)->startOfDay());
break;
case QMetaType::QDateTime:
*static_cast<QCborValue *>(result) = QCborValue(*v_cast<QDateTime>(d));
diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp
index 6eb84b327b..4a092abb3e 100644
--- a/src/corelib/plugin/qlibrary_unix.cpp
+++ b/src/corelib/plugin/qlibrary_unix.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation
+** Copyright (C) 2020 Intel Corporation
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -218,6 +218,8 @@ bool QLibraryPrivate::load_sys()
for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) {
if (!prefixes.at(prefix).isEmpty() && name.startsWith(prefixes.at(prefix)))
continue;
+ if (path.isEmpty() && prefixes.at(prefix).contains(QLatin1Char('/')))
+ continue;
if (!suffixes.at(suffix).isEmpty() && name.endsWith(suffixes.at(suffix)))
continue;
if (loadHints & QLibrary::LoadArchiveMemberHint) {
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
index aed1704d5f..f34578ea81 100644
--- a/src/corelib/plugin/qpluginloader.cpp
+++ b/src/corelib/plugin/qpluginloader.cpp
@@ -342,7 +342,7 @@ static QString locatePlugin(const QString& fileName)
QPluginLoader will automatically look for the file with the appropriate
suffix (see QLibrary::isLibrary()).
- When loading the plugin, QPluginLoader searches in the current directory and
+ When loading the plugin, QPluginLoader searches
in all plugin locations specified by QCoreApplication::libraryPaths(),
unless the file name has an absolute path. After loading the plugin
successfully, fileName() returns the fully-qualified file name of
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index fb551d5197..c1fa700959 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -3185,6 +3185,26 @@ QStateMachine::WrappedEvent::~WrappedEvent()
\sa QStateMachine::running
*/
+/*!
+ \fn QStateMachine::postDelayedEvent(QEvent *event, std::chrono::milliseconds delay)
+ \since 5.15
+ \overload
+ \threadsafe
+
+ Posts the given \a event for processing by this state machine, with the
+ given \a delay in milliseconds. Returns an identifier associated with the
+ delayed event, or -1 if the event could not be posted.
+
+ This function returns immediately. When the delay has expired, the event
+ will be added to the state machine's event queue for processing. The state
+ machine takes ownership of the event and deletes it once it has been
+ processed.
+
+ You can only post events when the state machine is running.
+
+ \sa cancelDelayedEvent(), postEvent()
+*/
+
QT_END_NAMESPACE
#include "qstatemachine.moc"
diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h
index 07781d09a4..b3c87a959b 100644
--- a/src/corelib/statemachine/qstatemachine.h
+++ b/src/corelib/statemachine/qstatemachine.h
@@ -48,6 +48,10 @@
#include <QtCore/qset.h>
#include <QtCore/qvariant.h>
+#if __has_include(<chrono>)
+# include <chrono>
+#endif
+
QT_REQUIRE_CONFIG(statemachine);
QT_BEGIN_NAMESPACE
@@ -145,6 +149,13 @@ public:
bool eventFilter(QObject *watched, QEvent *event) override;
#endif
+#if __has_include(<chrono>) || defined(Q_QDOC)
+ int postDelayedEvent(QEvent *event, std::chrono::milliseconds delay)
+ {
+ return postDelayedEvent(event, int(delay.count()));
+ }
+#endif
+
public Q_SLOTS:
void start();
void stop();
diff --git a/src/corelib/text/qcollator_icu.cpp b/src/corelib/text/qcollator_icu.cpp
index 8acda45070..0dca1ee9c9 100644
--- a/src/corelib/text/qcollator_icu.cpp
+++ b/src/corelib/text/qcollator_icu.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
** Contact: https://www.qt.io/licensing/
**
@@ -109,6 +109,11 @@ void QCollatorPrivate::cleanup()
int QCollator::compare(QStringView s1, QStringView s2) const
{
+ if (!s1.size())
+ return s2.size() ? -1 : 0;
+ if (!s2.size())
+ return +1;
+
if (d->dirty)
d->init();
diff --git a/src/corelib/text/qcollator_macx.cpp b/src/corelib/text/qcollator_macx.cpp
index 071d7c048f..cb8e073d4a 100644
--- a/src/corelib/text/qcollator_macx.cpp
+++ b/src/corelib/text/qcollator_macx.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
+** Copyright (C) 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -94,6 +94,11 @@ void QCollatorPrivate::cleanup()
int QCollator::compare(QStringView s1, QStringView s2) const
{
+ if (!s1.size())
+ return s2.size() ? -1 : 0;
+ if (!s2.size())
+ return +1;
+
if (d->dirty)
d->init();
if (!d->collator)
diff --git a/src/corelib/text/qcollator_posix.cpp b/src/corelib/text/qcollator_posix.cpp
index 9cbc539ebe..ffcd214cfb 100644
--- a/src/corelib/text/qcollator_posix.cpp
+++ b/src/corelib/text/qcollator_posix.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
+** Copyright (C) 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -75,6 +75,11 @@ static void stringToWCharArray(QVarLengthArray<wchar_t> &ret, QStringView string
int QCollator::compare(QStringView s1, QStringView s2) const
{
+ if (!s1.size())
+ return s2.size() ? -1 : 0;
+ if (!s2.size())
+ return +1;
+
if (d->isC())
return s1.compare(s2, caseSensitivity());
if (d->dirty)
diff --git a/src/corelib/text/qcollator_win.cpp b/src/corelib/text/qcollator_win.cpp
index 9d81de882f..54f57f1d24 100644
--- a/src/corelib/text/qcollator_win.cpp
+++ b/src/corelib/text/qcollator_win.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Aleix Pol Gonzalez <aleixpol@kde.org>
+** Copyright (C) 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -89,6 +89,11 @@ void QCollatorPrivate::cleanup()
int QCollator::compare(QStringView s1, QStringView s2) const
{
+ if (!s1.size())
+ return s2.size() ? -1 : 0;
+ if (!s2.size())
+ return +1;
+
if (d->isC())
return s1.compare(s2, d->caseSensitivity);
diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp
index 05fe638f46..268e96bfd2 100644
--- a/src/corelib/text/qlocale.cpp
+++ b/src/corelib/text/qlocale.cpp
@@ -660,6 +660,11 @@ static QLocalePrivate *c_private()
return &c_locale;
}
+static const QLocaleData *systemData();
+static QLocale::NumberOptions system_number_options = QLocale::DefaultNumberOptions;
+Q_GLOBAL_STATIC_WITH_ARGS(QExplicitlySharedDataPointer<QLocalePrivate>, systemLocalePrivate,
+ (QLocalePrivate::create(systemData(), system_number_options)))
+
#ifndef QT_NO_SYSTEMLOCALE
/******************************************************************************
** Default system locale behavior
@@ -711,6 +716,7 @@ static void updateSystemPrivate()
{
// This function is NOT thread-safe!
// It *should not* be called by anything but systemData()
+ // It *is* called before {system,default}LocalePrivate exist.
const QSystemLocale *sys_locale = systemLocale();
// tell the object that the system locale has changed.
@@ -718,11 +724,14 @@ static void updateSystemPrivate()
// Populate global with fallback as basis:
globalLocaleData = *sys_locale->fallbackUiLocaleData();
+ system_number_options = QLocale::DefaultNumberOptions;
QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant());
if (!res.isNull()) {
globalLocaleData.m_language_id = res.toInt();
globalLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility
+ if (globalLocaleData.m_language_id == QLocale::C)
+ system_number_options = QLocale::OmitGroupSeparator;
}
res = sys_locale->query(QSystemLocale::CountryId, QVariant());
if (!res.isNull()) {
@@ -737,9 +746,26 @@ static void updateSystemPrivate()
if (!res.isNull() && !res.toString().isEmpty())
globalLocaleData.m_decimal = res.toString().at(0).unicode();
+ // System may supply empty group separator to say we should omit grouping;
+ // and it makes no sense to use the same separator for decimal and grouping
+ // (which might happen by system supplying, as decimal, what CLDR has given
+ // us for grouping; or the other way round). Assume, at least, that each of
+ // system and CLDR has decimal != group, all the same.
res = sys_locale->query(QSystemLocale::GroupSeparator, QVariant());
- if (!res.isNull() && !res.toString().isEmpty())
- globalLocaleData.m_group = res.toString().at(0).unicode();
+ if (res.isNull()) {
+ // The case where system over-rides decimal but not group, and its
+ // decimal clashes with CLDR's group.
+ if (globalLocaleData.m_group == globalLocaleData.m_decimal)
+ system_number_options |= QLocale::OmitGroupSeparator;
+ } else if (res.toString().isEmpty()) {
+ system_number_options |= QLocale::OmitGroupSeparator;
+ } else {
+ const ushort group = res.toString().at(0).unicode();
+ if (group != globalLocaleData.m_decimal)
+ globalLocaleData.m_group = group;
+ else if (group == globalLocaleData.m_group)
+ qWarning("System-supplied decimal and grouping character are both 0x%hx", group);
+ }
res = sys_locale->query(QSystemLocale::ZeroDigit, QVariant());
if (!res.isNull() && !res.toString().isEmpty())
@@ -752,6 +778,10 @@ static void updateSystemPrivate()
res = sys_locale->query(QSystemLocale::PositiveSign, QVariant());
if (!res.isNull() && !res.toString().isEmpty())
globalLocaleData.m_plus = res.toString().at(0).unicode();
+
+ if (systemLocalePrivate.exists())
+ systemLocalePrivate->data()->m_numberOptions = system_number_options;
+ // else: system_number_options will be passed to create() when constructing.
}
#endif // !QT_NO_SYSTEMLOCALE
@@ -812,8 +842,6 @@ static const int locale_data_size = sizeof(locale_data)/sizeof(QLocaleData) - 1;
Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<QLocalePrivate>, defaultLocalePrivate,
(QLocalePrivate::create(defaultData())))
-Q_GLOBAL_STATIC_WITH_ARGS(QExplicitlySharedDataPointer<QLocalePrivate>, systemLocalePrivate,
- (QLocalePrivate::create(systemData())))
static QLocalePrivate *localePrivateByName(const QString &name)
{
@@ -1996,6 +2024,9 @@ QString QLocale::toString(const QDate &date, QStringView format) const
/*!
Returns a localized string representation of the given \a date according
to the specified \a format.
+
+ \note Some locales may use formats that limit the range of years they can
+ represent.
*/
QString QLocale::toString(const QDate &date, FormatType format) const
@@ -2150,6 +2181,9 @@ QString QLocale::toString(const QDateTime &dateTime, QStringView format, QCalend
Returns a localized string representation of the given \a dateTime according
to the specified \a format.
+
+ \note Some locales may use formats that limit the range of years they can
+ represent.
*/
QString QLocale::toString(const QDateTime &dateTime, FormatType format) const
@@ -2302,14 +2336,19 @@ QTime QLocale::toTime(const QString &string, FormatType format) const
return toTime(string, timeFormat(format));
}
+#if QT_DEPRECATED_SINCE(5, 15)
/*!
\since 5.14
\overload
+ \deprecated
*/
QTime QLocale::toTime(const QString &string, FormatType format, QCalendar cal) const
{
+QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
return toTime(string, timeFormat(format), cal);
+QT_WARNING_POP
}
+#endif
/*!
\since 4.4
@@ -2374,12 +2413,24 @@ QDateTime QLocale::toDateTime(const QString &string, FormatType format, QCalenda
*/
QTime QLocale::toTime(const QString &string, const QString &format) const
{
- return toTime(string, format, QCalendar());
+ QTime time;
+#if QT_CONFIG(datetimeparser)
+ QDateTimeParser dt(QMetaType::QTime, QDateTimeParser::FromString, QCalendar());
+ dt.setDefaultLocale(*this);
+ if (dt.parseFormat(format))
+ dt.fromString(string, nullptr, &time);
+#else
+ Q_UNUSED(string);
+ Q_UNUSED(format);
+#endif
+ return time;
}
+#if QT_DEPRECATED_SINCE(5, 15)
/*!
\since 5.14
\overload
+ \deprecated
*/
QTime QLocale::toTime(const QString &string, const QString &format, QCalendar cal) const
{
@@ -2396,6 +2447,7 @@ QTime QLocale::toTime(const QString &string, const QString &format, QCalendar ca
#endif
return time;
}
+#endif
/*!
\since 4.4
diff --git a/src/corelib/text/qlocale.h b/src/corelib/text/qlocale.h
index cbdcebc57d..a9933bbb2e 100644
--- a/src/corelib/text/qlocale.h
+++ b/src/corelib/text/qlocale.h
@@ -1038,11 +1038,15 @@ public:
QDateTime toDateTime(const QString &string, const QString &format) const;
// Calendar-aware API
QDate toDate(const QString &string, FormatType format, QCalendar cal) const;
- QTime toTime(const QString &string, FormatType format, QCalendar cal) const;
QDateTime toDateTime(const QString &string, FormatType format, QCalendar cal) const;
QDate toDate(const QString &string, const QString &format, QCalendar cal) const;
- QTime toTime(const QString &string, const QString &format, QCalendar cal) const;
QDateTime toDateTime(const QString &string, const QString &format, QCalendar cal) const;
+# if QT_DEPRECATED_SINCE(5, 15)
+ QT_DEPRECATED_X("Calendar is ignored when parsing times")
+ QTime toTime(const QString &string, FormatType format, QCalendar cal) const;
+ QT_DEPRECATED_X("Calendar is ignored when parsing times")
+ QTime toTime(const QString &string, const QString &format, QCalendar cal) const;
+# endif // 5.15
#endif
// ### Qt 6: We need to return QString from these function since
diff --git a/src/corelib/text/qlocale_mac.mm b/src/corelib/text/qlocale_mac.mm
index 31ede1352b..5381f0f975 100644
--- a/src/corelib/text/qlocale_mac.mm
+++ b/src/corelib/text/qlocale_mac.mm
@@ -119,7 +119,7 @@ static QString macDayName(int day, bool short_format)
return QString();
}
-static QString macDateToString(const QDate &date, bool short_format)
+static QString macDateToString(QDate date, bool short_format)
{
QCFType<CFDateRef> myDate = QDateTime(date, QTime()).toCFDate();
QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
@@ -131,7 +131,7 @@ static QString macDateToString(const QDate &date, bool short_format)
return QCFString(CFDateFormatterCreateStringWithDate(0, myFormatter, myDate));
}
-static QString macTimeToString(const QTime &time, bool short_format)
+static QString macTimeToString(QTime time, bool short_format)
{
QCFType<CFDateRef> myDate = QDateTime(QDate::currentDate(), time).toCFDate();
QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
@@ -283,10 +283,12 @@ static QString getMacTimeFormat(CFDateFormatterStyle style)
return macToQtFormat(QString::fromCFString(CFDateFormatterGetFormat(formatter)));
}
-static QString getCFLocaleValue(CFStringRef key)
+static QVariant getCFLocaleValue(CFStringRef key)
{
QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
CFTypeRef value = CFLocaleGetValue(locale, key);
+ if (!value)
+ return QVariant();
return QString::fromCFString(CFStringRef(static_cast<CFTypeRef>(value)));
}
@@ -411,14 +413,10 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
switch(type) {
// case Name:
// return getMacLocaleName();
- case DecimalPoint: {
- QString value = getCFLocaleValue(kCFLocaleDecimalSeparator);
- return value.isEmpty() ? QVariant() : value;
- }
- case GroupSeparator: {
- QString value = getCFLocaleValue(kCFLocaleGroupingSeparator);
- return value.isEmpty() ? QVariant() : value;
- }
+ case DecimalPoint:
+ return getCFLocaleValue(kCFLocaleDecimalSeparator);
+ case GroupSeparator:
+ return getCFLocaleValue(kCFLocaleGroupingSeparator);
case DateFormatLong:
case DateFormatShort:
return getMacDateFormat(type == DateFormatShort
diff --git a/src/corelib/text/qlocale_p.h b/src/corelib/text/qlocale_p.h
index a7c15d08fb..11a42b7fee 100644
--- a/src/corelib/text/qlocale_p.h
+++ b/src/corelib/text/qlocale_p.h
@@ -87,7 +87,7 @@ public:
LanguageId, // uint
CountryId, // uint
DecimalPoint, // QString
- GroupSeparator, // QString
+ GroupSeparator, // QString (empty QString means: don't group digits)
ZeroDigit, // QString
NegativeSign, // QString
DateFormatLong, // QString
diff --git a/src/corelib/text/qlocale_win.cpp b/src/corelib/text/qlocale_win.cpp
index 4b4152c519..4a38adf309 100644
--- a/src/corelib/text/qlocale_win.cpp
+++ b/src/corelib/text/qlocale_win.cpp
@@ -106,11 +106,11 @@ struct QSystemLocalePrivate
{
QSystemLocalePrivate();
- QString zeroDigit();
- QString decimalPoint();
- QString groupSeparator();
- QString negativeSign();
- QString positiveSign();
+ QVariant zeroDigit();
+ QVariant decimalPoint();
+ QVariant groupSeparator();
+ QVariant negativeSign();
+ QVariant positiveSign();
QVariant dateFormat(QLocale::FormatType);
QVariant timeFormat(QLocale::FormatType);
QVariant dateTimeFormat(QLocale::FormatType);
@@ -150,7 +150,9 @@ private:
QString zero; // cached value for zeroDigit()
int getLocaleInfo(LCTYPE type, LPWSTR data, int size);
- QString getLocaleInfo(LCTYPE type, int maxlen = 0);
+ // Need to distinguish empty QString packaged as (non-null) QVariant from null QVariant:
+ template <typename T = QString>
+ T getLocaleInfo(LCTYPE type, int maxlen = 0);
int getLocaleInfo_int(LCTYPE type, int maxlen = 0);
int getCurrencyFormat(DWORD flags, LPCWSTR value, const CURRENCYFMTW *format, LPWSTR data, int size);
@@ -211,19 +213,30 @@ inline int QSystemLocalePrivate::getLocaleInfo(LCTYPE type, LPWSTR data, int siz
#endif
}
-QString QSystemLocalePrivate::getLocaleInfo(LCTYPE type, int maxlen)
+template<typename T>
+T QSystemLocalePrivate::getLocaleInfo(LCTYPE type, int maxlen)
{
+ // https://docs.microsoft.com/en-us/windows/win32/intl/locale-spositivesign
+ // says empty for LOCALE_SPOSITIVESIGN means "+", although GetLocaleInfo()
+ // is documented to return 0 only on failure, so it's not clear how it
+ // returns empty to mean this; hence the two checks for it below.
+ const QString plus = QStringLiteral("+");
QVarLengthArray<wchar_t, 64> buf(maxlen ? maxlen : 64);
- if (!getLocaleInfo(type, buf.data(), buf.size()))
- return QString();
- if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ if (!getLocaleInfo(type, buf.data(), buf.size())) {
+ const auto lastError = GetLastError();
+ if (type == LOCALE_SPOSITIVESIGN && lastError == ERROR_SUCCESS)
+ return plus;
+ if (lastError != ERROR_INSUFFICIENT_BUFFER)
+ return {};
int cnt = getLocaleInfo(type, 0, 0);
if (cnt == 0)
- return QString();
+ return {};
buf.resize(cnt);
if (!getLocaleInfo(type, buf.data(), buf.size()))
- return QString();
+ return {};
}
+ if (type == LOCALE_SPOSITIVESIGN && !buf[0])
+ return plus;
return QString::fromWCharArray(buf.data());
}
@@ -298,7 +311,7 @@ QString &QSystemLocalePrivate::substituteDigits(QString &string)
return string;
}
-QString QSystemLocalePrivate::zeroDigit()
+QVariant QSystemLocalePrivate::zeroDigit()
{
if (zero.isEmpty()) {
/* Ten digits plus a terminator.
@@ -317,24 +330,24 @@ QString QSystemLocalePrivate::zeroDigit()
return zero;
}
-QString QSystemLocalePrivate::decimalPoint()
+QVariant QSystemLocalePrivate::decimalPoint()
{
- return getLocaleInfo(LOCALE_SDECIMAL);
+ return getLocaleInfo<QVariant>(LOCALE_SDECIMAL);
}
-QString QSystemLocalePrivate::groupSeparator()
+QVariant QSystemLocalePrivate::groupSeparator()
{
- return getLocaleInfo(LOCALE_STHOUSAND);
+ return getLocaleInfo<QVariant>(LOCALE_STHOUSAND);
}
-QString QSystemLocalePrivate::negativeSign()
+QVariant QSystemLocalePrivate::negativeSign()
{
- return getLocaleInfo(LOCALE_SNEGATIVESIGN);
+ return getLocaleInfo<QVariant>(LOCALE_SNEGATIVESIGN);
}
-QString QSystemLocalePrivate::positiveSign()
+QVariant QSystemLocalePrivate::positiveSign()
{
- return getLocaleInfo(LOCALE_SPOSITIVESIGN);
+ return getLocaleInfo<QVariant>(LOCALE_SPOSITIVESIGN);
}
QVariant QSystemLocalePrivate::dateFormat(QLocale::FormatType type)
@@ -392,10 +405,10 @@ QVariant QSystemLocalePrivate::dayName(int day, QLocale::FormatType type)
day -= 1;
if (type == QLocale::LongFormat)
- return getLocaleInfo(long_day_map[day]);
+ return getLocaleInfo<QVariant>(long_day_map[day]);
if (type == QLocale::NarrowFormat)
- return getLocaleInfo(narrow_day_map[day]);
- return getLocaleInfo(short_day_map[day]);
+ return getLocaleInfo<QVariant>(narrow_day_map[day]);
+ return getLocaleInfo<QVariant>(short_day_map[day]);
}
QVariant QSystemLocalePrivate::monthName(int month, QLocale::FormatType type)
@@ -418,7 +431,7 @@ QVariant QSystemLocalePrivate::monthName(int month, QLocale::FormatType type)
LCTYPE lctype = (type == QLocale::ShortFormat || type == QLocale::NarrowFormat)
? short_month_map[month] : long_month_map[month];
- return getLocaleInfo(lctype);
+ return getLocaleInfo<QVariant>(lctype);
}
QVariant QSystemLocalePrivate::toString(QDate date, QLocale::FormatType type)
@@ -485,7 +498,7 @@ QVariant QSystemLocalePrivate::measurementSystem()
QVariant QSystemLocalePrivate::collation()
{
- return getLocaleInfo(LOCALE_SSORTLOCALE);
+ return getLocaleInfo<QVariant>(LOCALE_SSORTLOCALE);
}
QVariant QSystemLocalePrivate::amText()
@@ -687,12 +700,12 @@ QVariant QSystemLocalePrivate::uiLanguages()
QVariant QSystemLocalePrivate::nativeLanguageName()
{
- return getLocaleInfo(LOCALE_SNATIVELANGUAGENAME);
+ return getLocaleInfo<QVariant>(LOCALE_SNATIVELANGUAGENAME);
}
QVariant QSystemLocalePrivate::nativeCountryName()
{
- return getLocaleInfo(LOCALE_SNATIVECOUNTRYNAME);
+ return getLocaleInfo<QVariant>(LOCALE_SNATIVECOUNTRYNAME);
}
diff --git a/src/corelib/thread/qrunnable.cpp b/src/corelib/thread/qrunnable.cpp
index b355ca605f..5b883a05da 100644
--- a/src/corelib/thread/qrunnable.cpp
+++ b/src/corelib/thread/qrunnable.cpp
@@ -113,4 +113,31 @@ QRunnable::~QRunnable()
\sa autoDelete(), QThreadPool
*/
+class FunctionRunnable : public QRunnable
+{
+ std::function<void()> m_functor;
+public:
+ FunctionRunnable(std::function<void()> functor) : m_functor(std::move(functor))
+ {
+ }
+ void run() override
+ {
+ m_functor();
+ }
+};
+
+/*!
+ \since 5.15
+
+ Creates a QRunnable that calls \a fun in run().
+
+ Auto-deletion is enabled by default.
+
+ \sa run(), autoDelete()
+*/
+QRunnable *QRunnable::create(std::function<void()> fun)
+{
+ return new FunctionRunnable(std::move(fun));
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qrunnable.h b/src/corelib/thread/qrunnable.h
index b8e842118c..c13aa3fa8c 100644
--- a/src/corelib/thread/qrunnable.h
+++ b/src/corelib/thread/qrunnable.h
@@ -41,6 +41,7 @@
#define QRUNNABLE_H
#include <QtCore/qglobal.h>
+#include <functional>
QT_BEGIN_NAMESPACE
@@ -59,6 +60,7 @@ public:
QRunnable() : ref(0) { }
virtual ~QRunnable();
+ static QRunnable *create(std::function<void()> fun);
bool autoDelete() const { return ref != -1; }
void setAutoDelete(bool _autoDelete) { ref = _autoDelete ? 0 : -1; }
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp
index 5f23a78c8a..d1875a69a9 100644
--- a/src/corelib/thread/qthreadpool.cpp
+++ b/src/corelib/thread/qthreadpool.cpp
@@ -512,6 +512,22 @@ void QThreadPool::start(QRunnable *runnable, int priority)
}
/*!
+ \overload
+ \since 5.15
+
+ Reserves a thread and uses it to run \a fun, unless this thread will
+ make the current thread count exceed maxThreadCount(). In that case,
+ \a fun is added to a run queue instead. The \a priority argument can
+ be used to control the run queue's order of execution.
+*/
+void QThreadPool::start(std::function<void()> fun, int priority)
+{
+ if (!fun)
+ return;
+ start(QRunnable::create(std::move(fun)), priority);
+}
+
+/*!
Attempts to reserve a thread to run \a runnable.
If no threads are available at the time of calling, then this function
@@ -542,6 +558,22 @@ bool QThreadPool::tryStart(QRunnable *runnable)
return d->tryStart(runnable);
}
+/*!
+ \overload
+ \since 5.15
+ Attempts to reserve a thread to run \a fun.
+
+ If no threads are available at the time of calling, then this function
+ does nothing and returns \c false. Otherwise, \a fun is run immediately
+ using one available thread and this function returns \c true.
+*/
+bool QThreadPool::tryStart(std::function<void()> fun)
+{
+ if (!fun)
+ return false;
+ return tryStart(QRunnable::create(std::move(fun)));
+}
+
/*! \property QThreadPool::expiryTimeout
Threads that are unused for \a expiryTimeout milliseconds are considered
diff --git a/src/corelib/thread/qthreadpool.h b/src/corelib/thread/qthreadpool.h
index cd27b7c08a..2eede44eca 100644
--- a/src/corelib/thread/qthreadpool.h
+++ b/src/corelib/thread/qthreadpool.h
@@ -45,6 +45,8 @@
#include <QtCore/qthread.h>
#include <QtCore/qrunnable.h>
+#include <functional>
+
QT_REQUIRE_CONFIG(thread);
QT_BEGIN_NAMESPACE
@@ -70,6 +72,9 @@ public:
void start(QRunnable *runnable, int priority = 0);
bool tryStart(QRunnable *runnable);
+ void start(std::function<void()> fun, int priority = 0);
+ bool tryStart(std::function<void()> fun);
+
int expiryTimeout() const;
void setExpiryTimeout(int expiryTimeout);
diff --git a/src/corelib/time/qcalendar.cpp b/src/corelib/time/qcalendar.cpp
index 9d485f181e..32f0a511a3 100644
--- a/src/corelib/time/qcalendar.cpp
+++ b/src/corelib/time/qcalendar.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -750,6 +750,8 @@ int QCalendar::daysInMonth(int month, int year) const
/*!
Returns the number of days in the given \a year.
+
+ Handling of \c Unspecified as \a year is undefined.
*/
int QCalendar::daysInYear(int year) const
{
@@ -758,10 +760,15 @@ int QCalendar::daysInYear(int year) const
/*!
Returns the number of months in the given \a year.
+
+ If \a year is \c Unspecified, returns the maximum number of months in a
+ year.
+
+ \sa maximumMonthsInYear()
*/
int QCalendar::monthsInYear(int year) const
{
- return d ? d->monthsInYear(year) : 0;
+ return d ? year == Unspecified ? d->maximumMonthsInYear() : d->monthsInYear(year) : 0;
}
/*!
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp
index 80751e60a0..773280ad68 100644
--- a/src/corelib/time/qdatetime.cpp
+++ b/src/corelib/time/qdatetime.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -682,7 +682,7 @@ static bool inDateTimeRange(qint64 jd, bool start)
return jd >= minDay && jd < maxDay;
}
-static QDateTime toEarliest(const QDate &day, const QDateTime &form)
+static QDateTime toEarliest(QDate day, const QDateTime &form)
{
const Qt::TimeSpec spec = form.timeSpec();
const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0;
@@ -806,7 +806,7 @@ QDateTime QDate::startOfDay(const QTimeZone &zone) const
}
#endif // timezone
-static QDateTime toLatest(const QDate &day, const QDateTime &form)
+static QDateTime toLatest(QDate day, const QDateTime &form)
{
const Qt::TimeSpec spec = form.timeSpec();
const int offset = (spec == Qt::OffsetFromUTC) ? form.offsetFromUtc() : 0;
@@ -1098,9 +1098,8 @@ QString QDate::longDayName(int weekday, MonthNameType type)
}
#endif // textdate && deprecated
-#if QT_CONFIG(datestring)
+#if QT_CONFIG(datestring) // depends on, so implies, textdate
-#if QT_CONFIG(textdate)
static QString toStringTextDate(QDate date, QCalendar cal)
{
if (date.isValid()) {
@@ -1115,13 +1114,7 @@ static QString toStringTextDate(QDate date, QCalendar cal)
return QString();
}
-static QString toStringTextDate(QDate date)
-{
- return toStringTextDate(date, QCalendar());
-}
-#endif // textdate
-
-static QString toStringIsoDate(const QDate &date)
+static QString toStringIsoDate(QDate date)
{
const auto parts = QCalendar().partsFromDate(date);
if (parts.isValid() && parts.year >= 0 && parts.year <= 9999)
@@ -1131,11 +1124,13 @@ static QString toStringIsoDate(const QDate &date)
/*!
\fn QString QDate::toString(Qt::DateFormat format) const
+ \fn QString QDate::toString(Qt::DateFormat format, QCalendar cal) const
\overload
- Returns the date as a string. The \a format parameter determines
- the format of the string.
+ Returns the date as a string. The \a format parameter determines the format
+ of the string. If \a cal is supplied, it determines the calendar used to
+ represent the date; it defaults to Gregorian.
If the \a format is Qt::TextDate, the string is formatted in the default
way. The day and month names will be localized names using the system
@@ -1148,18 +1143,16 @@ static QString toStringIsoDate(const QDate &date)
year, MM is the month of the year (between 01 and 12), and dd is
the day of the month between 01 and 31.
- If the \a format is Qt::SystemLocaleShortDate or
- Qt::SystemLocaleLongDate, the string format depends on the locale
- settings of the system. Identical to calling
- QLocale::system().toString(date, QLocale::ShortFormat) or
- QLocale::system().toString(date, QLocale::LongFormat).
-
- If the \a format is Qt::DefaultLocaleShortDate or
- Qt::DefaultLocaleLongDate, the string format depends on the
- default application locale. This is the locale set with
- QLocale::setDefault(), or the system locale if no default locale
- has been set. Identical to calling
- \l {QLocale::toString()}{QLocale().toString(date, QLocale::ShortFormat) } or
+ The \a format options Qt::SystemLocaleDate, Qt::SystemLocaleShortDate and
+ Qt::SystemLocaleLongDate shall be removed in Qt 6. Their use should be
+ replaced with
+ \l {QLocale::toString()}{QLocale::system().toString(date, QLocale::ShortFormat)} or
+ \l {QLocale::toString()}{QLocale::system().toString(date, QLocale::LongFormat)}.
+
+ The \a format options Qt::LocaleDate, Qt::DefaultLocaleShortDate and
+ Qt::DefaultLocaleLongDate shall be removed in Qt 6. Their use should be
+ replaced with
+ \l {QLocale::toString()}{QLocale().toString(date, QLocale::ShortFormat)} or
\l {QLocale::toString()}{QLocale().toString(date, QLocale::LongFormat)}.
If the \a format is Qt::RFC2822Date, the string is formatted in
@@ -1169,46 +1162,54 @@ static QString toStringIsoDate(const QDate &date)
If the date is invalid, an empty string will be returned.
\warning The Qt::ISODate format is only valid for years in the
- range 0 to 9999. This restriction may apply to locale-aware
- formats as well, depending on the locale settings.
+ range 0 to 9999.
\sa fromString(), QLocale::toString()
*/
QString QDate::toString(Qt::DateFormat format) const
{
+ return toString(format, QCalendar());
+}
+
+QString QDate::toString(Qt::DateFormat format, QCalendar cal) const
+{
if (!isValid())
return QString();
switch (format) {
+#if QT_DEPRECATED_SINCE(5, 15)
case Qt::SystemLocaleDate:
case Qt::SystemLocaleShortDate:
- return QLocale::system().toString(*this, QLocale::ShortFormat);
+ return QLocale::system().toString(*this, QLocale::ShortFormat, cal);
case Qt::SystemLocaleLongDate:
- return QLocale::system().toString(*this, QLocale::LongFormat);
+ return QLocale::system().toString(*this, QLocale::LongFormat, cal);
case Qt::LocaleDate:
case Qt::DefaultLocaleShortDate:
- return QLocale().toString(*this, QLocale::ShortFormat);
+ return QLocale().toString(*this, QLocale::ShortFormat, cal);
case Qt::DefaultLocaleLongDate:
- return QLocale().toString(*this, QLocale::LongFormat);
+ return QLocale().toString(*this, QLocale::LongFormat, cal);
+#endif // 5.15
case Qt::RFC2822Date:
- return QLocale::c().toString(*this, u"dd MMM yyyy");
+ return QLocale::c().toString(*this, QStringView(u"dd MMM yyyy"), cal);
default:
-#if QT_CONFIG(textdate)
case Qt::TextDate:
- return toStringTextDate(*this);
-#endif
+ return toStringTextDate(*this, cal);
case Qt::ISODate:
case Qt::ISODateWithMs:
+ // No calendar dependence
return toStringIsoDate(*this);
}
}
/*!
\fn QString QDate::toString(const QString &format) const
+ \fn QString QDate::toString(const QString &format, QCalendar cal) const
\fn QString QDate::toString(QStringView format) const
+ \fn QString QDate::toString(QStringView format, QCalendar cal) const
- Returns the date as a string. The \a format parameter determines
- the format of the result string.
+ Returns the date as a string. The \a format parameter determines the format
+ of the result string. If \cal is supplied, it determines the calendar used
+ to represent the date; it defaults to Gregorian.
These expressions may be used:
@@ -1263,43 +1264,7 @@ QString QDate::toString(Qt::DateFormat format) const
*/
QString QDate::toString(QStringView format) const
{
- return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
-}
-
-#if QT_STRINGVIEW_LEVEL < 2
-QString QDate::toString(const QString &format) const
-{
- return toString(qToStringViewIgnoringNull(format));
-}
-#endif
-
-QString QDate::toString(Qt::DateFormat format, QCalendar cal) const
-{
- if (!isValid())
- return QString();
-
- switch (format) {
- case Qt::SystemLocaleDate:
- case Qt::SystemLocaleShortDate:
- return QLocale::system().toString(*this, QLocale::ShortFormat, cal);
- case Qt::SystemLocaleLongDate:
- return QLocale::system().toString(*this, QLocale::LongFormat, cal);
- case Qt::LocaleDate:
- case Qt::DefaultLocaleShortDate:
- return QLocale().toString(*this, QLocale::ShortFormat, cal);
- case Qt::DefaultLocaleLongDate:
- return QLocale().toString(*this, QLocale::LongFormat, cal);
- case Qt::RFC2822Date:
- return QLocale::c().toString(*this, QStringView(u"dd MMM yyyy"), cal);
- default:
-#ifndef QT_NO_TEXTDATE
- case Qt::TextDate:
- return toStringTextDate(*this, cal);
-#endif
- case Qt::ISODate:
- case Qt::ISODateWithMs:
- return toStringIsoDate(*this);
- }
+ return toString(format, QCalendar());
}
QString QDate::toString(QStringView format, QCalendar cal) const
@@ -1308,6 +1273,11 @@ QString QDate::toString(QStringView format, QCalendar cal) const
}
#if QT_STRINGVIEW_LEVEL < 2
+QString QDate::toString(const QString &format) const
+{
+ return toString(qToStringViewIgnoringNull(format), QCalendar());
+}
+
QString QDate::toString(const QString &format, QCalendar cal) const
{
return toString(qToStringViewIgnoringNull(format), cal);
@@ -1625,7 +1595,7 @@ qint64 QDate::daysTo(const QDate &d) const
\sa QTime::currentTime(), QDateTime::currentDateTime()
*/
-#if QT_CONFIG(datestring)
+#if QT_CONFIG(datestring) // depends on, so implies, textdate
namespace {
struct ParsedInt { int value = 0; bool ok = false; };
@@ -1654,9 +1624,14 @@ ParsedInt readInt(QStringView text)
\a format given, or an invalid date if the string cannot be
parsed.
- Note for Qt::TextDate: It is recommended that you use the
- English short month names (e.g. "Jan"). Although localized month
- names can also be used, they depend on the user's locale settings.
+ Note for Qt::TextDate: It is recommended that you use the English short
+ month names (e.g. "Jan"). Although localized month names can also be used in
+ Qt 5, they depend on the user's locale settings.
+
+ \note Support for localized dates, including the format options
+ Qt::SystemLocaleDate, Qt::SystemLocaleShortDate, Qt::SystemLocaleLongDate,
+ Qt::LocaleDate, Qt::DefaultLocaleShortDate, and Qt::DefaultLocaleLongDate,
+ shall be removed in Qt 6. Use QLocale::toDate() instead.
\sa toString(), QLocale::toDate()
*/
@@ -1667,6 +1642,7 @@ QDate QDate::fromString(const QString &string, Qt::DateFormat format)
return QDate();
switch (format) {
+#if QT_DEPRECATED_SINCE(5, 15)
case Qt::SystemLocaleDate:
case Qt::SystemLocaleShortDate:
return QLocale::system().toDate(string, QLocale::ShortFormat);
@@ -1677,10 +1653,10 @@ QDate QDate::fromString(const QString &string, Qt::DateFormat format)
return QLocale().toDate(string, QLocale::ShortFormat);
case Qt::DefaultLocaleLongDate:
return QLocale().toDate(string, QLocale::LongFormat);
+#endif // 5.15
case Qt::RFC2822Date:
return rfcDateImpl(string).date;
default:
-#if QT_CONFIG(textdate)
case Qt::TextDate: {
QVector<QStringRef> parts = string.splitRef(QLatin1Char(' '), QString::SkipEmptyParts);
@@ -1699,7 +1675,6 @@ QDate QDate::fromString(const QString &string, Qt::DateFormat format)
return QDate(year, month, day);
}
-#endif // textdate
case Qt::ISODate:
// Semi-strict parsing, must be long enough and have punctuators as separators
if (string.size() >= 10 && string.at(4).isPunct() && string.at(7).isPunct()
@@ -2014,7 +1989,7 @@ int QTime::msec() const
return ds() % 1000;
}
-#if QT_CONFIG(datestring)
+#if QT_CONFIG(datestring) // depends on, so implies, textdate
/*!
\overload
@@ -2030,18 +2005,15 @@ int QTime::msec() const
date, use the \a format Qt::ISODateWithMs, which corresponds to
HH:mm:ss.zzz.
- If the \a format is Qt::SystemLocaleShortDate or
- Qt::SystemLocaleLongDate, the string format depends on the locale
- settings of the system. Identical to calling
- QLocale::system().toString(time, QLocale::ShortFormat) or
- QLocale::system().toString(time, QLocale::LongFormat).
-
- If the \a format is Qt::DefaultLocaleShortDate or
- Qt::DefaultLocaleLongDate, the string format depends on the
- default application locale. This is the locale set with
- QLocale::setDefault(), or the system locale if no default locale
- has been set. Identical to calling
+ The \a format options Qt::SystemLocaleDate:, Qt::SystemLocaleShortDate and
+ Qt::SystemLocaleLongDate shall be removed in Qt 6. Their use should be
+ replaced with:
+ \l {QLocale::toString()}{QLocale::system().toString(time, QLocale::ShortFormat)} or
+ \l {QLocale::toString()}{QLocale::system().toString(time, QLocale::LongFormat)}.
+ The \a format options Qt::LocaleDate, Qt::DefaultLocaleShortDate and
+ Qt::DefaultLocaleLongDate shall be removed in Qt 6. Their use should be
+ replaced with:
\l {QLocale::toString()}{QLocale().toString(time, QLocale::ShortFormat)} or
\l {QLocale::toString()}{QLocale().toString(time, QLocale::LongFormat)}.
@@ -2060,6 +2032,7 @@ QString QTime::toString(Qt::DateFormat format) const
return QString();
switch (format) {
+#if QT_DEPRECATED_SINCE(5, 15)
case Qt::SystemLocaleDate:
case Qt::SystemLocaleShortDate:
return QLocale::system().toString(*this, QLocale::ShortFormat);
@@ -2070,6 +2043,7 @@ QString QTime::toString(Qt::DateFormat format) const
return QLocale().toString(*this, QLocale::ShortFormat);
case Qt::DefaultLocaleLongDate:
return QLocale().toString(*this, QLocale::LongFormat);
+#endif // 5.15
case Qt::ISODateWithMs:
return QString::asprintf("%02d:%02d:%02d.%03d", hour(), minute(), second(), msec());
case Qt::RFC2822Date:
@@ -2347,7 +2321,7 @@ int QTime::msecsTo(const QTime &t) const
\sa QDateTime::currentDateTime(), QDateTime::currentDateTimeUtc()
*/
-#if QT_CONFIG(datestring)
+#if QT_CONFIG(datestring) // depends on, so implies, textdate
static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *isMidnight24)
{
@@ -2445,6 +2419,12 @@ static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *
fails for the default locale). This should be considered an
implementation detail.
+
+ \note Support for localized dates, including the format options
+ Qt::SystemLocaleDate, Qt::SystemLocaleShortDate, Qt::SystemLocaleLongDate,
+ Qt::LocaleDate, Qt::DefaultLocaleShortDate, and Qt::DefaultLocaleLongDate,
+ shall be removed in Qt 6. Use QLocale::toTime() instead.
+
\sa toString(), QLocale::toTime()
*/
QTime QTime::fromString(const QString &string, Qt::DateFormat format)
@@ -2453,6 +2433,7 @@ QTime QTime::fromString(const QString &string, Qt::DateFormat format)
return QTime();
switch (format) {
+#if QT_DEPRECATED_SINCE(5, 15)
case Qt::SystemLocaleDate:
case Qt::SystemLocaleShortDate:
return QLocale::system().toTime(string, QLocale::ShortFormat);
@@ -2463,6 +2444,7 @@ QTime QTime::fromString(const QString &string, Qt::DateFormat format)
return QLocale().toTime(string, QLocale::ShortFormat);
case Qt::DefaultLocaleLongDate:
return QLocale().toTime(string, QLocale::LongFormat);
+#endif // 5.15
case Qt::RFC2822Date:
return rfcDateImpl(string).time;
case Qt::ISODate:
@@ -2877,7 +2859,7 @@ static void msecsToTime(qint64 msecs, QDate *date, QTime *time)
}
// Converts a date/time value into msecs
-static qint64 timeToMSecs(const QDate &date, const QTime &time)
+static qint64 timeToMSecs(QDate date, QTime time)
{
return ((date.toJulianDay() - JULIAN_DAY_FOR_EPOCH) * MSECS_PER_DAY)
+ time.msecsSinceStartOfDay();
@@ -3222,7 +3204,7 @@ static void setTimeSpec(QDateTimeData &d, Qt::TimeSpec spec, int offsetSeconds)
}
}
-static void setDateTime(QDateTimeData &d, const QDate &date, const QTime &time)
+static void setDateTime(QDateTimeData &d, QDate date, QTime time)
{
// If the date is valid and the time is not we set time to 00:00:00
QTime useTime = time;
@@ -3631,15 +3613,18 @@ QDateTime::QDateTime() noexcept(Data::CanBeSmall)
}
+#if QT_DEPRECATED_SINCE(5, 17) // ### Qt 6: remove
/*!
- Constructs a datetime with the given \a date, a valid
- time(00:00:00.000), and sets the timeSpec() to Qt::LocalTime.
-*/
+ Constructs a datetime with the given \a date, using Qt::LocalTime as the
+ timeSpec() and the time at the start of that date.
+ \sa QDate::startOfDay()
+*/
QDateTime::QDateTime(const QDate &date)
- : d(QDateTimePrivate::create(date, QTime(0, 0), Qt::LocalTime, 0))
+ : QDateTime(date.startOfDay(Qt::LocalTime, 0))
{
}
+#endif
/*!
Constructs a datetime with the given \a date and \a time, using
@@ -4292,13 +4277,16 @@ void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
}
#endif
-#if QT_CONFIG(datestring)
+#if QT_CONFIG(datestring) // depends on, so implies, textdate
/*!
\fn QString QDateTime::toString(Qt::DateFormat format) const
+ \fn QString QDateTime::toString(Qt::DateFormat format, QCalendar cal) const
\overload
- Returns the datetime as a string in the \a format given.
+ Returns the datetime as a string in the \a format given. If \cal is
+ supplied, it determines the calendar used to represent the date; it defaults
+ to Gregorian.
If the \a format is Qt::TextDate, the string is formatted in the default
way. The day and month names will be localized names using the system
@@ -4315,19 +4303,17 @@ void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
date, use the \a format Qt::ISODateWithMs, which corresponds to
yyyy-MM-ddTHH:mm:ss.zzz[Z|[+|-]HH:mm].
- If the \a format is Qt::SystemLocaleShortDate or
- Qt::SystemLocaleLongDate, the string format depends on the locale
- settings of the system. Identical to calling
- QLocale::system().toString(datetime, QLocale::ShortFormat) or
- QLocale::system().toString(datetime, QLocale::LongFormat).
+ The \a format options Qt::SystemLocaleDate, Qt::SystemLocaleShortDate and
+ Qt::SystemLocaleLongDate shall be removed in Qt 6. Their use should be
+ replaced with
+ \l {QLocale::toString()}{QLocale::system().toString(datetime, QLocale::ShortFormat)} or
+ \l {QLocale::toString()}{QLocale::system().toString(datetime, QLocale::LongFormat)}.
- If the \a format is Qt::DefaultLocaleShortDate or
- Qt::DefaultLocaleLongDate, the string format depends on the
- default application locale. This is the locale set with
- QLocale::setDefault(), or the system locale if no default locale
- has been set. Identical to calling QLocale().toString(datetime,
- QLocale::ShortFormat) or QLocale().toString(datetime,
- QLocale::LongFormat).
+ The \a format options Qt::LocaleDate, Qt::DefaultLocaleShortDate and
+ Qt::DefaultLocaleLongDate shall be removed in Qt 6. Their use should be
+ replaced with
+ \l {QLocale::toString()}{QLocale().toString(datetime, QLocale::ShortFormat)} or
+ \l {QLocale::toString()}{QLocale().toString(datetime, QLocale::LongFormat)}.
If the \a format is Qt::RFC2822Date, the string is formatted
following \l{RFC 2822}.
@@ -4335,8 +4321,7 @@ void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
If the datetime is invalid, an empty string will be returned.
\warning The Qt::ISODate format is only valid for years in the
- range 0 to 9999. This restriction may apply to locale-aware
- formats as well, depending on the locale settings.
+ range 0 to 9999.
\sa fromString(), QDate::toString(), QTime::toString(),
QLocale::toString()
@@ -4344,31 +4329,37 @@ void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
QString QDateTime::toString(Qt::DateFormat format) const
{
+ return toString(format, QCalendar());
+}
+
+QString QDateTime::toString(Qt::DateFormat format, QCalendar cal) const
+{
QString buf;
if (!isValid())
return buf;
switch (format) {
+#if QT_DEPRECATED_SINCE(5, 15)
case Qt::SystemLocaleDate:
case Qt::SystemLocaleShortDate:
- return QLocale::system().toString(*this, QLocale::ShortFormat);
+ return QLocale::system().toString(*this, QLocale::ShortFormat, cal);
case Qt::SystemLocaleLongDate:
- return QLocale::system().toString(*this, QLocale::LongFormat);
+ return QLocale::system().toString(*this, QLocale::LongFormat, cal);
case Qt::LocaleDate:
case Qt::DefaultLocaleShortDate:
- return QLocale().toString(*this, QLocale::ShortFormat);
+ return QLocale().toString(*this, QLocale::ShortFormat, cal);
case Qt::DefaultLocaleLongDate:
- return QLocale().toString(*this, QLocale::LongFormat);
+ return QLocale().toString(*this, QLocale::LongFormat, cal);
+#endif // 5.15
case Qt::RFC2822Date: {
- buf = QLocale::c().toString(*this, u"dd MMM yyyy hh:mm:ss ");
+ buf = QLocale::c().toString(*this, u"dd MMM yyyy hh:mm:ss ", cal);
buf += toOffsetString(Qt::TextDate, offsetFromUtc());
return buf;
}
default:
-#if QT_CONFIG(textdate)
case Qt::TextDate: {
const QPair<QDate, QTime> p = getDateTime(d);
- buf = p.first.toString(Qt::TextDate);
+ buf = toStringTextDate(p.first, cal);
// Insert time between date's day and year:
buf.insert(buf.lastIndexOf(QLatin1Char(' ')),
QLatin1Char(' ') + p.second.toString(Qt::TextDate));
@@ -4376,11 +4367,11 @@ QString QDateTime::toString(Qt::DateFormat format) const
switch (timeSpec()) {
case Qt::LocalTime:
break;
-# if QT_CONFIG(timezone)
+#if QT_CONFIG(timezone)
case Qt::TimeZone:
buf += QLatin1Char(' ') + d->m_timeZone.abbreviation(*this);
break;
-# endif
+#endif
default:
buf += QLatin1String(" GMT");
if (getSpec(d) == Qt::OffsetFromUTC)
@@ -4388,17 +4379,14 @@ QString QDateTime::toString(Qt::DateFormat format) const
}
return buf;
}
-#endif
case Qt::ISODate:
case Qt::ISODateWithMs: {
+ // No calendar dependence
const QPair<QDate, QTime> p = getDateTime(d);
- const QDate &dt = p.first;
- const QTime &tm = p.second;
- buf = dt.toString(Qt::ISODate);
+ buf = toStringIsoDate(p.first);
if (buf.isEmpty())
return QString(); // failed to convert
- buf += QLatin1Char('T');
- buf += tm.toString(format);
+ buf += QLatin1Char('T') + p.second.toString(format);
switch (getSpec(d)) {
case Qt::UTC:
buf += QLatin1Char('Z');
@@ -4419,11 +4407,15 @@ QString QDateTime::toString(Qt::DateFormat format) const
/*!
\fn QString QDateTime::toString(const QString &format) const
+ \fn QString QDateTime::toString(const QString &format, QCalendar cal) const
\fn QString QDateTime::toString(QStringView format) const
+ \fn QString QDateTime::toString(QStringView format, QCalendar cal) const
Returns the datetime as a string. The \a format parameter determines the
- format of the result string. See QTime::toString() and QDate::toString() for
- the supported specifiers for time and date, respectively.
+ format of the result string. If \cal is supplied, it determines the calendar
+ used to represent the date; it defaults to Gregorian. See QTime::toString()
+ and QDate::toString() for the supported specifiers for time and date,
+ respectively.
Any sequence of characters enclosed in single quotes will be included
verbatim in the output string (stripped of the quotes), even if it contains
@@ -4454,13 +4446,23 @@ QString QDateTime::toString(Qt::DateFormat format) const
*/
QString QDateTime::toString(QStringView format) const
{
- return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
+ return toString(format, QCalendar());
+}
+
+QString QDateTime::toString(QStringView format, QCalendar cal) const
+{
+ return QLocale::system().toString(*this, format, cal); // QLocale::c() ### Qt6
}
#if QT_STRINGVIEW_LEVEL < 2
QString QDateTime::toString(const QString &format) const
{
- return toString(qToStringViewIgnoringNull(format));
+ return toString(qToStringViewIgnoringNull(format), QCalendar());
+}
+
+QString QDateTime::toString(const QString &format, QCalendar cal) const
+{
+ return toString(qToStringViewIgnoringNull(format), cal);
}
#endif
@@ -5202,15 +5204,20 @@ int QDateTime::utcOffset() const
}
#endif // QT_DEPRECATED_SINCE
-#if QT_CONFIG(datestring)
+#if QT_CONFIG(datestring) // depends on, so implies, textdate
/*!
Returns the QDateTime represented by the \a string, using the
\a format given, or an invalid datetime if this is not possible.
- Note for Qt::TextDate: It is recommended that you use the
- English short month names (e.g. "Jan"). Although localized month
- names can also be used, they depend on the user's locale settings.
+ Note for Qt::TextDate: It is recommended that you use the English short
+ month names (e.g. "Jan"). Although localized month names can also be used in
+ Qt 5, they depend on the user's locale settings.
+
+ \note Support for localized dates, including the format options
+ Qt::SystemLocaleDate, Qt::SystemLocaleShortDate, Qt::SystemLocaleLongDate,
+ Qt::LocaleDate, Qt::DefaultLocaleShortDate, and Qt::DefaultLocaleLongDate,
+ shall be removed in Qt 6. Use QLocale::toDateTime() instead.
\sa toString(), QLocale::toDateTime()
*/
@@ -5220,6 +5227,7 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
return QDateTime();
switch (format) {
+#if QT_DEPRECATED_SINCE(5, 15)
case Qt::SystemLocaleDate:
case Qt::SystemLocaleShortDate:
return QLocale::system().toDateTime(string, QLocale::ShortFormat);
@@ -5230,6 +5238,7 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
return QLocale().toDateTime(string, QLocale::ShortFormat);
case Qt::DefaultLocaleLongDate:
return QLocale().toDateTime(string, QLocale::LongFormat);
+#endif // 5.15
case Qt::RFC2822Date: {
const ParsedRfcDateTime rfc = rfcDateImpl(string);
@@ -5306,7 +5315,6 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
date = date.addDays(1);
return QDateTime(date, time, spec, offset);
}
-#if QT_CONFIG(textdate)
case Qt::TextDate: {
QVector<QStringRef> parts = string.splitRef(QLatin1Char(' '), QString::SkipEmptyParts);
@@ -5412,7 +5420,6 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
return QDateTime(date, time, Qt::UTC);
}
}
-#endif // textdate
}
return QDateTime();
diff --git a/src/corelib/time/qdatetime.h b/src/corelib/time/qdatetime.h
index 3eae8ebf64..c1653b5585 100644
--- a/src/corelib/time/qdatetime.h
+++ b/src/corelib/time/qdatetime.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -110,14 +110,15 @@ public:
static QString longDayName(int weekday, MonthNameType type = DateFormat);
#endif // textdate && deprecated
#if QT_CONFIG(datestring)
- QString toString(Qt::DateFormat f = Qt::TextDate) const;
+ QString toString(Qt::DateFormat format = Qt::TextDate) const;
+ QString toString(Qt::DateFormat format, QCalendar cal) const;
+
#if QT_STRINGVIEW_LEVEL < 2
QString toString(const QString &format) const;
QString toString(const QString &format, QCalendar cal) const;
#endif
QString toString(QStringView format) const;
- QString toString(Qt::DateFormat f, QCalendar cal) const;
QString toString(QStringView format, QCalendar cal) const;
#endif
#if QT_DEPRECATED_SINCE(5,0)
@@ -287,7 +288,9 @@ class Q_CORE_EXPORT QDateTime
public:
QDateTime() noexcept(Data::CanBeSmall);
- explicit QDateTime(const QDate &); // ### Qt 6: plain QDate, QTime
+#if QT_DEPRECATED_SINCE(5, 15) // ### Qt 6: remove
+ QT_DEPRECATED_X("Use QDate::startOfDay()") explicit QDateTime(const QDate &);
+#endif
QDateTime(const QDate &, const QTime &, Qt::TimeSpec spec = Qt::LocalTime);
// ### Qt 6: Merge with above with default offsetSeconds = 0
QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec, int offsetSeconds);
@@ -330,11 +333,14 @@ public:
void setSecsSinceEpoch(qint64 secs);
#if QT_CONFIG(datestring)
- QString toString(Qt::DateFormat f = Qt::TextDate) const;
+ QString toString(Qt::DateFormat format = Qt::TextDate) const;
+ QString toString(Qt::DateFormat format, QCalendar cal) const;
#if QT_STRINGVIEW_LEVEL < 2
QString toString(const QString &format) const;
+ QString toString(const QString &format, QCalendar cal) const;
#endif
QString toString(QStringView format) const;
+ QString toString(QStringView format, QCalendar cal) const;
#endif
Q_REQUIRED_RESULT QDateTime addDays(qint64 days) const;
Q_REQUIRED_RESULT QDateTime addMonths(int months) const;
diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp
index 70460ae632..790c20004a 100644
--- a/src/corelib/time/qdatetimeparser.cpp
+++ b/src/corelib/time/qdatetimeparser.cpp
@@ -219,7 +219,8 @@ int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
const SectionNode &sn = sectionNode(s);
switch (sn.type) {
#if QT_CONFIG(timezone)
- case TimeZoneSection: return QTimeZone::MaxUtcOffsetSecs;
+ case TimeZoneSection:
+ return QTimeZone::MaxUtcOffsetSecs;
#endif
case Hour24Section:
case Hour12Section:
@@ -227,20 +228,25 @@ int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
// We want it to be 23 for the stepBy case.
return 23;
case MinuteSection:
- case SecondSection: return 59;
- case MSecSection: return 999;
+ case SecondSection:
+ return 59;
+ case MSecSection:
+ return 999;
case YearSection2Digits:
case YearSection:
// sectionMaxSize will prevent people from typing in a larger number in
// count == 2 sections; stepBy() will work on real years anyway.
return 9999;
- case MonthSection: return calendar.maximumMonthsInYear();
+ case MonthSection:
+ return calendar.maximumMonthsInYear();
case DaySection:
case DayOfWeekSectionShort:
case DayOfWeekSectionLong:
return cur.isValid() ? cur.date().daysInMonth(calendar) : calendar.maximumDaysInMonth();
- case AmPmSection: return 1;
- default: break;
+ case AmPmSection:
+ return 1;
+ default:
+ break;
}
qWarning("QDateTimeParser::absoluteMax() Internal error (%ls)",
qUtf16Printable(sn.name()));
@@ -620,7 +626,8 @@ int QDateTimeParser::sectionMaxSize(Section s, int count) const
switch (s) {
case FirstSection:
case NoSection:
- case LastSection: return 0;
+ case LastSection:
+ return 0;
case AmPmSection: {
const int lowerMax = qMax(getAmPmText(AmText, LowerCase).size(),
@@ -634,7 +641,9 @@ int QDateTimeParser::sectionMaxSize(Section s, int count) const
case Hour12Section:
case MinuteSection:
case SecondSection:
- case DaySection: return 2;
+ case DaySection:
+ return 2;
+
case DayOfWeekSectionShort:
case DayOfWeekSectionLong:
#if !QT_CONFIG(textdate)
@@ -663,11 +672,15 @@ int QDateTimeParser::sectionMaxSize(Section s, int count) const
return ret;
}
#endif
- case MSecSection: return 3;
- case YearSection: return 4;
- case YearSection2Digits: return 2;
+ case MSecSection:
+ return 3;
+ case YearSection:
+ return 4;
+ case YearSection2Digits:
+ return 2;
+ case TimeZoneSection:
// Arbitrarily many tokens (each up to 14 bytes) joined with / separators:
- case TimeZoneSection: return std::numeric_limits<int>::max();
+ return std::numeric_limits<int>::max();
case CalendarPopupSection:
case Internal:
@@ -903,7 +916,7 @@ QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
by \a weekDay.
*/
-static int weekDayWithinMonth(const QCalendar &calendar, const QDate &rough, int weekDay)
+static int weekDayWithinMonth(QCalendar calendar, QDate rough, int weekDay)
{
// TODO: can we adapt this to cope gracefully with intercallary days (day of
// week > 7) without making it slower for more widely-used calendars ?
diff --git a/src/corelib/time/qtimezoneprivate_win.cpp b/src/corelib/time/qtimezoneprivate_win.cpp
index 0fec5355b2..0aaf469ed9 100644
--- a/src/corelib/time/qtimezoneprivate_win.cpp
+++ b/src/corelib/time/qtimezoneprivate_win.cpp
@@ -363,7 +363,7 @@ QDate calculateTransitionLocalDate(const SYSTEMTIME &rule, int year)
}
// Converts a date/time value into msecs
-inline qint64 timeToMSecs(const QDate &date, const QTime &time)
+inline qint64 timeToMSecs(QDate date, QTime time)
{
return ((date.toJulianDay() - JULIAN_DAY_FOR_EPOCH) * MSECS_PER_DAY)
+ time.msecsSinceStartOfDay();
diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp
index a1dd537d4d..12ad6f4573 100644
--- a/src/corelib/tools/qbitarray.cpp
+++ b/src/corelib/tools/qbitarray.cpp
@@ -305,7 +305,7 @@ void QBitArray::fill(bool value, int begin, int end)
\since 5.11
Returns a pointer to a dense bit array for this QBitArray. Bits are counted
- upwards from the least significant bit in each byte. The the number of bits
+ upwards from the least significant bit in each byte. The number of bits
relevant in the last byte is given by \c{size() % 8}.
\sa fromBits(), size()
diff --git a/src/corelib/tools/qcontainerfwd.h b/src/corelib/tools/qcontainerfwd.h
index f6efa99b6a..d6e30d77e3 100644
--- a/src/corelib/tools/qcontainerfwd.h
+++ b/src/corelib/tools/qcontainerfwd.h
@@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE
template <class Key, class T> class QCache;
template <class Key, class T> class QHash;
-#ifndef QT_NO_LINKED_LIST
+#if !defined(QT_NO_LINKED_LIST) && QT_DEPRECATED_SINCE(5, 15)
template <class T> class QLinkedList;
#endif
template <class Key, class T> class QMap;
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index c56324eef7..47fa0520d9 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -1245,6 +1245,7 @@ Q_OUTOFLINE_TEMPLATE int QMultiHash<Key, T>::count(const Key &akey) const
return cnt;
}
+#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
template <class Key, class T>
class QHashIterator
{
@@ -1419,6 +1420,7 @@ public:
}
#endif
};
+#endif // !QT_NO_JAVA_STYLE_ITERATORS
template <class Key, class T>
uint qHash(const QHash<Key, T> &key, uint seed = 0)
diff --git a/src/corelib/tools/qiterator.qdoc b/src/corelib/tools/qiterator.qdoc
index b4d332b7b1..3531fb202c 100644
--- a/src/corelib/tools/qiterator.qdoc
+++ b/src/corelib/tools/qiterator.qdoc
@@ -203,6 +203,7 @@
/*!
\class QLinkedListIterator
\inmodule QtCore
+ \obsolete
\brief The QLinkedListIterator class provides a Java-style const iterator for QLinkedList.
@@ -416,6 +417,7 @@
/*!
\class QMutableLinkedListIterator
\inmodule QtCore
+ \obsolete
\brief The QMutableLinkedListIterator class provides a Java-style non-const iterator for QLinkedList.
diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp
index 3b1bc8aab1..6a423545da 100644
--- a/src/corelib/tools/qlinkedlist.cpp
+++ b/src/corelib/tools/qlinkedlist.cpp
@@ -45,6 +45,11 @@
QT_BEGIN_NAMESPACE
+#if QT_DEPRECATED_SINCE(5, 15)
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+
const QLinkedListData QLinkedListData::shared_null = {
const_cast<QLinkedListData *>(&QLinkedListData::shared_null),
const_cast<QLinkedListData *>(&QLinkedListData::shared_null),
@@ -53,6 +58,7 @@ const QLinkedListData QLinkedListData::shared_null = {
/*! \class QLinkedList
\inmodule QtCore
+ \obsolete
\brief The QLinkedList class is a template class that provides linked lists.
\ingroup tools
@@ -60,6 +66,8 @@ const QLinkedListData QLinkedListData::shared_null = {
\reentrant
+ \note This class is obsolete, please use std::list instead.
+
QLinkedList\<T\> is one of Qt's generic \l{container classes}. It
stores a list of values and provides iterator-based access as
well as \l{constant time} insertions and removals.
@@ -720,6 +728,7 @@ const QLinkedListData QLinkedListData::shared_null = {
/*! \class QLinkedList::iterator
\inmodule QtCore
+ \obsolete
\brief The QLinkedList::iterator class provides an STL-style non-const iterator for QLinkedList.
QLinkedList features both \l{STL-style iterators} and
@@ -965,6 +974,7 @@ const QLinkedListData QLinkedListData::shared_null = {
/*! \class QLinkedList::const_iterator
\inmodule QtCore
+ \obsolete
\brief The QLinkedList::const_iterator class provides an STL-style const iterator for QLinkedList.
QLinkedList features both \l{STL-style iterators} and
@@ -1221,4 +1231,8 @@ const QLinkedListData QLinkedListData::shared_null = {
\sa fromStdList()
*/
+QT_WARNING_POP
+
+#endif // QT_DEPRECATED_SINCE(5, 15)
+
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h
index e3713d2c1c..fd3df74059 100644
--- a/src/corelib/tools/qlinkedlist.h
+++ b/src/corelib/tools/qlinkedlist.h
@@ -55,10 +55,22 @@
#include <iterator>
#include <list>
-QT_BEGIN_NAMESPACE
+#if 0
+// This is needed because of QTBUG-80347
+#pragma qt_class(QLinkedList)
+#pragma qt_class(QLinkedListData)
+#pragma qt_class(QLinkedListNode)
+#endif
+
+#if QT_DEPRECATED_SINCE(5, 15)
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
-struct Q_CORE_EXPORT QLinkedListData
+QT_BEGIN_NAMESPACE
+
+struct QT_DEPRECATED_VERSION_5_15 Q_CORE_EXPORT QLinkedListData
{
QLinkedListData *n, *p;
QtPrivate::RefCount ref;
@@ -69,7 +81,7 @@ struct Q_CORE_EXPORT QLinkedListData
};
template <typename T>
-struct QLinkedListNode
+struct QT_DEPRECATED_VERSION_5_15 QLinkedListNode
{
inline QLinkedListNode(const T &arg): t(arg) { }
QLinkedListNode *n, *p;
@@ -77,7 +89,7 @@ struct QLinkedListNode
};
template <class T>
-class QLinkedList
+class QT_DEPRECATED_VERSION_X_5_15("Use std::list instead") QLinkedList
{
typedef QLinkedListNode<T> Node;
union { QLinkedListData *d; QLinkedListNode<T> *e; };
@@ -591,6 +603,10 @@ QT_END_NAMESPACE
Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(QLinkedList)
+QT_WARNING_POP
+
+#endif // QT_DEPRECATED_SINCE(5, 15)
+
#endif // QT_NO_LINKED_LIST
#endif // QLINKEDLIST_H
diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp
index e2b7705b55..9b9c67e42b 100644
--- a/src/corelib/tools/qmap.cpp
+++ b/src/corelib/tools/qmap.cpp
@@ -1999,7 +1999,7 @@ void QMapDataBase::freeData(QMapDataBase *d)
\sa replace()
*/
-/*! \fn template <class Key, class T> typename QMap<Key, T>::iterator QMultiMap<Key, T>::insert(typename QMap<Key, T>::const_iterator pos, const Key &key, const T &value)
+/*! \fn template <class Key, class T> typename QMultiMap<Key, T>::iterator QMultiMap<Key, T>::insert(typename QMultiMap<Key, T>::const_iterator pos, const Key &key, const T &value)
\since 5.1
Inserts a new item with the key \a key and value \a value and with hint \a pos
diff --git a/src/corelib/tools/qscopeguard.h b/src/corelib/tools/qscopeguard.h
index 40d2747b1d..6a5bc6cc61 100644
--- a/src/corelib/tools/qscopeguard.h
+++ b/src/corelib/tools/qscopeguard.h
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com>
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -42,13 +43,11 @@
#include <QtCore/qglobal.h>
+#include <type_traits>
+#include <utility>
QT_BEGIN_NAMESPACE
-
-template <typename F> class QScopeGuard;
-template <typename F> QScopeGuard<F> qScopeGuard(F f);
-
template <typename F>
class
#if __has_cpp_attribute(nodiscard)
@@ -59,13 +58,23 @@ Q_REQUIRED_RESULT
QScopeGuard
{
public:
+ explicit QScopeGuard(F &&f) noexcept
+ : m_func(std::move(f))
+ {
+ }
+
+ explicit QScopeGuard(const F &f) noexcept
+ : m_func(f)
+ {
+ }
+
QScopeGuard(QScopeGuard &&other) noexcept
: m_func(std::move(other.m_func))
, m_invoke(qExchange(other.m_invoke, false))
{
}
- ~QScopeGuard()
+ ~QScopeGuard() noexcept
{
if (m_invoke)
m_func();
@@ -77,26 +86,23 @@ public:
}
private:
- explicit QScopeGuard(F &&f) noexcept
- : m_func(std::move(f))
- {
- }
-
Q_DISABLE_COPY(QScopeGuard)
F m_func;
bool m_invoke = true;
- friend QScopeGuard qScopeGuard<F>(F);
};
+#ifdef __cpp_deduction_guides
+template <typename F> QScopeGuard(F(&)()) -> QScopeGuard<F(*)()>;
+#endif
template <typename F>
#if __has_cpp_attribute(nodiscard)
Q_REQUIRED_RESULT
#endif
-QScopeGuard<F> qScopeGuard(F f)
+QScopeGuard<typename std::decay<F>::type> qScopeGuard(F &&f)
{
- return QScopeGuard<F>(std::move(f));
+ return QScopeGuard<typename std::decay<F>::type>(std::forward<F>(f));
}
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qscopeguard.qdoc b/src/corelib/tools/qscopeguard.qdoc
index 6b3c942e84..572934d890 100644
--- a/src/corelib/tools/qscopeguard.qdoc
+++ b/src/corelib/tools/qscopeguard.qdoc
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com>
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -35,6 +36,30 @@ QT_BEGIN_NAMESPACE
\inmodule QtCore
\brief Provides a scope guard for calling a function at the end of
a scope.
+
+ QScopeGuard<F> is a class of which the sole purpose is to run the function
+ \a f in its destructor. This is useful for guaranteeing
+ your cleanup code is executed, whether the function is exited normally,
+ exited early by a return statement, or exited by an exception.
+
+ \note Exceptions are not supported. The callable shouldn't throw when
+ executed, copied or moved.
+
+ \sa QScopedValueRollback
+*/
+
+/*!
+ \fn template <typename F> QScopeGuard<F>::QScopeGuard(F &&f)
+ \fn template <typename F> QScopeGuard<F>::QScopeGuard(const F &f)
+
+ Create a scope guard that will execute \a f at the end of the scope.
+
+ If \e F is a lambda, its type cannot be written. In that case you need to
+ either rely on class template argument deduction (C++17 feature) and leave
+ the template parameter out completely or use the helper function
+ qScopeGuard() instead of this constructor.
+
+ \since 5.15
*/
/*! \fn template <typename F> void QScopeGuard<F>::dismiss()
@@ -51,23 +76,17 @@ QT_BEGIN_NAMESPACE
of the scope.
\ingroup misc
- QScopeGuard<F> is a class of which the sole purpose is to run the function
- \a f in its destructor. This is useful for guaranteeing
- your cleanup code is executed, whether the function is exited normally,
- exited early by a return statement, or exited by an exception.
+ Create a scope guard that will execute \a f at the end of the scope.
- If \e F is a lambda then you cannot instantiate the template directly,
- therefore the qScopeGuard() helper is provided and QScopeGuard<F> is made a
- private implementation detail.
+ This helper function is provided so that you can easily construct a
+ QScopeGuard without having to name the template parameter for the type of
+ the callable. If \e F is a lambda then you cannot write its type and relying
+ on this helper or class template argument deduction is necessary.
Example usage is as follows:
\snippet code/src_corelib_tools_qscopeguard.cpp 0
- \note Exceptions are not supported. The callable shouldn't throw when
- executed, copied or moved.
-
- \sa QScopedValueRollback
*/
QT_END_NAMESPACE
diff --git a/src/gui/.prev_CMakeLists.txt b/src/gui/.prev_CMakeLists.txt
index f8529ba650..933a8eae6d 100644
--- a/src/gui/.prev_CMakeLists.txt
+++ b/src/gui/.prev_CMakeLists.txt
@@ -456,7 +456,7 @@ if(NOT ANDROID)
)
endif()
-qt_extend_target(Gui CONDITION ANDROID AND TEST_architecture_arch STREQUAL arm64
+qt_extend_target(Gui CONDITION (NOT (NOT ANDROID)) AND (TEST_architecture_arch STREQUAL arm64 ORTEST_architecture_arch STREQUAL arm)
SOURCES
image/qimage_neon.cpp
painting/qdrawhelper_neon.cpp painting/qdrawhelper_neon_p.h
@@ -502,6 +502,8 @@ qt_extend_target(Gui CONDITION QT_FEATURE_system_textmarkdownreader AND QT_FEATU
qt_extend_target(Gui CONDITION QT_FEATURE_textmarkdownreader AND NOT QT_FEATURE_system_textmarkdownreader
SOURCES
../3rdparty/md4c/md4c.c ../3rdparty/md4c/md4c.h
+ DEFINES
+ MD4C_USE_UTF8
INCLUDE_DIRECTORIES
../3rdparty/md4c
)
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index ab1b3884cb..3e93b1ddea 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -538,7 +538,7 @@ if(NOT ANDROID)
)
endif()
-qt_extend_target(Gui CONDITION ANDROID AND TEST_architecture_arch STREQUAL arm64
+qt_extend_target(Gui CONDITION ANDROID AND (TEST_architecture_arch STREQUAL arm64 OR TEST_architecture_arch STREQUAL arm) # special case
SOURCES
image/qimage_neon.cpp
painting/qdrawhelper_neon.cpp painting/qdrawhelper_neon_p.h
@@ -603,6 +603,8 @@ qt_extend_target(Gui CONDITION QT_FEATURE_system_textmarkdownreader AND QT_FEATU
qt_extend_target(Gui CONDITION QT_FEATURE_textmarkdownreader AND NOT QT_FEATURE_system_textmarkdownreader
SOURCES
../3rdparty/md4c/md4c.c ../3rdparty/md4c/md4c.h
+ DEFINES
+ MD4C_USE_UTF8
INCLUDE_DIRECTORIES
../3rdparty/md4c
)
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h
index 2220efd5cb..f7564a3076 100644
--- a/src/gui/accessible/qaccessible.h
+++ b/src/gui/accessible/qaccessible.h
@@ -280,7 +280,7 @@ public:
HotkeyField = 0x00000032,
Slider = 0x00000033,
SpinBox = 0x00000034,
- Canvas = 0x00000035, // Diagram for MSAA
+ Canvas = 0x00000035, // MSAA: ROLE_SYSTEM_DIAGRAM - The object represents a graphical image that is used to diagram data.
Animation = 0x00000036,
Equation = 0x00000037,
ButtonDropDown = 0x00000038, // The object represents a button that expands a grid.
@@ -302,7 +302,7 @@ public:
Notification = 0x00000086,
// IAccessible2 roles
- // IA2_ROLE_CANVAS = 0x401, ### Qt 6 use this one instead of Canvas above
+ // IA2_ROLE_CANVAS = 0x401, // An object that can be drawn into and to manage events from the objects drawn into it
// IA2_ROLE_CAPTION = 0x402,
// IA2_ROLE_CHECK_MENU_ITEM = 0x403,
ColorChooser = 0x404,
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri
index 760b737ec3..0c033609c4 100644
--- a/src/gui/image/image.pri
+++ b/src/gui/image/image.pri
@@ -92,7 +92,7 @@ qtConfig(png) {
MIPS_DSPR2_ASM += image/qimage_mips_dspr2_asm.S
} else {
# see https://developer.android.com/ndk/guides/abis
- arm64-v8a {
+ arm64-v8a | armeabi-v7a {
SOURCES += image/qimage_neon.cpp
}
x86 | x86_64 {
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 38285dd827..41fe649fc5 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -1527,7 +1527,7 @@ QDebug operator<<(QDebug dbg, const QIcon &i)
\internal
\since 5.6
Attempts to find a suitable @Nx file for the given \a targetDevicePixelRatio
- Returns the the \a baseFileName if no such file was found.
+ Returns the \a baseFileName if no such file was found.
Given base foo.png and a target dpr of 2.5, this function will look for
foo@3x.png, then foo@2x, then fall back to foo.png if not found.
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 738aa29794..1319d9dffc 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1587,7 +1587,9 @@ const uchar *QImage::scanLine(int i) const
Returns a pointer to the pixel data at the scanline with index \a
i. The first scanline is at index 0.
- The scanline data is aligned on a 32-bit boundary.
+ The scanline data is as minimum 32-bit aligned. For 64-bit formats
+ it follows the native alignment of 64-bit integers (64-bit for most
+ platforms, but notably 32-bit on i386).
Note that QImage uses \l{Implicit Data Sharing} {implicit data
sharing}, but this function does \e not perform a deep copy of the
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 6139cf99c9..3eb1e01863 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -1149,6 +1149,7 @@ bool QImageReader::autoTransform() const
return false;
}
+#if QT_DEPRECATED_SINCE(5, 15)
/*!
\since 5.6
@@ -1181,6 +1182,7 @@ float QImageReader::gamma() const
return d->handler->option(QImageIOHandler::Gamma).toFloat();
return 0.0;
}
+#endif
/*!
Returns \c true if an image can be read for the device (i.e., the
diff --git a/src/gui/image/qimagereader.h b/src/gui/image/qimagereader.h
index 4e9a08b6e6..7cd3b81a7d 100644
--- a/src/gui/image/qimagereader.h
+++ b/src/gui/image/qimagereader.h
@@ -117,8 +117,12 @@ public:
void setAutoTransform(bool enabled);
bool autoTransform() const;
+#if QT_DEPRECATED_SINCE(5, 15)
+ QT_DEPRECATED_VERSION_X_5_15("Use QColorSpace instead")
void setGamma(float gamma);
+ QT_DEPRECATED_VERSION_X_5_15("Use QColorSpace instead")
float gamma() const;
+#endif
QByteArray subType() const;
QList<QByteArray> supportedSubTypes() const;
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index 512da5c432..6e74b23f76 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -498,6 +498,7 @@ int QImageWriter::compression() const
return d->compression;
}
+#if QT_DEPRECATED_SINCE(5, 15)
/*!
This is an image format specific function that sets the gamma
level of the image to \a gamma. For image formats that do not
@@ -522,6 +523,7 @@ float QImageWriter::gamma() const
{
return d->gamma;
}
+#endif
/*!
\since 5.4
diff --git a/src/gui/image/qimagewriter.h b/src/gui/image/qimagewriter.h
index ef84a59b7c..5c8ed7e211 100644
--- a/src/gui/image/qimagewriter.h
+++ b/src/gui/image/qimagewriter.h
@@ -84,8 +84,12 @@ public:
void setCompression(int compression);
int compression() const;
+#if QT_DEPRECATED_SINCE(5, 15)
+ QT_DEPRECATED_VERSION_X_5_15("Use QColorSpace instead")
void setGamma(float gamma);
+ QT_DEPRECATED_VERSION_X_5_15("Use QColorSpace instead")
float gamma() const;
+#endif
void setSubType(const QByteArray &type);
QByteArray subType() const;
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index 49f9550519..8435e5a0fe 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -606,7 +606,7 @@ bool QPngHandlerPrivate::readPngHeader()
#endif
png_uint_32 profLen;
png_get_iCCP(png_ptr, info_ptr, &name, &compressionType, &profileData, &profLen);
- colorSpace = QColorSpace::fromIccProfile(QByteArray::fromRawData((const char *)profileData, profLen));
+ colorSpace = QColorSpace::fromIccProfile(QByteArray((const char *)profileData, profLen));
if (!colorSpace.isValid()) {
qWarning() << "QPngHandler: Failed to parse ICC profile";
} else {
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index 7f6fdafbd0..1efa28a5af 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -621,7 +621,7 @@ const QBitmap *QCursor::mask() const
QBitmap bmpVal = cursor->bitmap();
\endcode
*/
-QBitmap QCursor::bitmap(Qt::ReturnByValue_t) const
+QBitmap QCursor::bitmap(Qt::ReturnByValueConstant) const
{
if (!QCursorData::initialized)
QCursorData::initialize();
@@ -653,7 +653,7 @@ QBitmap QCursor::bitmap(Qt::ReturnByValue_t) const
QBitmap bmpVal = cursor->mask();
\endcode
*/
-QBitmap QCursor::mask(Qt::ReturnByValue_t) const
+QBitmap QCursor::mask(Qt::ReturnByValueConstant) const
{
if (!QCursorData::initialized)
QCursorData::initialize();
diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h
index 7a11fe59ee..3ae6b98ced 100644
--- a/src/gui/kernel/qcursor.h
+++ b/src/gui/kernel/qcursor.h
@@ -104,11 +104,11 @@ public:
QT_DEPRECATED_VERSION_X(5, 15, "Use the other overload which returns QBitmap by-value")
const QBitmap *mask() const; // ### Qt 7: Remove function
- QBitmap bitmap(Qt::ReturnByValue_t) const;
- QBitmap mask(Qt::ReturnByValue_t) const;
+ QBitmap bitmap(Qt::ReturnByValueConstant) const;
+ QBitmap mask(Qt::ReturnByValueConstant) const;
#else
- QBitmap bitmap(Qt::ReturnByValue_t = Qt::ReturnByValue) const; // ### Qt 7: Remove arg
- QBitmap mask(Qt::ReturnByValue_t = Qt::ReturnByValue) const; // ### Qt 7: Remove arg
+ QBitmap bitmap(Qt::ReturnByValueConstant = Qt::ReturnByValue) const; // ### Qt 7: Remove arg
+ QBitmap mask(Qt::ReturnByValueConstant = Qt::ReturnByValue) const; // ### Qt 7: Remove arg
#endif // QT_DEPRECATED_SINCE(5, 15)
QPixmap pixmap() const;
QPoint hotSpot() const;
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
index fde6bb0180..671c2d93ef 100644
--- a/src/gui/kernel/qhighdpiscaling.cpp
+++ b/src/gui/kernel/qhighdpiscaling.cpp
@@ -535,7 +535,7 @@ void QHighDpiScaling::updateHighDpiScaling()
++i;
}
}
- m_active = m_globalScalingActive || m_screenFactorSet || m_usePixelDensity;
+ m_active = m_globalScalingActive || m_screenFactorSet || m_pixelDensityScalingActive;
}
/*
diff --git a/src/gui/kernel/qpixelformat.cpp b/src/gui/kernel/qpixelformat.cpp
index c28fe7ac63..3100d13398 100644
--- a/src/gui/kernel/qpixelformat.cpp
+++ b/src/gui/kernel/qpixelformat.cpp
@@ -485,7 +485,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn ByteOrder QPixelFormat::byteOrder() const
- The byte order is almost always set the the byte order of the current
+ The byte order is almost always set the byte order of the current
system. However, it can be useful to describe some YUV formats. This
function should never return QPixelFormat::CurrentSystemEndian as this
value is translated to a endian value in the constructor.
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index 65accc9f68..15d7505133 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -482,19 +482,17 @@ bool QPlatformWindow::windowEvent(QEvent *event)
}
/*!
- Reimplement this method to start a system size grip drag
- operation if the system supports it and return true to indicate
- success.
- It is called from the mouse press event handler of the size grip.
+ Reimplement this method to start a system resize operation if
+ the system supports it and return true to indicate success.
+
+ The default implementation is empty and does nothing with \a edges.
- The default implementation is empty and does nothing with \a pos
- and \a corner.
+ \since 5.15
*/
-bool QPlatformWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
+bool QPlatformWindow::startSystemResize(Qt::Edges edges)
{
- Q_UNUSED(pos)
- Q_UNUSED(corner)
+ Q_UNUSED(edges)
return false;
}
@@ -502,18 +500,13 @@ bool QPlatformWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
Reimplement this method to start a system move operation if
the system supports it and return true to indicate success.
- The \a pos is a position of MouseButtonPress event or TouchBegin
- event from a sequence of mouse events that triggered the movement.
- It must be specified in window coordinates.
-
- The default implementation is empty and does nothing with \a pos.
+ The default implementation is empty and does nothing.
- \since 5.11
+ \since 5.15
*/
-bool QPlatformWindow::startSystemMove(const QPoint &pos)
+bool QPlatformWindow::startSystemMove()
{
- Q_UNUSED(pos)
return false;
}
@@ -747,7 +740,7 @@ QRect QPlatformWindow::initialGeometry(const QWindow *w, const QRect &initialGeo
QPlatformWindow subclasses can re-implement this function to
provide display refresh synchronized updates. The event
should be delivered using QPlatformWindow::deliverUpdateRequest()
- to not get out of sync with the the internal state of QWindow.
+ to not get out of sync with the internal state of QWindow.
The default implementation posts an UpdateRequest event to the
window after 5 ms. The additional time is there to give the event
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
index b6aeb3a86a..7b85090cc0 100644
--- a/src/gui/kernel/qplatformwindow.h
+++ b/src/gui/kernel/qplatformwindow.h
@@ -132,8 +132,8 @@ public:
virtual bool windowEvent(QEvent *event);
- virtual bool startSystemResize(const QPoint &pos, Qt::Corner corner);
- virtual bool startSystemMove(const QPoint &pos);
+ virtual bool startSystemResize(Qt::Edges edges);
+ virtual bool startSystemMove();
virtual void setFrameStrutEventsEnabled(bool enabled);
virtual bool frameStrutEventsEnabled() const;
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
index 9de59f8c7e..fd25becbca 100644
--- a/src/gui/kernel/qscreen.cpp
+++ b/src/gui/kernel/qscreen.cpp
@@ -149,6 +149,8 @@ QScreen::~QScreen()
/*!
Get the platform screen handle.
+
+ \sa {Qt Platform Abstraction}{Qt Platform Abstraction (QPA)}
*/
QPlatformScreen *QScreen::handle() const
{
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index dad1b6ba2d..c099ec9692 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1051,6 +1051,71 @@ void QWindow::lower()
}
/*!
+ \brief Start a system-specific resize operation
+ \since 5.15
+
+ Calling this will start an interactive resize operation on the window by platforms
+ that support it. The actual behavior may vary depending on the platform. Usually,
+ it will make the window resize so that its edge follows the mouse cursor.
+
+ On platforms that support it, this method of resizing windows is preferred over
+ \c setGeometry, because it allows a more native look-and-feel of resizing windows, e.g.
+ letting the window manager snap this window against other windows, or special resizing
+ behavior with animations when dragged to the edge of the screen.
+
+ \a edges should either be a single edge, or two adjacent edges (a corner). Other values
+ are not allowed.
+
+ Returns true if the operation was supported by the system.
+*/
+bool QWindow::startSystemResize(Qt::Edges edges)
+{
+ Q_D(QWindow);
+ if (Q_UNLIKELY(!isVisible() || !d->platformWindow || d->maximumSize == d->minimumSize))
+ return false;
+
+ const bool isSingleEdge = edges == Qt::TopEdge || edges == Qt::RightEdge || edges == Qt::BottomEdge || edges == Qt::LeftEdge;
+ const bool isCorner =
+ edges == (Qt::TopEdge | Qt::LeftEdge) ||
+ edges == (Qt::TopEdge | Qt::RightEdge) ||
+ edges == (Qt::BottomEdge | Qt::RightEdge) ||
+ edges == (Qt::BottomEdge | Qt::LeftEdge);
+
+ if (Q_UNLIKELY(!isSingleEdge && !isCorner)) {
+ qWarning() << "Invalid edges" << edges << "passed to QWindow::startSystemResize, ignoring.";
+ return false;
+ }
+
+ return d->platformWindow->startSystemResize(edges);
+}
+
+/*!
+ \brief Start a system-specific move operation
+ \since 5.15
+
+ Calling this will start an interactive move operation on the window by platforms
+ that support it. The actual behavior may vary depending on the platform. Usually,
+ it will make the window follow the mouse cursor until a mouse button is released.
+
+ On platforms that support it, this method of moving windows is preferred over
+ \c setPosition, because it allows a more native look-and-feel of moving windows, e.g.
+ letting the window manager snap this window against other windows, or special tiling
+ or resizing behavior with animations when dragged to the edge of the screen.
+ Furthermore, on some platforms such as Wayland, \c setPosition is not supported, so
+ this is the only way the application can influence its position.
+
+ Returns true if the operation was supported by the system.
+*/
+bool QWindow::startSystemMove()
+{
+ Q_D(QWindow);
+ if (Q_UNLIKELY(!isVisible() || !d->platformWindow))
+ return false;
+
+ return d->platformWindow->startSystemMove();
+}
+
+/*!
\property QWindow::opacity
\brief The opacity of the window in the windowing system.
\since 5.1
@@ -1793,7 +1858,10 @@ void QWindow::setFramePosition(const QPoint &point)
The position is in relation to the virtualGeometry() of its screen.
- \sa position()
+ For interactively moving windows, see startSystemMove(). For interactively
+ resizing windows, see startSystemResize().
+
+ \sa position(), startSystemMove()
*/
void QWindow::setPosition(const QPoint &pt)
{
@@ -1830,6 +1898,8 @@ void QWindow::setPosition(int posx, int posy)
set the size of the window, excluding any window frame, to a QSize
constructed from width \a w and height \a h
+ For interactively resizing windows, see startSystemResize().
+
\sa size(), geometry()
*/
void QWindow::resize(int w, int h)
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index 5ee1d00f5b..7aae7ffffa 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -292,6 +292,8 @@ public Q_SLOTS:
bool close();
void raise();
void lower();
+ bool startSystemResize(Qt::Edges edges);
+ bool startSystemMove();
void setTitle(const QString &);
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index 1a0f4f11e4..94a88f55dc 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -161,7 +161,7 @@ gcc:equals(QT_GCC_MAJOR_VERSION, 5) {
DEFINES += QT_COMPILER_SUPPORTS_SSE4_1 QT_COMPILER_SUPPORTS_SSE4_2
SOURCES += painting/qdrawhelper_sse4.cpp painting/qimagescale_sse4.cpp
}
- arm64-v8a {
+ arm64-v8a | armeabi-v7a {
SOURCES += painting/qdrawhelper_neon.cpp painting/qimagescale_neon.cpp
HEADERS += painting/qdrawhelper_neon_p.h
}
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 0a49269c36..2147d9d61d 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -281,7 +281,7 @@ QSize QBackingStore::size() const
bool QBackingStore::scroll(const QRegion &area, int dx, int dy)
{
// Disable scrolling for non-integer scroll deltas. For this case
- // the the existing rendered pixels can't be re-used, and we return
+ // the existing rendered pixels can't be re-used, and we return
// false to signal that a repaint is needed.
const qreal nativeDx = QHighDpi::toNativePixels(qreal(dx), d_ptr->window);
const qreal nativeDy = QHighDpi::toNativePixels(qreal(dy), d_ptr->window);
diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp
index 7ebd5f1bf4..7e7bbec870 100644
--- a/src/gui/painting/qcolorspace.cpp
+++ b/src/gui/painting/qcolorspace.cpp
@@ -549,8 +549,12 @@ float QColorSpace::gamma() const noexcept
*/
void QColorSpace::setTransferFunction(QColorSpace::TransferFunction transferFunction, float gamma)
{
- if (!isValid() || transferFunction == QColorSpace::TransferFunction::Custom)
+ if (transferFunction == TransferFunction::Custom)
+ return;
+ if (!d_ptr) {
+ d_ptr = new QColorSpacePrivate(Primaries::Custom, transferFunction, gamma);
return;
+ }
if (d_ptr->transferFunction == transferFunction && d_ptr->gamma == gamma)
return;
QColorSpacePrivate::getWritable(*this); // detach
@@ -585,8 +589,12 @@ QColorSpace QColorSpace::withTransferFunction(QColorSpace::TransferFunction tran
*/
void QColorSpace::setPrimaries(QColorSpace::Primaries primariesId)
{
- if (!isValid() || primariesId == QColorSpace::Primaries::Custom)
+ if (primariesId == Primaries::Custom)
return;
+ if (!d_ptr) {
+ d_ptr = new QColorSpacePrivate(primariesId, TransferFunction::Custom, 0.0f);
+ return;
+ }
if (d_ptr->primaries == primariesId)
return;
QColorSpacePrivate::getWritable(*this); // detach
@@ -605,11 +613,13 @@ void QColorSpace::setPrimaries(QColorSpace::Primaries primariesId)
void QColorSpace::setPrimaries(const QPointF &whitePoint, const QPointF &redPoint,
const QPointF &greenPoint, const QPointF &bluePoint)
{
- if (!isValid())
- return;
QColorSpacePrimaries primaries(whitePoint, redPoint, greenPoint, bluePoint);
if (!primaries.areValid())
return;
+ if (!d_ptr) {
+ d_ptr = new QColorSpacePrivate(primaries, TransferFunction::Custom, 0.0f);
+ return;
+ }
QColorMatrix toXyz = primaries.toXyzMatrix();
if (QColorVector(primaries.whitePoint) == d_ptr->whitePoint && toXyz == d_ptr->toXyz)
return;
@@ -692,12 +702,14 @@ bool operator==(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2)
const bool valid1 = colorSpace1.isValid();
const bool valid2 = colorSpace2.isValid();
- if (!valid1 && !valid2)
- return colorSpace1.d_ptr->iccProfile == colorSpace2.d_ptr->iccProfile;
- else if (!valid1 || !valid2)
+ if (valid1 != valid2)
return false;
+ if (!valid1 && !valid2) {
+ if (!colorSpace1.d_ptr->iccProfile.isEmpty() || !colorSpace2.d_ptr->iccProfile.isEmpty())
+ return colorSpace1.d_ptr->iccProfile == colorSpace2.d_ptr->iccProfile;
+ }
- // At this point one or both color spaces are unknown but valid, and must be compared in detail instead
+ // At this point one or both color spaces are unknown, and must be compared in detail instead
if (colorSpace1.primaries() != QColorSpace::Primaries::Custom && colorSpace2.primaries() != QColorSpace::Primaries::Custom) {
if (colorSpace1.primaries() != colorSpace2.primaries())
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index a9c6835687..f0bf19bd91 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -1652,7 +1652,7 @@ QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QRhiTextureUplo
Constructs a texture upload description with the specified \a list of entries.
\note \a list can also contain multiple QRhiTextureUploadEntry elements
- with the the same layer and level. This makes sense when those uploads are
+ with the same layer and level. This makes sense when those uploads are
partial, meaning their subresource description has a source size or image
smaller than the subresource dimensions, and can be more efficient than
issuing separate uploadTexture()'s.
@@ -2297,11 +2297,10 @@ bool QRhiTexture::buildFrom(QRhiTexture::NativeTexture src)
*/
QRhiSampler::QRhiSampler(QRhiImplementation *rhi,
Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
- AddressMode u_, AddressMode v_)
+ AddressMode u_, AddressMode v_, AddressMode w_)
: QRhiResource(rhi),
m_magFilter(magFilter_), m_minFilter(minFilter_), m_mipmapMode(mipmapMode_),
- m_addressU(u_), m_addressV(v_),
- m_addressW(QRhiSampler::ClampToEdge),
+ m_addressU(u_), m_addressV(v_), m_addressW(w_),
m_compareOp(QRhiSampler::Never)
{
}
@@ -3506,7 +3505,7 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
\l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the QSurfaceFormat of
the QWindow in addition.
- \value UsedAsTransferSource Indicates the the swapchain will be used as the
+ \value UsedAsTransferSource Indicates the swapchain will be used as the
source of a readback in QRhiResourceUpdateBatch::readBackTexture().
\value NoVSync Requests disabling waiting for vertical sync, also avoiding
@@ -3623,7 +3622,7 @@ QRhiResource::Type QRhiSwapChain::resourceType() const
\fn QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget()
\return a render target that can used with beginPass() in order to render
- the the swapchain's current backbuffer. Only valid within a
+ the swapchain's current backbuffer. Only valid within a
QRhi::beginFrame() - QRhi::endFrame() block where beginFrame() was called
with this swapchain.
@@ -4449,7 +4448,7 @@ void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex, int layer)
recorded.
\note the return value is not owned by the caller and must never be
- destroyed. Instead, the batch is returned the the pool for reuse by passing
+ destroyed. Instead, the batch is returned the pool for reuse by passing
it to QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), or
QRhiCommandBuffer::resourceUpdate(), or by calling
QRhiResourceUpdateBatch::release() on it.
@@ -5059,13 +5058,24 @@ bool QRhi::isYUpInNDC() const
}
/*!
- \return \c true if the underlying graphics API uses depth 0 - 1 in clip
- space.
+ \return \c true if the underlying graphics API uses depth range [0, 1] in
+ clip space.
- In practice this is \c false for OpenGL only.
+ In practice this is \c false for OpenGL only, because OpenGL uses a
+ post-projection depth range of [-1, 1]. (not to be confused with the
+ NDC-to-window mapping controlled by glDepthRange(), which uses a range of
+ [0, 1], unless overridden by the QRhiViewport) In some OpenGL versions
+ glClipControl() could be used to change this, but the OpenGL backend of
+ QRhi does not use that function as it is not available in OpenGL ES or
+ OpenGL versions lower than 4.5.
\note clipSpaceCorrMatrix() includes the corresponding adjustment in its
- returned matrix.
+ returned matrix. Therefore, many users of QRhi do not need to take any
+ further measures apart from pre-multiplying their projection matrices with
+ clipSpaceCorrMatrix(). However, some graphics techniques, such as, some
+ types of shadow mapping, involve working with and outputting depth values
+ in the shaders. These will need to query and take the value of this
+ function into account as appropriate.
*/
bool QRhi::isClipDepthZeroToOne() const
{
@@ -5075,11 +5085,15 @@ bool QRhi::isClipDepthZeroToOne() const
/*!
\return a matrix that can be used to allow applications keep using
OpenGL-targeted vertex data and perspective projection matrices (such as,
- the ones generated by QMatrix4x4::perspective()), regardless of the
- backend. Once \c{this_matrix * mvp} is used instead of just \c mvp, vertex
- data with Y up and viewports with depth range 0 - 1 can be used without
- considering what backend and so graphics API is going to be used at run
- time.
+ the ones generated by QMatrix4x4::perspective()), regardless of the active
+ QRhi backend.
+
+ In a typical renderer, once \c{this_matrix * mvp} is used instead of just
+ \c mvp, vertex data with Y up and viewports with depth range 0 - 1 can be
+ used without considering what backend (and so graphics API) is going to be
+ used at run time. This way branching based on isYUpInNDC() and
+ isClipDepthZeroToOne() can be avoided (although such logic may still become
+ required when implementing certain advanced graphics techniques).
See
\l{https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/}{this
@@ -5321,16 +5335,19 @@ QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
/*!
\return a new sampler with the specified magnification filter \a magFilter,
- minification filter \a minFilter, mipmapping mode \a mipmapMpde, and S/T
- addressing modes \a u and \a v.
+ minification filter \a minFilter, mipmapping mode \a mipmapMode, and the
+ addressing (wrap) modes \a addressU, \a addressV, and \a addressW.
\sa QRhiResource::release()
*/
-QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v)
+ QRhiSampler::AddressMode addressU,
+ QRhiSampler::AddressMode addressV,
+ QRhiSampler::AddressMode addressW)
{
- return d->createSampler(magFilter, minFilter, mipmapMode, u, v);
+ return d->createSampler(magFilter, minFilter, mipmapMode, addressU, addressV, addressW);
}
/*!
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h
index 3a64835c22..d17112a241 100644
--- a/src/gui/rhi/qrhi_p.h
+++ b/src/gui/rhi/qrhi_p.h
@@ -850,7 +850,7 @@ public:
protected:
QRhiSampler(QRhiImplementation *rhi,
Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
- AddressMode u_, AddressMode v_);
+ AddressMode u_, AddressMode v_, AddressMode w_);
Filter m_magFilter;
Filter m_minFilter;
Filter m_mipmapMode;
@@ -1155,6 +1155,12 @@ public:
float lineWidth() const { return m_lineWidth; }
void setLineWidth(float width) { m_lineWidth = width; }
+ int depthBias() const { return m_depthBias; }
+ void setDepthBias(int bias) { m_depthBias = bias; }
+
+ float slopeScaledDepthBias() const { return m_slopeScaledDepthBias; }
+ void setSlopeScaledDepthBias(float bias) { m_slopeScaledDepthBias = bias; }
+
void setShaderStages(std::initializer_list<QRhiShaderStage> list) { m_shaderStages = list; }
template<typename InputIterator>
void setShaderStages(InputIterator first, InputIterator last)
@@ -1193,6 +1199,8 @@ protected:
quint32 m_stencilWriteMask = 0xFF;
int m_sampleCount = 1;
float m_lineWidth = 1.0f;
+ int m_depthBias = 0;
+ float m_slopeScaledDepthBias = 0.0f;
QVarLengthArray<QRhiShaderStage, 4> m_shaderStages;
QRhiVertexInputLayout m_vertexInputLayout;
QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr;
@@ -1474,9 +1482,12 @@ public:
int sampleCount = 1,
QRhiTexture::Flags flags = QRhiTexture::Flags());
- QRhiSampler *newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler *newSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler::AddressMode u, QRhiSampler::AddressMode v);
+ QRhiSampler::AddressMode addressU,
+ QRhiSampler::AddressMode addressV,
+ QRhiSampler::AddressMode addressW = QRhiSampler::Repeat);
QRhiTextureRenderTarget *newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags = QRhiTextureRenderTarget::Flags());
diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h
index baffe28202..4a4c044a29 100644
--- a/src/gui/rhi/qrhi_p_p.h
+++ b/src/gui/rhi/qrhi_p_p.h
@@ -85,9 +85,12 @@ public:
const QSize &pixelSize,
int sampleCount,
QRhiTexture::Flags flags) = 0;
- virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) = 0;
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) = 0;
virtual QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags) = 0;
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index 445d162595..75b90b6995 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -527,9 +527,9 @@ QRhiTexture *QRhiD3D11::createTexture(QRhiTexture::Format format, const QSize &p
QRhiSampler *QRhiD3D11::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
{
- return new QD3D11Sampler(this, magFilter, minFilter, mipmapMode, u, v);
+ return new QD3D11Sampler(this, magFilter, minFilter, mipmapMode, u, v, w);
}
QRhiTextureRenderTarget *QRhiD3D11::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
@@ -2768,8 +2768,8 @@ ID3D11UnorderedAccessView *QD3D11Texture::unorderedAccessViewForLevel(int level)
}
QD3D11Sampler::QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v)
- : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v)
+ AddressMode u, AddressMode v, AddressMode w)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w)
{
}
@@ -3467,6 +3467,9 @@ bool QD3D11GraphicsPipeline::build()
rastDesc.FillMode = D3D11_FILL_SOLID;
rastDesc.CullMode = toD3DCullMode(m_cullMode);
rastDesc.FrontCounterClockwise = m_frontFace == CCW;
+ rastDesc.DepthBias = m_depthBias;
+ rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
+ rastDesc.DepthClipEnable = true;
rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
rastDesc.MultisampleEnable = rhiD->effectiveSampleCount(m_sampleCount).Count > 1;
HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h
index 9ddd2aa797..c3a4021241 100644
--- a/src/gui/rhi/qrhid3d11_p_p.h
+++ b/src/gui/rhi/qrhid3d11_p_p.h
@@ -120,7 +120,7 @@ struct QD3D11Texture : public QRhiTexture
struct QD3D11Sampler : public QRhiSampler
{
QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v);
+ AddressMode u, AddressMode v, AddressMode w);
~QD3D11Sampler();
void release() override;
bool build() override;
@@ -559,9 +559,12 @@ public:
const QSize &pixelSize,
int sampleCount,
QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags) override;
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index ec5e531e14..62f808ce81 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -838,9 +838,9 @@ QRhiTexture *QRhiGles2::createTexture(QRhiTexture::Format format, const QSize &p
QRhiSampler *QRhiGles2::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
{
- return new QGles2Sampler(this, magFilter, minFilter, mipmapMode, u, v);
+ return new QGles2Sampler(this, magFilter, minFilter, mipmapMode, u, v, w);
}
QRhiTextureRenderTarget *QRhiGles2::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
@@ -2386,7 +2386,14 @@ void QRhiGles2::executeBindGraphicsPipeline(QRhiGraphicsPipeline *ps)
f->glDisable(GL_STENCIL_TEST);
}
- if (psD->topology() == QRhiGraphicsPipeline::Lines || psD->topology() == QRhiGraphicsPipeline::LineStrip)
+ if (psD->m_depthBias != 0 || !qFuzzyIsNull(psD->m_slopeScaledDepthBias)) {
+ f->glPolygonOffset(psD->m_slopeScaledDepthBias, psD->m_depthBias);
+ f->glEnable(GL_POLYGON_OFFSET_FILL);
+ } else {
+ f->glDisable(GL_POLYGON_OFFSET_FILL);
+ }
+
+ if (psD->m_topology == QRhiGraphicsPipeline::Lines || psD->m_topology == QRhiGraphicsPipeline::LineStrip)
f->glLineWidth(psD->m_lineWidth);
f->glUseProgram(psD->program);
@@ -3626,8 +3633,8 @@ QRhiTexture::NativeTexture QGles2Texture::nativeTexture()
}
QGles2Sampler::QGles2Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v)
- : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v)
+ AddressMode u, AddressMode v, AddressMode w)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w)
{
}
diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h
index 679f806004..00caf40118 100644
--- a/src/gui/rhi/qrhigles2_p_p.h
+++ b/src/gui/rhi/qrhigles2_p_p.h
@@ -170,7 +170,7 @@ struct QGles2Texture : public QRhiTexture
struct QGles2Sampler : public QRhiSampler
{
QGles2Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v);
+ AddressMode u, AddressMode v, AddressMode w);
~QGles2Sampler();
void release() override;
bool build() override;
@@ -613,9 +613,12 @@ public:
const QSize &pixelSize,
int sampleCount,
QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags) override;
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 98cbd416b5..9e8f1ac096 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -298,6 +298,8 @@ struct QMetalGraphicsPipelineData
MTLPrimitiveType primitiveType;
MTLWinding winding;
MTLCullMode cullMode;
+ float depthBias;
+ float slopeScaledDepthBias;
QMetalShader vs;
QMetalShader fs;
};
@@ -626,9 +628,9 @@ QRhiTexture *QRhiMetal::createTexture(QRhiTexture::Format format, const QSize &p
QRhiSampler *QRhiMetal::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
{
- return new QMetalSampler(this, magFilter, minFilter, mipmapMode, u, v);
+ return new QMetalSampler(this, magFilter, minFilter, mipmapMode, u, v, w);
}
QRhiTextureRenderTarget *QRhiMetal::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
@@ -684,11 +686,27 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
bool offsetOnlyChange,
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[SUPPORTED_STAGES])
{
- struct {
- QRhiBatchedBindings<id<MTLBuffer> > buffers;
- QRhiBatchedBindings<NSUInteger> bufferOffsets;
- QRhiBatchedBindings<id<MTLTexture> > textures;
- QRhiBatchedBindings<id<MTLSamplerState> > samplers;
+ struct Stage {
+ struct Buffer {
+ int nativeBinding;
+ id<MTLBuffer> mtlbuf;
+ uint offset;
+ };
+ struct Texture {
+ int nativeBinding;
+ id<MTLTexture> mtltex;
+ };
+ struct Sampler {
+ int nativeBinding;
+ id<MTLSamplerState> mtlsampler;
+ };
+ QVarLengthArray<Buffer, 8> buffers;
+ QVarLengthArray<Texture, 8> textures;
+ QVarLengthArray<Sampler, 8> samplers;
+ QRhiBatchedBindings<id<MTLBuffer> > bufferBatches;
+ QRhiBatchedBindings<NSUInteger> bufferOffsetBatches;
+ QRhiBatchedBindings<id<MTLTexture> > textureBatches;
+ QRhiBatchedBindings<id<MTLSamplerState> > samplerBatches;
} res[SUPPORTED_STAGES];
enum { VERTEX = 0, FRAGMENT = 1, COMPUTE = 2 };
@@ -709,24 +727,18 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
}
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
const int nativeBinding = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0) {
- res[VERTEX].buffers.feed(nativeBinding, mtlbuf);
- res[VERTEX].bufferOffsets.feed(b->binding, offset);
- }
+ if (nativeBinding >= 0)
+ res[VERTEX].buffers.append({ nativeBinding, mtlbuf, offset });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
const int nativeBinding = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0) {
- res[FRAGMENT].buffers.feed(nativeBinding, mtlbuf);
- res[FRAGMENT].bufferOffsets.feed(b->binding, offset);
- }
+ if (nativeBinding >= 0)
+ res[FRAGMENT].buffers.append({ nativeBinding, mtlbuf, offset });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
const int nativeBinding = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0) {
- res[COMPUTE].buffers.feed(nativeBinding, mtlbuf);
- res[COMPUTE].bufferOffsets.feed(b->binding, offset);
- }
+ if (nativeBinding >= 0)
+ res[COMPUTE].buffers.append({ nativeBinding, mtlbuf, offset });
}
}
break;
@@ -738,24 +750,24 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
const int nativeBindingTexture = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Texture);
const int nativeBindingSampler = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Sampler);
if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
- res[VERTEX].textures.feed(nativeBindingTexture, texD->d->tex);
- res[VERTEX].samplers.feed(nativeBindingSampler, samplerD->d->samplerState);
+ res[VERTEX].textures.append({ nativeBindingTexture, texD->d->tex });
+ res[VERTEX].samplers.append({ nativeBindingSampler, samplerD->d->samplerState });
}
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
const int nativeBindingTexture = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Texture);
const int nativeBindingSampler = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Sampler);
if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
- res[FRAGMENT].textures.feed(nativeBindingTexture, texD->d->tex);
- res[FRAGMENT].samplers.feed(nativeBindingSampler, samplerD->d->samplerState);
+ res[FRAGMENT].textures.append({ nativeBindingTexture, texD->d->tex });
+ res[FRAGMENT].samplers.append({ nativeBindingSampler, samplerD->d->samplerState });
}
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
const int nativeBindingTexture = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Texture);
const int nativeBindingSampler = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Sampler);
if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
- res[COMPUTE].textures.feed(nativeBindingTexture, texD->d->tex);
- res[COMPUTE].samplers.feed(nativeBindingSampler, samplerD->d->samplerState);
+ res[COMPUTE].textures.append({ nativeBindingTexture, texD->d->tex });
+ res[COMPUTE].samplers.append({ nativeBindingSampler, samplerD->d->samplerState });
}
}
}
@@ -769,17 +781,17 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
const int nativeBinding = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Texture);
if (nativeBinding >= 0)
- res[VERTEX].textures.feed(nativeBinding, t);
+ res[VERTEX].textures.append({ nativeBinding, t });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
const int nativeBinding = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Texture);
if (nativeBinding >= 0)
- res[FRAGMENT].textures.feed(nativeBinding, t);
+ res[FRAGMENT].textures.append({ nativeBinding, t });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
const int nativeBinding = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Texture);
if (nativeBinding >= 0)
- res[COMPUTE].textures.feed(nativeBinding, t);
+ res[COMPUTE].textures.append({ nativeBinding, t });
}
}
break;
@@ -792,24 +804,18 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
uint offset = uint(b->u.sbuf.offset);
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
const int nativeBinding = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0) {
- res[VERTEX].buffers.feed(nativeBinding, mtlbuf);
- res[VERTEX].bufferOffsets.feed(b->binding, offset);
- }
+ if (nativeBinding >= 0)
+ res[VERTEX].buffers.append({ nativeBinding, mtlbuf, offset });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
const int nativeBinding = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0) {
- res[FRAGMENT].buffers.feed(nativeBinding, mtlbuf);
- res[FRAGMENT].bufferOffsets.feed(b->binding, offset);
- }
+ if (nativeBinding >= 0)
+ res[FRAGMENT].buffers.append({ nativeBinding, mtlbuf, offset });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
const int nativeBinding = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0) {
- res[COMPUTE].buffers.feed(nativeBinding, mtlbuf);
- res[COMPUTE].bufferOffsets.feed(b->binding, offset);
- }
+ if (nativeBinding >= 0)
+ res[COMPUTE].buffers.append({ nativeBinding, mtlbuf, offset });
}
}
break;
@@ -825,12 +831,26 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
if (cbD->recordingPass != QMetalCommandBuffer::ComputePass && stage == COMPUTE)
continue;
- res[stage].buffers.finish();
- res[stage].bufferOffsets.finish();
+ // QRhiBatchedBindings works with the native bindings and expects
+ // sorted input. The pre-sorted QRhiShaderResourceBinding list (based
+ // on the QRhi (SPIR-V) binding) is not helpful in this regard, so we
+ // have to sort here every time.
+
+ std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](const Stage::Buffer &a, const Stage::Buffer &b) {
+ return a.nativeBinding < b.nativeBinding;
+ });
+
+ for (const Stage::Buffer &buf : qAsConst(res[stage].buffers)) {
+ res[stage].bufferBatches.feed(buf.nativeBinding, buf.mtlbuf);
+ res[stage].bufferOffsetBatches.feed(buf.nativeBinding, buf.offset);
+ }
+
+ res[stage].bufferBatches.finish();
+ res[stage].bufferOffsetBatches.finish();
- for (int i = 0, ie = res[stage].buffers.batches.count(); i != ie; ++i) {
- const auto &bufferBatch(res[stage].buffers.batches[i]);
- const auto &offsetBatch(res[stage].bufferOffsets.batches[i]);
+ for (int i = 0, ie = res[stage].bufferBatches.batches.count(); i != ie; ++i) {
+ const auto &bufferBatch(res[stage].bufferBatches.batches[i]);
+ const auto &offsetBatch(res[stage].bufferOffsetBatches.batches[i]);
switch (stage) {
case VERTEX:
[cbD->d->currentRenderPassEncoder setVertexBuffers: bufferBatch.resources.constData()
@@ -856,11 +876,25 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
if (offsetOnlyChange)
continue;
- res[stage].textures.finish();
- res[stage].samplers.finish();
+ std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](const Stage::Texture &a, const Stage::Texture &b) {
+ return a.nativeBinding < b.nativeBinding;
+ });
- for (int i = 0, ie = res[stage].textures.batches.count(); i != ie; ++i) {
- const auto &batch(res[stage].textures.batches[i]);
+ std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](const Stage::Sampler &a, const Stage::Sampler &b) {
+ return a.nativeBinding < b.nativeBinding;
+ });
+
+ for (const Stage::Texture &t : qAsConst(res[stage].textures))
+ res[stage].textureBatches.feed(t.nativeBinding, t.mtltex);
+
+ for (const Stage::Sampler &s : qAsConst(res[stage].samplers))
+ res[stage].samplerBatches.feed(s.nativeBinding, s.mtlsampler);
+
+ res[stage].textureBatches.finish();
+ res[stage].samplerBatches.finish();
+
+ for (int i = 0, ie = res[stage].textureBatches.batches.count(); i != ie; ++i) {
+ const auto &batch(res[stage].textureBatches.batches[i]);
switch (stage) {
case VERTEX:
[cbD->d->currentRenderPassEncoder setVertexTextures: batch.resources.constData()
@@ -879,8 +913,8 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
break;
}
}
- for (int i = 0, ie = res[stage].samplers.batches.count(); i != ie; ++i) {
- const auto &batch(res[stage].samplers.batches[i]);
+ for (int i = 0, ie = res[stage].samplerBatches.batches.count(); i != ie; ++i) {
+ const auto &batch(res[stage].samplerBatches.batches[i]);
switch (stage) {
case VERTEX:
[cbD->d->currentRenderPassEncoder setVertexSamplerStates: batch.resources.constData()
@@ -924,6 +958,14 @@ void QRhiMetal::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
[cbD->d->currentRenderPassEncoder setFrontFacingWinding: psD->d->winding];
cbD->currentFrontFaceWinding = int(psD->d->winding);
}
+ if (!qFuzzyCompare(psD->d->depthBias, cbD->currentDepthBiasValues.first)
+ || !qFuzzyCompare(psD->d->slopeScaledDepthBias, cbD->currentDepthBiasValues.second))
+ {
+ [cbD->d->currentRenderPassEncoder setDepthBias: psD->d->depthBias
+ slopeScale: psD->d->slopeScaledDepthBias
+ clamp: 0.0f];
+ cbD->currentDepthBiasValues = { psD->d->depthBias, psD->d->slopeScaledDepthBias };
+ }
}
psD->lastActiveFrameSlot = currentFrameSlot;
@@ -2548,8 +2590,8 @@ id<MTLTexture> QMetalTextureData::viewForLevel(int level)
}
QMetalSampler::QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v)
- : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v),
+ AddressMode u, AddressMode v, AddressMode w)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w),
d(new QMetalSamplerData)
{
}
@@ -3422,6 +3464,8 @@ bool QMetalGraphicsPipeline::build()
d->primitiveType = toMetalPrimitiveType(m_topology);
d->winding = m_frontFace == CCW ? MTLWindingCounterClockwise : MTLWindingClockwise;
d->cullMode = toMetalCullMode(m_cullMode);
+ d->depthBias = float(m_depthBias);
+ d->slopeScaledDepthBias = m_slopeScaledDepthBias;
lastActiveFrameSlot = -1;
generation += 1;
@@ -3570,6 +3614,7 @@ void QMetalCommandBuffer::resetPerPassCachedState()
currentIndexFormat = QRhiCommandBuffer::IndexUInt16;
currentCullMode = -1;
currentFrontFaceWinding = -1;
+ currentDepthBiasValues = { 0.0f, 0.0f };
d->currentFirstVertexBinding = -1;
d->currentVertexInputsBuffers.clear();
diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h
index 71d4325b1a..58e93e2cdb 100644
--- a/src/gui/rhi/qrhimetal_p_p.h
+++ b/src/gui/rhi/qrhimetal_p_p.h
@@ -120,7 +120,7 @@ struct QMetalSamplerData;
struct QMetalSampler : public QRhiSampler
{
QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v);
+ AddressMode u, AddressMode v, AddressMode w);
~QMetalSampler();
void release() override;
bool build() override;
@@ -288,6 +288,7 @@ struct QMetalCommandBuffer : public QRhiCommandBuffer
QRhiCommandBuffer::IndexFormat currentIndexFormat;
int currentCullMode;
int currentFrontFaceWinding;
+ QPair<float, float> currentDepthBiasValues;
const QRhiNativeHandles *nativeHandles();
void resetState();
@@ -349,9 +350,12 @@ public:
const QSize &pixelSize,
int sampleCount,
QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags) override;
diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp
index ea67f80138..4c59900aa6 100644
--- a/src/gui/rhi/qrhinull.cpp
+++ b/src/gui/rhi/qrhinull.cpp
@@ -193,9 +193,9 @@ QRhiTexture *QRhiNull::createTexture(QRhiTexture::Format format, const QSize &pi
QRhiSampler *QRhiNull::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
{
- return new QNullSampler(this, magFilter, minFilter, mipmapMode, u, v);
+ return new QNullSampler(this, magFilter, minFilter, mipmapMode, u, v, w);
}
QRhiTextureRenderTarget *QRhiNull::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
@@ -645,8 +645,8 @@ bool QNullTexture::buildFrom(QRhiTexture::NativeTexture src)
}
QNullSampler::QNullSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v)
- : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v)
+ AddressMode u, AddressMode v, AddressMode w)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w)
{
}
diff --git a/src/gui/rhi/qrhinull_p_p.h b/src/gui/rhi/qrhinull_p_p.h
index f541fd90b8..0b3d40f1aa 100644
--- a/src/gui/rhi/qrhinull_p_p.h
+++ b/src/gui/rhi/qrhinull_p_p.h
@@ -88,7 +88,7 @@ struct QNullTexture : public QRhiTexture
struct QNullSampler : public QRhiSampler
{
QNullSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v);
+ AddressMode u, AddressMode v, AddressMode w);
~QNullSampler();
void release() override;
bool build() override;
@@ -212,9 +212,12 @@ public:
const QSize &pixelSize,
int sampleCount,
QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags) override;
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index e7faa0cadd..84ca835392 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -2462,9 +2462,10 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
{
QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, srb);
- QVarLengthArray<VkDescriptorBufferInfo, 4> bufferInfos;
- QVarLengthArray<VkDescriptorImageInfo, 4> imageInfos;
- QVarLengthArray<VkWriteDescriptorSet, 8> writeInfos;
+ QVarLengthArray<VkDescriptorBufferInfo, 8> bufferInfos;
+ QVarLengthArray<VkDescriptorImageInfo, 8> imageInfos;
+ QVarLengthArray<VkWriteDescriptorSet, 12> writeInfos;
+ QVarLengthArray<QPair<int, int>, 12> infoIndices;
const bool updateAll = descSetIdx < 0;
int frameSlot = updateAll ? 0 : descSetIdx;
@@ -2481,6 +2482,9 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
writeInfo.dstBinding = uint32_t(b->binding);
writeInfo.descriptorCount = 1;
+ int bufferInfoIndex = -1;
+ int imageInfoIndex = -1;
+
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
{
@@ -2496,8 +2500,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
bufInfo.range = VkDeviceSize(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size);
// be nice and assert when we know the vulkan device would die a horrible death due to non-aligned reads
Q_ASSERT(aligned(bufInfo.offset, ubufAlign) == bufInfo.offset);
+ bufferInfoIndex = bufferInfos.count();
bufferInfos.append(bufInfo);
- writeInfo.pBufferInfo = &bufferInfos.last();
}
break;
case QRhiShaderResourceBinding::SampledTexture:
@@ -2513,8 +2517,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
imageInfo.sampler = samplerD->sampler;
imageInfo.imageView = texD->imageView;
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ imageInfoIndex = imageInfos.count();
imageInfos.append(imageInfo);
- writeInfo.pImageInfo = &imageInfos.last();
}
break;
case QRhiShaderResourceBinding::ImageLoad:
@@ -2531,8 +2535,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
imageInfo.sampler = VK_NULL_HANDLE;
imageInfo.imageView = view;
imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
+ imageInfoIndex = imageInfos.count();
imageInfos.append(imageInfo);
- writeInfo.pImageInfo = &imageInfos.last();
}
}
break;
@@ -2548,8 +2552,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
bufInfo.buffer = bufD->m_type == QRhiBuffer::Dynamic ? bufD->buffers[frameSlot] : bufD->buffers[0];
bufInfo.offset = VkDeviceSize(b->u.ubuf.offset);
bufInfo.range = VkDeviceSize(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size);
+ bufferInfoIndex = bufferInfos.count();
bufferInfos.append(bufInfo);
- writeInfo.pBufferInfo = &bufferInfos.last();
}
break;
default:
@@ -2557,10 +2561,20 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
}
writeInfos.append(writeInfo);
+ infoIndices.append({ bufferInfoIndex, imageInfoIndex });
}
++frameSlot;
}
+ for (int i = 0, writeInfoCount = writeInfos.count(); i < writeInfoCount; ++i) {
+ const int bufferInfoIndex = infoIndices[i].first;
+ const int imageInfoIndex = infoIndices[i].second;
+ if (bufferInfoIndex >= 0)
+ writeInfos[i].pBufferInfo = &bufferInfos[bufferInfoIndex];
+ else if (imageInfoIndex >= 0)
+ writeInfos[i].pImageInfo = &imageInfos[imageInfoIndex];
+ }
+
df->vkUpdateDescriptorSets(dev, uint32_t(writeInfos.count()), writeInfos.constData(), 0, nullptr);
}
@@ -4046,9 +4060,9 @@ QRhiTexture *QRhiVulkan::createTexture(QRhiTexture::Format format, const QSize &
QRhiSampler *QRhiVulkan::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
{
- return new QVkSampler(this, magFilter, minFilter, mipmapMode, u, v);
+ return new QVkSampler(this, magFilter, minFilter, mipmapMode, u, v, w);
}
QRhiTextureRenderTarget *QRhiVulkan::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
@@ -5543,8 +5557,8 @@ VkImageView QVkTexture::imageViewForLevel(int level)
}
QVkSampler::QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v)
- : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v)
+ AddressMode u, AddressMode v, AddressMode w)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w)
{
}
@@ -6208,6 +6222,11 @@ bool QVkGraphicsPipeline::build()
rastInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rastInfo.cullMode = toVkCullMode(m_cullMode);
rastInfo.frontFace = toVkFrontFace(m_frontFace);
+ if (m_depthBias != 0 || !qFuzzyIsNull(m_slopeScaledDepthBias)) {
+ rastInfo.depthBiasEnable = true;
+ rastInfo.depthBiasConstantFactor = float(m_depthBias);
+ rastInfo.depthBiasSlopeFactor = m_slopeScaledDepthBias;
+ }
rastInfo.lineWidth = rhiD->hasWideLines ? m_lineWidth : 1.0f;
pipelineInfo.pRasterizationState = &rastInfo;
diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h
index b0e90dae56..d42b83b882 100644
--- a/src/gui/rhi/qrhivulkan_p_p.h
+++ b/src/gui/rhi/qrhivulkan_p_p.h
@@ -154,7 +154,7 @@ struct QVkTexture : public QRhiTexture
struct QVkSampler : public QRhiSampler
{
QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v);
+ AddressMode u, AddressMode v, AddressMode w);
~QVkSampler();
void release() override;
bool build() override;
@@ -657,9 +657,12 @@ public:
const QSize &pixelSize,
int sampleCount,
QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags) override;
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 0024f070ea..ac39a8cf69 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1762,7 +1762,10 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
}
#endif
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (!actualFontEngine->supportsSubPixelPositions() || (actualFontEngine->fontDef.styleStrategy & QFont::ForceIntegerMetrics)) {
+QT_WARNING_POP
for (uint i = 0; i < num_glyphs; ++i)
g.advances[i] = g.advances[i].round();
}
diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp
index 88965046ce..7e18a10895 100644
--- a/src/gui/text/qtextmarkdownimporter.cpp
+++ b/src/gui/text/qtextmarkdownimporter.cpp
@@ -397,10 +397,12 @@ int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det)
break;
case MD_SPAN_A: {
MD_SPAN_A_DETAIL *detail = static_cast<MD_SPAN_A_DETAIL *>(det);
- QString url = QString::fromLatin1(detail->href.text, int(detail->href.size));
- QString title = QString::fromLatin1(detail->title.text, int(detail->title.size));
+ QString url = QString::fromUtf8(detail->href.text, int(detail->href.size));
+ QString title = QString::fromUtf8(detail->title.text, int(detail->title.size));
+ charFmt.setAnchor(true);
charFmt.setAnchorHref(url);
- charFmt.setAnchorNames(QStringList(title));
+ if (!title.isEmpty())
+ charFmt.setToolTip(title);
charFmt.setForeground(m_palette.link());
qCDebug(lcMD) << "anchor" << url << title;
} break;
diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp
index c9a63920c3..7bd321becc 100644
--- a/src/gui/text/qtextmarkdownwriter.cpp
+++ b/src/gui/text/qtextmarkdownwriter.cpp
@@ -56,10 +56,13 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcMDW, "qt.text.markdown.writer")
static const QChar Space = QLatin1Char(' ');
+static const QChar Tab = QLatin1Char('\t');
static const QChar Newline = QLatin1Char('\n');
+static const QChar CarriageReturn = QLatin1Char('\r');
static const QChar LineBreak = QChar(0x2028);
static const QChar DoubleQuote = QLatin1Char('"');
static const QChar Backtick = QLatin1Char('`');
+static const QChar Backslash = QLatin1Char('\\');
static const QChar Period = QLatin1Char('.');
QTextMarkdownWriter::QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features)
@@ -291,6 +294,72 @@ static void maybeEscapeFirstChar(QString &s)
}
}
+struct LineEndPositions {
+ const QChar *lineEnd;
+ const QChar *nextLineBegin;
+};
+
+static LineEndPositions findLineEnd(const QChar *begin, const QChar *end)
+{
+ LineEndPositions result{ end, end };
+
+ while (begin < end) {
+ if (*begin == Newline) {
+ result.lineEnd = begin;
+ result.nextLineBegin = begin + 1;
+ break;
+ } else if (*begin == CarriageReturn) {
+ result.lineEnd = begin;
+ result.nextLineBegin = begin + 1;
+ if (((begin + 1) < end) && begin[1] == Newline)
+ ++result.nextLineBegin;
+ break;
+ }
+
+ ++begin;
+ }
+
+ return result;
+}
+
+static bool isBlankLine(const QChar *begin, const QChar *end)
+{
+ while (begin < end) {
+ if (*begin != Space && *begin != Tab)
+ return false;
+ ++begin;
+ }
+ return true;
+}
+
+static QString createLinkTitle(const QString &title)
+{
+ QString result;
+ result.reserve(title.size() + 2);
+ result += DoubleQuote;
+
+ const QChar *data = title.data();
+ const QChar *end = data + title.size();
+
+ while (data < end) {
+ const auto lineEndPositions = findLineEnd(data, end);
+
+ if (!isBlankLine(data, lineEndPositions.lineEnd)) {
+ while (data < lineEndPositions.nextLineBegin) {
+ if (*data == DoubleQuote)
+ result += Backslash;
+ result += *data;
+ ++data;
+ }
+ }
+
+ data = lineEndPositions.nextLineBegin;
+ }
+
+ result += DoubleQuote;
+ return result;
+}
+
int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat, bool ignoreEmpty)
{
if (block.text().isEmpty() && ignoreEmpty)
@@ -445,7 +514,12 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
col += s.length();
} else if (fmt.hasProperty(QTextFormat::AnchorHref)) {
QString s = QLatin1Char('[') + fragmentText + QLatin1String("](") +
- fmt.property(QTextFormat::AnchorHref).toString() + QLatin1Char(')');
+ fmt.property(QTextFormat::AnchorHref).toString();
+ if (fmt.hasProperty(QTextFormat::TextToolTip)) {
+ s += Space;
+ s += createLinkTitle(fmt.property(QTextFormat::TextToolTip).toString());
+ }
+ s += QLatin1Char(')');
if (wrap && col + s.length() > ColumnLimit) {
m_stream << Newline << wrapIndentString;
col = m_wrappedLineIndent;
diff --git a/src/network/access/qftp.cpp b/src/network/access/qftp.cpp
index 66dd3f9371..cda800ce35 100644
--- a/src/network/access/qftp.cpp
+++ b/src/network/access/qftp.cpp
@@ -317,7 +317,7 @@ void QFtpDTP::connectToHost(const QString & host, quint16 port)
socket = nullptr;
}
socket = new QTcpSocket(this);
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
//copy network session down to the socket
socket->setProperty("_q_networksession", property("_q_networksession"));
#endif
@@ -333,7 +333,7 @@ void QFtpDTP::connectToHost(const QString & host, quint16 port)
int QFtpDTP::setupListener(const QHostAddress &address)
{
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
//copy network session down to the socket
listener.setProperty("_q_networksession", property("_q_networksession"));
#endif
@@ -817,7 +817,7 @@ QFtpPI::QFtpPI(QObject *parent) :
void QFtpPI::connectToHost(const QString &host, quint16 port)
{
emit connectState(QFtp::HostLookup);
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
//copy network session down to the socket & DTP
commandSocket.setProperty("_q_networksession", property("_q_networksession"));
dtp.setProperty("_q_networksession", property("_q_networksession"));
@@ -2287,7 +2287,7 @@ void QFtpPrivate::_q_startNextCommand()
c->rawCmds.clear();
_q_piFinished(QLatin1String("Proxy set to ") + proxyHost + QLatin1Char(':') + QString::number(proxyPort));
} else if (c->command == QFtp::ConnectToHost) {
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
//copy network session down to the PI
pi.setProperty("_q_networksession", q->property("_q_networksession"));
#endif
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 04f63e8735..b64e4fde86 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -132,7 +132,7 @@ void QHttpNetworkConnectionPrivate::init()
for (int i = 0; i < channelCount; i++) {
channels[i].setConnection(this->q_func());
channels[i].ssl = encrypt;
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
//push session down to channels
channels[i].networkSession = networkSession;
#endif
@@ -1267,7 +1267,7 @@ void QHttpNetworkConnectionPrivate::startNetworkLayerStateLookup()
channels[1].networkLayerPreference = QAbstractSocket::IPv6Protocol;
int timeout = 300;
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
if (networkSession) {
const QNetworkConfiguration::BearerType bearerType = networkSession->configuration().bearerType();
if (bearerType == QNetworkConfiguration::Bearer2G)
@@ -1309,7 +1309,7 @@ void QHttpNetworkConnectionPrivate::_q_connectDelayedChannel()
channels[1].ensureConnection();
}
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt,
QHttpNetworkConnection::ConnectionType connectionType,
QObject *parent, QSharedPointer<QNetworkSession> networkSession)
diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h
index fee84bb6c0..cfce3ecc00 100644
--- a/src/network/access/qhttpnetworkconnection_p.h
+++ b/src/network/access/qhttpnetworkconnection_p.h
@@ -100,7 +100,7 @@ public:
ConnectionTypeHTTP2Direct
};
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
explicit QHttpNetworkConnection(const QString &hostName, quint16 port = 80, bool encrypt = false,
ConnectionType connectionType = ConnectionTypeHTTP,
QObject *parent = nullptr, QSharedPointer<QNetworkSession> networkSession
@@ -290,7 +290,7 @@ public:
QSharedPointer<QSslContext> sslContext;
#endif
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
QSharedPointer<QNetworkSession> networkSession;
#endif
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 98809e460b..a3c8172a70 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -56,7 +56,7 @@
# include <QtNetwork/qsslcipher.h>
#endif
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
#include "private/qnetworksession_p.h"
#endif
@@ -123,7 +123,7 @@ void QHttpNetworkConnectionChannel::init()
#else
socket = new QTcpSocket;
#endif
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
//push session down to socket
if (networkSession)
socket->setProperty("_q_networksession", QVariant::fromValue(networkSession));
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index 44ad2d7959..c73c4c3bd5 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -136,7 +136,7 @@ public:
#endif
// to emit the signal for all in-flight replies:
void emitFinishedWithError(QNetworkReply::NetworkError error, const char *message);
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
QSharedPointer<QNetworkSession> networkSession;
#endif
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index 6322c773ac..5a0940aa24 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -185,7 +185,7 @@ public:
QNetworkAccessCachedHttpConnection(const QString &hostName, quint16 port, bool encrypt,
QHttpNetworkConnection::ConnectionType connectionType)
: QHttpNetworkConnection(hostName, port, encrypt, connectionType)
-#else
+#else // ### Qt6: Remove section
QNetworkAccessCachedHttpConnection(const QString &hostName, quint16 port, bool encrypt,
QHttpNetworkConnection::ConnectionType connectionType,
QSharedPointer<QNetworkSession> networkSession)
@@ -337,7 +337,7 @@ void QHttpThreadDelegate::startRequest()
#ifdef QT_NO_BEARERMANAGEMENT
httpConnection = new QNetworkAccessCachedHttpConnection(urlCopy.host(), urlCopy.port(), ssl,
connectionType);
-#else
+#else // ### Qt6: Remove section
httpConnection = new QNetworkAccessCachedHttpConnection(urlCopy.host(), urlCopy.port(), ssl,
connectionType,
networkSession);
diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h
index 208b2cb149..8a197b0b98 100644
--- a/src/network/access/qhttpthreaddelegate_p.h
+++ b/src/network/access/qhttpthreaddelegate_p.h
@@ -118,7 +118,7 @@ public:
QNetworkReply::NetworkError incomingErrorCode;
QString incomingErrorDetail;
QHttp2Configuration http2Parameters;
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
QSharedPointer<QNetworkSession> networkSession;
#endif
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index 8f42f3690b..9d7e7200fa 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -371,7 +371,7 @@ void QNetworkAccessBackend::sslErrors(const QList<QSslError> &errors)
*/
bool QNetworkAccessBackend::start()
{
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
// For bearer, check if session start is required
QSharedPointer<QNetworkSession> networkSession(manager->getNetworkSession());
if (networkSession) {
diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp
index fb8cd79c12..7b09608499 100644
--- a/src/network/access/qnetworkaccessftpbackend.cpp
+++ b/src/network/access/qnetworkaccessftpbackend.cpp
@@ -161,7 +161,7 @@ void QNetworkAccessFtpBackend::open()
if (!objectCache->requestEntry(cacheKey, this,
SLOT(ftpConnectionReady(QNetworkAccessCache::CacheableObject*)))) {
ftp = new QNetworkAccessCachedFtpConnection;
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
//copy network session down to the QFtp
ftp->setProperty("_q_networksession", property("_q_networksession"));
#endif
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index c80600d1b7..38807d3cda 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -311,6 +311,7 @@ static void ensureInitialized()
/*!
\fn void QNetworkAccessManager::networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible)
+ \obsolete
This signal is emitted when the value of the \l networkAccessible property changes.
\a accessible is the new network accessibility.
@@ -320,6 +321,7 @@ static void ensureInitialized()
\fn void QNetworkAccessManager::networkSessionConnected()
\since 4.7
+ \obsolete
\internal
@@ -1008,10 +1010,11 @@ QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &requ
return d_func()->postProcess(createRequest(QNetworkAccessManager::DeleteOperation, request));
}
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
/*!
\since 4.7
+ \obsolete
Sets the network configuration that will be used when creating the
\l {QNetworkSession}{network session} to \a config.
@@ -1049,6 +1052,7 @@ void QNetworkAccessManager::setConfiguration(const QNetworkConfiguration &config
/*!
\since 4.7
+ \obsolete
Returns the network configuration that will be used to create the
\l {QNetworkSession}{network session} which will be used when processing network requests.
@@ -1069,6 +1073,7 @@ QNetworkConfiguration QNetworkAccessManager::configuration() const
/*!
\since 4.7
+ \obsolete
Returns the current active network configuration.
@@ -1097,6 +1102,7 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const
/*!
\since 4.7
+ \obsolete
Overrides the reported network accessibility. If \a accessible is NotAccessible the reported
network accessiblity will always be NotAccessible. Otherwise the reported network
@@ -1109,16 +1115,20 @@ void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkA
d->defaultAccessControl = accessible == NotAccessible ? false : true;
if (d->networkAccessible != accessible) {
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
NetworkAccessibility previous = networkAccessible();
d->networkAccessible = accessible;
NetworkAccessibility current = networkAccessible();
if (previous != current)
emit networkAccessibleChanged(current);
+QT_WARNING_POP
}
}
/*!
\since 4.7
+ \obsolete
Returns the current network accessibility.
*/
@@ -1482,7 +1492,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
if (!d->statusMonitor.isMonitoring() && !d->statusMonitor.start())
qWarning(lcNetMon, "failed to start network status monitoring");
} else {
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
// Return a disabled network reply if network access is disabled.
// Except if the scheme is empty or file:// or if the host resolves to a loopback address.
if (d->networkAccessible == NotAccessible && !isLocalFile) {
@@ -1556,7 +1566,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
}
#endif
QNetworkReplyHttpImpl *reply = new QNetworkReplyHttpImpl(this, request, op, outgoingData);
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
if (!d->statusMonitor.isEnabled()) {
connect(this, SIGNAL(networkSessionConnected()),
reply, SLOT(_q_networkSessionConnected()));
@@ -1568,7 +1578,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
// first step: create the reply
QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
// NETMONTODO: network reply impl must be augmented to use the same monitoring
// capabilities as http network reply impl does. Once it does: uncomment the condition below
if (!isLocalFile /*&& !d->statusMonitor.isEnabled()*/) {
@@ -1759,7 +1769,7 @@ void QNetworkAccessManagerPrivate::_q_replyFinished(QNetworkReply *reply)
if (reply->request().attribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, false).toBool())
QMetaObject::invokeMethod(reply, [reply] { reply->deleteLater(); }, Qt::QueuedConnection);
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
// If there are no active requests, release our reference to the network session.
// It will not be destroyed immediately, but rather when the connection cache is flushed
// after 2 minutes.
@@ -1817,7 +1827,7 @@ QNetworkReply *QNetworkAccessManagerPrivate::postProcess(QNetworkReply *reply)
q->connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(_q_replySslErrors(QList<QSslError>)));
q->connect(reply, SIGNAL(preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)), SLOT(_q_replyPreSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*)));
#endif
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
activeReplyCount++;
#endif
@@ -1987,7 +1997,7 @@ void QNetworkAccessManagerPrivate::destroyThread()
}
}
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &config)
{
Q_Q(QNetworkAccessManager);
@@ -2022,10 +2032,13 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co
if (!networkSessionStrongRef) {
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (networkAccessible == QNetworkAccessManager::NotAccessible || !online)
emit q->networkAccessibleChanged(QNetworkAccessManager::NotAccessible);
else
emit q->networkAccessibleChanged(QNetworkAccessManager::UnknownAccessibility);
+QT_WARNING_POP
return;
}
@@ -2072,6 +2085,8 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession
bool reallyOnline = false;
//Do not emit the networkSessionConnected signal here, except for roaming -> connected
//transition, otherwise it is emitted twice in a row when opening a connection.
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (state == QNetworkSession::Connected && lastSessionState != QNetworkSession::Roaming)
emit q->networkSessionConnected();
lastSessionState = state;
@@ -2107,6 +2122,7 @@ void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession
_q_networkSessionClosed();
createSession(q->configuration());
}
+QT_WARNING_POP
}
void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline)
@@ -2118,6 +2134,8 @@ void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline)
return;
}
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
// if the user set a config, we only care whether this one is active.
// Otherwise, this QNAM is online if there is an online config.
@@ -2143,6 +2161,7 @@ void QNetworkAccessManagerPrivate::_q_onlineStateChanged(bool isOnline)
emit q->networkAccessibleChanged(networkAccessible);
}
}
+QT_WARNING_POP
}
void QNetworkAccessManagerPrivate::_q_configurationChanged(const QNetworkConfiguration &configuration)
diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h
index c84116fd41..cfb75f0f90 100644
--- a/src/network/access/qnetworkaccessmanager.h
+++ b/src/network/access/qnetworkaccessmanager.h
@@ -63,7 +63,7 @@ class QNetworkProxy;
class QNetworkProxyFactory;
class QSslError;
class QHstsPolicy;
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
class QNetworkConfiguration;
#endif
class QHttpMultiPart;
@@ -74,7 +74,7 @@ class Q_NETWORK_EXPORT QNetworkAccessManager: public QObject
{
Q_OBJECT
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
Q_PROPERTY(NetworkAccessibility networkAccessible READ networkAccessible WRITE setNetworkAccessible NOTIFY networkAccessibleChanged)
#endif
@@ -90,7 +90,7 @@ public:
UnknownOperation = 0
};
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
enum NetworkAccessibility {
UnknownAccessibility = -1,
NotAccessible = 0,
@@ -145,13 +145,13 @@ public:
QNetworkReply *sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QHttpMultiPart *multiPart);
#endif
-#ifndef QT_NO_BEARERMANAGEMENT
- void setConfiguration(const QNetworkConfiguration &config);
- QNetworkConfiguration configuration() const;
- QNetworkConfiguration activeConfiguration() const;
+#if !defined(QT_NO_BEARERMANAGEMENT) // ### Qt6: Remove section
+ QT_DEPRECATED_VERSION_5_15 void setConfiguration(const QNetworkConfiguration &config);
+ QT_DEPRECATED_VERSION_5_15 QNetworkConfiguration configuration() const;
+ QT_DEPRECATED_VERSION_5_15 QNetworkConfiguration activeConfiguration() const;
- void setNetworkAccessible(NetworkAccessibility accessible);
- NetworkAccessibility networkAccessible() const;
+ QT_DEPRECATED_VERSION_5_15 void setNetworkAccessible(NetworkAccessibility accessible);
+ QT_DEPRECATED_VERSION_5_15 NetworkAccessibility networkAccessible() const;
#endif
#ifndef QT_NO_SSL
@@ -184,10 +184,10 @@ Q_SIGNALS:
void preSharedKeyAuthenticationRequired(QNetworkReply *reply, QSslPreSharedKeyAuthenticator *authenticator);
#endif
-#ifndef QT_NO_BEARERMANAGEMENT
- void networkSessionConnected();
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
+ QT_DEPRECATED_VERSION_5_15 void networkSessionConnected();
- void networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible);
+ QT_DEPRECATED_VERSION_5_15 void networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible);
#endif
protected:
@@ -209,7 +209,7 @@ private:
Q_DECLARE_PRIVATE(QNetworkAccessManager)
Q_PRIVATE_SLOT(d_func(), void _q_replySslErrors(QList<QSslError>))
Q_PRIVATE_SLOT(d_func(), void _q_replyPreSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator*))
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionClosed())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State))
Q_PRIVATE_SLOT(d_func(), void _q_configurationChanged(const QNetworkConfiguration &))
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index da92cad704..7926463d56 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -62,7 +62,7 @@
#include "QtNetwork/qnetworkproxy.h"
#include "QtNetwork/qnetworksession.h"
#include "qnetworkaccessauthenticationmanager_p.h"
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
#include "QtNetwork/qnetworkconfigmanager.h"
#endif
@@ -87,7 +87,7 @@ public:
#ifndef QT_NO_NETWORKPROXY
proxyFactory(nullptr),
#endif
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
lastSessionState(QNetworkSession::Invalid),
networkConfiguration(networkConfigurationManager.defaultConfiguration()),
customNetworkConfiguration(false),
@@ -102,7 +102,7 @@ public:
redirectPolicy(QNetworkRequest::ManualRedirectPolicy),
authenticationManager(QSharedPointer<QNetworkAccessAuthenticationManager>::create())
{
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
// we would need all active configurations to check for
// d->networkConfigurationManager.isOnline(), which is asynchronous
// and potentially expensive. We can just check the configuration here
@@ -153,7 +153,7 @@ public:
QStringList backendSupportedSchemes() const;
void _q_onlineStateChanged(bool isOnline);
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
void createSession(const QNetworkConfiguration &config);
QSharedPointer<QNetworkSession> getNetworkSession() const;
@@ -186,7 +186,7 @@ public:
QNetworkProxyFactory *proxyFactory;
#endif
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
QSharedPointer<QNetworkSession> networkSessionStrongRef;
QWeakPointer<QNetworkSession> networkSessionWeakRef;
QNetworkSession::State lastSessionState;
@@ -231,7 +231,7 @@ public:
int transferTimeout = 0;
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
Q_AUTOTEST_EXPORT static const QWeakPointer<const QNetworkSession> getNetworkSession(const QNetworkAccessManager *manager);
#endif
Q_DECLARE_PUBLIC(QNetworkAccessManager)
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 002d9ec5d1..c7d22be8f5 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -164,7 +164,7 @@ static QHash<QByteArray, QByteArray> parseHttpOptionHeader(const QByteArray &hea
}
}
-#if QT_CONFIG(bearermanagement)
+#if QT_CONFIG(bearermanagement) // ### Qt6: Remove section
static bool isSessionNeeded(const QUrl &url)
{
if (QNetworkStatusMonitor::isEnabled()) {
@@ -798,7 +798,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
QHttpThreadDelegate *delegate = new QHttpThreadDelegate;
// Propagate Http/2 settings:
delegate->http2Parameters = request.http2Configuration();
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
if (!QNetworkStatusMonitor::isEnabled())
delegate->networkSession = managerPrivate->getNetworkSession();
#endif
@@ -1206,7 +1206,7 @@ void QNetworkReplyHttpImplPrivate::followRedirect()
if (managerPrivate->thread)
managerPrivate->thread->disconnect();
-#if QT_CONFIG(bearermanagement)
+#if QT_CONFIG(bearermanagement) // ### Qt6: Remove section
// If the original request didn't need a session (i.e. it was to localhost)
// then we might not have a session open, to which to redirect, if the
// new URL is remote. When this happens, we need to open the session now:
@@ -1782,13 +1782,13 @@ void QNetworkReplyHttpImplPrivate::setResumeOffset(quint64 offset)
*/
bool QNetworkReplyHttpImplPrivate::start(const QNetworkRequest &newHttpRequest)
{
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
QSharedPointer<QNetworkSession> networkSession(managerPrivate->getNetworkSession());
if (!networkSession || QNetworkStatusMonitor::isEnabled()) {
#endif
postRequest(newHttpRequest);
return true;
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
}
// This is not ideal.
@@ -1817,7 +1817,7 @@ bool QNetworkReplyHttpImplPrivate::start(const QNetworkRequest &newHttpRequest)
#endif
}
-#if QT_CONFIG(bearermanagement)
+#if QT_CONFIG(bearermanagement) // ### Qt6: Remove section
bool QNetworkReplyHttpImplPrivate::startWaitForSession(QSharedPointer<QNetworkSession> &session)
{
Q_Q(QNetworkReplyHttpImpl);
@@ -1853,7 +1853,7 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation()
state = Working;
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
// Do not start background requests if they are not allowed by session policy
QSharedPointer<QNetworkSession> session(manager->d_func()->getNetworkSession());
QVariant isBackground = request.attribute(QNetworkRequest::BackgroundRequestAttribute, QVariant::fromValue(false));
@@ -2049,7 +2049,7 @@ void QNetworkReplyHttpImplPrivate::setupTransferTimeout()
}
}
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
void QNetworkReplyHttpImplPrivate::_q_networkSessionConnected()
{
Q_Q(QNetworkReplyHttpImpl);
@@ -2185,7 +2185,7 @@ void QNetworkReplyHttpImplPrivate::finished()
if (preMigrationDownloaded != Q_INT64_C(-1))
totalSize = totalSize.toLongLong() + preMigrationDownloaded;
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
Q_ASSERT(managerPrivate);
QSharedPointer<QNetworkSession> session = managerPrivate->getNetworkSession();
if (!QNetworkStatusMonitor::isEnabled() && session && session->state() == QNetworkSession::Roaming &&
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index dec0c4c589..c4de63990b 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -66,7 +66,7 @@
#include <private/qhttpnetworkrequest_p.h>
#include <private/qnetworkreply_p.h>
#include <QtNetwork/QNetworkProxy>
-#include <QtNetwork/QNetworkSession>
+#include <QtNetwork/QNetworkSession> // ### Qt6: Remove include
#ifndef QT_NO_SSL
#include <QtNetwork/QSslConfiguration>
@@ -102,7 +102,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingData())
Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingDataFinished())
Q_PRIVATE_SLOT(d_func(), void _q_transferTimedOut())
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State))
@@ -162,7 +162,7 @@ signals:
class QNetworkReplyHttpImplPrivate: public QNetworkReplyPrivate
{
-#if QT_CONFIG(bearermanagement)
+#if QT_CONFIG(bearermanagement) // ### Qt6: Remove section
bool startWaitForSession(QSharedPointer<QNetworkSession> &session);
#endif
@@ -186,7 +186,7 @@ public:
void _q_transferTimedOut();
void setupTransferTimeout();
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
void _q_networkSessionConnected();
void _q_networkSessionFailed();
void _q_networkSessionStateChanged(QNetworkSession::State);
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index a43a29a239..51bb386186 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -45,7 +45,7 @@
#include "QtCore/qcoreapplication.h"
#include "QtCore/qdatetime.h"
#include "QtNetwork/qsslconfiguration.h"
-#include "QtNetwork/qnetworksession.h"
+#include "QtNetwork/qnetworksession.h" // ### Qt6: Remove include
#include "qnetworkaccessmanager_p.h"
#include <QtCore/QCoreApplication>
@@ -88,7 +88,7 @@ void QNetworkReplyImplPrivate::_q_startOperation()
return;
}
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
Q_Q(QNetworkReplyImpl);
// Do not start background requests if they are not allowed by session policy
QSharedPointer<QNetworkSession> session(manager->d_func()->getNetworkSession());
@@ -102,7 +102,7 @@ void QNetworkReplyImplPrivate::_q_startOperation()
#endif
if (!backend->start()) {
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
// backend failed to start because the session state is not Connected.
// QNetworkAccessManager will call _q_startOperation again for us when the session
// state changes.
@@ -132,7 +132,7 @@ void QNetworkReplyImplPrivate::_q_startOperation()
#endif
return;
} else {
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
if (session) {
QObject::connect(session.data(), SIGNAL(stateChanged(QNetworkSession::State)),
q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection);
@@ -140,7 +140,7 @@ void QNetworkReplyImplPrivate::_q_startOperation()
#endif
}
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
if (session) {
//get notification of policy changes.
QObject::connect(session.data(), SIGNAL(usagePoliciesChanged(QNetworkSession::UsagePolicies)),
@@ -287,7 +287,7 @@ void QNetworkReplyImplPrivate::_q_bufferOutgoingData()
}
}
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
void QNetworkReplyImplPrivate::_q_networkSessionConnected()
{
Q_Q(QNetworkReplyImpl);
@@ -787,7 +787,7 @@ void QNetworkReplyImplPrivate::finished()
totalSize = totalSize.toLongLong() + preMigrationDownloaded;
if (!manager.isNull()) {
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
QSharedPointer<QNetworkSession> session (manager->d_func()->getNetworkSession());
if (session && session->state() == QNetworkSession::Roaming &&
state == Working && errorCode != QNetworkReply::OperationCanceledError) {
diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h
index 8cec79541a..f98f773775 100644
--- a/src/network/access/qnetworkreplyimpl_p.h
+++ b/src/network/access/qnetworkreplyimpl_p.h
@@ -62,7 +62,7 @@
#include "private/qringbuffer_p.h"
#include "private/qbytedata_p.h"
#include <QSharedPointer>
-#include <QtNetwork/QNetworkSession>
+#include <QtNetwork/QNetworkSession> // ### Qt6: Remove include
QT_BEGIN_NAMESPACE
@@ -92,7 +92,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void _q_copyReadChannelFinished())
Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingData())
Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingDataFinished())
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State))
@@ -124,7 +124,7 @@ public:
void _q_copyReadChannelFinished();
void _q_bufferOutgoingData();
void _q_bufferOutgoingDataFinished();
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
void _q_networkSessionConnected();
void _q_networkSessionFailed();
void _q_networkSessionStateChanged(QNetworkSession::State);
diff --git a/src/network/doc/snippets/network/tcpwait.cpp b/src/network/doc/snippets/network/tcpwait.cpp
index 97856e157f..d57305930c 100644
--- a/src/network/doc/snippets/network/tcpwait.cpp
+++ b/src/network/doc/snippets/network/tcpwait.cpp
@@ -51,8 +51,6 @@
#include <QtGui>
#include <QTcpSocket>
-#include "server.h"
-
int main(int argv, char **args)
{
QCoreApplication app(argv, args);
diff --git a/src/network/doc/snippets/snippets.pro b/src/network/doc/snippets/snippets.pro
new file mode 100644
index 0000000000..39153e0c8e
--- /dev/null
+++ b/src/network/doc/snippets/snippets.pro
@@ -0,0 +1,7 @@
+TEMPLATE = app
+
+TARGET = network_cppsnippets
+
+QT += network
+
+SOURCES += network/tcpwait.cpp
diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp
index 90c8b75a86..3cabdd0bd5 100644
--- a/src/network/kernel/qnetworkproxy.cpp
+++ b/src/network/kernel/qnetworkproxy.cpp
@@ -241,7 +241,7 @@
#include "qstringlist.h"
#include "qurl.h"
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
#include <QtNetwork/QNetworkConfiguration>
#endif
@@ -984,11 +984,6 @@ template<> void QSharedDataPointer<QNetworkProxyQueryPrivate>::detach()
like choosing an caching HTTP proxy for HTTP-based connections,
but a more powerful SOCKSv5 proxy for all others.
- The network configuration specifies which configuration to use,
- when bearer management is used. For example on a mobile phone
- the proxy settings are likely to be different for the cellular
- network vs WLAN.
-
Some of the criteria may not make sense in all of the types of
query. The following table lists the criteria that are most
commonly used, according to the type of query.
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index b8957ce818..3d88c0337d 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -464,7 +464,10 @@
#include "qabstractsocket_p.h"
#include "private/qhostinfo_p.h"
+#if QT_CONFIG(bearermanagement) // ### Qt6: Remove section
#include "private/qnetworksession_p.h"
+#endif
+#include "private/qnetworkconfiguration_p.h" // ### Qt6: Remove include
#include <qabstracteventdispatcher.h>
#include <qhostaddress.h>
@@ -643,7 +646,7 @@ bool QAbstractSocketPrivate::initSocketLayer(QAbstractSocket::NetworkLayerProtoc
QAbstractSocket::tr("Operation on socket is not supported"));
return false;
}
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
//copy network session down to the socket engine (if it has been set)
socketEngine->setProperty("_q_networksession", q->property("_q_networksession"));
#endif
@@ -1146,7 +1149,7 @@ void QAbstractSocketPrivate::_q_connectToNextAddress()
Qt::DirectConnection);
}
int connectTimeout = QNetworkConfigurationPrivate::DefaultTimeout;
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
QSharedPointer<QNetworkSession> networkSession = qvariant_cast< QSharedPointer<QNetworkSession> >(q->property("_q_networksession"));
if (networkSession) {
QNetworkConfiguration networkConfiguration = networkSession->configuration();
@@ -1941,7 +1944,7 @@ bool QAbstractSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState
d->setError(UnsupportedSocketOperationError, tr("Operation on socket is not supported"));
return false;
}
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
//copy network session down to the socket engine (if it has been set)
d->socketEngine->setProperty("_q_networksession", property("_q_networksession"));
#endif
@@ -2134,7 +2137,7 @@ bool QAbstractSocket::waitForConnected(int msecs)
QElapsedTimer stopWatch;
stopWatch.start();
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
QSharedPointer<QNetworkSession> networkSession = qvariant_cast< QSharedPointer<QNetworkSession> >(property("_q_networksession"));
#endif
@@ -2157,7 +2160,7 @@ bool QAbstractSocket::waitForConnected(int msecs)
return false; // connect not im progress anymore!
int connectTimeout = QNetworkConfigurationPrivate::DefaultTimeout;
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
if (networkSession) {
QNetworkConfiguration networkConfiguration = networkSession->configuration();
connectTimeout = networkConfiguration.connectTimeout();
diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp
index 98f850ba1b..b80bdec992 100644
--- a/src/network/socket/qhttpsocketengine.cpp
+++ b/src/network/socket/qhttpsocketengine.cpp
@@ -72,7 +72,7 @@ bool QHttpSocketEngine::initialize(QAbstractSocket::SocketType type, QAbstractSo
setSocketType(type);
d->socket = new QTcpSocket(this);
d->reply = new QHttpNetworkReply(QUrl(), this);
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
d->socket->setProperty("_q_networkSession", property("_q_networkSession"));
#endif
diff --git a/src/network/socket/qlocalsocket.cpp b/src/network/socket/qlocalsocket.cpp
index d517f91aad..38e47d6e26 100644
--- a/src/network/socket/qlocalsocket.cpp
+++ b/src/network/socket/qlocalsocket.cpp
@@ -74,7 +74,7 @@ QT_BEGIN_NAMESPACE
The socket is opened in the given \a openMode and first enters ConnectingState.
If a connection is established, QLocalSocket enters ConnectedState and emits connected().
- After calling this function, the socket can emit error() to signal that an error occurred.
+ After calling this function, the socket can emit errorOccurred() to signal that an error occurred.
\sa state(), serverName(), waitForConnected()
*/
@@ -87,7 +87,7 @@ QT_BEGIN_NAMESPACE
Note that unlike in most other QIODevice subclasses, open() may not open the device directly.
The function return false if the socket was already connected or if the server to connect
- to was not defined and true in any other case. The connected() or error() signals will be
+ to was not defined and true in any other case. The connected() or errorOccurred() signals will be
emitted once the device is actualy open (or the connection failed).
See connectToServer() for more details.
@@ -220,25 +220,11 @@ QT_BEGIN_NAMESPACE
/*!
\fn QLocalSocket::LocalSocketError QLocalSocket::error() const
- \deprecated
-
- Use socketError() instead.
-
- Returns the type of error that last occurred.
-
- \sa state(), errorString(), socketError()
-*/
-
-/*!
- \fn QLocalSocket::LocalSocketError QLocalSocket::socketError() const
- \since 5.15
-
Returns the type of error that last occurred.
\sa state(), errorString()
*/
-
/*!
\fn bool QLocalSocket::isValid() const
@@ -286,7 +272,7 @@ QT_BEGIN_NAMESPACE
Waits until the socket is connected, up to \a msecs milliseconds. If the
connection has been established, this function returns \c true; otherwise
it returns \c false. In the case where it returns \c false, you can call
- socketError() to determine the cause of the error.
+ error() to determine the cause of the error.
The following example waits up to one second for a connection
to be established:
@@ -305,7 +291,7 @@ QT_BEGIN_NAMESPACE
connection was successfully disconnected, this function returns \c true;
otherwise it returns \c false (if the operation timed out, if an error
occurred, or if this QLocalSocket is already disconnected). In the case
- where it returns \c false, you can call socketError() to determine the cause of
+ where it returns \c false, you can call error() to determine the cause of
the error.
The following example waits up to one second for a connection
@@ -343,6 +329,14 @@ QT_BEGIN_NAMESPACE
/*!
\fn void QLocalSocket::error(QLocalSocket::LocalSocketError socketError)
+ \obsolete
+
+ Use errorOccurred() instead.
+*/
+
+/*!
+ \fn void QLocalSocket::errorOccurred(QLocalSocket::LocalSocketError socketError)
+ \since 5.15
This signal is emitted after an error occurred. The \a socketError
parameter describes the type of error that occurred.
@@ -351,7 +345,7 @@ QT_BEGIN_NAMESPACE
connections, you will have to register it with Q_DECLARE_METATYPE() and
qRegisterMetaType().
- \sa socketError(), errorString(), {Creating Custom Qt Types}
+ \sa error(), errorString(), {Creating Custom Qt Types}
*/
/*!
@@ -376,6 +370,9 @@ QLocalSocket::QLocalSocket(QObject * parent)
{
Q_D(QLocalSocket);
d->init();
+
+ // Support the deprecated error() signal:
+ connect(this, &QLocalSocket::errorOccurred, this, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error));
}
/*!
@@ -403,7 +400,7 @@ bool QLocalSocket::open(OpenMode openMode)
The socket is opened in the given \a openMode and first enters ConnectingState.
If a connection is established, QLocalSocket enters ConnectedState and emits connected().
- After calling this function, the socket can emit error() to signal that an error occurred.
+ After calling this function, the socket can emit errorOccurred() to signal that an error occurred.
\sa state(), serverName(), waitForConnected()
*/
@@ -460,7 +457,7 @@ QString QLocalSocket::fullServerName() const
/*!
Returns the state of the socket.
- \sa socketError()
+ \sa error()
*/
QLocalSocket::LocalSocketState QLocalSocket::state() const
{
@@ -480,7 +477,7 @@ bool QLocalSocket::isSequential() const
The LocalServerError enumeration represents the errors that can occur.
The most recent error can be retrieved through a call to
- \l QLocalSocket::socketError().
+ \l QLocalSocket::error().
\value ConnectionRefusedError The connection was refused by
the peer (or timed out).
diff --git a/src/network/socket/qlocalsocket.h b/src/network/socket/qlocalsocket.h
index 9cf76d1022..ae78c86b3c 100644
--- a/src/network/socket/qlocalsocket.h
+++ b/src/network/socket/qlocalsocket.h
@@ -97,12 +97,7 @@ public:
virtual bool canReadLine() const override;
virtual bool open(OpenMode openMode = ReadWrite) override;
virtual void close() override;
-
-#if QT_DEPRECATED_SINCE(5, 15)
- QT_DEPRECATED_X("Use socketError()") LocalSocketError error() const;
-#endif // QT_DEPRECATED_SINCE(5, 15)
-
- LocalSocketError socketError() const;
+ LocalSocketError error() const;
bool flush();
bool isValid() const;
qint64 readBufferSize() const;
@@ -122,7 +117,11 @@ public:
Q_SIGNALS:
void connected();
void disconnected();
+#if QT_DEPRECATED_SINCE(5,15)
+ QT_DEPRECATED_X("Use QLocalSocket::errorOccurred(QLocalSocket::LocalSocketError) instead")
void error(QLocalSocket::LocalSocketError socketError);
+#endif
+ void errorOccurred(QLocalSocket::LocalSocketError socketError);
void stateChanged(QLocalSocket::LocalSocketState socketState);
protected:
diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h
index d93b53be0c..e3bcd92326 100644
--- a/src/network/socket/qlocalsocket_p.h
+++ b/src/network/socket/qlocalsocket_p.h
@@ -125,7 +125,7 @@ public:
bool ownsTcpSocket;
void setSocket(QLocalUnixSocket*);
QString generateErrorString(QLocalSocket::LocalSocketError, const QString &function) const;
- void errorOccurred(QLocalSocket::LocalSocketError, const QString &function);
+ void setErrorAndEmit(QLocalSocket::LocalSocketError, const QString &function);
void _q_stateChanged(QAbstractSocket::SocketState newState);
void _q_error(QAbstractSocket::SocketError newError);
#elif defined(Q_OS_WIN)
@@ -142,7 +142,7 @@ public:
qint64 skip(qint64 maxSize) override;
QLocalUnixSocket unixSocket;
QString generateErrorString(QLocalSocket::LocalSocketError, const QString &function) const;
- void errorOccurred(QLocalSocket::LocalSocketError, const QString &function);
+ void setErrorAndEmit(QLocalSocket::LocalSocketError, const QString &function);
void _q_stateChanged(QAbstractSocket::SocketState newState);
void _q_error(QAbstractSocket::SocketError newError);
void _q_connectToSocket();
diff --git a/src/network/socket/qlocalsocket_tcp.cpp b/src/network/socket/qlocalsocket_tcp.cpp
index 74d3d547b9..e13bcfc0cb 100644
--- a/src/network/socket/qlocalsocket_tcp.cpp
+++ b/src/network/socket/qlocalsocket_tcp.cpp
@@ -95,7 +95,7 @@ void QLocalSocketPrivate::_q_error(QAbstractSocket::SocketError socketError)
QLocalSocket::LocalSocketError error = (QLocalSocket::LocalSocketError)socketError;
QString errorString = generateErrorString(error, function);
q->setErrorString(errorString);
- emit q->error(error);
+ emit q->errorOccurred(error);
}
void QLocalSocketPrivate::_q_stateChanged(QAbstractSocket::SocketState newState)
@@ -168,7 +168,7 @@ QString QLocalSocketPrivate::generateErrorString(QLocalSocket::LocalSocketError
return errorString;
}
-void QLocalSocketPrivate::errorOccurred(QLocalSocket::LocalSocketError error, const QString &function)
+void QLocalSocketPrivate::setErrorAndEmit(QLocalSocket::LocalSocketError error, const QString &function)
{
Q_Q(QLocalSocket);
switch (error) {
@@ -206,7 +206,7 @@ void QLocalSocketPrivate::errorOccurred(QLocalSocket::LocalSocketError error, co
QString errorString = generateErrorString(error, function);
q->setErrorString(errorString);
- emit q->error(error);
+ emit q->errorOccurred(error);
// errors cause a disconnect
tcpSocket->setSocketState(QAbstractSocket::UnconnectedState);
@@ -222,7 +222,7 @@ void QLocalSocket::connectToServer(OpenMode openMode)
Q_D(QLocalSocket);
if (state() == ConnectedState || state() == ConnectingState) {
setErrorString(tr("Trying to connect while connection is in progress"));
- emit error(QLocalSocket::OperationError);
+ emit errorOccurred(QLocalSocket::OperationError);
return;
}
@@ -231,8 +231,8 @@ void QLocalSocket::connectToServer(OpenMode openMode)
emit stateChanged(d->state);
if (d->serverName.isEmpty()) {
- d->errorOccurred(ServerNotFoundError,
- QLatin1String("QLocalSocket::connectToServer"));
+ d->setErrorAndEmit(ServerNotFoundError,
+ QLatin1String("QLocalSocket::connectToServer"));
return;
}
@@ -246,8 +246,8 @@ void QLocalSocket::connectToServer(OpenMode openMode)
bool ok;
const quint16 port = settings.value(d->fullServerName).toUInt(&ok);
if (!ok) {
- d->errorOccurred(ServerNotFoundError,
- QLatin1String("QLocalSocket::connectToServer"));
+ d->setErrorAndEmit(ServerNotFoundError,
+ QLatin1String("QLocalSocket::connectToServer"));
return;
}
QIODevice::open(openMode);
@@ -363,15 +363,8 @@ void QLocalSocket::disconnectFromServer()
d->tcpSocket->disconnectFromHost();
}
-#if QT_DEPRECATED_SINCE(5, 15)
QLocalSocket::LocalSocketError QLocalSocket::error() const
{
- return socketError();
-}
-#endif // QT_DEPRECATED_SINCE(5, 15)
-
-QLocalSocket::LocalSocketError QLocalSocket::socketError() const
-{
Q_D(const QLocalSocket);
switch (d->tcpSocket->error()) {
case QAbstractSocket::ConnectionRefusedError:
diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp
index 2e2eb7dee9..e860b880d5 100644
--- a/src/network/socket/qlocalsocket_unix.cpp
+++ b/src/network/socket/qlocalsocket_unix.cpp
@@ -99,7 +99,7 @@ void QLocalSocketPrivate::_q_error(QAbstractSocket::SocketError socketError)
QLocalSocket::LocalSocketError error = (QLocalSocket::LocalSocketError)socketError;
QString errorString = generateErrorString(error, function);
q->setErrorString(errorString);
- emit q->error(error);
+ emit q->errorOccurred(error);
}
void QLocalSocketPrivate::_q_stateChanged(QAbstractSocket::SocketState newState)
@@ -172,7 +172,7 @@ QString QLocalSocketPrivate::generateErrorString(QLocalSocket::LocalSocketError
return errorString;
}
-void QLocalSocketPrivate::errorOccurred(QLocalSocket::LocalSocketError error, const QString &function)
+void QLocalSocketPrivate::setErrorAndEmit(QLocalSocket::LocalSocketError error, const QString &function)
{
Q_Q(QLocalSocket);
switch (error) {
@@ -210,7 +210,7 @@ void QLocalSocketPrivate::errorOccurred(QLocalSocket::LocalSocketError error, co
QString errorString = generateErrorString(error, function);
q->setErrorString(errorString);
- emit q->error(error);
+ emit q->errorOccurred(error);
// errors cause a disconnect
unixSocket.setSocketState(QAbstractSocket::UnconnectedState);
@@ -227,7 +227,7 @@ void QLocalSocket::connectToServer(OpenMode openMode)
if (state() == ConnectedState || state() == ConnectingState) {
QString errorString = d->generateErrorString(QLocalSocket::OperationError, QLatin1String("QLocalSocket::connectToserver"));
setErrorString(errorString);
- emit error(QLocalSocket::OperationError);
+ emit errorOccurred(QLocalSocket::OperationError);
return;
}
@@ -237,15 +237,15 @@ void QLocalSocket::connectToServer(OpenMode openMode)
emit stateChanged(d->state);
if (d->serverName.isEmpty()) {
- d->errorOccurred(ServerNotFoundError,
- QLatin1String("QLocalSocket::connectToServer"));
+ d->setErrorAndEmit(ServerNotFoundError,
+ QLatin1String("QLocalSocket::connectToServer"));
return;
}
// create the socket
if (-1 == (d->connectingSocket = qt_safe_socket(PF_UNIX, SOCK_STREAM, 0, O_NONBLOCK))) {
- d->errorOccurred(UnsupportedSocketOperationError,
- QLatin1String("QLocalSocket::connectToServer"));
+ d->setErrorAndEmit(UnsupportedSocketOperationError,
+ QLatin1String("QLocalSocket::connectToServer"));
return;
}
@@ -281,7 +281,7 @@ void QLocalSocketPrivate::_q_connectToSocket()
name.sun_family = PF_UNIX;
if (sizeof(name.sun_path) < (uint)encodedConnectingPathName.size() + 1) {
QString function = QLatin1String("QLocalSocket::connectToServer");
- errorOccurred(QLocalSocket::ServerNotFoundError, function);
+ setErrorAndEmit(QLocalSocket::ServerNotFoundError, function);
return;
}
::memcpy(name.sun_path, encodedConnectingPathName.constData(),
@@ -292,17 +292,17 @@ void QLocalSocketPrivate::_q_connectToSocket()
{
case EINVAL:
case ECONNREFUSED:
- errorOccurred(QLocalSocket::ConnectionRefusedError, function);
+ setErrorAndEmit(QLocalSocket::ConnectionRefusedError, function);
break;
case ENOENT:
- errorOccurred(QLocalSocket::ServerNotFoundError, function);
+ setErrorAndEmit(QLocalSocket::ServerNotFoundError, function);
break;
case EACCES:
case EPERM:
- errorOccurred(QLocalSocket::SocketAccessError, function);
+ setErrorAndEmit(QLocalSocket::SocketAccessError, function);
break;
case ETIMEDOUT:
- errorOccurred(QLocalSocket::SocketTimeoutError, function);
+ setErrorAndEmit(QLocalSocket::SocketTimeoutError, function);
break;
case EAGAIN:
// Try again later, all of the sockets listening are full
@@ -320,7 +320,7 @@ void QLocalSocketPrivate::_q_connectToSocket()
delayConnect->setEnabled(true);
break;
default:
- errorOccurred(QLocalSocket::UnknownSocketError, function);
+ setErrorAndEmit(QLocalSocket::UnknownSocketError, function);
}
return;
}
@@ -336,7 +336,7 @@ void QLocalSocketPrivate::_q_connectToSocket()
q->emit connected();
} else {
QString function = QLatin1String("QLocalSocket::connectToServer");
- errorOccurred(QLocalSocket::UnknownSocketError, function);
+ setErrorAndEmit(QLocalSocket::UnknownSocketError, function);
}
connectingSocket = -1;
connectingName.clear();
@@ -461,15 +461,8 @@ void QLocalSocket::disconnectFromServer()
d->unixSocket.disconnectFromHost();
}
-#if QT_DEPRECATED_SINCE(5, 15)
QLocalSocket::LocalSocketError QLocalSocket::error() const
{
- return socketError();
-}
-#endif // QT_DEPRECATED_SINCE(5, 15)
-
-QLocalSocket::LocalSocketError QLocalSocket::socketError() const
-{
Q_D(const QLocalSocket);
switch (d->unixSocket.socketError()) {
case QAbstractSocket::ConnectionRefusedError:
@@ -536,8 +529,8 @@ bool QLocalSocket::waitForConnected(int msec)
const int result = qt_poll_msecs(&pfd, 1, timeout);
if (result == -1)
- d->errorOccurred(QLocalSocket::UnknownSocketError,
- QLatin1String("QLocalSocket::waitForConnected"));
+ d->setErrorAndEmit(QLocalSocket::UnknownSocketError,
+ QLatin1String("QLocalSocket::waitForConnected"));
else if (result > 0)
d->_q_connectToSocket();
} while (state() == ConnectingState && !timer.hasExpired(msec));
diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp
index 657790519b..48ffd87beb 100644
--- a/src/network/socket/qlocalsocket_win.cpp
+++ b/src/network/socket/qlocalsocket_win.cpp
@@ -91,7 +91,7 @@ void QLocalSocketPrivate::_q_winError(ulong windowsError, const QString &functio
if (state == QLocalSocket::UnconnectedState && currentState != QLocalSocket::ConnectingState)
emit q->disconnected();
}
- emit q->error(error);
+ emit q->errorOccurred(error);
}
QLocalSocketPrivate::QLocalSocketPrivate() : QIODevicePrivate(),
@@ -123,7 +123,7 @@ void QLocalSocket::connectToServer(OpenMode openMode)
if (state() == ConnectedState || state() == ConnectingState) {
d->error = OperationError;
d->errorString = tr("Trying to connect while connection is in progress");
- emit error(QLocalSocket::OperationError);
+ emit errorOccurred(QLocalSocket::OperationError);
return;
}
@@ -135,7 +135,7 @@ void QLocalSocket::connectToServer(OpenMode openMode)
d->error = ServerNotFoundError;
d->errorString = tr("%1: Invalid name").arg(QLatin1String("QLocalSocket::connectToServer"));
d->state = UnconnectedState;
- emit error(d->error);
+ emit errorOccurred(d->error);
emit stateChanged(d->state);
return;
}
@@ -330,15 +330,8 @@ void QLocalSocket::disconnectFromServer()
}
}
-#if QT_DEPRECATED_SINCE(5, 15)
QLocalSocket::LocalSocketError QLocalSocket::error() const
{
- return socketError();
-}
-#endif // QT_DEPRECATED_SINCE(5, 15)
-
-QLocalSocket::LocalSocketError QLocalSocket::socketError() const
-{
Q_D(const QLocalSocket);
return d->error;
}
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index b2eefa352f..eb5d181134 100644
--- a/src/network/socket/qsocks5socketengine.cpp
+++ b/src/network/socket/qsocks5socketengine.cpp
@@ -535,7 +535,7 @@ void QSocks5SocketEnginePrivate::initialize(Socks5Mode socks5Mode)
udpData = new QSocks5UdpAssociateData;
data = udpData;
udpData->udpSocket = new QUdpSocket(q);
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
udpData->udpSocket->setProperty("_q_networksession", q->property("_q_networksession"));
#endif
udpData->udpSocket->setProxy(QNetworkProxy::NoProxy);
@@ -549,7 +549,7 @@ void QSocks5SocketEnginePrivate::initialize(Socks5Mode socks5Mode)
}
data->controlSocket = new QTcpSocket(q);
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
data->controlSocket->setProperty("_q_networksession", q->property("_q_networksession"));
#endif
data->controlSocket->setProxy(QNetworkProxy::NoProxy);
diff --git a/src/network/socket/qtcpserver.cpp b/src/network/socket/qtcpserver.cpp
index 9916c75e65..c23b143de3 100644
--- a/src/network/socket/qtcpserver.cpp
+++ b/src/network/socket/qtcpserver.cpp
@@ -314,7 +314,7 @@ bool QTcpServer::listen(const QHostAddress &address, quint16 port)
d->serverSocketErrorString = tr("Operation on socket is not supported");
return false;
}
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
//copy network session down to the socket engine (if it has been set)
d->socketEngine->setProperty("_q_networksession", property("_q_networksession"));
#endif
@@ -436,7 +436,7 @@ bool QTcpServer::setSocketDescriptor(qintptr socketDescriptor)
d->serverSocketErrorString = tr("Operation on socket is not supported");
return false;
}
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
//copy network session down to the socket engine (if it has been set)
d->socketEngine->setProperty("_q_networksession", property("_q_networksession"));
#endif
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index b6199a2b16..8c7437a8de 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -657,6 +657,8 @@ void QSslConfiguration::setCaCertificates(const QList<QSslCertificate> &certific
}
/*!
+ \since 5.15
+
Searches all files in the \a path for certificates encoded in the
specified \a format and adds them to this socket's CA certificate
database. \a path must be a file or a pattern matching one or more
@@ -672,7 +674,7 @@ void QSslConfiguration::setCaCertificates(const QList<QSslCertificate> &certific
\sa addCaCertificate(), QSslCertificate::fromPath()
*/
bool QSslConfiguration::addCaCertificates(const QString &path, QSsl::EncodingFormat format,
- QRegExp::PatternSyntax syntax)
+ QSslCertificate::PatternSyntax syntax)
{
QList<QSslCertificate> certs = QSslCertificate::fromPath(path, format, syntax);
if (certs.isEmpty())
@@ -777,7 +779,7 @@ bool QSslConfiguration::testSslOption(QSsl::SslOption option) const
knowledge of the session allows for eavesdropping on data
encrypted with the session parameters.
- \sa setSessionTicket(), QSsl::SslOptionDisableSessionPersistence, setSslOption()
+ \sa setSessionTicket(), QSsl::SslOptionDisableSessionPersistence, setSslOption(), QSslSocket::newSessionTicketReceived()
*/
QByteArray QSslConfiguration::sessionTicket() const
{
@@ -792,7 +794,7 @@ QByteArray QSslConfiguration::sessionTicket() const
for this to work, and \a sessionTicket must be in ASN.1 format
as returned by sessionTicket().
- \sa sessionTicket(), QSsl::SslOptionDisableSessionPersistence, setSslOption()
+ \sa sessionTicket(), QSsl::SslOptionDisableSessionPersistence, setSslOption(), QSslSocket::newSessionTicketReceived()
*/
void QSslConfiguration::setSessionTicket(const QByteArray &sessionTicket)
{
@@ -810,7 +812,7 @@ void QSslConfiguration::setSessionTicket(const QByteArray &sessionTicket)
QSsl::SslOptionDisableSessionPersistence was not turned off,
this function returns -1.
- \sa sessionTicket(), QSsl::SslOptionDisableSessionPersistence, setSslOption()
+ \sa sessionTicket(), QSsl::SslOptionDisableSessionPersistence, setSslOption(), QSslSocket::newSessionTicketReceived()
*/
int QSslConfiguration::sessionTicketLifeTimeHint() const
{
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index dc4587a835..5732deaaef 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -131,7 +131,7 @@ public:
QList<QSslCertificate> caCertificates() const;
void setCaCertificates(const QList<QSslCertificate> &certificates);
bool addCaCertificates(const QString &path, QSsl::EncodingFormat format = QSsl::Pem,
- QRegExp::PatternSyntax syntax = QRegExp::FixedString);
+ QSslCertificate::PatternSyntax syntax = QSslCertificate::FixedString);
void addCaCertificate(const QSslCertificate &certificate);
void addCaCertificates(const QList<QSslCertificate> &certificates);
diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp
index 574f48a2b5..78e37460c8 100644
--- a/src/network/ssl/qsslcontext_openssl.cpp
+++ b/src/network/ssl/qsslcontext_openssl.cpp
@@ -71,6 +71,10 @@ extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
}
#endif // dtls
+#ifdef TLS1_3_VERSION
+extern "C" int q_ssl_sess_set_new_cb(SSL *context, SSL_SESSION *session);
+#endif // TLS1_3_VERSION
+
// Defined in qsslsocket.cpp
QList<QSslCipher> q_getDefaultDtlsCiphers();
@@ -169,8 +173,8 @@ SSL* QSslContext::createSsl()
if (!session && !sessionASN1().isEmpty()
&& !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
const unsigned char *data = reinterpret_cast<const unsigned char *>(m_sessionASN1.constData());
- session = q_d2i_SSL_SESSION(
- nullptr, &data, m_sessionASN1.size()); // refcount is 1 already, set by function above
+ session = q_d2i_SSL_SESSION(nullptr, &data, m_sessionASN1.size());
+ // 'session' has refcount 1 already, set by the function above
}
if (session) {
@@ -568,7 +572,8 @@ init_context:
}
}
- // Initialize peer verification.
+ // Initialize peer verification, different callbacks, TLS/DTLS verification first
+ // (note, all these set_some_callback do not have return value):
if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, nullptr);
} else {
@@ -588,7 +593,17 @@ init_context:
q_SSL_CTX_set_verify(sslContext->ctx, verificationMode, verificationCallback);
}
+#ifdef TLS1_3_VERSION
+ // NewSessionTicket callback:
+ if (mode == QSslSocket::SslClientMode && !isDtls) {
+ q_SSL_CTX_sess_set_new_cb(sslContext->ctx, q_ssl_sess_set_new_cb);
+ q_SSL_CTX_set_session_cache_mode(sslContext->ctx, SSL_SESS_CACHE_CLIENT);
+ }
+
+#endif // TLS1_3_VERSION
+
#if QT_CONFIG(dtls)
+ // DTLS cookies:
if (mode == QSslSocket::SslServerMode && isDtls && configuration.dtlsCookieVerificationEnabled()) {
q_SSL_CTX_set_cookie_generate_cb(sslContext->ctx, dtlscallbacks::q_generate_cookie_callback);
q_SSL_CTX_set_cookie_verify_cb(sslContext->ctx, dtlscallbacks::q_verify_cookie_callback);
diff --git a/src/network/ssl/qsslpresharedkeyauthenticator.cpp b/src/network/ssl/qsslpresharedkeyauthenticator.cpp
index 01e1501763..ed6dbb87cf 100644
--- a/src/network/ssl/qsslpresharedkeyauthenticator.cpp
+++ b/src/network/ssl/qsslpresharedkeyauthenticator.cpp
@@ -141,7 +141,7 @@ QSslPreSharedKeyAuthenticator &QSslPreSharedKeyAuthenticator::operator=(const QS
/*!
\fn QSslPreSharedKeyAuthenticator &QSslPreSharedKeyAuthenticator::operator=(QSslPreSharedKeyAuthenticator &&authenticator)
- Move-assigns the the QSslPreSharedKeyAuthenticator object \a authenticator to this
+ Move-assigns the QSslPreSharedKeyAuthenticator object \a authenticator to this
object, and returns a reference to the moved instance.
*/
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 504e27a463..64c6629645 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -432,6 +432,23 @@
\sa continueInterruptedHandshake(), sslErrors(), QSslConfiguration::setHandshakeMustInterruptOnError()
*/
+
+/*!
+ \fn void QSslSocket::newSessionTicketReceived()
+ \since 5.15
+
+ If TLS 1.3 protocol was negotiated during a handshake, QSslSocket
+ emits this signal after receiving NewSessionTicket message. Session
+ and session ticket's lifetime hint are updated in the socket's
+ configuration. The session can be used for session resumption (and
+ a shortened handshake) in future TLS connections.
+
+ \note This functionality enabled only with OpenSSL backend and requires
+ OpenSSL v 1.1.1 or above.
+
+ \sa QSslSocket::sslConfiguration(), QSslConfiguration::sessionTicket(), QSslConfiguration::sessionTicketLifeTimeHint()
+*/
+
#include "qssl_p.h"
#include "qsslsocket.h"
#include "qsslcipher.h"
@@ -1530,7 +1547,10 @@ bool QSslSocket::addCaCertificates(const QString &path, QSsl::EncodingFormat for
QRegExp::PatternSyntax syntax)
{
Q_D(QSslSocket);
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
QList<QSslCertificate> certs = QSslCertificate::fromPath(path, format, syntax);
+QT_WARNING_POP
if (certs.isEmpty())
return false;
@@ -2502,7 +2522,10 @@ bool QSslSocketPrivate::addDefaultCaCertificates(const QString &path, QSsl::Enco
QRegExp::PatternSyntax syntax)
{
QSslSocketPrivate::ensureInitialized();
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
QList<QSslCertificate> certs = QSslCertificate::fromPath(path, format, syntax);
+QT_WARNING_POP
if (certs.isEmpty())
return false;
@@ -2642,7 +2665,7 @@ void QSslSocketPrivate::createPlainSocket(QIODevice::OpenMode openMode)
q->setPeerName(QString());
plainSocket = new QTcpSocket(q);
-#ifndef QT_NO_BEARERMANAGEMENT
+#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
//copy network session down to the plain socket (if it has been set)
plainSocket->setProperty("_q_networksession", q->property("_q_networksession"));
#endif
diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h
index c12bb53334..e99c79a967 100644
--- a/src/network/ssl/qsslsocket.h
+++ b/src/network/ssl/qsslsocket.h
@@ -261,6 +261,7 @@ Q_SIGNALS:
void modeChanged(QSslSocket::SslMode newMode);
void encryptedBytesWritten(qint64 totalBytes);
void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator);
+ void newSessionTicketReceived();
void alertSent(QAlertLevel level, QAlertType type, const QString &description);
void alertReceived(QAlertLevel level, QAlertType type, const QString &description);
void handshakeInterruptedOnError(const QSslError &error);
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 11989cd2ef..f033d3b298 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -300,6 +300,22 @@ static int q_ssl_psk_use_session_callback(SSL *ssl, const EVP_MD *md, const unsi
return 1; // need to return 1 or else "the connection setup fails."
}
+
+int q_ssl_sess_set_new_cb(SSL *ssl, SSL_SESSION *session)
+{
+ if (!ssl) {
+ qCWarning(lcSsl, "Invalid SSL (nullptr)");
+ return 0;
+ }
+ if (!session) {
+ qCWarning(lcSsl, "Invalid SSL_SESSION (nullptr)");
+ return 0;
+ }
+
+ auto socketPrivate = static_cast<QSslSocketBackendPrivate *>(q_SSL_get_ex_data(ssl,
+ QSslSocketBackendPrivate::s_indexForSSLExtraData));
+ return socketPrivate->handleNewSessionTicket(ssl);
+}
#endif // TLS1_3_VERSION
#endif // !OPENSSL_NO_PSK
@@ -1526,6 +1542,60 @@ void QSslSocketBackendPrivate::storePeerCertificates()
}
}
+int QSslSocketBackendPrivate::handleNewSessionTicket(SSL *connection)
+{
+ // If we return 1, this means we own the session, but we don't.
+ // 0 would tell OpenSSL to deref (but they still have it in the
+ // internal cache).
+ Q_Q(QSslSocket);
+
+ Q_ASSERT(connection);
+
+ if (q->sslConfiguration().testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
+ // We silently ignore, do nothing, remove from cache.
+ return 0;
+ }
+
+ SSL_SESSION *currentSession = q_SSL_get_session(connection);
+ if (!currentSession) {
+ qCWarning(lcSsl,
+ "New session ticket callback, the session is invalid (nullptr)");
+ return 0;
+ }
+
+ if (q_SSL_version(connection) < 0x304) {
+ // We only rely on this mechanics with TLS >= 1.3
+ return 0;
+ }
+
+#ifdef TLS1_3_VERSION
+ if (!q_SSL_SESSION_is_resumable(currentSession)) {
+ qCDebug(lcSsl, "New session ticket, but the session is non-resumable");
+ return 0;
+ }
+#endif // TLS1_3_VERSION
+
+ const int sessionSize = q_i2d_SSL_SESSION(currentSession, nullptr);
+ if (sessionSize <= 0) {
+ qCWarning(lcSsl, "could not store persistent version of SSL session");
+ return 0;
+ }
+
+ // We have somewhat perverse naming, it's not a ticket, it's a session.
+ QByteArray sessionTicket(sessionSize, 0);
+ auto data = reinterpret_cast<unsigned char *>(sessionTicket.data());
+ if (!q_i2d_SSL_SESSION(currentSession, &data)) {
+ qCWarning(lcSsl, "could not store persistent version of SSL session");
+ return 0;
+ }
+
+ configuration.sslSession = sessionTicket;
+ configuration.sslSessionTicketLifeTimeHint = int(q_SSL_SESSION_get_ticket_lifetime_hint(currentSession));
+
+ emit q->newSessionTicketReceived();
+ return 0;
+}
+
bool QSslSocketBackendPrivate::checkSslErrors()
{
Q_Q(QSslSocket);
diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h
index 06af9f5974..6c1ffb7237 100644
--- a/src/network/ssl/qsslsocket_openssl_p.h
+++ b/src/network/ssl/qsslsocket_openssl_p.h
@@ -150,6 +150,7 @@ public:
void continueHandshake() override;
bool checkSslErrors();
void storePeerCertificates();
+ int handleNewSessionTicket(SSL *context);
unsigned int tlsPskClientCallback(const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len);
unsigned int tlsPskServerCallback(const char *identity, unsigned char *psk, unsigned int max_psk_len);
#ifdef Q_OS_WIN
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index 5b0a70d495..21f37789ff 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -163,6 +163,8 @@ DEFINEFUNC(const char *, SSL_alert_desc_string_long, int value, value, return nu
#ifdef TLS1_3_VERSION
DEFINEFUNC2(int, SSL_CTX_set_ciphersuites, SSL_CTX *ctx, ctx, const char *str, str, return 0, return)
DEFINEFUNC2(void, SSL_set_psk_use_session_callback, SSL *ssl, ssl, q_SSL_psk_use_session_cb_func_t callback, callback, return, DUMMYARG)
+DEFINEFUNC2(void, SSL_CTX_sess_set_new_cb, SSL_CTX *ctx, ctx, NewSessionCallback cb, cb, return, return)
+DEFINEFUNC(int, SSL_SESSION_is_resumable, const SSL_SESSION *s, s, return 0, return)
#endif
DEFINEFUNC3(size_t, SSL_get_client_random, SSL *a, a, unsigned char *out, out, size_t outlen, outlen, return 0, return)
DEFINEFUNC3(size_t, SSL_SESSION_get_master_key, const SSL_SESSION *ses, ses, unsigned char *out, out, size_t outlen, outlen, return 0, return)
@@ -849,6 +851,8 @@ bool q_resolveOpenSslSymbols()
#ifdef TLS1_3_VERSION
RESOLVEFUNC(SSL_CTX_set_ciphersuites)
RESOLVEFUNC(SSL_set_psk_use_session_callback)
+ RESOLVEFUNC(SSL_CTX_sess_set_new_cb)
+ RESOLVEFUNC(SSL_SESSION_is_resumable)
#endif // TLS 1.3 or OpenSSL > 1.1.1
RESOLVEFUNC(SSL_get_client_random)
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index ac6aa1760f..273a4f359a 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -224,7 +224,6 @@ QT_BEGIN_NAMESPACE
// To reduce the amount of the change, I'm directly copying and pasting the
// content of the header here. Later, can be better sorted/split into groups,
// depending on the functionality.
-//#include "qsslsocket_openssl11_symbols_p.h"
const unsigned char * q_ASN1_STRING_get0_data(const ASN1_STRING *x);
@@ -287,6 +286,23 @@ unsigned long q_SSL_set_options(SSL *s, unsigned long op);
#ifdef TLS1_3_VERSION
int q_SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str);
+
+// The functions below do not really have to be ifdefed like this, but for now
+// they only used in TLS 1.3 handshake (and probably future versions).
+// Plus, 'is resumalbe' is OpenSSL 1.1.1-only (and again we need it for
+// TLS 1.3-specific session management).
+
+extern "C"
+{
+using NewSessionCallback = int (*)(SSL *, SSL_SESSION *);
+}
+
+void q_SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, NewSessionCallback cb);
+int q_SSL_SESSION_is_resumable(const SSL_SESSION *s);
+
+#define q_SSL_CTX_set_session_cache_mode(ctx,m) \
+ q_SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL)
+
#endif
#if QT_CONFIG(dtls)
diff --git a/src/opengl/qopengltexture.cpp b/src/opengl/qopengltexture.cpp
index 35d90898e5..49ebdfbec2 100644
--- a/src/opengl/qopengltexture.cpp
+++ b/src/opengl/qopengltexture.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -2127,6 +2128,7 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target
/*!
\enum QOpenGLTexture::Target
This enum defines the texture target of a QOpenGLTexture object.
+ For more information on creating array textures, see \l{Array Texture}.
\value Target1D A 1-dimensional texture.
Equivalent to GL_TEXTURE_1D.
@@ -2134,7 +2136,7 @@ QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target
Equivalent to GL_TEXTURE_1D_ARRAY
\value Target2D A 2-dimensional texture.
Equivalent to GL_TEXTURE_2D
- \value Target2DArray An array of 1-dimensional textures.
+ \value Target2DArray An array of 2-dimensional textures.
Equivalent to GL_TEXTURE_2D_ARRAY
\value Target3D A 3-dimensional texture.
Equivalent to GL_TEXTURE_3D
diff --git a/src/opengl/qopenglwidget.cpp b/src/opengl/qopenglwidget.cpp
index 91e9fd545d..b334ba867b 100644
--- a/src/opengl/qopenglwidget.cpp
+++ b/src/opengl/qopenglwidget.cpp
@@ -381,7 +381,7 @@ QT_BEGIN_NAMESPACE
This is naturally not the only possible solution. One alternative is to use
the \l{QOpenGLContext::aboutToBeDestroyed()}{aboutToBeDestroyed()} signal of
QOpenGLContext. By connecting a slot, using direct connection, to this signal,
- it is possible to perform cleanup whenever the the underlying native context
+ it is possible to perform cleanup whenever the underlying native context
handle, or the entire QOpenGLContext instance, is going to be released. The
following snippet is in principle equivalent to the previous one:
diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
index ca78063f08..a2619b2d25 100644
--- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
+++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
@@ -1334,7 +1334,10 @@ void QFontEngineFT::doKerning(QGlyphLayout *g, QFontEngine::ShaperFlags flags) c
}
}
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (shouldUseDesignMetrics(flags) && !(fontDef.styleStrategy & QFont::ForceIntegerMetrics))
+QT_WARNING_POP
flags |= DesignMetrics;
else
flags &= ~DesignMetrics;
@@ -1664,7 +1667,10 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlag
if (face)
unlockFace();
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+QT_WARNING_POP
for (int i = 0; i < glyphs->numGlyphs; ++i)
glyphs->advances[i] = glyphs->advances[i].round();
}
@@ -1744,7 +1750,10 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
overall.width = g->width;
overall.height = g->height;
overall.xoff = g->advance;
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+QT_WARNING_POP
overall.xoff = overall.xoff.round();
if (!cacheEnabled && g != &emptyGlyph)
delete g;
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
index 30c80ebd86..ce793dfafa 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
@@ -345,7 +345,10 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *
glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs)
{
QFixed w;
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
bool round = fontDef.styleStrategy & QFont::ForceIntegerMetrics;
+QT_WARNING_POP
for (int i = 0; i < glyphs.numGlyphs; ++i) {
w += round ? glyphs.effectiveAdvance(i).round()
@@ -371,7 +374,10 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
ret.xoff = QFixed::fromReal(advances[0].width);
ret.yoff = QFixed::fromReal(advances[0].height);
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+QT_WARNING_POP
ret.xoff = ret.xoff.round();
ret.yoff = ret.yoff.round();
}
@@ -381,9 +387,12 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
QFixed QCoreTextFontEngine::ascent() const
{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
? QFixed::fromReal(CTFontGetAscent(ctfont)).round()
: QFixed::fromReal(CTFontGetAscent(ctfont));
+QT_WARNING_POP
}
QFixed QCoreTextFontEngine::capHeight() const
@@ -392,7 +401,10 @@ QFixed QCoreTextFontEngine::capHeight() const
if (c <= 0)
return calculatedCapHeight();
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+QT_WARNING_POP
c = c.round();
return c;
@@ -401,28 +413,40 @@ QFixed QCoreTextFontEngine::capHeight() const
QFixed QCoreTextFontEngine::descent() const
{
QFixed d = QFixed::fromReal(CTFontGetDescent(ctfont));
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+QT_WARNING_POP
d = d.round();
return d;
}
QFixed QCoreTextFontEngine::leading() const
{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
? QFixed::fromReal(CTFontGetLeading(ctfont)).round()
: QFixed::fromReal(CTFontGetLeading(ctfont));
+QT_WARNING_POP
}
QFixed QCoreTextFontEngine::xHeight() const
{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
? QFixed::fromReal(CTFontGetXHeight(ctfont)).round()
: QFixed::fromReal(CTFontGetXHeight(ctfont));
+QT_WARNING_POP
}
QFixed QCoreTextFontEngine::averageCharWidth() const
{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
return (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
? avgCharWidth.round() : avgCharWidth;
+QT_WARNING_POP
}
qreal QCoreTextFontEngine::maxCharWidth() const
@@ -917,8 +941,11 @@ void QCoreTextFontEngine::loadAdvancesForGlyphs(QVarLengthArray<CGGlyph> &cgGlyp
for (int i = 0; i < numGlyphs; ++i) {
QFixed advance = QFixed::fromReal(advances[i].width);
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
glyphs->advances[i] = fontDef.styleStrategy & QFont::ForceIntegerMetrics
? advance.round() : advance;
+QT_WARNING_POP
}
}
@@ -1027,7 +1054,10 @@ QFontEngine::Properties QCoreTextFontEngine::properties() const
result.capHeight = QFixed::fromReal(CTFontGetCapHeight(ctfont) * scale);
result.lineWidth = QFixed::fromReal(CTFontGetUnderlineThickness(ctfont) * scale);
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+QT_WARNING_POP
result.ascent = result.ascent.round();
result.descent = result.descent.round();
result.leading = result.leading.round();
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp
index 45ce396d5e..b11ad46bc7 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp
@@ -509,7 +509,10 @@ void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEn
qreal stretch = fontDef.stretch != QFont::AnyStretch ? fontDef.stretch / 100.0 : 1.0;
for (int i = 0; i < glyphs->numGlyphs; ++i)
glyphs->advances[i] = DESIGN_TO_LOGICAL(glyphMetrics[i].advanceWidth * stretch);
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+QT_WARNING_POP
for (int i = 0; i < glyphs->numGlyphs; ++i)
glyphs->advances[i] = glyphs->advances[i].round();
}
@@ -553,7 +556,10 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::boundingBox(const QGlyphLayout &g
if (glyphs.numGlyphs == 0)
return glyph_metrics_t();
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
bool round = fontDef.styleStrategy & QFont::ForceIntegerMetrics;
+QT_WARNING_POP
QFixed w = 0;
for (int i = 0; i < glyphs.numGlyphs; ++i) {
@@ -579,7 +585,10 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::boundingBox(glyph_t g)
QFixed topSideBearing = DESIGN_TO_LOGICAL(glyphMetrics.topSideBearing);
QFixed bottomSideBearing = DESIGN_TO_LOGICAL(glyphMetrics.bottomSideBearing);
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) {
+QT_WARNING_POP
advanceWidth = advanceWidth.round();
advanceHeight = advanceHeight.round();
}
@@ -601,9 +610,12 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::boundingBox(glyph_t g)
QFixed QWindowsFontEngineDirectWrite::ascent() const
{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
return fontDef.styleStrategy & QFont::ForceIntegerMetrics
? m_ascent.round()
: m_ascent;
+QT_WARNING_POP
}
QFixed QWindowsFontEngineDirectWrite::capHeight() const
@@ -611,37 +623,52 @@ QFixed QWindowsFontEngineDirectWrite::capHeight() const
if (m_capHeight <= 0)
return calculatedCapHeight();
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
return fontDef.styleStrategy & QFont::ForceIntegerMetrics
? m_capHeight.round()
: m_capHeight;
+QT_WARNING_POP
}
QFixed QWindowsFontEngineDirectWrite::descent() const
{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
return fontDef.styleStrategy & QFont::ForceIntegerMetrics
? m_descent.round()
: m_descent;
+QT_WARNING_POP
}
QFixed QWindowsFontEngineDirectWrite::leading() const
{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
return fontDef.styleStrategy & QFont::ForceIntegerMetrics
? m_lineGap.round()
: m_lineGap;
+QT_WARNING_POP
}
QFixed QWindowsFontEngineDirectWrite::xHeight() const
{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
return fontDef.styleStrategy & QFont::ForceIntegerMetrics
? m_xHeight.round()
: m_xHeight;
+QT_WARNING_POP
}
qreal QWindowsFontEngineDirectWrite::maxCharWidth() const
{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
return fontDef.styleStrategy & QFont::ForceIntegerMetrics
? m_maxAdvanceWidth.round().toReal()
: m_maxAdvanceWidth.toReal();
+QT_WARNING_POP
}
QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)
@@ -720,7 +747,7 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
&transform,
renderMode,
measureMode,
- 0.0, 0.0,
+ margin, margin,
&glyphAnalysis
);
@@ -1022,6 +1049,7 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph
hintingPreferenceToRenderingMode(QFont::HintingPreference(fontDef.hintingPreference));
DWRITE_MEASURING_MODE measureMode = renderModeToMeasureMode(renderMode);
+ const int margin = glyphMargin(QFontEngine::Format_A32);
IDWriteGlyphRunAnalysis *glyphAnalysis = NULL;
HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis(
&glyphRun,
@@ -1029,7 +1057,7 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph
&transform,
renderMode,
measureMode,
- 0.0, 0.0,
+ margin, margin,
&glyphAnalysis
);
@@ -1038,8 +1066,6 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph
glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
glyphAnalysis->Release();
- int margin = glyphMargin(QFontEngine::Format_A32);
-
return glyph_metrics_t(rect.left - margin,
rect.top - margin,
rect.right - rect.left + margin * 2,
diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
index fcc08ea00d..ca16efe34f 100644
--- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
+++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp
@@ -110,6 +110,8 @@ public:
static AssetItem::Type fileType(const QString &filePath)
{
+ if (filePath.isEmpty())
+ return AssetItem::Type::Folder;
const QStringList paths = filePath.split(QLatin1Char('/'));
QString fullPath;
AssetItem::Type res = AssetItem::Type::Invalid;
@@ -146,7 +148,7 @@ public:
jobjectArray jFiles = static_cast<jobjectArray>(files.object());
const jint nFiles = env->GetArrayLength(jFiles);
for (int i = 0; i < nFiles; ++i) {
- AssetItem item{QJNIObjectPrivate(env->GetObjectArrayElement(jFiles, i)).toString()};
+ AssetItem item{QJNIObjectPrivate::fromLocalRef(env->GetObjectArrayElement(jFiles, i)).toString()};
insert(std::upper_bound(begin(), end(), item, [](const auto &a, const auto &b){
return a.name < b.name;
}), item);
@@ -399,7 +401,8 @@ public:
private:
AAsset *m_assetFile = nullptr;
AAssetManager *m_assetManager = nullptr;
- QString m_fileName;
+ // initialize with a name that can't be used as a file name
+ QString m_fileName = QLatin1String(".");
bool m_isFolder = false;
};
diff --git a/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp b/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp
index 4fb271a75c..fb979ab6cc 100644
--- a/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp
+++ b/src/plugins/platforms/android/qandroidplatformfiledialoghelper.cpp
@@ -100,10 +100,14 @@ bool QAndroidPlatformFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::Win
void QAndroidPlatformFileDialogHelper::exec()
{
+ m_eventLoop.exec(QEventLoop::DialogExec);
}
void QAndroidPlatformFileDialogHelper::hide()
{
+ if (m_eventLoop.isRunning())
+ m_eventLoop.exit();
+ QtAndroidPrivate::unregisterActivityResultListener(this);
}
QString QAndroidPlatformFileDialogHelper::selectedNameFilter() const
diff --git a/src/plugins/platforms/android/qandroidplatformfiledialoghelper.h b/src/plugins/platforms/android/qandroidplatformfiledialoghelper.h
index e445aa2fef..5cd26af7c9 100644
--- a/src/plugins/platforms/android/qandroidplatformfiledialoghelper.h
+++ b/src/plugins/platforms/android/qandroidplatformfiledialoghelper.h
@@ -41,6 +41,7 @@
#define QANDROIDPLATFORMFILEDIALOGHELPER_H
#include <jni.h>
+#include <QEventLoop>
#include <qpa/qplatformdialoghelper.h>
#include <QtCore/private/qjnihelpers_p.h>
@@ -72,6 +73,7 @@ public:
bool handleActivityResult(jint requestCode, jint resultCode, jobject data) override;
private:
+ QEventLoop m_eventLoop;
QUrl m_selectedFile;
};
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp
index ae584965e6..592b78d936 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp
@@ -77,6 +77,8 @@
#include "qandroidplatformvulkaninstance.h"
#endif
+#include <QtGui/qpa/qplatforminputcontextfactory_p.h>
+
QT_BEGIN_NAMESPACE
int QAndroidPlatformIntegration::m_defaultGeometryWidth = 320;
@@ -258,6 +260,15 @@ static bool needsBasicRenderloopWorkaround()
return needsWorkaround;
}
+void QAndroidPlatformIntegration::initialize()
+{
+ const QString icStr = QPlatformInputContextFactory::requested();
+ if (icStr.isNull())
+ m_inputContext.reset(new QAndroidInputContext);
+ else
+ m_inputContext.reset(QPlatformInputContextFactory::create(icStr));
+}
+
bool QAndroidPlatformIntegration::hasCapability(Capability cap) const
{
switch (cap) {
@@ -374,7 +385,7 @@ QPlatformClipboard *QAndroidPlatformIntegration::clipboard() const
QPlatformInputContext *QAndroidPlatformIntegration::inputContext() const
{
- return &m_platformInputContext;
+ return m_inputContext.data();
}
QPlatformNativeInterface *QAndroidPlatformIntegration::nativeInterface() const
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h
index c795c499bc..ecbde4f951 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.h
+++ b/src/plugins/platforms/android/qandroidplatformintegration.h
@@ -81,6 +81,8 @@ public:
QAndroidPlatformIntegration(const QStringList &paramList);
~QAndroidPlatformIntegration();
+ void initialize() override;
+
bool hasCapability(QPlatformIntegration::Capability cap) const override;
QPlatformWindow *createPlatformWindow(QWindow *window) const override;
@@ -167,7 +169,7 @@ private:
mutable QPlatformAccessibility *m_accessibility;
#endif
- mutable QAndroidInputContext m_platformInputContext;
+ QScopedPointer<QPlatformInputContext> m_inputContext;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 1e46cd2dde..4bff1de515 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -219,6 +219,8 @@ protected:
void toggleFullScreen();
bool isTransitioningToFullScreen() const;
+ bool startSystemMove() override;
+
// private:
public: // for QNSView
friend class QCocoaBackingStore;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index ad232d6d80..28da4fcf5d 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -291,6 +291,22 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
// will call QPlatformWindow::setGeometry(rect) during resize confirmation (see qnsview.mm)
}
+bool QCocoaWindow::startSystemMove()
+{
+ switch (NSApp.currentEvent.type) {
+ case NSEventTypeLeftMouseDown:
+ case NSEventTypeRightMouseDown:
+ case NSEventTypeOtherMouseDown:
+ case NSEventTypeMouseMoved:
+ // The documentation only describes starting a system move
+ // based on mouse down events, but move events also work.
+ [m_view.window performWindowDragWithEvent:NSApp.currentEvent];
+ return true;
+ default:
+ return false;
+ }
+}
+
void QCocoaWindow::setVisible(bool visible)
{
qCDebug(lcQpaWindow) << "QCocoaWindow::setVisible" << window() << visible;
diff --git a/src/plugins/platforms/ios/qiostextinputoverlay.mm b/src/plugins/platforms/ios/qiostextinputoverlay.mm
index 0561a826c6..3da4ba5480 100644
--- a/src/plugins/platforms/ios/qiostextinputoverlay.mm
+++ b/src/plugins/platforms/ios/qiostextinputoverlay.mm
@@ -511,7 +511,7 @@ static void executeBlockWithoutAnimation(Block block)
- (void)createLoupe
{
- // We magnify the the desktop view. But the loupe itself will be added as a child
+ // We magnify the desktop view. But the loupe itself will be added as a child
// of the desktop view's parent, so it doesn't become a part of what we magnify.
_loupeLayer = [[self createLoupeLayer] retain];
_loupeLayer.targetView = _desktopView;
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index ce2aa96ca5..cd4af46ef7 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -452,7 +452,7 @@
if (!focusWindow->screen() || focusWindow->screen()->handle() != self.platformScreen)
return;
- // All decisions are based on the the top level window
+ // All decisions are based on the top level window
focusWindow = qt_window_private(focusWindow)->topLevelWindow();
#ifndef Q_OS_TVOS
diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp
index 3bd6a86b59..25f7b09a60 100644
--- a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp
+++ b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp
@@ -94,6 +94,11 @@ void *QQnxNativeInterface::nativeResourceForIntegration(const QByteArray &resour
if (resource == "screenContext")
return m_integration->screenContext();
+#if QT_CONFIG(opengl)
+ if (resource.toLower() == "egldisplay")
+ return m_integration->eglDisplay();
+#endif
+
return 0;
}
diff --git a/src/plugins/platforms/wasm/qwasmclipboard.cpp b/src/plugins/platforms/wasm/qwasmclipboard.cpp
index f02c2c6ccb..890b01fa3c 100644
--- a/src/plugins/platforms/wasm/qwasmclipboard.cpp
+++ b/src/plugins/platforms/wasm/qwasmclipboard.cpp
@@ -192,15 +192,12 @@ void QWasmClipboard::initClipboardEvents()
permissions.call<val>("query", writePermissionsMap);
}
-void QWasmClipboard::installEventHandlers(const QString &canvasId)
+void QWasmClipboard::installEventHandlers(const emscripten::val &canvas)
{
if (hasClipboardApi)
return;
// Fallback path for browsers which do not support direct clipboard access
- val document = val::global("document");
- val canvas = document.call<val>("getElementById", QWasmString::fromQString(canvasId));
-
canvas.call<void>("addEventListener", val("cut"),
val::module_property("qtClipboardCutTo"));
canvas.call<void>("addEventListener", val("copy"),
diff --git a/src/plugins/platforms/wasm/qwasmclipboard.h b/src/plugins/platforms/wasm/qwasmclipboard.h
index 00aae8fead..3b28e2c381 100644
--- a/src/plugins/platforms/wasm/qwasmclipboard.h
+++ b/src/plugins/platforms/wasm/qwasmclipboard.h
@@ -36,6 +36,7 @@
#include <QMimeData>
#include <emscripten/bind.h>
+#include <emscripten/val.h>
class QWasmClipboard : public QObject, public QPlatformClipboard
{
@@ -51,7 +52,7 @@ public:
static void qWasmClipboardPaste(QMimeData *mData);
void initClipboardEvents();
- void installEventHandlers(const QString &canvasId);
+ void installEventHandlers(const emscripten::val &canvas);
bool hasClipboardApi;
void readTextFromClipboard();
void writeTextToClipboard();
diff --git a/src/plugins/platforms/wasm/qwasmcursor.cpp b/src/plugins/platforms/wasm/qwasmcursor.cpp
index 616456b2fa..61204517ce 100644
--- a/src/plugins/platforms/wasm/qwasmcursor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcursor.cpp
@@ -57,9 +57,7 @@ void QWasmCursor::changeCursor(QCursor *windowCursor, QWindow *window)
htmlCursorName = "auto";
// Set cursor on the canvas
- val jsCanvasId = QWasmString::fromQString(QWasmScreen::get(screen)->canvasId());
- val document = val::global("document");
- val canvas = document.call<val>("getElementById", jsCanvasId);
+ val canvas = QWasmScreen::get(screen)->canvas();
val canvasStyle = canvas["style"];
canvasStyle.set("cursor", val(htmlCursorName.constData()));
}
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
index d99c202c48..3e6043b083 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
@@ -339,8 +339,7 @@ QWasmEventTranslator::QWasmEventTranslator(QWasmScreen *screen)
void QWasmEventTranslator::initEventHandlers()
{
- QByteArray _canvasId = screen()->canvasId().toUtf8();
- const char *canvasId = _canvasId.constData();
+ QByteArray canvasSelector = "#" + screen()->canvasId().toUtf8();
// The Platform Detect: expand coverage and move as needed
enum Platform {
@@ -355,30 +354,28 @@ void QWasmEventTranslator::initEventHandlers()
g_useNaturalScrolling = false; // make this !default on macOS
if (emscripten::val::global("window")["safari"].isUndefined()) {
- val document = val::global("document");
- val jsCanvasId = QWasmString::fromQString(screen()->canvasId());
- val canvas = document.call<val>("getElementById", jsCanvasId);
+ val canvas = screen()->canvas();
canvas.call<void>("addEventListener",
val("wheel"),
val::module_property("qtMouseWheelEvent"));
}
}
- emscripten_set_keydown_callback(canvasId, (void *)this, 1, &keyboard_cb);
- emscripten_set_keyup_callback(canvasId, (void *)this, 1, &keyboard_cb);
+ emscripten_set_keydown_callback(canvasSelector.constData(), (void *)this, 1, &keyboard_cb);
+ emscripten_set_keyup_callback(canvasSelector.constData(), (void *)this, 1, &keyboard_cb);
- emscripten_set_mousedown_callback(canvasId, (void *)this, 1, &mouse_cb);
- emscripten_set_mouseup_callback(canvasId, (void *)this, 1, &mouse_cb);
- emscripten_set_mousemove_callback(canvasId, (void *)this, 1, &mouse_cb);
+ emscripten_set_mousedown_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb);
+ emscripten_set_mouseup_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb);
+ emscripten_set_mousemove_callback(canvasSelector.constData(), (void *)this, 1, &mouse_cb);
- emscripten_set_focus_callback(canvasId, (void *)this, 1, &focus_cb);
+ emscripten_set_focus_callback(canvasSelector.constData(), (void *)this, 1, &focus_cb);
- emscripten_set_wheel_callback(canvasId, (void *)this, 1, &wheel_cb);
+ emscripten_set_wheel_callback(canvasSelector.constData(), (void *)this, 1, &wheel_cb);
- emscripten_set_touchstart_callback(canvasId, (void *)this, 1, &touchCallback);
- emscripten_set_touchend_callback(canvasId, (void *)this, 1, &touchCallback);
- emscripten_set_touchmove_callback(canvasId, (void *)this, 1, &touchCallback);
- emscripten_set_touchcancel_callback(canvasId, (void *)this, 1, &touchCallback);
+ emscripten_set_touchstart_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
+ emscripten_set_touchend_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
+ emscripten_set_touchmove_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
+ emscripten_set_touchcancel_callback(canvasSelector.constData(), (void *)this, 1, &touchCallback);
}
template <typename Event>
diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp
index ce83ad4e2f..d1901d840e 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.cpp
+++ b/src/plugins/platforms/wasm/qwasmintegration.cpp
@@ -69,20 +69,17 @@ static void browserBeforeUnload(emscripten::val)
static void addCanvasElement(emscripten::val canvas)
{
- QString canvasId = QWasmString::toQString(canvas["id"]);
- QWasmIntegration::get()->addScreen(canvasId);
+ QWasmIntegration::get()->addScreen(canvas);
}
static void removeCanvasElement(emscripten::val canvas)
{
- QString canvasId = QWasmString::toQString(canvas["id"]);
- QWasmIntegration::get()->removeScreen(canvasId);
+ QWasmIntegration::get()->removeScreen(canvas);
}
static void resizeCanvasElement(emscripten::val canvas)
{
- QString canvasId = QWasmString::toQString(canvas["id"]);
- QWasmIntegration::get()->resizeScreen(canvasId);
+ QWasmIntegration::get()->resizeScreen(canvas);
}
static void qtUpdateDpi()
@@ -109,20 +106,18 @@ QWasmIntegration::QWasmIntegration()
s_instance = this;
// We expect that qtloader.js has populated Module.qtCanvasElements with one or more canvases.
- // Also check Module.canvas, which may be set if the emscripen or a custom loader is used.
emscripten::val qtCanvaseElements = val::module_property("qtCanvasElements");
- emscripten::val canvas = val::module_property("canvas");
+ emscripten::val canvas = val::module_property("canvas"); // TODO: remove for Qt 6.0
if (!qtCanvaseElements.isUndefined()) {
int screenCount = qtCanvaseElements["length"].as<int>();
for (int i = 0; i < screenCount; ++i) {
- emscripten::val canvas = qtCanvaseElements[i].as<emscripten::val>();
- QString canvasId = QWasmString::toQString(canvas["id"]);
- addScreen(canvasId);
+ addScreen(qtCanvaseElements[i].as<emscripten::val>());
}
- } else if (!canvas.isUndefined()){
- QString canvasId = QWasmString::toQString(canvas["id"]);
- addScreen(canvasId);
+ } else if (!canvas.isUndefined()) {
+ qWarning() << "Module.canvas is deprecated. A future version of Qt will stop reading this property. "
+ << "Instead, set Module.qtCanvasElements to be an array of canvas elements, or use qtloader.js.";
+ addScreen(canvas);
}
emscripten::val::global("window").set("onbeforeunload", val::module_property("qtBrowserBeforeUnload"));
@@ -134,13 +129,13 @@ QWasmIntegration::QWasmIntegration()
Q_UNUSED(userData);
// This resize event is called when the HTML window is resized. Depending
- // on the page layout the the canvas(es) might also have been resized, so we
+ // on the page layout the canvas(es) might also have been resized, so we
// update the Qt screen sizes (and canvas render sizes).
if (QWasmIntegration *integration = QWasmIntegration::get())
integration->resizeAllScreens();
return 0;
};
- emscripten_set_resize_callback(nullptr, nullptr, 1, onWindowResize);
+ emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, 1, onWindowResize);
}
QWasmIntegration::~QWasmIntegration()
@@ -148,8 +143,8 @@ QWasmIntegration::~QWasmIntegration()
delete m_fontDb;
delete m_desktopServices;
- for (auto it = m_screens.constBegin(); it != m_screens.constEnd(); ++it)
- QWindowSystemInterface::handleScreenRemoved(*it);
+ for (const auto &canvasAndScreen : m_screens)
+ QWindowSystemInterface::handleScreenRemoved(canvasAndScreen.second);
m_screens.clear();
s_instance = nullptr;
@@ -272,24 +267,37 @@ QPlatformClipboard* QWasmIntegration::clipboard() const
return m_clipboard;
}
-void QWasmIntegration::addScreen(const QString &canvasId)
+void QWasmIntegration::addScreen(const emscripten::val &canvas)
{
- QWasmScreen *screen = new QWasmScreen(canvasId);
- m_clipboard->installEventHandlers(canvasId);
- m_screens.insert(canvasId, screen);
+ QWasmScreen *screen = new QWasmScreen(canvas);
+ m_screens.append(qMakePair(canvas, screen));
+ m_clipboard->installEventHandlers(canvas);
QWindowSystemInterface::handleScreenAdded(screen);
}
-void QWasmIntegration::removeScreen(const QString &canvasId)
+void QWasmIntegration::removeScreen(const emscripten::val &canvas)
{
- QWasmScreen *exScreen = m_screens.take(canvasId);
+ auto it = std::find_if(m_screens.begin(), m_screens.end(),
+ [&] (const QPair<emscripten::val, QWasmScreen *> &candidate) { return candidate.first.equals(canvas); });
+ if (it == m_screens.end()) {
+ qWarning() << "Attempting to remove non-existing screen for canvas" << QWasmString::toQString(canvas["id"]);;
+ return;
+ }
+ QWasmScreen *exScreen = it->second;
+ m_screens.erase(it);
exScreen->destroy(); // clean up before deleting the screen
QWindowSystemInterface::handleScreenRemoved(exScreen);
}
-void QWasmIntegration::resizeScreen(const QString &canvasId)
+void QWasmIntegration::resizeScreen(const emscripten::val &canvas)
{
- m_screens.value(canvasId)->updateQScreenAndCanvasRenderSize();
+ auto it = std::find_if(m_screens.begin(), m_screens.end(),
+ [&] (const QPair<emscripten::val, QWasmScreen *> &candidate) { return candidate.first.equals(canvas); });
+ if (it == m_screens.end()) {
+ qWarning() << "Attempting to resize non-existing screen for canvas" << QWasmString::toQString(canvas["id"]);;
+ return;
+ }
+ it->second->updateQScreenAndCanvasRenderSize();
}
void QWasmIntegration::updateDpi()
@@ -298,15 +306,14 @@ void QWasmIntegration::updateDpi()
if (dpi.isUndefined())
return;
qreal dpiValue = dpi.as<qreal>();
- for (QWasmScreen *screen : m_screens)
- QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen->screen(), dpiValue, dpiValue);
+ for (const auto &canvasAndScreen : m_screens)
+ QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(canvasAndScreen.second->screen(), dpiValue, dpiValue);
}
void QWasmIntegration::resizeAllScreens()
{
- qDebug() << "resizeAllScreens";
- for (QWasmScreen *screen : m_screens)
- screen->updateQScreenAndCanvasRenderSize();
+ for (const auto &canvasAndScreen : m_screens)
+ canvasAndScreen.second->updateQScreenAndCanvasRenderSize();
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmintegration.h b/src/plugins/platforms/wasm/qwasmintegration.h
index 2102f5c226..08b68cb5f7 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.h
+++ b/src/plugins/platforms/wasm/qwasmintegration.h
@@ -40,6 +40,7 @@
#include <emscripten.h>
#include <emscripten/html5.h>
+#include <emscripten/val.h>
QT_BEGIN_NAMESPACE
@@ -83,9 +84,9 @@ public:
static QWasmIntegration *get() { return s_instance; }
static void QWasmBrowserExit();
- void addScreen(const QString &canvasId);
- void removeScreen(const QString &canvasId);
- void resizeScreen(const QString &canvasId);
+ void addScreen(const emscripten::val &canvas);
+ void removeScreen(const emscripten::val &canvas);
+ void resizeScreen(const emscripten::val &canvas);
void resizeAllScreens();
void updateDpi();
@@ -93,8 +94,7 @@ private:
mutable QWasmFontDatabase *m_fontDb;
mutable QWasmServices *m_desktopServices;
mutable QHash<QWindow *, QWasmBackingStore *> m_backingStores;
-
- QHash<QString, QWasmScreen *> m_screens;
+ QVector<QPair<emscripten::val, QWasmScreen *>> m_screens;
mutable QWasmClipboard *m_clipboard;
qreal m_fontDpi = -1;
mutable QScopedPointer<QPlatformInputContext> m_inputContext;
diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
index 501ab99116..4ddd56fd8c 100644
--- a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
+++ b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
@@ -106,7 +106,8 @@ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(cons
attributes.depth = useDepthStencil;
attributes.stencil = useDepthStencil;
- EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context(canvasId.toUtf8().constData(), &attributes);
+ QByteArray convasSelector = "#" + canvasId.toUtf8();
+ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context(convasSelector.constData(), &attributes);
return context;
}
diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp
index 5e6f94b9ed..a2bcd4fcb4 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.cpp
+++ b/src/plugins/platforms/wasm/qwasmscreen.cpp
@@ -50,15 +50,13 @@ using namespace emscripten;
QT_BEGIN_NAMESPACE
-QWasmScreen::QWasmScreen(const QString &canvasId)
- : m_canvasId(canvasId)
-
+QWasmScreen::QWasmScreen(const emscripten::val &canvas)
+ : m_canvas(canvas)
{
m_compositor = new QWasmCompositor(this);
m_eventTranslator = new QWasmEventTranslator(this);
updateQScreenAndCanvasRenderSize();
- emscripten::val canvas = emscripten::val::global(m_canvasId.toUtf8().constData());
- canvas.call<void>("focus");
+ m_canvas.call<void>("focus");
}
QWasmScreen::~QWasmScreen()
@@ -91,9 +89,14 @@ QWasmEventTranslator *QWasmScreen::eventTranslator()
return m_eventTranslator;
}
+emscripten::val QWasmScreen::canvas() const
+{
+ return m_canvas;
+}
+
QString QWasmScreen::canvasId() const
{
- return m_canvasId;
+ return QWasmString::toQString(m_canvas["id"]);
}
QRect QWasmScreen::geometry() const
@@ -134,7 +137,7 @@ qreal QWasmScreen::devicePixelRatio() const
QString QWasmScreen::name() const
{
- return m_canvasId;
+ return canvasId();
}
QPlatformCursor *QWasmScreen::cursor() const
@@ -180,24 +183,22 @@ void QWasmScreen::updateQScreenAndCanvasRenderSize()
// Setting the render size to a value larger than the CSS size enables high-dpi
// rendering.
- QByteArray canvasId = m_canvasId.toUtf8();
+ QByteArray canvasSelector = "#" + canvasId().toUtf8();
double css_width;
double css_height;
- emscripten_get_element_css_size(canvasId.constData(), &css_width, &css_height);
+ emscripten_get_element_css_size(canvasSelector.constData(), &css_width, &css_height);
QSizeF cssSize(css_width, css_height);
QSizeF canvasSize = cssSize * devicePixelRatio();
- val document = val::global("document");
- val canvas = document.call<val>("getElementById", QWasmString::fromQString(m_canvasId));
- canvas.set("width", canvasSize.width());
- canvas.set("height", canvasSize.height());
+ m_canvas.set("width", canvasSize.width());
+ m_canvas.set("height", canvasSize.height());
QPoint offset;
- offset.setX(canvas["offsetTop"].as<int>());
- offset.setY(canvas["offsetLeft"].as<int>());
+ offset.setX(m_canvas["offsetTop"].as<int>());
+ offset.setY(m_canvas["offsetLeft"].as<int>());
- emscripten::val rect = canvas.call<emscripten::val>("getBoundingClientRect");
+ emscripten::val rect = m_canvas.call<emscripten::val>("getBoundingClientRect");
QPoint position(rect["left"].as<int>() - offset.x(), rect["top"].as<int>() - offset.y());
setGeometry(QRect(position, cssSize.toSize()));
diff --git a/src/plugins/platforms/wasm/qwasmscreen.h b/src/plugins/platforms/wasm/qwasmscreen.h
index fcf693681c..ea7ffc4193 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.h
+++ b/src/plugins/platforms/wasm/qwasmscreen.h
@@ -37,6 +37,8 @@
#include <QtCore/qscopedpointer.h>
#include <QtCore/qtextstream.h>
+#include <emscripten/val.h>
+
QT_BEGIN_NAMESPACE
class QPlatformOpenGLContext;
@@ -50,12 +52,13 @@ class QWasmScreen : public QObject, public QPlatformScreen
{
Q_OBJECT
public:
- QWasmScreen(const QString &canvasId);
+ QWasmScreen(const emscripten::val &canvas);
~QWasmScreen();
void destroy();
static QWasmScreen *get(QPlatformScreen *screen);
static QWasmScreen *get(QScreen *screen);
+ emscripten::val canvas() const;
QString canvasId() const;
QWasmCompositor *compositor();
@@ -80,7 +83,7 @@ public slots:
void setGeometry(const QRect &rect);
private:
- QString m_canvasId;
+ emscripten::val m_canvas;
QWasmCompositor *m_compositor = nullptr;
QWasmEventTranslator *m_eventTranslator = nullptr;
QRect m_geometry = QRect(0, 0, 100, 100);
diff --git a/src/plugins/platforms/wasm/qwasmstring.cpp b/src/plugins/platforms/wasm/qwasmstring.cpp
index 05b571c459..b1be405eeb 100644
--- a/src/plugins/platforms/wasm/qwasmstring.cpp
+++ b/src/plugins/platforms/wasm/qwasmstring.cpp
@@ -52,9 +52,10 @@ QString QWasmString::toQString(const val &v)
val::global("Module")["stringToUTF16"]);
static const val length("length");
- result.resize(v[length].as<int>());
+ int len = v[length].as<int>();
+ result.resize(len);
auto ptr = quintptr(result.utf16());
- stringToUTF16(v, val(ptr));
+ stringToUTF16(v, val(ptr), val((len + 1) * 2));
return result;
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index d22cc75647..ee65b393d4 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1946,12 +1946,13 @@ void QWindowsWindow::checkForScreenChanged(ScreenChangeMode mode)
if (newScreen == nullptr || newScreen == currentScreen)
return;
// For screens with different DPI: postpone until WM_DPICHANGE
- if (mode == FromGeometryChange
+ // Check on currentScreen as it can be 0 when resuming a session (QTBUG-80436).
+ if (mode == FromGeometryChange && currentScreen != nullptr
&& !equalDpi(currentScreen->logicalDpi(), newScreen->logicalDpi())) {
return;
}
qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
- << ' ' << window() << " \"" << currentScreen->name()
+ << ' ' << window() << " \"" << (currentScreen ? currentScreen->name() : QString())
<< "\"->\"" << newScreen->name() << '"';
if (mode == FromGeometryChange)
setFlag(SynchronousGeometryChangeEvent);
@@ -2604,37 +2605,41 @@ bool QWindowsWindow::setMouseGrabEnabled(bool grab)
return grab;
}
-static inline DWORD cornerToWinOrientation(Qt::Corner corner)
+static inline DWORD edgesToWinOrientation(Qt::Edges edges)
{
- switch (corner) {
- case Qt::TopLeftCorner:
- return 0xf004; // SZ_SIZETOPLEFT;
- case Qt::TopRightCorner:
- return 0xf005; // SZ_SIZETOPRIGHT
- case Qt::BottomLeftCorner:
- return 0xf007; // SZ_SIZEBOTTOMLEFT
- case Qt::BottomRightCorner:
- return 0xf008; // SZ_SIZEBOTTOMRIGHT
- }
- return 0;
+ if (edges == Qt::LeftEdge)
+ return 0xf001; // SC_SIZELEFT;
+ else if (edges == (Qt::RightEdge))
+ return 0xf002; // SC_SIZERIGHT
+ else if (edges == (Qt::TopEdge))
+ return 0xf003; // SC_SIZETOP
+ else if (edges == (Qt::TopEdge | Qt::LeftEdge))
+ return 0xf004; // SC_SIZETOPLEFT
+ else if (edges == (Qt::TopEdge | Qt::RightEdge))
+ return 0xf005; // SC_SIZETOPRIGHT
+ else if (edges == (Qt::BottomEdge))
+ return 0xf006; // SC_SIZEBOTTOM
+ else if (edges == (Qt::BottomEdge | Qt::LeftEdge))
+ return 0xf007; // SC_SIZEBOTTOMLEFT
+ else if (edges == (Qt::BottomEdge | Qt::RightEdge))
+ return 0xf008; // SC_SIZEBOTTOMRIGHT
+
+ return 0xf000; // SC_SIZE
}
-bool QWindowsWindow::startSystemResize(const QPoint &, Qt::Corner corner)
+bool QWindowsWindow::startSystemResize(Qt::Edges edges)
{
- if (!GetSystemMenu(m_data.hwnd, FALSE))
+ if (Q_UNLIKELY(!(window()->flags() & Qt::MSWindowsFixedSizeDialogHint)))
return false;
ReleaseCapture();
- PostMessage(m_data.hwnd, WM_SYSCOMMAND, cornerToWinOrientation(corner), 0);
+ PostMessage(m_data.hwnd, WM_SYSCOMMAND, edgesToWinOrientation(edges), 0);
setFlag(SizeGripOperation);
return true;
}
-bool QWindowsWindow::startSystemMove(const QPoint &)
+bool QWindowsWindow::startSystemMove()
{
- if (!GetSystemMenu(m_data.hwnd, FALSE))
- return false;
-
ReleaseCapture();
PostMessage(m_data.hwnd, WM_SYSCOMMAND, 0xF012 /*SC_DRAGMOVE*/, 0);
return true;
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 7c37c6b115..e1f7908687 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -277,8 +277,8 @@ public:
bool setMouseGrabEnabled(bool grab) override;
inline bool hasMouseCapture() const { return GetCapture() == m_data.hwnd; }
- bool startSystemResize(const QPoint &pos, Qt::Corner corner) override;
- bool startSystemMove(const QPoint &pos) override;
+ bool startSystemResize(Qt::Edges edges) override;
+ bool startSystemMove() override;
void setFrameStrutEventsEnabled(bool enabled) override;
bool frameStrutEventsEnabled() const override { return testFlag(FrameStrutEventsEnabled); }
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 2d89b971dc..8a4b577d2e 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -230,7 +230,7 @@ public:
bool xi2MouseEventsDisabled() const;
Qt::MouseButton xiToQtMouseButton(uint32_t b);
void xi2UpdateScrollingDevices();
- bool startSystemMoveResizeForTouchBegin(xcb_window_t window, const QPoint &point, int corner);
+ bool startSystemMoveResizeForTouch(xcb_window_t window, int edges);
void abortSystemMoveResizeForTouch();
bool isTouchScreen(int id);
@@ -334,7 +334,7 @@ private:
xcb_window_t window = XCB_NONE;
uint16_t deviceid;
uint32_t pointid;
- int corner;
+ int edges;
} m_startSystemMoveResizeInfo;
const bool m_canGrabServer;
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 2d114c51b3..4620f0fd1d 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -753,7 +753,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
xcb_input_xi_allow_events(xcb_connection(), XCB_CURRENT_TIME, xiDeviceEvent->deviceid,
XCB_INPUT_EVENT_MODE_REJECT_TOUCH,
xiDeviceEvent->detail, xiDeviceEvent->event);
- window->doStartSystemMoveResize(QPoint(x, y), m_startSystemMoveResizeInfo.corner);
+ window->doStartSystemMoveResize(QPoint(x, y), m_startSystemMoveResizeInfo.edges);
m_startSystemMoveResizeInfo.window = XCB_NONE;
}
}
@@ -787,19 +787,20 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
touchPoint.state = Qt::TouchPointStationary;
}
-bool QXcbConnection::startSystemMoveResizeForTouchBegin(xcb_window_t window, const QPoint &point, int corner)
+bool QXcbConnection::startSystemMoveResizeForTouch(xcb_window_t window, int edges)
{
QHash<int, TouchDeviceData>::const_iterator devIt = m_touchDevices.constBegin();
for (; devIt != m_touchDevices.constEnd(); ++devIt) {
TouchDeviceData deviceData = devIt.value();
if (deviceData.qtTouchDevice->type() == QTouchDevice::TouchScreen) {
- QHash<int, QPointF>::const_iterator pointIt = deviceData.pointPressedPosition.constBegin();
- for (; pointIt != deviceData.pointPressedPosition.constEnd(); ++pointIt) {
- if (pointIt.value().toPoint() == point) {
+ auto pointIt = deviceData.touchPoints.constBegin();
+ for (; pointIt != deviceData.touchPoints.constEnd(); ++pointIt) {
+ Qt::TouchPointState state = pointIt.value().state;
+ if (state == Qt::TouchPointMoved || state == Qt::TouchPointPressed || state == Qt::TouchPointStationary) {
m_startSystemMoveResizeInfo.window = window;
m_startSystemMoveResizeInfo.deviceid = devIt.key();
m_startSystemMoveResizeInfo.pointid = pointIt.key();
- m_startSystemMoveResizeInfo.corner = corner;
+ m_startSystemMoveResizeInfo.edges = edges;
return true;
}
}
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 2426b5243a..698be45aa8 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -41,7 +41,6 @@
#include "qxcbwindow.h"
#include "qxcbcursor.h"
#include "qxcbimage.h"
-#include "qxcbintegration.h"
#include "qnamespace.h"
#include "qxcbxsettings.h"
@@ -50,7 +49,6 @@
#include <QDebug>
#include <QtAlgorithms>
-#include <qpa/qplatformservices.h>
#include <qpa/qwindowsysteminterface.h>
#include <private/qmath_p.h>
#include <QtGui/private/qhighdpiscaling_p.h>
@@ -368,15 +366,6 @@ static QFontEngine::SubpixelAntialiasingType parseXftRgba(const QByteArray& stri
void QXcbVirtualDesktop::readXResources()
{
- const QPlatformServices *services = QXcbIntegration::instance()->services();
- bool useXftConf = false;
- if (services) {
- const QList<QByteArray> desktopEnv = services->desktopEnvironment().split(':');
- useXftConf = desktopEnv.contains("GNOME") || desktopEnv.contains("UNITY") || desktopEnv.contains("XFCE");
- }
- if (!useXftConf)
- return;
-
int offset = 0;
QByteArray resources;
while (true) {
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index adca902c69..71ec47b053 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -2161,6 +2161,7 @@ QXcbWindow *QXcbWindow::toWindow() { return this; }
void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, const QPoint &global,
Qt::KeyboardModifiers modifiers, QEvent::Type type, Qt::MouseEventSource source)
{
+ m_lastPointerPosition = local;
connection()->setTime(time);
Qt::MouseButton button = type == QEvent::MouseMove ? Qt::NoButton : connection()->button();
QWindowSystemInterface::handleMouseEvent(window(), time, local, global,
@@ -2345,45 +2346,65 @@ bool QXcbWindow::windowEvent(QEvent *event)
return QPlatformWindow::windowEvent(event);
}
-bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
+bool QXcbWindow::startSystemResize(Qt::Edges edges)
{
- return startSystemMoveResize(pos, corner);
+ return startSystemMoveResize(m_lastPointerPosition, edges);
}
-bool QXcbWindow::startSystemMove(const QPoint &pos)
+bool QXcbWindow::startSystemMove()
{
- return startSystemMoveResize(pos, 4);
+ return startSystemMoveResize(m_lastPointerPosition, 16);
}
-bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int corner)
+bool QXcbWindow::startSystemMoveResize(const QPoint &pos, int edges)
{
- return false; // ### FIXME QTBUG-69716
const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
if (!connection()->wmSupport()->isSupportedByWM(moveResize))
return false;
- const QPoint globalPos = QHighDpi::toNativePixels(window()->mapToGlobal(pos), window()->screen());
-
// ### FIXME QTBUG-53389
- bool startedByTouch = connection()->startSystemMoveResizeForTouchBegin(m_window, globalPos, corner);
+ bool startedByTouch = connection()->startSystemMoveResizeForTouch(m_window, edges);
if (startedByTouch) {
- if (connection()->isUnity() || connection()->isGnome()) {
- // These desktops fail to move/resize via _NET_WM_MOVERESIZE (WM bug?).
+ if (connection()->isUnity()) {
+ // Unity fails to move/resize via _NET_WM_MOVERESIZE (WM bug?).
connection()->abortSystemMoveResizeForTouch();
return false;
}
- // KWin, Openbox, AwesomeWM have been tested to work with _NET_WM_MOVERESIZE.
+ // KWin, Openbox, AwesomeWM and Gnome have been tested to work with _NET_WM_MOVERESIZE.
} else { // Started by mouse press.
if (connection()->isUnity())
return false; // _NET_WM_MOVERESIZE on this WM is bouncy (WM bug?).
- doStartSystemMoveResize(globalPos, corner);
+ doStartSystemMoveResize(mapToGlobal(pos), edges);
}
return true;
}
-void QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int corner)
+static uint qtEdgesToXcbMoveResizeDirection(Qt::Edges edges)
+{
+ if (edges == (Qt::TopEdge | Qt::LeftEdge))
+ return 0;
+ if (edges == Qt::TopEdge)
+ return 1;
+ if (edges == (Qt::TopEdge | Qt::RightEdge))
+ return 2;
+ if (edges == Qt::RightEdge)
+ return 3;
+ if (edges == (Qt::RightEdge | Qt::BottomEdge))
+ return 4;
+ if (edges == Qt::BottomEdge)
+ return 5;
+ if (edges == (Qt::BottomEdge | Qt::LeftEdge))
+ return 6;
+ if (edges == Qt::LeftEdge)
+ return 7;
+
+ qWarning() << "Cannot convert " << edges << "to _NET_WM_MOVERESIZE direction.";
+ return 0;
+}
+
+void QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int edges)
{
const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
xcb_client_message_event_t xev;
@@ -2394,16 +2415,10 @@ void QXcbWindow::doStartSystemMoveResize(const QPoint &globalPos, int corner)
xev.format = 32;
xev.data.data32[0] = globalPos.x();
xev.data.data32[1] = globalPos.y();
- if (corner == 4) {
+ if (edges == 16)
xev.data.data32[2] = 8; // move
- } else {
- const bool bottom = corner == Qt::BottomRightCorner || corner == Qt::BottomLeftCorner;
- const bool left = corner == Qt::BottomLeftCorner || corner == Qt::TopLeftCorner;
- if (bottom)
- xev.data.data32[2] = left ? 6 : 4; // bottomleft/bottomright
- else
- xev.data.data32[2] = left ? 0 : 2; // topleft/topright
- }
+ else
+ xev.data.data32[2] = qtEdgesToXcbMoveResizeDirection(Qt::Edges(edges));
xev.data.data32[3] = XCB_BUTTON_INDEX_1;
xev.data.data32[4] = 0;
xcb_ungrab_pointer(connection()->xcb_connection(), XCB_CURRENT_TIME);
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 976a442b11..d6f370eebe 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -107,8 +107,8 @@ public:
bool windowEvent(QEvent *event) override;
- bool startSystemResize(const QPoint &pos, Qt::Corner corner) override;
- bool startSystemMove(const QPoint &pos) override;
+ bool startSystemResize(Qt::Edges edges) override;
+ bool startSystemMove() override;
void setOpacity(qreal level) override;
void setMask(const QRegion &region) override;
@@ -168,8 +168,8 @@ public:
QXcbScreen *xcbScreen() const;
- bool startSystemMoveResize(const QPoint &pos, int corner);
- void doStartSystemMoveResize(const QPoint &globalPos, int corner);
+ bool startSystemMoveResize(const QPoint &pos, int edges);
+ void doStartSystemMoveResize(const QPoint &globalPos, int edges);
static bool isTrayIconWindow(QWindow *window)
{
@@ -264,6 +264,7 @@ protected:
QRegion m_exposeRegion;
QSize m_oldWindowSize;
+ QPoint m_lastPointerPosition;
xcb_visualid_t m_visualId = 0;
// Last sent state. Initialized to an invalid state, on purpose.
diff --git a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
index ae213365b7..09c0655f3d 100644
--- a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
+++ b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
@@ -250,7 +250,7 @@ static QDateTime fromTimeStamp(char *buffer)
return QDateTime(d, t);
}
-static ISC_TIME toTime(const QTime &t)
+static ISC_TIME toTime(QTime t)
{
static const QTime midnight(0, 0, 0, 0);
return (ISC_TIME)midnight.msecsTo(t) * 10;
@@ -266,7 +266,7 @@ static QTime fromTime(char *buffer)
return t;
}
-static ISC_DATE toDate(const QDate &t)
+static ISC_DATE toDate(QDate t)
{
static const QDate basedate(1858, 11, 17);
ISC_DATE date;
diff --git a/src/plugins/sqldrivers/mysql/mysql.json b/src/plugins/sqldrivers/mysql/mysql.json
index 0caaadb7ce..89f5e65fb9 100644
--- a/src/plugins/sqldrivers/mysql/mysql.json
+++ b/src/plugins/sqldrivers/mysql/mysql.json
@@ -1,3 +1,3 @@
{
- "Keys": [ "QMYSQL3", "QMYSQL" ]
+ "Keys": [ "QMYSQL3", "QMYSQL", "QMARIADB" ]
}
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index 24efb641f2..e2599e8c6b 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -3096,13 +3096,18 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
bool needTranslation = false;
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave
&& !qt_mac_applicationIsInDarkMode()) {
- // Another surprise from AppKit (SDK 10.14) - -displayRectIgnoringOpacity:
- // is different from drawRect: for some Apple-known reason box is smaller
- // in height than we need, resulting in tab buttons sitting too high/not
- // centered. Attempts to play with insets etc did not work - the same wrong
- // height. Simple translation is not working (too much space "at bottom"),
- // so we make it bigger and translate (otherwise it's clipped at bottom btw).
- adjustedRect.adjust(0, 0, 0, 3);
+ // In Aqua theme we have to use the 'default' NSBox (as opposite
+ // to the 'custom' QDarkNSBox we use in dark theme). Since -drawRect:
+ // does nothing in default NSBox, we call -displayRectIgnoringOpaticty:.
+ // Unfortunately, the resulting box is smaller then the actual rect we
+ // wanted. This can be seen, e.g. because tabs (buttons) are misaligned
+ // vertically and even worse, if QTabWidget has autoFillBackground
+ // set, this background overpaints NSBox making it to disappear.
+ // We trick our NSBox to render in a larger rectangle, so that
+ // the actuall result (which is again smaller than requested),
+ // more or less is what we really want. We'll have to adjust CTM
+ // and translate accordingly.
+ adjustedRect.adjust(0, 0, 6, 6);
needTranslation = true;
}
d->drawNSViewInRect(box, adjustedRect, p, ^(CGContextRef ctx, const CGRect &rect) {
@@ -3117,7 +3122,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
[box drawRect:rect];
} else {
if (needTranslation)
- CGContextTranslateCTM(ctx, 0.0, 4.0);
+ CGContextTranslateCTM(ctx, -3.0, 5.0);
[box displayRectIgnoringOpacity:box.bounds inContext:NSGraphicsContext.currentContext];
}
});
@@ -4613,6 +4618,7 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
case SE_ToolBoxTabContents:
rect = QCommonStyle::subElementRect(sr, opt, widget);
break;
+ case SE_PushButtonBevel:
case SE_PushButtonContents:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
// Comment from the old HITheme days:
@@ -4626,9 +4632,20 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
const auto ct = cocoaControlType(btn, widget);
const auto cs = d->effectiveAquaSizeConstrain(btn, widget);
const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
- const auto frameRect = cw.adjustedControlFrame(btn->rect);
- const auto titleMargins = cw.titleMargins();
- rect = (frameRect - titleMargins).toRect();
+ auto frameRect = cw.adjustedControlFrame(btn->rect);
+ if (sr == SE_PushButtonContents) {
+ frameRect -= cw.titleMargins();
+ } else {
+ auto *pb = static_cast<NSButton *>(d->cocoaControl(cw));
+ if (cw.type != QMacStylePrivate::Button_SquareButton) {
+ frameRect = QRectF::fromCGRect([pb alignmentRectForFrame:pb.frame]);
+ if (cw.type == QMacStylePrivate::Button_PushButton)
+ frameRect -= pushButtonShadowMargins[cw.size];
+ else if (cw.type == QMacStylePrivate::Button_PullDown)
+ frameRect -= pullDownButtonShadowMargins[cw.size];
+ }
+ }
+ rect = frameRect.toRect();
}
break;
case SE_HeaderLabel: {
diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
index 9ae8bd6c90..9d143da169 100644
--- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
@@ -665,7 +665,7 @@ static inline bool isFullyOpaque(const XPThemeData &themeData)
\note drawBackgroundThruNativeBuffer() can return false for large
sizes due to buffer()/CreateDIBSection() failing.
*/
-bool QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData)
+bool QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData, qreal correctionFactor)
{
if (themeData.rect.isEmpty())
return true;
@@ -710,9 +710,9 @@ bool QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData)
}
const HDC dc = canDrawDirectly ? hdcForWidgetBackingStore(themeData.widget) : nullptr;
- const bool result = dc
+ const bool result = dc && qFuzzyCompare(correctionFactor, qreal(1))
? drawBackgroundDirectly(dc, themeData, aditionalDevicePixelRatio)
- : drawBackgroundThruNativeBuffer(themeData, aditionalDevicePixelRatio);
+ : drawBackgroundThruNativeBuffer(themeData, aditionalDevicePixelRatio, correctionFactor);
painter->restore();
return result;
}
@@ -786,9 +786,14 @@ bool QWindowsXPStylePrivate::drawBackgroundDirectly(HDC dc, XPThemeData &themeDa
other pixmaps etc), or when special transformations are needed (e.g.
flips (horizonal mirroring only, vertical are handled by the theme
engine).
+
+ \a correctionFactor is an additional factor used to scale up controls
+ that are too small on High DPI screens, as has been observed for
+ WP_MDICLOSEBUTTON, WP_MDIRESTOREBUTTON, WP_MDIMINBUTTON (QTBUG-75927).
*/
bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeData,
- qreal additionalDevicePixelRatio)
+ qreal additionalDevicePixelRatio,
+ qreal correctionFactor)
{
QPainter *painter = themeData.painter;
QRectF rectF = scaleRect(QRectF(themeData.rect), additionalDevicePixelRatio);
@@ -797,7 +802,11 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
rectF = QRectF(0, 0, rectF.height(), rectF.width());
}
rectF.moveTo(0, 0);
+
+ const bool hasCorrectionFactor = !qFuzzyCompare(correctionFactor, qreal(1));
QRect rect = rectF.toRect();
+ QRect drawRect = hasCorrectionFactor
+ ? QRectF(rectF.topLeft() / correctionFactor, rectF.size() / correctionFactor).toRect() : rect;
int partId = themeData.partId;
int stateId = themeData.stateId;
int w = rect.width();
@@ -826,6 +835,10 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
pixmapCacheKey.append(QLatin1Char('h'));
pixmapCacheKey.append(QString::number(additionalDevicePixelRatio));
pixmapCacheKey.append(QLatin1Char('d'));
+ if (hasCorrectionFactor) {
+ pixmapCacheKey.append(QLatin1Char('c'));
+ pixmapCacheKey.append(QString::number(correctionFactor));
+ }
QPixmap cachedPixmap;
ThemeMapKey key(themeData);
@@ -884,7 +897,7 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
// and DTGB_OMITCONTENT
bool addBorderContentClipping = false;
QRegion extraClip;
- QRect area = rect;
+ QRect area = drawRect;
if (themeData.noBorder || themeData.noContent) {
extraClip = area;
// We are running on a system where the uxtheme.dll does not have
@@ -915,19 +928,19 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
QImage img;
if (!haveCachedPixmap) { // If the pixmap is not cached, generate it! -------------------------
- if (!buffer(w, h)) // Ensure a buffer of at least (w, h) in size
+ if (!buffer(drawRect.width(), drawRect.height())) // Ensure a buffer of at least (w, h) in size
return false;
HDC dc = bufferHDC();
// Clear the buffer
if (alphaType != NoAlpha) {
// Consider have separate "memset" function for small chunks for more speedup
- memset(bufferPixels, 0x00, bufferW * h * 4);
+ memset(bufferPixels, 0x00, bufferW * drawRect.height() * 4);
}
// Difference between area and rect
- int dx = area.x() - rect.x();
- int dy = area.y() - rect.y();
+ int dx = area.x() - drawRect.x();
+ int dy = area.y() - drawRect.y();
// Adjust so painting rect starts from Origo
rect.moveTo(0,0);
@@ -957,7 +970,7 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
if (!hasAlpha && partIsTransparent)
potentialInvalidAlpha = true;
#if defined(DEBUG_XP_STYLE) && 1
- dumpNativeDIB(w, h);
+ dumpNativeDIB(drawRect.width(), drawRect.height());
#endif
}
@@ -985,6 +998,8 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
printf("Image format is: %s\n", alphaType == RealAlpha ? "Real Alpha" : alphaType == MaskAlpha ? "Masked Alpha" : "No Alpha");
#endif
img = QImage(bufferPixels, bufferW, bufferH, format);
+ if (hasCorrectionFactor)
+ img = img.scaled(w, h, Qt::KeepAspectRatio, Qt::SmoothTransformation);
img.setDevicePixelRatio(additionalDevicePixelRatio);
}
@@ -2463,6 +2478,61 @@ QRect QWindowsXPStylePrivate::scrollBarGripperBounds(QStyle::State flags, const
return sufficientSpace ? QRect(theme->rect.topLeft() + QPoint(hSpace, vSpace) / 2, size) : QRect();
}
+#if QT_CONFIG(mdiarea)
+// Helper for drawing MDI buttons into the corner widget of QMenuBar in case a
+// QMdiSubWindow is maximized.
+static void populateMdiButtonTheme(const QStyle *proxy, const QWidget *widget,
+ const QStyleOptionComplex *option,
+ QStyle::SubControl subControl, int part,
+ XPThemeData *theme)
+{
+ theme->partId = part;
+ theme->rect = proxy->subControlRect(QStyle::CC_MdiControls, option, subControl, widget);
+ if (!option->state.testFlag(QStyle::State_Enabled))
+ theme->stateId = CBS_INACTIVE;
+ else if (option->state.testFlag(QStyle::State_Sunken) && option->activeSubControls.testFlag(subControl))
+ theme->stateId = CBS_PUSHED;
+ else if (option->state.testFlag(QStyle::State_MouseOver) && option->activeSubControls.testFlag(subControl))
+ theme->stateId = CBS_HOT;
+ else
+ theme->stateId = CBS_NORMAL;
+}
+
+// Calculate an small (max 2), empirical correction factor for scaling up
+// WP_MDICLOSEBUTTON, WP_MDIRESTOREBUTTON, WP_MDIMINBUTTON, which are too
+// small on High DPI screens (QTBUG-75927).
+qreal mdiButtonCorrectionFactor(XPThemeData &theme, const QPaintDevice *pd = nullptr)
+{
+ const auto dpr = pd ? pd->devicePixelRatioF() : qApp->devicePixelRatio();
+ const QSizeF nativeSize = QSizeF(theme.size()) / dpr;
+ const QSizeF requestedSize(theme.rect.size());
+ const auto rawFactor = qMin(requestedSize.width() / nativeSize.width(),
+ requestedSize.height() / nativeSize.height());
+ const auto factor = rawFactor >= qreal(2) ? qreal(2) : qreal(1);
+ return factor;
+}
+#endif // QT_CONFIG(mdiarea)
+
+static void populateTitleBarButtonTheme(const QStyle *proxy, const QWidget *widget,
+ const QStyleOptionComplex *option,
+ QStyle::SubControl subControl,
+ bool isTitleBarActive, int part,
+ XPThemeData *theme)
+{
+ theme->rect = proxy->subControlRect(QStyle::CC_TitleBar, option, subControl, widget);
+ theme->partId = part;
+ if (widget && !widget->isEnabled())
+ theme->stateId = RBS_DISABLED;
+ else if (option->activeSubControls == subControl && option->state.testFlag(QStyle::State_Sunken))
+ theme->stateId = RBS_PUSHED;
+ else if (option->activeSubControls == subControl && option->state.testFlag(QStyle::State_MouseOver))
+ theme->stateId = RBS_HOT;
+ else if (!isTitleBarActive)
+ theme->stateId = RBS_INACTIVE;
+ else
+ theme->stateId = RBS_NORMAL;
+}
+
/*!
\reimp
*/
@@ -3024,56 +3094,17 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
if (sub & SC_TitleBarMinButton && tb->titleBarFlags & Qt::WindowMinimizeButtonHint
&& !(tb->titleBarState & Qt::WindowMinimized)) {
- theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarMinButton, widget);
- partId = WP_MINBUTTON;
- if (widget && !widget->isEnabled())
- stateId = MINBS_DISABLED;
- else if (option->activeSubControls == SC_TitleBarMinButton && (option->state & State_Sunken))
- stateId = MINBS_PUSHED;
- else if (option->activeSubControls == SC_TitleBarMinButton && (option->state & State_MouseOver))
- stateId = MINBS_HOT;
- else if (!isActive)
- stateId = MINBS_INACTIVE;
- else
- stateId = MINBS_NORMAL;
- theme.partId = partId;
- theme.stateId = stateId;
+ populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarMinButton, isActive, WP_MINBUTTON, &theme);
d->drawBackground(theme);
}
if (sub & SC_TitleBarMaxButton && tb->titleBarFlags & Qt::WindowMaximizeButtonHint
&& !(tb->titleBarState & Qt::WindowMaximized)) {
- theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarMaxButton, widget);
- partId = WP_MAXBUTTON;
- if (widget && !widget->isEnabled())
- stateId = MAXBS_DISABLED;
- else if (option->activeSubControls == SC_TitleBarMaxButton && (option->state & State_Sunken))
- stateId = MAXBS_PUSHED;
- else if (option->activeSubControls == SC_TitleBarMaxButton && (option->state & State_MouseOver))
- stateId = MAXBS_HOT;
- else if (!isActive)
- stateId = MAXBS_INACTIVE;
- else
- stateId = MAXBS_NORMAL;
- theme.partId = partId;
- theme.stateId = stateId;
+ populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarMaxButton, isActive, WP_MAXBUTTON, &theme);
d->drawBackground(theme);
}
if (sub & SC_TitleBarContextHelpButton
&& tb->titleBarFlags & Qt::WindowContextHelpButtonHint) {
- theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarContextHelpButton, widget);
- partId = WP_HELPBUTTON;
- if (widget && !widget->isEnabled())
- stateId = MINBS_DISABLED;
- else if (option->activeSubControls == SC_TitleBarContextHelpButton && (option->state & State_Sunken))
- stateId = MINBS_PUSHED;
- else if (option->activeSubControls == SC_TitleBarContextHelpButton && (option->state & State_MouseOver))
- stateId = MINBS_HOT;
- else if (!isActive)
- stateId = MINBS_INACTIVE;
- else
- stateId = MINBS_NORMAL;
- theme.partId = partId;
- theme.stateId = stateId;
+ populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarContextHelpButton, isActive, WP_HELPBUTTON, &theme);
d->drawBackground(theme);
}
bool drawNormalButton = (sub & SC_TitleBarNormalButton)
@@ -3082,74 +3113,21 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
|| ((tb->titleBarFlags & Qt::WindowMaximizeButtonHint)
&& (tb->titleBarState & Qt::WindowMaximized)));
if (drawNormalButton) {
- theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarNormalButton, widget);
- partId = WP_RESTOREBUTTON;
- if (widget && !widget->isEnabled())
- stateId = RBS_DISABLED;
- else if (option->activeSubControls == SC_TitleBarNormalButton && (option->state & State_Sunken))
- stateId = RBS_PUSHED;
- else if (option->activeSubControls == SC_TitleBarNormalButton && (option->state & State_MouseOver))
- stateId = RBS_HOT;
- else if (!isActive)
- stateId = RBS_INACTIVE;
- else
- stateId = RBS_NORMAL;
- theme.partId = partId;
- theme.stateId = stateId;
+ populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarNormalButton, isActive, WP_RESTOREBUTTON, &theme);
d->drawBackground(theme);
}
if (sub & SC_TitleBarShadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint
&& !(tb->titleBarState & Qt::WindowMinimized)) {
- theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarShadeButton, widget);
- partId = WP_MINBUTTON;
- if (widget && !widget->isEnabled())
- stateId = MINBS_DISABLED;
- else if (option->activeSubControls == SC_TitleBarShadeButton && (option->state & State_Sunken))
- stateId = MINBS_PUSHED;
- else if (option->activeSubControls == SC_TitleBarShadeButton && (option->state & State_MouseOver))
- stateId = MINBS_HOT;
- else if (!isActive)
- stateId = MINBS_INACTIVE;
- else
- stateId = MINBS_NORMAL;
- theme.partId = partId;
- theme.stateId = stateId;
+ populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarShadeButton, isActive, WP_MINBUTTON, &theme);
d->drawBackground(theme);
}
if (sub & SC_TitleBarUnshadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint
&& tb->titleBarState & Qt::WindowMinimized) {
- theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarUnshadeButton, widget);
- partId = WP_RESTOREBUTTON;
- if (widget && !widget->isEnabled())
- stateId = RBS_DISABLED;
- else if (option->activeSubControls == SC_TitleBarUnshadeButton && (option->state & State_Sunken))
- stateId = RBS_PUSHED;
- else if (option->activeSubControls == SC_TitleBarUnshadeButton && (option->state & State_MouseOver))
- stateId = RBS_HOT;
- else if (!isActive)
- stateId = RBS_INACTIVE;
- else
- stateId = RBS_NORMAL;
- theme.partId = partId;
- theme.stateId = stateId;
+ populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarUnshadeButton, isActive, WP_RESTOREBUTTON, &theme);
d->drawBackground(theme);
}
if (sub & SC_TitleBarCloseButton && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
- theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarCloseButton, widget);
- //partId = titlebar->testWFlags(Qt::WA_WState_Tool) ? WP_SMALLCLOSEBUTTON : WP_CLOSEBUTTON;
- partId = WP_CLOSEBUTTON;
- if (widget && !widget->isEnabled())
- stateId = CBS_DISABLED;
- else if (option->activeSubControls == SC_TitleBarCloseButton && (option->state & State_Sunken))
- stateId = CBS_PUSHED;
- else if (option->activeSubControls == SC_TitleBarCloseButton && (option->state & State_MouseOver))
- stateId = CBS_HOT;
- else if (!isActive)
- stateId = CBS_INACTIVE;
- else
- stateId = CBS_NORMAL;
- theme.partId = partId;
- theme.stateId = stateId;
+ populateTitleBarButtonTheme(proxy(), widget, option, SC_TitleBarCloseButton, isActive, WP_CLOSEBUTTON, &theme);
d->drawBackground(theme);
}
}
@@ -3159,56 +3137,21 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
#if QT_CONFIG(mdiarea)
case CC_MdiControls:
{
- QRect buttonRect;
XPThemeData theme(widget, p, QWindowsXPStylePrivate::WindowTheme, WP_MDICLOSEBUTTON, CBS_NORMAL);
+ if (Q_UNLIKELY(!theme.isValid()))
+ return;
- if (option->subControls & SC_MdiCloseButton) {
- buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiCloseButton, widget);
- if (theme.isValid()) {
- theme.partId = WP_MDICLOSEBUTTON;
- theme.rect = buttonRect;
- if (!(flags & State_Enabled))
- theme.stateId = CBS_INACTIVE;
- else if (flags & State_Sunken && (option->activeSubControls & SC_MdiCloseButton))
- theme.stateId = CBS_PUSHED;
- else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiCloseButton))
- theme.stateId = CBS_HOT;
- else
- theme.stateId = CBS_NORMAL;
- d->drawBackground(theme);
- }
+ if (option->subControls.testFlag(SC_MdiCloseButton)) {
+ populateMdiButtonTheme(proxy(), widget, option, SC_MdiCloseButton, WP_MDICLOSEBUTTON, &theme);
+ d->drawBackground(theme, mdiButtonCorrectionFactor(theme, widget));
}
- if (option->subControls & SC_MdiNormalButton) {
- buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiNormalButton, widget);
- if (theme.isValid()) {
- theme.partId = WP_MDIRESTOREBUTTON;
- theme.rect = buttonRect;
- if (!(flags & State_Enabled))
- theme.stateId = CBS_INACTIVE;
- else if (flags & State_Sunken && (option->activeSubControls & SC_MdiNormalButton))
- theme.stateId = CBS_PUSHED;
- else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiNormalButton))
- theme.stateId = CBS_HOT;
- else
- theme.stateId = CBS_NORMAL;
- d->drawBackground(theme);
- }
+ if (option->subControls.testFlag(SC_MdiNormalButton)) {
+ populateMdiButtonTheme(proxy(), widget, option, SC_MdiNormalButton, WP_MDIRESTOREBUTTON, &theme);
+ d->drawBackground(theme, mdiButtonCorrectionFactor(theme, widget));
}
- if (option->subControls & QStyle::SC_MdiMinButton) {
- buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiMinButton, widget);
- if (theme.isValid()) {
- theme.partId = WP_MDIMINBUTTON;
- theme.rect = buttonRect;
- if (!(flags & State_Enabled))
- theme.stateId = CBS_INACTIVE;
- else if (flags & State_Sunken && (option->activeSubControls & SC_MdiMinButton))
- theme.stateId = CBS_PUSHED;
- else if (flags & State_MouseOver && (option->activeSubControls & SC_MdiMinButton))
- theme.stateId = CBS_HOT;
- else
- theme.stateId = CBS_NORMAL;
- d->drawBackground(theme);
- }
+ if (option->subControls.testFlag(QStyle::SC_MdiMinButton)) {
+ populateMdiButtonTheme(proxy(), widget, option, SC_MdiMinButton, WP_MDIMINBUTTON, &theme);
+ d->drawBackground(theme, mdiButtonCorrectionFactor(theme, widget));
}
}
break;
@@ -3670,19 +3613,20 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt
sz = QWindowsStyle::sizeFromContents(ct, option, sz, widget);
break;
- case CT_MdiControls:
+ case CT_MdiControls: {
+ sz.setHeight(int(QStyleHelper::dpiScaled(19, option)));
+ int width = 54;
if (const QStyleOptionComplex *styleOpt = qstyleoption_cast<const QStyleOptionComplex *>(option)) {
- int width = 0;
+ width = 0;
if (styleOpt->subControls & SC_MdiMinButton)
width += 17 + 1;
if (styleOpt->subControls & SC_MdiNormalButton)
width += 17 + 1;
if (styleOpt->subControls & SC_MdiCloseButton)
width += 17 + 1;
- sz = QSize(width, 19);
- } else {
- sz = QSize(54, 19);
}
+ sz.setWidth(int(QStyleHelper::dpiScaled(width, option)));
+ }
break;
default:
diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h b/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h
index ad7754e3d4..06b37a6e5c 100644
--- a/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h
@@ -241,8 +241,8 @@ public:
bool isTransparent(XPThemeData &themeData);
QRegion region(XPThemeData &themeData);
- bool drawBackground(XPThemeData &themeData);
- bool drawBackgroundThruNativeBuffer(XPThemeData &themeData, qreal aditionalDevicePixelRatio);
+ bool drawBackground(XPThemeData &themeData, qreal correctionFactor = 1);
+ bool drawBackgroundThruNativeBuffer(XPThemeData &themeData, qreal aditionalDevicePixelRatio, qreal correctionFactor);
bool drawBackgroundDirectly(HDC dc, XPThemeData &themeData, qreal aditionalDevicePixelRatio);
bool hasAlphaChannel(const QRect &rect);
diff --git a/src/printsupport/doc/snippets/printing-qprinter/errors.cpp b/src/printsupport/doc/snippets/printing-qprinter/errors.cpp
index 40acf9293c..c07bb8b76d 100644
--- a/src/printsupport/doc/snippets/printing-qprinter/errors.cpp
+++ b/src/printsupport/doc/snippets/printing-qprinter/errors.cpp
@@ -48,7 +48,11 @@
**
****************************************************************************/
-#include <QtGui>
+#include <QtWidgets>
+#include <QtPrintSupport/qtprintsupportglobal.h>
+#if QT_CONFIG(printdialog)
+#include <QPrinter>
+#endif
int main(int argc, char **argv)
{
diff --git a/src/printsupport/doc/snippets/printing-qprinter/object.cpp b/src/printsupport/doc/snippets/printing-qprinter/object.cpp
index c4987af4a6..6e246ff615 100644
--- a/src/printsupport/doc/snippets/printing-qprinter/object.cpp
+++ b/src/printsupport/doc/snippets/printing-qprinter/object.cpp
@@ -48,9 +48,14 @@
**
****************************************************************************/
-#include <QtGui>
#include "object.h"
+#include <QtWidgets>
+#include <QtPrintSupport/qtprintsupportglobal.h>
+#if QT_CONFIG(printdialog)
+#include <QPrinter>
+#endif
+
Object::Object(QObject *parent)
: QObject(parent)
{
diff --git a/src/printsupport/doc/snippets/widgetprinting.cpp b/src/printsupport/doc/snippets/widgetprinting.cpp
index 6e0256cb92..d64a1536fb 100644
--- a/src/printsupport/doc/snippets/widgetprinting.cpp
+++ b/src/printsupport/doc/snippets/widgetprinting.cpp
@@ -48,7 +48,6 @@
**
****************************************************************************/
-#include <QtGui>
#include <QtWidgets>
#include <QtPrintSupport/qtprintsupportglobal.h>
#if QT_CONFIG(printdialog)
@@ -61,11 +60,12 @@ class Window : public QWidget
Q_OBJECT
public:
- Window() {
+ Window()
+ {
myWidget = new QPushButton("Print Me");
- connect(myWidget, SIGNAL(clicked()), this, SLOT(print()));
+ connect(myWidget, &QPushButton::clicked, this, &Window::print);
myWidget2 = new QPushButton("Print Document");
- connect(myWidget2, SIGNAL(clicked()), this, SLOT(printFile()));
+ connect(myWidget2, &QPushButton::clicked, this, &Window::printFile);
editor = new QTextEdit(this);
QVBoxLayout *layout = new QVBoxLayout;
@@ -76,8 +76,9 @@ public:
}
private slots:
- void print() {
- #if !defined(QT_NO_PRINTER)
+ void print()
+ {
+ #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
QPrinter printer(QPrinter::HighResolution);
printer.setOutputFileName("test.pdf");
@@ -85,8 +86,8 @@ private slots:
//! [0]
QPainter painter;
painter.begin(&printer);
- double xscale = printer.pageRect().width()/double(myWidget->width());
- double yscale = printer.pageRect().height()/double(myWidget->height());
+ double xscale = printer.pageRect().width() / double(myWidget->width());
+ double yscale = printer.pageRect().height() / double(myWidget->height());
double scale = qMin(xscale, yscale);
painter.translate(printer.paperRect().x() + printer.pageRect().width()/2,
printer.paperRect().y() + printer.pageRect().height()/2);
@@ -98,8 +99,9 @@ private slots:
#endif
}
- void printFile() {
- #if QT_CONFIG(printdialog)
+ void printFile()
+ {
+ #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog)
//! [1]
QPrinter printer;
diff --git a/src/sql/doc/src/sql-driver.qdoc b/src/sql/doc/src/sql-driver.qdoc
index 28841a58de..95fa8355c7 100644
--- a/src/sql/doc/src/sql-driver.qdoc
+++ b/src/sql/doc/src/sql-driver.qdoc
@@ -206,8 +206,8 @@
When you distribute your application, remember to include libmysql.dll / libmariadb.dll
in your installation package. It must be placed in the same folder
as the application executable. \e libmysql.dll additionally needs the
- MSVC runtime libraries which can be installed with vcredist.exe
- (\l {https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads}{vcredist.exe}
+ MSVC runtime libraries which can be installed with
+ \l {https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads}{vcredist.exe}
\target QOCI
\section2 QOCI for the Oracle Call Interface (OCI)
diff --git a/src/testlib/.prev_CMakeLists.txt b/src/testlib/.prev_CMakeLists.txt
index 29c73d597e..8279b0719b 100644
--- a/src/testlib/.prev_CMakeLists.txt
+++ b/src/testlib/.prev_CMakeLists.txt
@@ -17,6 +17,7 @@ qt_add_module(Test
qbenchmarkperfevents.cpp qbenchmarkperfevents_p.h
qbenchmarktimemeasurers_p.h
qcsvbenchmarklogger.cpp qcsvbenchmarklogger_p.h
+ qjunittestlogger.cpp qjunittestlogger_p.h
qplaintestlogger.cpp qplaintestlogger_p.h
qsignaldumper.cpp qsignaldumper_p.h
qsignalspy.h
@@ -38,6 +39,7 @@ qt_add_module(Test
qtestevent.h
qtesteventloop.h
qtesthelpers_p.h
+ qtestjunitstreamer.cpp qtestjunitstreamer_p.h
qtestkeyboard.h
qtestlog.cpp qtestlog_p.h
qtestmouse.cpp qtestmouse.h
@@ -46,10 +48,8 @@ qt_add_module(Test
qtestsystem.h
qtesttable.cpp qtesttable_p.h
qtesttouch.h
- qtestxunitstreamer.cpp qtestxunitstreamer_p.h
qttestglobal.h
qxmltestlogger.cpp qxmltestlogger_p.h
- qxunittestlogger.cpp qxunittestlogger_p.h
DEFINES
QT_NO_CAST_FROM_ASCII
QT_NO_CAST_TO_ASCII
@@ -105,6 +105,7 @@ qt_extend_target(Test CONDITION APPLE_OSX
SOURCES
qtestutil_macos.mm qtestutil_macos_p.h
PUBLIC_LIBRARIES
+ ${FWAppKit}
${FWApplicationServices}
${FWFoundation}
${FWIOKit}
diff --git a/src/testlib/CMakeLists.txt b/src/testlib/CMakeLists.txt
index 79138707e3..8e2a3caafa 100644
--- a/src/testlib/CMakeLists.txt
+++ b/src/testlib/CMakeLists.txt
@@ -17,6 +17,7 @@ qt_add_module(Test
qbenchmarkperfevents.cpp qbenchmarkperfevents_p.h
qbenchmarktimemeasurers_p.h
qcsvbenchmarklogger.cpp qcsvbenchmarklogger_p.h
+ qjunittestlogger.cpp qjunittestlogger_p.h
qplaintestlogger.cpp qplaintestlogger_p.h
qsignaldumper.cpp qsignaldumper_p.h
qsignalspy.h
@@ -38,6 +39,7 @@ qt_add_module(Test
qtestevent.h
qtesteventloop.h
qtesthelpers_p.h
+ qtestjunitstreamer.cpp qtestjunitstreamer_p.h
qtestkeyboard.h
qtestlog.cpp qtestlog_p.h
qtestmouse.cpp qtestmouse.h
@@ -46,10 +48,8 @@ qt_add_module(Test
qtestsystem.h
qtesttable.cpp qtesttable_p.h
qtesttouch.h
- qtestxunitstreamer.cpp qtestxunitstreamer_p.h
qttestglobal.h
qxmltestlogger.cpp qxmltestlogger_p.h
- qxunittestlogger.cpp qxunittestlogger_p.h
DEFINES
QT_NO_CAST_FROM_ASCII
QT_NO_CAST_TO_ASCII
@@ -103,6 +103,7 @@ qt_extend_target(Test CONDITION APPLE_OSX
SOURCES
qtestutil_macos.mm qtestutil_macos_p.h
PUBLIC_LIBRARIES
+ ${FWAppKit}
${FWApplicationServices}
${FWFoundation}
${FWIOKit}
diff --git a/src/testlib/doc/src/qttestlib-manual.qdoc b/src/testlib/doc/src/qttestlib-manual.qdoc
index 89edabf3f3..3acc08d8f4 100644
--- a/src/testlib/doc/src/qttestlib-manual.qdoc
+++ b/src/testlib/doc/src/qttestlib-manual.qdoc
@@ -237,7 +237,7 @@
\list
\li \c -o \e{filename,format} \br
Writes output to the specified file, in the specified format (one of
- \c txt, \c xml, \c lightxml, \c xunitxml or \c tap). The special filename \c -
+ \c txt, \c xml, \c lightxml, \c junitxml or \c tap). The special filename \c -
may be used to log to standard output.
\li \c -o \e filename \br
Writes output to the specified file.
@@ -247,8 +247,8 @@
Outputs results as an XML document.
\li \c -lightxml \br
Outputs results as a stream of XML tags.
- \li \c -xunitxml \br
- Outputs results as an Xunit XML document.
+ \li \c -junitxml \br
+ Outputs results as an JUnit XML document.
\li \c -csv \br
Outputs results as comma-separated values (CSV). This mode is only suitable for
benchmarks, since it suppresses normal pass/fail messages.
@@ -264,7 +264,7 @@
If the first version of the \c -o option is used, neither the second version
of the \c -o option nor the \c -txt, \c -xml, \c -lightxml, \c -teamcity,
- \c -xunitxml or \c -tap options should be used.
+ \c -junitxml or \c -tap options should be used.
If neither version of the \c -o option is used, test results will be logged to
standard output. If no format option is used, test results will be logged in
diff --git a/src/testlib/qxunittestlogger.cpp b/src/testlib/qjunittestlogger.cpp
index b3cac9cb82..2d71f7967b 100644
--- a/src/testlib/qxunittestlogger.cpp
+++ b/src/testlib/qjunittestlogger.cpp
@@ -37,9 +37,9 @@
**
****************************************************************************/
-#include <QtTest/private/qxunittestlogger_p.h>
+#include <QtTest/private/qjunittestlogger_p.h>
#include <QtTest/private/qtestelement_p.h>
-#include <QtTest/private/qtestxunitstreamer_p.h>
+#include <QtTest/private/qtestjunitstreamer_p.h>
#include <QtTest/qtestcase.h>
#include <QtTest/private/qtestresult_p.h>
#include <QtTest/private/qbenchmark_p.h>
@@ -57,27 +57,27 @@
QT_BEGIN_NAMESPACE
-QXunitTestLogger::QXunitTestLogger(const char *filename)
+QJUnitTestLogger::QJUnitTestLogger(const char *filename)
: QAbstractTestLogger(filename)
{
}
-QXunitTestLogger::~QXunitTestLogger()
+QJUnitTestLogger::~QJUnitTestLogger()
{
delete currentLogElement;
delete logFormatter;
}
-void QXunitTestLogger::startLogging()
+void QJUnitTestLogger::startLogging()
{
QAbstractTestLogger::startLogging();
- logFormatter = new QTestXunitStreamer(this);
+ logFormatter = new QTestJUnitStreamer(this);
delete errorLogElement;
errorLogElement = new QTestElement(QTest::LET_SystemError);
}
-void QXunitTestLogger::stopLogging()
+void QJUnitTestLogger::stopLogging()
{
QTestElement *iterator = listOfTestcases;
@@ -132,7 +132,7 @@ void QXunitTestLogger::stopLogging()
QAbstractTestLogger::stopLogging();
}
-void QXunitTestLogger::enterTestFunction(const char *function)
+void QJUnitTestLogger::enterTestFunction(const char *function)
{
currentLogElement = new QTestElement(QTest::LET_TestCase);
currentLogElement->addAttribute(QTest::AI_Name, function);
@@ -141,11 +141,11 @@ void QXunitTestLogger::enterTestFunction(const char *function)
++testCounter;
}
-void QXunitTestLogger::leaveTestFunction()
+void QJUnitTestLogger::leaveTestFunction()
{
}
-void QXunitTestLogger::addIncident(IncidentTypes type, const char *description,
+void QJUnitTestLogger::addIncident(IncidentTypes type, const char *description,
const char *file, int line)
{
const char *typeBuf = nullptr;
@@ -242,15 +242,15 @@ void QXunitTestLogger::addIncident(IncidentTypes type, const char *description,
currentLogElement->addAttribute(QTest::AI_Line, buf);
/*
- Since XFAIL does not add a failure to the testlog in xunitxml, add a message, so we still
+ Since XFAIL does not add a failure to the testlog in junitxml, add a message, so we still
have some information about the expected failure.
*/
if (type == QAbstractTestLogger::XFail) {
- QXunitTestLogger::addMessage(QAbstractTestLogger::Info, QString::fromUtf8(description), file, line);
+ QJUnitTestLogger::addMessage(QAbstractTestLogger::Info, QString::fromUtf8(description), file, line);
}
}
-void QXunitTestLogger::addBenchmarkResult(const QBenchmarkResult &result)
+void QJUnitTestLogger::addBenchmarkResult(const QBenchmarkResult &result)
{
QTestElement *benchmarkElement = new QTestElement(QTest::LET_Benchmark);
@@ -268,7 +268,7 @@ void QXunitTestLogger::addBenchmarkResult(const QBenchmarkResult &result)
currentLogElement->addLogElement(benchmarkElement);
}
-void QXunitTestLogger::addTag(QTestElement* element)
+void QJUnitTestLogger::addTag(QTestElement* element)
{
const char *tag = QTestResult::currentDataTag();
const char *gtag = QTestResult::currentGlobalDataTag();
@@ -289,7 +289,7 @@ void QXunitTestLogger::addTag(QTestElement* element)
element->addAttribute(QTest::AI_Tag, buf.constData());
}
-void QXunitTestLogger::addMessage(MessageTypes type, const QString &message, const char *file, int line)
+void QJUnitTestLogger::addMessage(MessageTypes type, const QString &message, const char *file, int line)
{
QTestElement *errorElement = new QTestElement(QTest::LET_Error);
const char *typeBuf = nullptr;
diff --git a/src/testlib/qxunittestlogger_p.h b/src/testlib/qjunittestlogger_p.h
index 518ba098f4..6fd4e4c331 100644
--- a/src/testlib/qxunittestlogger_p.h
+++ b/src/testlib/qjunittestlogger_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QXUNITTESTLOGGER_P_H
-#define QXUNITTESTLOGGER_P_H
+#ifndef QJUNITTESTLOGGER_P_H
+#define QJUNITTESTLOGGER_P_H
//
// W A R N I N G
@@ -55,14 +55,14 @@
QT_BEGIN_NAMESPACE
-class QTestXunitStreamer;
+class QTestJUnitStreamer;
class QTestElement;
-class QXunitTestLogger : public QAbstractTestLogger
+class QJUnitTestLogger : public QAbstractTestLogger
{
public:
- QXunitTestLogger(const char *filename);
- ~QXunitTestLogger();
+ QJUnitTestLogger(const char *filename);
+ ~QJUnitTestLogger();
void startLogging() override;
void stopLogging() override;
@@ -82,7 +82,7 @@ class QXunitTestLogger : public QAbstractTestLogger
QTestElement *listOfTestcases = nullptr;
QTestElement *currentLogElement = nullptr;
QTestElement *errorLogElement = nullptr;
- QTestXunitStreamer *logFormatter = nullptr;
+ QTestJUnitStreamer *logFormatter = nullptr;
int testCounter = 0;
int failureCounter = 0;
@@ -91,4 +91,4 @@ class QXunitTestLogger : public QAbstractTestLogger
QT_END_NAMESPACE
-#endif // QXUNITTESTLOGGER_P_H
+#endif // QJUNITTESTLOGGER_P_H
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index cb8061737d..fc6b22f062 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -154,10 +154,6 @@ static bool debuggerPresent()
#elif defined(Q_OS_WIN)
return IsDebuggerPresent();
#elif defined(Q_OS_MACOS)
- auto equals = [](CFStringRef str1, CFStringRef str2) -> bool {
- return CFStringCompare(str1, str2, kCFCompareCaseInsensitive) == kCFCompareEqualTo;
- };
-
// Check if there is an exception handler for the process:
mach_msg_type_number_t portCount = 0;
exception_mask_t masks[EXC_TYPES_COUNT];
@@ -174,25 +170,22 @@ static bool debuggerPresent()
}
}
}
-
- // Ok, no debugger attached. So, let's see if CrashReporter will throw up a dialog. If so, we
- // leave it to the OS to do the stack trace.
- CFStringRef crashReporterType = static_cast<CFStringRef>(
- CFPreferencesCopyAppValue(CFSTR("DialogType"), CFSTR("com.apple.CrashReporter")));
- if (crashReporterType == nullptr)
- return true;
-
- const bool createsStackTrace =
- !equals(crashReporterType, CFSTR("server")) &&
- !equals(crashReporterType, CFSTR("none"));
- CFRelease(crashReporterType);
- return createsStackTrace;
+ return false;
#else
// TODO
return false;
#endif
}
+static bool hasSystemCrashReporter()
+{
+#if defined(Q_OS_MACOS)
+ return QTestPrivate::macCrashReporterWillShowDialog();
+#else
+ return false;
+#endif
+}
+
static void disableCoreDump()
{
bool ok = false;
@@ -216,7 +209,7 @@ static void stackTrace()
if (ok && disableStackDump == 1)
return;
- if (debuggerPresent())
+ if (debuggerPresent() || hasSystemCrashReporter())
return;
#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
@@ -290,14 +283,15 @@ namespace QTestPrivate
namespace QTest
{
+extern Q_TESTLIB_EXPORT int lastMouseTimestamp;
+
class WatchDog;
static QObject *currentTestObject = nullptr;
static QString mainSourcePath;
#if defined(Q_OS_MACOS)
-bool macNeedsActivate = false;
-IOPMAssertionID powerID;
+static IOPMAssertionID macPowerSavingDisabled = 0;
#endif
class TestMethods {
@@ -536,7 +530,7 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, const char *const argv[], bool
" Valid formats are:\n"
" txt : Plain text\n"
" csv : CSV format (suitable for benchmarks)\n"
- " xunitxml : XML XUnit document\n"
+ " junitxml : XML JUnit document\n"
" xml : XML document\n"
" lightxml : A stream of XML tags\n"
" teamcity : TeamCity format\n"
@@ -548,7 +542,7 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, const char *const argv[], bool
" -o filename : Write the output into file\n"
" -txt : Output results in Plain Text\n"
" -csv : Output results in a CSV format (suitable for benchmarks)\n"
- " -xunitxml : Output results as XML XUnit document\n"
+ " -junitxml : Output results as XML JUnit document\n"
" -xml : Output results as XML document\n"
" -lightxml : Output results as stream of XML tags\n"
" -teamcity : Output results in TeamCity format\n"
@@ -632,8 +626,8 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, const char *const argv[], bool
logFormat = QTestLog::Plain;
} else if (strcmp(argv[i], "-csv") == 0) {
logFormat = QTestLog::CSV;
- } else if (strcmp(argv[i], "-xunitxml") == 0) {
- logFormat = QTestLog::XunitXML;
+ } else if (strcmp(argv[i], "-junitxml") == 0 || strcmp(argv[i], "-xunitxml") == 0) {
+ logFormat = QTestLog::JUnitXML;
} else if (strcmp(argv[i], "-xml") == 0) {
logFormat = QTestLog::XML;
} else if (strcmp(argv[i], "-lightxml") == 0) {
@@ -672,14 +666,14 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, const char *const argv[], bool
logFormat = QTestLog::LightXML;
else if (strcmp(format, "xml") == 0)
logFormat = QTestLog::XML;
- else if (strcmp(format, "xunitxml") == 0)
- logFormat = QTestLog::XunitXML;
+ else if (strcmp(format, "junitxml") == 0 || strcmp(format, "xunitxml") == 0)
+ logFormat = QTestLog::JUnitXML;
else if (strcmp(format, "teamcity") == 0)
logFormat = QTestLog::TeamCity;
else if (strcmp(format, "tap") == 0)
logFormat = QTestLog::TAP;
else {
- fprintf(stderr, "output format must be one of txt, csv, lightxml, xml, tap, teamcity or xunitxml\n");
+ fprintf(stderr, "output format must be one of txt, csv, lightxml, xml, tap, teamcity or junitxml\n");
exit(1);
}
if (strcmp(filename, "-") == 0 && QTestLog::loggerUsingStdout()) {
@@ -1168,6 +1162,7 @@ bool TestMethods::invokeTest(int index, const char *data, WatchDog *watchDog) co
QTestPrivate::qtestMouseButtons = Qt::NoButton;
if (watchDog)
watchDog->beginTest();
+ QTest::lastMouseTimestamp += 500; // Maintain at least 500ms mouse event timestamps between each test function call
invokeTestOnData(index);
if (watchDog)
watchDog->testFinished();
@@ -1332,7 +1327,7 @@ char *toPrettyCString(const char *p, int length)
// 3 bytes: "" and a character
// 4 bytes: an hex escape sequence (\xHH)
if (dst - buffer.data() > 246) {
- // plus the the quote, the three dots and NUL, it's 255 in the worst case
+ // plus the quote, the three dots and NUL, it's 255 in the worst case
trimmed = true;
break;
}
@@ -1425,7 +1420,7 @@ char *toPrettyUnicode(QStringView string)
*dst++ = '"';
for ( ; p != end; ++p) {
if (dst - buffer.data() > 245) {
- // plus the the quote, the three dots and NUL, it's 250, 251 or 255
+ // plus the quote, the three dots and NUL, it's 250, 251 or 255
trimmed = true;
break;
}
@@ -1528,126 +1523,6 @@ void TestMethods::invokeTests(QObject *testObject) const
QTestResult::setCurrentTestFunction(nullptr);
}
-#if defined(Q_OS_UNIX) && !defined(Q_OS_WASM)
-class FatalSignalHandler
-{
-public:
- FatalSignalHandler();
- ~FatalSignalHandler();
-
-private:
- static void signal(int);
- sigset_t handledSignals;
-};
-
-void FatalSignalHandler::signal(int signum)
-{
- const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime());
- const int msecsTotalTime = qRound(QTestLog::msecsTotalTime());
- if (signum != SIGINT) {
- stackTrace();
- if (qEnvironmentVariableIsSet("QTEST_PAUSE_ON_CRASH")) {
- fprintf(stderr, "Pausing process %d for debugging\n", getpid());
- raise(SIGSTOP);
- }
- }
- qFatal("Received signal %d\n"
- " Function time: %dms Total time: %dms",
- signum, msecsFunctionTime, msecsTotalTime);
-#if defined(Q_OS_INTEGRITY)
- {
- struct sigaction act;
- memset(&act, 0, sizeof(struct sigaction));
- act.sa_handler = SIG_DFL;
- sigaction(signum, &act, NULL);
- }
-#endif
-}
-
-FatalSignalHandler::FatalSignalHandler()
-{
- sigemptyset(&handledSignals);
-
- const int fatalSignals[] = {
- SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGPIPE, SIGTERM, 0 };
-
- struct sigaction act;
- memset(&act, 0, sizeof(act));
- act.sa_handler = FatalSignalHandler::signal;
-
- // Remove the handler after it is invoked.
-#if !defined(Q_OS_INTEGRITY)
- act.sa_flags = SA_RESETHAND;
-#endif
-
-// tvOS/watchOS both define SA_ONSTACK (in sys/signal.h) but mark sigaltstack() as
-// unavailable (__WATCHOS_PROHIBITED __TVOS_PROHIBITED in signal.h)
-#if defined(SA_ONSTACK) && !defined(Q_OS_TVOS) && !defined(Q_OS_WATCHOS)
- // Let the signal handlers use an alternate stack
- // This is necessary if SIGSEGV is to catch a stack overflow
-# if defined(Q_CC_GNU) && defined(Q_OF_ELF)
- // Put the alternate stack in the .lbss (large BSS) section so that it doesn't
- // interfere with normal .bss symbols
- __attribute__((section(".lbss.altstack"), aligned(4096)))
-# endif
- static char alternate_stack[16 * 1024];
- stack_t stack;
- stack.ss_flags = 0;
- stack.ss_size = sizeof alternate_stack;
- stack.ss_sp = alternate_stack;
- sigaltstack(&stack, nullptr);
- act.sa_flags |= SA_ONSTACK;
-#endif
-
- // Block all fatal signals in our signal handler so we don't try to close
- // the testlog twice.
- sigemptyset(&act.sa_mask);
- for (int i = 0; fatalSignals[i]; ++i)
- sigaddset(&act.sa_mask, fatalSignals[i]);
-
- struct sigaction oldact;
-
- for (int i = 0; fatalSignals[i]; ++i) {
- sigaction(fatalSignals[i], &act, &oldact);
- if (
-#ifdef SA_SIGINFO
- oldact.sa_flags & SA_SIGINFO ||
-#endif
- oldact.sa_handler != SIG_DFL) {
- sigaction(fatalSignals[i], &oldact, nullptr);
- } else
- {
- sigaddset(&handledSignals, fatalSignals[i]);
- }
- }
-}
-
-
-FatalSignalHandler::~FatalSignalHandler()
-{
- // Unregister any of our remaining signal handlers
- struct sigaction act;
- memset(&act, 0, sizeof(act));
- act.sa_handler = SIG_DFL;
-
- struct sigaction oldact;
-
- for (int i = 1; i < 32; ++i) {
- if (!sigismember(&handledSignals, i))
- continue;
- sigaction(i, &act, &oldact);
-
- // If someone overwrote it in the mean time, put it back
- if (oldact.sa_handler != FatalSignalHandler::signal)
- sigaction(i, &oldact, nullptr);
- }
-}
-
-#endif
-
-
-} // namespace
-
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
// Helper class for resolving symbol names by dynamically loading "dbghelp.dll".
@@ -1746,49 +1621,177 @@ DebugSymbolResolver::Symbol DebugSymbolResolver::resolveSymbol(DWORD64 address)
return result;
}
-static LONG WINAPI windowsFaultHandler(struct _EXCEPTION_POINTERS *exInfo)
+#endif // Q_OS_WIN && !Q_OS_WINRT
+
+class FatalSignalHandler
{
- enum { maxStackFrames = 100 };
- char appName[MAX_PATH];
- if (!GetModuleFileNameA(NULL, appName, MAX_PATH))
- appName[0] = 0;
- const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime());
- const int msecsTotalTime = qRound(QTestLog::msecsTotalTime());
- const void *exceptionAddress = exInfo->ExceptionRecord->ExceptionAddress;
- printf("A crash occurred in %s.\n"
- "Function time: %dms Total time: %dms\n\n"
- "Exception address: 0x%p\n"
- "Exception code : 0x%lx\n",
- appName, msecsFunctionTime, msecsTotalTime,
- exceptionAddress, exInfo->ExceptionRecord->ExceptionCode);
-
- DebugSymbolResolver resolver(GetCurrentProcess());
- if (resolver.isValid()) {
- DebugSymbolResolver::Symbol exceptionSymbol = resolver.resolveSymbol(DWORD64(exceptionAddress));
- if (exceptionSymbol.name) {
- printf("Nearby symbol : %s\n", exceptionSymbol.name);
- delete [] exceptionSymbol.name;
+public:
+ FatalSignalHandler()
+ {
+#if defined(Q_OS_WIN)
+# if !defined(Q_CC_MINGW)
+ _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
+# endif
+# if !defined(Q_OS_WINRT)
+ SetErrorMode(SetErrorMode(0) | SEM_NOGPFAULTERRORBOX);
+ SetUnhandledExceptionFilter(windowsFaultHandler);
+# endif
+#elif defined(Q_OS_UNIX) && !defined(Q_OS_WASM)
+ sigemptyset(&handledSignals);
+
+ const int fatalSignals[] = {
+ SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGPIPE, SIGTERM, 0 };
+
+ struct sigaction act;
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = FatalSignalHandler::signal;
+
+ // Remove the handler after it is invoked.
+# if !defined(Q_OS_INTEGRITY)
+ act.sa_flags = SA_RESETHAND;
+# endif
+
+ // tvOS/watchOS both define SA_ONSTACK (in sys/signal.h) but mark sigaltstack() as
+ // unavailable (__WATCHOS_PROHIBITED __TVOS_PROHIBITED in signal.h)
+# if defined(SA_ONSTACK) && !defined(Q_OS_TVOS) && !defined(Q_OS_WATCHOS)
+ // Let the signal handlers use an alternate stack
+ // This is necessary if SIGSEGV is to catch a stack overflow
+# if defined(Q_CC_GNU) && defined(Q_OF_ELF)
+ // Put the alternate stack in the .lbss (large BSS) section so that it doesn't
+ // interfere with normal .bss symbols
+ __attribute__((section(".lbss.altstack"), aligned(4096)))
+# endif
+ static char alternate_stack[16 * 1024];
+ stack_t stack;
+ stack.ss_flags = 0;
+ stack.ss_size = sizeof alternate_stack;
+ stack.ss_sp = alternate_stack;
+ sigaltstack(&stack, nullptr);
+ act.sa_flags |= SA_ONSTACK;
+# endif
+
+ // Block all fatal signals in our signal handler so we don't try to close
+ // the testlog twice.
+ sigemptyset(&act.sa_mask);
+ for (int i = 0; fatalSignals[i]; ++i)
+ sigaddset(&act.sa_mask, fatalSignals[i]);
+
+ struct sigaction oldact;
+
+ for (int i = 0; fatalSignals[i]; ++i) {
+ sigaction(fatalSignals[i], &act, &oldact);
+ if (
+# ifdef SA_SIGINFO
+ oldact.sa_flags & SA_SIGINFO ||
+# endif
+ oldact.sa_handler != SIG_DFL) {
+ sigaction(fatalSignals[i], &oldact, nullptr);
+ } else
+ {
+ sigaddset(&handledSignals, fatalSignals[i]);
+ }
}
- void *stack[maxStackFrames];
- fputs("\nStack:\n", stdout);
- const unsigned frameCount = CaptureStackBackTrace(0, DWORD(maxStackFrames), stack, NULL);
- for (unsigned f = 0; f < frameCount; ++f) {
- DebugSymbolResolver::Symbol symbol = resolver.resolveSymbol(DWORD64(stack[f]));
- if (symbol.name) {
- printf("#%3u: %s() - 0x%p\n", f + 1, symbol.name, (const void *)symbol.address);
- delete [] symbol.name;
- } else {
- printf("#%3u: Unable to obtain symbol\n", f + 1);
+#endif // defined(Q_OS_UNIX) && !defined(Q_OS_WASM)
+ }
+
+ ~FatalSignalHandler()
+ {
+#if defined(Q_OS_UNIX) && !defined(Q_OS_WASM)
+ // Unregister any of our remaining signal handlers
+ struct sigaction act;
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = SIG_DFL;
+
+ struct sigaction oldact;
+
+ for (int i = 1; i < 32; ++i) {
+ if (!sigismember(&handledSignals, i))
+ continue;
+ sigaction(i, &act, &oldact);
+
+ // If someone overwrote it in the mean time, put it back
+ if (oldact.sa_handler != FatalSignalHandler::signal)
+ sigaction(i, &oldact, nullptr);
+ }
+#endif
+ }
+
+private:
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ static LONG WINAPI windowsFaultHandler(struct _EXCEPTION_POINTERS *exInfo)
+ {
+ enum { maxStackFrames = 100 };
+ char appName[MAX_PATH];
+ if (!GetModuleFileNameA(NULL, appName, MAX_PATH))
+ appName[0] = 0;
+ const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime());
+ const int msecsTotalTime = qRound(QTestLog::msecsTotalTime());
+ const void *exceptionAddress = exInfo->ExceptionRecord->ExceptionAddress;
+ printf("A crash occurred in %s.\n"
+ "Function time: %dms Total time: %dms\n\n"
+ "Exception address: 0x%p\n"
+ "Exception code : 0x%lx\n",
+ appName, msecsFunctionTime, msecsTotalTime,
+ exceptionAddress, exInfo->ExceptionRecord->ExceptionCode);
+
+ DebugSymbolResolver resolver(GetCurrentProcess());
+ if (resolver.isValid()) {
+ DebugSymbolResolver::Symbol exceptionSymbol = resolver.resolveSymbol(DWORD64(exceptionAddress));
+ if (exceptionSymbol.name) {
+ printf("Nearby symbol : %s\n", exceptionSymbol.name);
+ delete [] exceptionSymbol.name;
+ }
+ void *stack[maxStackFrames];
+ fputs("\nStack:\n", stdout);
+ const unsigned frameCount = CaptureStackBackTrace(0, DWORD(maxStackFrames), stack, NULL);
+ for (unsigned f = 0; f < frameCount; ++f) {
+ DebugSymbolResolver::Symbol symbol = resolver.resolveSymbol(DWORD64(stack[f]));
+ if (symbol.name) {
+ printf("#%3u: %s() - 0x%p\n", f + 1, symbol.name, (const void *)symbol.address);
+ delete [] symbol.name;
+ } else {
+ printf("#%3u: Unable to obtain symbol\n", f + 1);
+ }
+ }
+ }
+
+ fputc('\n', stdout);
+ fflush(stdout);
+
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+#endif // defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_WASM)
+ static void signal(int signum)
+ {
+ const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime());
+ const int msecsTotalTime = qRound(QTestLog::msecsTotalTime());
+ if (signum != SIGINT) {
+ stackTrace();
+ if (qEnvironmentVariableIsSet("QTEST_PAUSE_ON_CRASH")) {
+ fprintf(stderr, "Pausing process %d for debugging\n", getpid());
+ raise(SIGSTOP);
}
}
+ qFatal("Received signal %d\n"
+ " Function time: %dms Total time: %dms",
+ signum, msecsFunctionTime, msecsTotalTime);
+# if defined(Q_OS_INTEGRITY)
+ {
+ struct sigaction act;
+ memset(&act, 0, sizeof(struct sigaction));
+ act.sa_handler = SIG_DFL;
+ sigaction(signum, &act, NULL);
+ }
+# endif
}
- fputc('\n', stdout);
- fflush(stdout);
+ sigset_t handledSignals;
+#endif // defined(Q_OS_UNIX) && !defined(Q_OS_WASM)
+};
- return EXCEPTION_EXECUTE_HANDLER;
-}
-#endif // Q_OS_WIN) && !Q_OS_WINRT
+} // namespace
static void initEnvironment()
{
@@ -1848,23 +1851,17 @@ void QTest::qInit(QObject *testObject, int argc, char **argv)
initEnvironment();
QBenchmarkGlobalData::current = new QBenchmarkGlobalData;
-#if defined(Q_OS_MACX)
- macNeedsActivate = qApp && (qstrcmp(qApp->metaObject()->className(), "QApplication") == 0);
-
- // Don't restore saved window state for auto tests.
+#if defined(Q_OS_MACOS)
+ // Don't restore saved window state for auto tests
QTestPrivate::disableWindowRestore();
- // Disable App Nap which may cause tests to stall.
+ // Disable App Nap which may cause tests to stall
QTestPrivate::AppNapDisabler appNapDisabler;
-#endif
-#if defined(Q_OS_MACX)
- if (macNeedsActivate) {
- CFStringRef reasonForActivity= CFSTR("No Display Sleep");
- IOReturn ok = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, reasonForActivity, &powerID);
-
- if (ok != kIOReturnSuccess)
- macNeedsActivate = false; // no need to release the assertion on exit.
+ if (qApp && (qstrcmp(qApp->metaObject()->className(), "QApplication") == 0)) {
+ IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep,
+ kIOPMAssertionLevelOn, CFSTR("QtTest running tests"),
+ &macPowerSavingDisabled);
}
#endif
@@ -1902,18 +1899,6 @@ int QTest::qRun()
try {
#endif
-#if defined(Q_OS_WIN)
- if (!noCrashHandler) {
-# ifndef Q_CC_MINGW
- _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
-# endif
-# ifndef Q_OS_WINRT
- SetErrorMode(SetErrorMode(0) | SEM_NOGPFAULTERRORBOX);
- SetUnhandledExceptionFilter(windowsFaultHandler);
-# endif
- } // !noCrashHandler
-#endif // Q_OS_WIN
-
#if QT_CONFIG(valgrind)
if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess) {
if (Q_UNLIKELY(!qApp))
@@ -1928,11 +1913,10 @@ int QTest::qRun()
} else
#endif
{
-#if defined(Q_OS_UNIX) && !defined(Q_OS_WASM)
QScopedPointer<FatalSignalHandler> handler;
if (!noCrashHandler)
handler.reset(new FatalSignalHandler);
-#endif
+
TestMethods::MetaMethods commandLineMethods;
for (const QString &tf : qAsConst(QTest::testFunctions)) {
const QByteArray tfB = tf.toLatin1();
@@ -1951,25 +1935,19 @@ int QTest::qRun()
}
#ifndef QT_NO_EXCEPTIONS
- } catch (...) {
- QTestResult::addFailure("Caught unhandled exception", __FILE__, __LINE__);
- if (QTestResult::currentTestFunction()) {
- QTestResult::finishedCurrentTestFunction();
- QTestResult::setCurrentTestFunction(nullptr);
- }
-
- QTestLog::stopLogging();
-#if defined(Q_OS_MACX)
- if (macNeedsActivate) {
- IOPMAssertionRelease(powerID);
- }
-#endif
- currentTestObject = nullptr;
+ } catch (...) {
+ QTestResult::addFailure("Caught unhandled exception", __FILE__, __LINE__);
+ if (QTestResult::currentTestFunction()) {
+ QTestResult::finishedCurrentTestFunction();
+ QTestResult::setCurrentTestFunction(nullptr);
+ }
- // Rethrow exception to make debugging easier.
- throw;
- return 1;
- }
+ qCleanup();
+
+ // Re-throw exception to make debugging easier
+ throw;
+ return 1;
+ }
#endif
#if QT_CONFIG(valgrind)
@@ -1996,8 +1974,7 @@ void QTest::qCleanup()
QSignalDumper::endDump();
#if defined(Q_OS_MACOS)
- if (macNeedsActivate)
- IOPMAssertionRelease(powerID);
+ IOPMAssertionRelease(macPowerSavingDisabled);
#endif
}
diff --git a/src/testlib/qtestxunitstreamer.cpp b/src/testlib/qtestjunitstreamer.cpp
index bdbdfa9610..9c3a9c9ca5 100644
--- a/src/testlib/qtestxunitstreamer.cpp
+++ b/src/testlib/qtestjunitstreamer.cpp
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#include <QtTest/private/qtestxunitstreamer_p.h>
-#include <QtTest/private/qxunittestlogger_p.h>
+#include <QtTest/private/qtestjunitstreamer_p.h>
+#include <QtTest/private/qjunittestlogger_p.h>
#include <QtTest/private/qtestelement_p.h>
#include <QtTest/private/qtestelementattribute_p.h>
#include <QtTest/qtestassert.h>
@@ -48,15 +48,15 @@
QT_BEGIN_NAMESPACE
-QTestXunitStreamer::QTestXunitStreamer(QXunitTestLogger *logger)
+QTestJUnitStreamer::QTestJUnitStreamer(QJUnitTestLogger *logger)
: testLogger(logger)
{
QTEST_ASSERT(testLogger);
}
-QTestXunitStreamer::~QTestXunitStreamer() = default;
+QTestJUnitStreamer::~QTestJUnitStreamer() = default;
-void QTestXunitStreamer::indentForElement(const QTestElement* element, char* buf, int size)
+void QTestJUnitStreamer::indentForElement(const QTestElement* element, char* buf, int size)
{
if (size == 0) return;
@@ -74,7 +74,7 @@ void QTestXunitStreamer::indentForElement(const QTestElement* element, char* buf
}
}
-void QTestXunitStreamer::formatStart(const QTestElement *element, QTestCharBuffer *formatted) const
+void QTestJUnitStreamer::formatStart(const QTestElement *element, QTestCharBuffer *formatted) const
{
if (!element || !formatted )
return;
@@ -95,7 +95,7 @@ void QTestXunitStreamer::formatStart(const QTestElement *element, QTestCharBuffe
QTest::qt_asprintf(formatted, "%s<%s", indent, element->elementName());
}
-void QTestXunitStreamer::formatEnd(const QTestElement *element, QTestCharBuffer *formatted) const
+void QTestJUnitStreamer::formatEnd(const QTestElement *element, QTestCharBuffer *formatted) const
{
if (!element || !formatted )
return;
@@ -111,7 +111,7 @@ void QTestXunitStreamer::formatEnd(const QTestElement *element, QTestCharBuffer
QTest::qt_asprintf(formatted, "%s</%s>\n", indent, element->elementName());
}
-void QTestXunitStreamer::formatAttributes(const QTestElement* element, const QTestElementAttribute *attribute, QTestCharBuffer *formatted) const
+void QTestJUnitStreamer::formatAttributes(const QTestElement* element, const QTestElementAttribute *attribute, QTestCharBuffer *formatted) const
{
if (!attribute || !formatted )
return;
@@ -143,7 +143,7 @@ void QTestXunitStreamer::formatAttributes(const QTestElement* element, const QTe
}
}
-void QTestXunitStreamer::formatAfterAttributes(const QTestElement *element, QTestCharBuffer *formatted) const
+void QTestJUnitStreamer::formatAfterAttributes(const QTestElement *element, QTestCharBuffer *formatted) const
{
if (!element || !formatted )
return;
@@ -164,7 +164,7 @@ void QTestXunitStreamer::formatAfterAttributes(const QTestElement *element, QTes
QTest::qt_asprintf(formatted, ">\n");
}
-void QTestXunitStreamer::output(QTestElement *element) const
+void QTestJUnitStreamer::output(QTestElement *element) const
{
QTEST_ASSERT(element);
@@ -172,7 +172,7 @@ void QTestXunitStreamer::output(QTestElement *element) const
outputElements(element);
}
-void QTestXunitStreamer::outputElements(QTestElement *element, bool) const
+void QTestJUnitStreamer::outputElements(QTestElement *element, bool) const
{
QTestCharBuffer buf;
bool hasChildren;
@@ -205,7 +205,7 @@ void QTestXunitStreamer::outputElements(QTestElement *element, bool) const
}
}
-void QTestXunitStreamer::outputElementAttributes(const QTestElement* element, QTestElementAttribute *attribute) const
+void QTestJUnitStreamer::outputElementAttributes(const QTestElement* element, QTestElementAttribute *attribute) const
{
QTestCharBuffer buf;
while (attribute) {
@@ -215,7 +215,7 @@ void QTestXunitStreamer::outputElementAttributes(const QTestElement* element, QT
}
}
-void QTestXunitStreamer::outputString(const char *msg) const
+void QTestJUnitStreamer::outputString(const char *msg) const
{
testLogger->outputString(msg);
}
diff --git a/src/testlib/qtestxunitstreamer_p.h b/src/testlib/qtestjunitstreamer_p.h
index db6d2896f7..7d91e2b66c 100644
--- a/src/testlib/qtestxunitstreamer_p.h
+++ b/src/testlib/qtestjunitstreamer_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QTESTXUNITSTREAMER_P_H
-#define QTESTXUNITSTREAMER_P_H
+#ifndef QTESTJUNITSTREAMER_P_H
+#define QTESTJUNITSTREAMER_P_H
//
// W A R N I N G
@@ -58,14 +58,14 @@ QT_BEGIN_NAMESPACE
class QTestElement;
class QTestElementAttribute;
-class QXunitTestLogger;
+class QJUnitTestLogger;
struct QTestCharBuffer;
-class QTestXunitStreamer
+class QTestJUnitStreamer
{
public:
- QTestXunitStreamer(QXunitTestLogger *logger);
- ~QTestXunitStreamer();
+ QTestJUnitStreamer(QJUnitTestLogger *logger);
+ ~QTestJUnitStreamer();
void formatStart(const QTestElement *element, QTestCharBuffer *formatted) const;
void formatEnd(const QTestElement *element, QTestCharBuffer *formatted) const;
@@ -78,10 +78,9 @@ class QTestXunitStreamer
void outputString(const char *msg) const;
private:
- void displayXunitXmlHeader() const;
static void indentForElement(const QTestElement* element, char* buf, int size);
- QXunitTestLogger *testLogger;
+ QJUnitTestLogger *testLogger;
};
QT_END_NAMESPACE
diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp
index 2776740784..7bd108ab00 100644
--- a/src/testlib/qtestlog.cpp
+++ b/src/testlib/qtestlog.cpp
@@ -44,7 +44,7 @@
#include <QtTest/private/qabstracttestlogger_p.h>
#include <QtTest/private/qplaintestlogger_p.h>
#include <QtTest/private/qcsvbenchmarklogger_p.h>
-#include <QtTest/private/qxunittestlogger_p.h>
+#include <QtTest/private/qjunittestlogger_p.h>
#include <QtTest/private/qxmltestlogger_p.h>
#include <QtTest/private/qteamcitylogger_p.h>
#include <QtTest/private/qtaptestlogger_p.h>
@@ -456,8 +456,8 @@ void QTestLog::addLogger(LogMode mode, const char *filename)
case QTestLog::LightXML:
logger = new QXmlTestLogger(QXmlTestLogger::Light, filename);
break;
- case QTestLog::XunitXML:
- logger = new QXunitTestLogger(filename);
+ case QTestLog::JUnitXML:
+ logger = new QJUnitTestLogger(filename);
break;
case QTestLog::TeamCity:
logger = new QTeamCityLogger(filename);
@@ -597,4 +597,6 @@ qint64 QTestLog::nsecsFunctionTime()
return elapsedFunctionTime.nsecsElapsed();
}
+#include "moc_qtestlog_p.cpp"
+
QT_END_NAMESPACE
diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h
index fff36f290d..ddaf14ed9b 100644
--- a/src/testlib/qtestlog_p.h
+++ b/src/testlib/qtestlog_p.h
@@ -57,6 +57,8 @@
#include <QtCore/private/qcore_mac_p.h>
#endif
+#include <QtCore/qobjectdefs.h>
+
QT_BEGIN_NAMESPACE
class QBenchmarkResult;
@@ -65,13 +67,14 @@ class QTestData;
class Q_TESTLIB_EXPORT QTestLog
{
+ Q_GADGET
public:
QTestLog() = delete;
~QTestLog() = delete;
Q_DISABLE_COPY_MOVE(QTestLog)
enum LogMode {
- Plain = 0, XML, LightXML, XunitXML, CSV, TeamCity, TAP
+ Plain = 0, XML, LightXML, JUnitXML, CSV, TeamCity, TAP
#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
, Apple
#endif
@@ -79,6 +82,7 @@ public:
, XCTest
#endif
};
+ Q_ENUM(LogMode);
static void enterTestFunction(const char* function);
static void leaveTestFunction();
diff --git a/src/testlib/qtestutil_macos.mm b/src/testlib/qtestutil_macos.mm
index 7579c3b164..880cd0f91f 100644
--- a/src/testlib/qtestutil_macos.mm
+++ b/src/testlib/qtestutil_macos.mm
@@ -39,6 +39,8 @@
#include "qtestutil_macos_p.h"
+#include "QtCore/private/qcore_mac_p.h"
+
#import <AppKit/AppKit.h>
QT_BEGIN_NAMESPACE
@@ -55,6 +57,32 @@ namespace QTestPrivate {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"ApplePersistenceIgnoreState"];
}
+ bool macCrashReporterWillShowDialog()
+ {
+ auto dialogType = QCFType<CFStringRef>(CFPreferencesCopyAppValue(
+ CFSTR("DialogType"), CFSTR("com.apple.CrashReporter")));
+
+ auto stringCompare = [](CFStringRef str1, CFStringRef str2) -> bool {
+ return CFStringCompare(str1, str2, kCFCompareCaseInsensitive) == kCFCompareEqualTo;
+ };
+
+ if (!dialogType || stringCompare(dialogType, CFSTR("basic"))) {
+ // The default (basic) dialog type only shows up if the
+ // application is 'user visible', as indicated by the
+ // activation policy.
+ auto *runningApp = NSRunningApplication.currentApplication;
+ return runningApp && runningApp.activationPolicy == NSApplicationActivationPolicyRegular;
+ } else if (stringCompare(dialogType, CFSTR("developer"))
+ || stringCompare(dialogType, CFSTR("crashreport"))) {
+ // While in developer mode the dialog will show for all
+ // crashed applications, including backgrounded ones.
+ return true;
+ } else {
+ // Finally, 'server' or 'none' will result in no dialog
+ return false;
+ }
+ }
+
/*! \internal
\class AppNapDisabler
\brief Disables App Nap by registereing a bacground activity.
diff --git a/src/testlib/qtestutil_macos_p.h b/src/testlib/qtestutil_macos_p.h
index 36f27167c0..c9a152dfdb 100644
--- a/src/testlib/qtestutil_macos_p.h
+++ b/src/testlib/qtestutil_macos_p.h
@@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE
namespace QTestPrivate {
void disableWindowRestore();
+ bool macCrashReporterWillShowDialog();
class AppNapDisabler
{
diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro
index 530bc6b425..787df6b648 100644
--- a/src/testlib/testlib.pro
+++ b/src/testlib/testlib.pro
@@ -51,10 +51,10 @@ HEADERS = \
qtestblacklist_p.h \
qtesthelpers_p.h \
qttestglobal.h \
- qtestxunitstreamer_p.h \
+ qtestjunitstreamer_p.h \
qtaptestlogger_p.h \
qxmltestlogger_p.h \
- qxunittestlogger_p.h
+ qjunittestlogger_p.h
SOURCES = \
qtestcase.cpp \
@@ -77,8 +77,8 @@ SOURCES = \
qtestelement.cpp \
qtestelementattribute.cpp \
qtestmouse.cpp \
- qtestxunitstreamer.cpp \
- qxunittestlogger.cpp \
+ qtestjunitstreamer.cpp \
+ qjunittestlogger.cpp \
qtestblacklist.cpp \
qtaptestlogger.cpp
@@ -112,7 +112,7 @@ mac {
macos {
HEADERS += qtestutil_macos_p.h
OBJECTIVE_SOURCES += qtestutil_macos.mm
- LIBS += -framework Foundation -framework ApplicationServices -framework IOKit
+ LIBS += -framework Foundation -framework ApplicationServices -framework IOKit -framework AppKit
}
# XCTest support (disabled for now)
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp
index 9912539a84..91fe4bd37b 100644
--- a/src/tools/androiddeployqt/main.cpp
+++ b/src/tools/androiddeployqt/main.cpp
@@ -421,7 +421,7 @@ Options parseOptions()
options.buildAAB = true;
options.build = true;
options.jarSigner = true;
- } else if (options.buildAAB && argument.compare(QLatin1String("--no-build"), Qt::CaseInsensitive) == 0) {
+ } else if (!options.buildAAB && argument.compare(QLatin1String("--no-build"), Qt::CaseInsensitive) == 0) {
options.build = false;
} else if (argument.compare(QLatin1String("--install"), Qt::CaseInsensitive) == 0) {
options.installApk = true;
@@ -2308,7 +2308,8 @@ static bool mergeGradleProperties(const QString &path, GradleProperties properti
bool buildAndroidProject(const Options &options)
{
GradleProperties localProperties;
- localProperties["sdk.dir"] = options.sdkPath.toLocal8Bit();
+ localProperties["sdk.dir"] = options.sdkPath.toUtf8();
+ localProperties["ndk.dir"] = options.ndkPath.toUtf8();
if (!mergeGradleProperties(options.outputDirectory + QLatin1String("local.properties"), localProperties))
return false;
diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp
index 5290abf9f6..58ed210d3b 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.cpp
+++ b/src/tools/uic/cpp/cppwriteinitialization.cpp
@@ -1174,7 +1174,7 @@ void WriteInitialization::writeProperties(const QString &varName,
m_output << m_indent << "if (" << varName << "->objectName().isEmpty())\n";
break;
case Language::Python:
- m_output << m_indent << "if " << varName << ".objectName():\n";
+ m_output << m_indent << "if not " << varName << ".objectName():\n";
break;
}
}
diff --git a/src/tools/uic/python/pythonwriteimports.cpp b/src/tools/uic/python/pythonwriteimports.cpp
index 963244d450..d33b4c6210 100644
--- a/src/tools/uic/python/pythonwriteimports.cpp
+++ b/src/tools/uic/python/pythonwriteimports.cpp
@@ -39,11 +39,11 @@
QT_BEGIN_NAMESPACE
static const char *standardImports =
-R"I(from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint,
- QRect, QSize, QUrl, Qt)
+R"I(from PySide2.QtCore import (QCoreApplication, QDate, QDateTime, QMetaObject,
+ QObject, QPoint, QRect, QSize, QTime, QUrl, Qt)
from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont,
- QFontDatabase, QIcon, QLinearGradient, QPalette, QPainter, QPixmap,
- QRadialGradient)
+ QFontDatabase, QIcon, QKeySequence, QLinearGradient, QPalette, QPainter,
+ QPixmap, QRadialGradient)
from PySide2.QtWidgets import *
)I";
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp
index a723c3a955..d516b1b312 100644
--- a/src/widgets/dialogs/qfilesystemmodel.cpp
+++ b/src/widgets/dialogs/qfilesystemmodel.cpp
@@ -797,7 +797,7 @@ QString QFileSystemModelPrivate::time(const QModelIndex &index) const
if (!index.isValid())
return QString();
#if QT_CONFIG(datestring)
- return node(index)->lastModified().toString(Qt::SystemLocaleDate);
+ return QLocale::system().toString(node(index)->lastModified(), QLocale::ShortFormat);
#else
Q_UNUSED(index);
return QString();
diff --git a/src/widgets/dialogs/qinputdialog.cpp b/src/widgets/dialogs/qinputdialog.cpp
index 1cb4be0682..eeb0613d79 100644
--- a/src/widgets/dialogs/qinputdialog.cpp
+++ b/src/widgets/dialogs/qinputdialog.cpp
@@ -1349,6 +1349,7 @@ int QInputDialog::getInt(QWidget *parent, const QString &title, const QString &l
\sa getText(), getDouble(), getItem(), getMultiLineText()
*/
+#if QT_DEPRECATED_SINCE(5, 15)
/*!
Static convenience function to get a floating point number from the user.
@@ -1380,7 +1381,7 @@ double QInputDialog::getDouble(QWidget *parent, const QString &title, const QStr
{
return QInputDialog::getDouble(parent, title, label, value, min, max, decimals, ok, flags, 1.0);
}
-
+#endif
/*!
\overload
Static convenience function to get a floating point number from the user.
diff --git a/src/widgets/dialogs/qinputdialog.h b/src/widgets/dialogs/qinputdialog.h
index c3a5e59d53..ca893172f9 100644
--- a/src/widgets/dialogs/qinputdialog.h
+++ b/src/widgets/dialogs/qinputdialog.h
@@ -176,13 +176,24 @@ public:
static int getInt(QWidget *parent, const QString &title, const QString &label, int value = 0,
int minValue = -2147483647, int maxValue = 2147483647,
int step = 1, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
+
+#if QT_DEPRECATED_SINCE(5, 15)
+ QT_DEPRECATED_X("This overload is deprecated. Use the overload that takes step as a final argument")
static double getDouble(QWidget *parent, const QString &title, const QString &label, double value = 0,
double minValue = -2147483647, double maxValue = 2147483647,
int decimals = 1, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
+#endif
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ static double getDouble(QWidget *parent, const QString &title, const QString &label, double value = 0,
+ double minValue = -2147483647, double maxValue = 2147483647,
+ int decimals = 1, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags(),
+ double step = 1);
+#else
// ### Qt 6: merge overloads
static double getDouble(QWidget *parent, const QString &title, const QString &label, double value,
double minValue, double maxValue, int decimals, bool *ok, Qt::WindowFlags flags,
double step);
+#endif
#if QT_DEPRECATED_SINCE(5, 0)
QT_DEPRECATED static inline int getInteger(QWidget *parent, const QString &title, const QString &label, int value = 0,
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index 26f5a3baf2..db5c53a48a 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -2326,12 +2326,17 @@ void QGraphicsItem::setCursor(const QCursor &cursor)
view->viewport()->setMouseTracking(true);
// Note: Some of this logic is duplicated in QGraphicsView's mouse events.
if (view->underMouse()) {
- const auto itemsUnderCursor = view->items(view->mapFromGlobal(QCursor::pos()));
- for (QGraphicsItem *itemUnderCursor : itemsUnderCursor) {
- if (itemUnderCursor->hasCursor()) {
- QMetaObject::invokeMethod(view, "_q_setViewportCursor",
- Q_ARG(QCursor, itemUnderCursor->cursor()));
- break;
+ const QPoint viewPoint = view->mapFromGlobal(QCursor::pos());
+ const QPointF cursorPos = mapFromScene(view->mapToScene(viewPoint));
+ // the cursor can only change if the current item is under the mouse
+ if (boundingRect().contains(cursorPos)) {
+ const auto itemsUnderCursor = view->items(viewPoint);
+ for (QGraphicsItem *itemUnderCursor : itemsUnderCursor) {
+ if (itemUnderCursor->hasCursor()) {
+ QMetaObject::invokeMethod(view, "_q_setViewportCursor",
+ Q_ARG(QCursor, itemUnderCursor->cursor()));
+ break;
+ }
}
}
break;
diff --git a/src/widgets/itemviews/qdirmodel.cpp b/src/widgets/itemviews/qdirmodel.cpp
index 0d387d7def..8d1538a213 100644
--- a/src/widgets/itemviews/qdirmodel.cpp
+++ b/src/widgets/itemviews/qdirmodel.cpp
@@ -1321,7 +1321,7 @@ QString QDirModelPrivate::type(const QModelIndex &index) const
QString QDirModelPrivate::time(const QModelIndex &index) const
{
#if QT_CONFIG(datestring)
- return node(index)->info.lastModified().toString(Qt::LocalDate);
+ return QLocale::system().toString(node(index)->info.lastModified(), QLocale::ShortFormat);
#else
Q_UNUSED(index);
return QString();
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 25ca732c9e..397fb345c2 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -2347,7 +2347,9 @@ QWidget *QWidget::find(WId id)
*/
WId QWidget::winId() const
{
- if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
+ if (!data->in_destructor
+ && (!testAttribute(Qt::WA_WState_Created) || !internalWinId()))
+ {
#ifdef ALIEN_DEBUG
qDebug() << "QWidget::winId: creating native window for" << this;
#endif
@@ -6306,7 +6308,7 @@ void QWidget::setFocus(Qt::FocusReason reason)
previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
if (previousProxyFocus && previousProxyFocus->focusProxy())
previousProxyFocus = previousProxyFocus->focusProxy();
- if (previousProxyFocus == this && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
+ if (previousProxyFocus == f && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
return;
}
}
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index 1e5830d216..f4a53c9dfe 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -1350,6 +1350,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
QRect ir = btn->rect;
QStyleOptionButton newBtn = *btn;
newBtn.rect = QRect(ir.right() - mbi + 2, ir.height()/2 - mbi/2 + 3, mbi - 6, mbi - 6);
+ newBtn.rect = visualRect(btn->direction, br, newBtn.rect);
proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
}
}
@@ -1378,7 +1379,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
int iconSpacing = 4;//### 4 is currently hardcoded in QPushButton::sizeHint()
if (!button->text.isEmpty()) {
int textWidth = button->fontMetrics.boundingRect(opt->rect, tf, button->text).width();
- labelWidth += (textWidth + iconSpacing);
+ labelWidth += (textWidth + iconSpacing * 2);
}
QRect iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
@@ -2465,6 +2466,12 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
r = visualRect(opt->direction, opt->rect, r);
}
break;
+ case SE_PushButtonBevel:
+ {
+ r = opt->rect;
+ r = visualRect(opt->direction, opt->rect, r);
+ }
+ break;
case SE_CheckBoxIndicator:
{
int h = proxy()->pixelMetric(PM_IndicatorHeight, opt, widget);
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index c4bc52aa87..2b59e5736b 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -2416,7 +2416,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
QStyle::State oldState = static_cast<QStyle::State>(qvariant_cast<QStyle::State::Int>(styleObject->property("_q_stylestate")));
uint oldActiveControls = styleObject->property("_q_stylecontrols").toUInt();
- // a scrollbar is transient when the the scrollbar itself and
+ // a scrollbar is transient when the scrollbar itself and
// its sibling are both inactive (ie. not pressed/hovered/moved)
bool transient = !option->activeSubControls && !(option->state & State_On);
diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp
index 1110cc3323..4ac0a11a36 100644
--- a/src/widgets/styles/qstyle.cpp
+++ b/src/widgets/styles/qstyle.cpp
@@ -1011,6 +1011,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value SE_PushButtonFocusRect Area for the focus rect (usually
larger than the contents rect).
\value SE_PushButtonLayoutItem Area that counts for the parent layout.
+ \value SE_PushButtonBevel Area used for the bevel of the button.
\value SE_CheckBoxIndicator Area for the state indicator (e.g., check mark).
\value SE_CheckBoxContents Area for the label (text or pixmap).
@@ -1119,6 +1120,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\header \li Sub Element \li QStyleOption Subclass
\row \li \l SE_PushButtonContents \li \l QStyleOptionButton
\row \li \l SE_PushButtonFocusRect \li \l QStyleOptionButton
+ \row \li \l SE_PushButtonBevel \li \l QStyleOptionButton
\row \li \l SE_CheckBoxIndicator \li \l QStyleOptionButton
\row \li \l SE_CheckBoxContents \li \l QStyleOptionButton
\row \li \l SE_CheckBoxFocusRect \li \l QStyleOptionButton
diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h
index b51bcbe8d6..f37604e0fa 100644
--- a/src/widgets/styles/qstyle.h
+++ b/src/widgets/styles/qstyle.h
@@ -355,6 +355,8 @@ public:
SE_TabBarScrollRightButton,
SE_TabBarTearIndicatorRight,
+ SE_PushButtonBevel,
+
// do not add any values below/greater than this
SE_CustomBase = 0xf0000000
};
diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp
index 5a2ca2f2e7..bf365585d4 100644
--- a/src/widgets/styles/qstyleoption.cpp
+++ b/src/widgets/styles/qstyleoption.cpp
@@ -1646,7 +1646,7 @@ QStyleOptionProgressBar::QStyleOptionProgressBar(int version)
the default orentation is Qt::Horizontal
\deprecated
- Use the QStyle::State_Horizontal flag instead (in the the QStyleOption::state member).
+ Use the QStyle::State_Horizontal flag instead (in the QStyleOption::state member).
\sa QProgressBar::orientation
*/
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index 105eba370a..8eb24d7557 100644
--- a/src/widgets/styles/qwindowsstyle.cpp
+++ b/src/widgets/styles/qwindowsstyle.cpp
@@ -2136,7 +2136,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
#if QT_CONFIG(combobox)
case CC_ComboBox:
if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
- QBrush editBrush = cmb->palette.brush(QPalette::Base);
+ QBrush editBrush = cmb->palette.brush(QPalette::Button);
if ((cmb->subControls & SC_ComboBoxFrame)) {
if (cmb->frame) {
QPalette shadePal = opt->palette;
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp
index b249608ccc..3cfa213245 100644
--- a/src/widgets/widgets/qcombobox.cpp
+++ b/src/widgets/widgets/qcombobox.cpp
@@ -940,6 +940,8 @@ QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const
changes either through user interaction or programmatically. The
item's \a index is passed or -1 if the combobox becomes empty or the
currentIndex was reset.
+
+ \obsolete Use currentIndexChanged(int index, const QString &text) instead
*/
/*!
@@ -949,6 +951,18 @@ QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const
This signal is sent whenever the currentIndex in the combobox
changes either through user interaction or programmatically. The
item's \a text is passed.
+
+ \obsolete Use currentIndexChanged(int index, const QString &text) instead
+*/
+
+/*!
+ \fn void QComboBox::currentIndexChanged(int index, const QString &text)
+ \since 5.15
+
+ This signal is sent whenever the currentIndex in the combobox
+ changes either through user interaction or programmatically. The
+ item's \a index is passed or -1 if the combobox becomes empty or
+ the currentIndex was reset. The item's \a text is also passed.
*/
/*!
@@ -1421,13 +1435,14 @@ void QComboBoxPrivate::_q_emitCurrentIndexChanged(const QModelIndex &index)
{
Q_Q(QComboBox);
const QString text = itemText(index);
- emit q->currentIndexChanged(index.row());
-#if QT_DEPRECATED_SINCE(5, 13)
+#if QT_DEPRECATED_SINCE(5, 15)
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
+ emit q->currentIndexChanged(index.row());
emit q->currentIndexChanged(text);
QT_WARNING_POP
#endif
+ emit q->currentIndexChanged(index.row(), text);
// signal lineEdit.textChanged already connected to signal currentTextChanged, so don't emit double here
if (!lineEdit)
emit q->currentTextChanged(text);
@@ -3099,12 +3114,14 @@ void QComboBox::changeEvent(QEvent *e)
d->updateViewContainerPaletteAndOpacity();
break;
}
- case QEvent::FontChange:
+ case QEvent::FontChange: {
d->sizeHint = QSize(); // invalidate size hint
d->viewContainer()->setFont(font());
+ d->viewContainer()->itemView()->doItemsLayout();
if (d->lineEdit)
d->updateLineEditGeometry();
break;
+ }
default:
break;
}
diff --git a/src/widgets/widgets/qcombobox.h b/src/widgets/widgets/qcombobox.h
index 19bdf39233..56386a4b8c 100644
--- a/src/widgets/widgets/qcombobox.h
+++ b/src/widgets/widgets/qcombobox.h
@@ -230,8 +230,13 @@ Q_SIGNALS:
void textActivated(const QString &);
void highlighted(int index);
void textHighlighted(const QString &);
+#if QT_DEPRECATED_SINCE(5, 15)
+ QT_DEPRECATED_VERSION_X_5_15("Use currentIndexChanged(int, const QString &) instead")
void currentIndexChanged(int index);
+ QT_DEPRECATED_VERSION_X_5_15("Use currentIndexChanged(int, const QString &) instead")
void currentIndexChanged(const QString &);
+#endif
+ void currentIndexChanged(int index, const QString &text);
void currentTextChanged(const QString &);
protected:
diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp
index 147ab9b855..a0b5bdd39f 100644
--- a/src/widgets/widgets/qlabel.cpp
+++ b/src/widgets/widgets/qlabel.cpp
@@ -226,7 +226,7 @@ const QPicture *QLabel::picture() const
\endcode
*/
-QPicture QLabel::picture(Qt::ReturnByValue_t) const
+QPicture QLabel::picture(Qt::ReturnByValueConstant) const
{
Q_D(const QLabel);
if (d->picture)
@@ -442,7 +442,7 @@ const QPixmap *QLabel::pixmap() const
/*!
\since 5.15
*/
-QPixmap QLabel::pixmap(Qt::ReturnByValue_t) const
+QPixmap QLabel::pixmap(Qt::ReturnByValueConstant) const
{
Q_D(const QLabel);
if (d->pixmap)
diff --git a/src/widgets/widgets/qlabel.h b/src/widgets/widgets/qlabel.h
index 288022a71e..c9552efd8a 100644
--- a/src/widgets/widgets/qlabel.h
+++ b/src/widgets/widgets/qlabel.h
@@ -77,9 +77,9 @@ public:
QT_DEPRECATED_VERSION_X(5, 15, "Use the other overload which returns QPixmap by-value")
const QPixmap *pixmap() const; // ### Qt 7: Remove function
- QPixmap pixmap(Qt::ReturnByValue_t) const;
+ QPixmap pixmap(Qt::ReturnByValueConstant) const;
#else
- QPixmap pixmap(Qt::ReturnByValue_t = Qt::ReturnByValue) const; // ### Qt 7: Remove arg
+ QPixmap pixmap(Qt::ReturnByValueConstant = Qt::ReturnByValue) const; // ### Qt 7: Remove arg
#endif // QT_DEPRECATED_SINCE(5,15)
#ifndef QT_NO_PICTURE
@@ -87,9 +87,9 @@ public:
QT_DEPRECATED_VERSION_X(5, 15, "Use the other overload which returns QPicture by-value")
const QPicture *picture() const; // ### Qt 7: Remove function
- QPicture picture(Qt::ReturnByValue_t) const;
+ QPicture picture(Qt::ReturnByValueConstant) const;
# else
- QPicture picture(Qt::ReturnByValue_t = Qt::ReturnByValue) const; // ### Qt 7: Remove arg
+ QPicture picture(Qt::ReturnByValueConstant = Qt::ReturnByValue) const; // ### Qt 7: Remove arg
# endif // QT_DEPRECATED_SINCE(5,15)
#endif
#if QT_CONFIG(movie)
diff --git a/src/widgets/widgets/qpushbutton.cpp b/src/widgets/widgets/qpushbutton.cpp
index b0d3ba51f9..3d075bf92f 100644
--- a/src/widgets/widgets/qpushbutton.cpp
+++ b/src/widgets/widgets/qpushbutton.cpp
@@ -509,6 +509,17 @@ void QPushButton::focusOutEvent(QFocusEvent *e)
#endif
}
+/*!
+ \reimp
+*/
+bool QPushButton::hitButton(const QPoint &pos) const
+{
+ QStyleOptionButton option;
+ initStyleOption(&option);
+ const QRect bevel = style()->subElementRect(QStyle::SE_PushButtonBevel, &option, this);
+ return bevel.contains(pos);
+}
+
#if QT_CONFIG(menu)
/*!
Associates the popup menu \a menu with this push button. This
diff --git a/src/widgets/widgets/qpushbutton.h b/src/widgets/widgets/qpushbutton.h
index b02ba63d07..283dfe2c61 100644
--- a/src/widgets/widgets/qpushbutton.h
+++ b/src/widgets/widgets/qpushbutton.h
@@ -94,6 +94,7 @@ protected:
void focusInEvent(QFocusEvent *) override;
void focusOutEvent(QFocusEvent *) override;
void initStyleOption(QStyleOptionButton *option) const;
+ bool hitButton(const QPoint &pos) const override;
QPushButton(QPushButtonPrivate &dd, QWidget* parent = nullptr);
public:
diff --git a/src/widgets/widgets/qsizegrip.cpp b/src/widgets/widgets/qsizegrip.cpp
index 2a4b4a0ad4..95a4beeb57 100644
--- a/src/widgets/widgets/qsizegrip.cpp
+++ b/src/widgets/widgets/qsizegrip.cpp
@@ -260,6 +260,17 @@ void QSizeGrip::paintEvent(QPaintEvent *event)
parameter.
*/
+static Qt::Edges edgesFromCorner(Qt::Corner corner)
+{
+ switch (corner) {
+ case Qt::TopLeftCorner: return Qt::TopEdge | Qt::LeftEdge;
+ case Qt::TopRightCorner: return Qt::TopEdge | Qt::RightEdge;
+ case Qt::BottomLeftCorner: return Qt::BottomEdge | Qt::LeftEdge;
+ case Qt::BottomRightCorner: return Qt::BottomEdge | Qt::RightEdge;
+ }
+ return Qt::Edges{};
+}
+
void QSizeGrip::mousePressEvent(QMouseEvent * e)
{
if (e->button() != Qt::LeftButton) {
@@ -281,8 +292,9 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e)
&& !tlw->testAttribute(Qt::WA_DontShowOnScreen)
&& !tlw->hasHeightForWidth()) {
QPlatformWindow *platformWindow = tlw->windowHandle()->handle();
- const QPoint topLevelPos = mapTo(tlw, e->pos());
- d->m_platformSizeGrip = platformWindow && platformWindow->startSystemResize(topLevelPos, d->m_corner);
+ const Qt::Edges edges = edgesFromCorner(d->m_corner);
+ if (!QGuiApplication::platformName().contains(QStringLiteral("xcb"))) // ### FIXME QTBUG-69716
+ d->m_platformSizeGrip = platformWindow && platformWindow->startSystemResize(edges);
}
if (d->m_platformSizeGrip)
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp
index 913ca6ec16..8ddda78f7d 100644
--- a/src/widgets/widgets/qtextedit.cpp
+++ b/src/widgets/widgets/qtextedit.cpp
@@ -1272,6 +1272,7 @@ QString QTextEdit::toHtml() const
The default is \c MarkdownDialectGitHub.
\sa plainText, html, QTextDocument::toMarkdown(), QTextDocument::setMarkdown()
+ \since 5.14
*/
#endif