summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config.tests/unix/cups/cups.cpp4
-rwxr-xr-xconfigure127
-rw-r--r--dist/changes-5.3.017
-rw-r--r--doc/global/qt-cpp-defines.qdocconf2
-rw-r--r--examples/gui/analogclock/main.cpp2
-rw-r--r--examples/network/dnslookup/dnslookup.cpp171
-rw-r--r--examples/network/dnslookup/dnslookup.h20
-rw-r--r--examples/opengl/contextinfo/renderwindow.cpp9
-rw-r--r--examples/opengl/contextinfo/widget.cpp41
-rw-r--r--examples/opengl/contextinfo/widget.h4
-rw-r--r--examples/opengl/cube/mainwidget.cpp7
-rw-r--r--examples/widgets/mainwindows/application/mainwindow.cpp11
-rw-r--r--mkspecs/android-g++/qmake.conf10
-rw-r--r--mkspecs/common/winrt_winphone/manifests/8.0/AppxManifest.xml.in4
-rw-r--r--mkspecs/common/winrt_winphone/manifests/8.0/WMAppManifest.xml.in3
-rw-r--r--mkspecs/common/winrt_winphone/manifests/8.1/AppxManifest.xml.in4
-rw-r--r--mkspecs/features/qt_common.prf1
-rw-r--r--mkspecs/features/qt_plugin.prf17
-rw-r--r--mkspecs/features/testcase.prf22
-rw-r--r--mkspecs/features/unix/separate_debug_info.prf2
-rw-r--r--mkspecs/features/winrt/package_manifest.prf33
-rw-r--r--mkspecs/macx-ios-clang/features/default_post.prf1
-rw-r--r--mkspecs/win32-msvc2005/qmake.conf1
-rw-r--r--mkspecs/win32-msvc2008/qmake.conf1
-rw-r--r--mkspecs/win32-msvc2010/qmake.conf1
-rw-r--r--mkspecs/win32-msvc2012/qmake.conf1
-rw-r--r--mkspecs/win32-msvc2013/qmake.conf1
-rw-r--r--mkspecs/winphone-arm-msvc2012/qmake.conf4
-rw-r--r--mkspecs/winphone-x86-msvc2012/qmake.conf4
-rw-r--r--qmake/doc/snippets/qmake/qtconfiguration.pro2
-rw-r--r--qmake/doc/src/qmake-manual.qdoc7
-rw-r--r--qmake/generators/win32/msvc_nmake.cpp5
-rw-r--r--qmake/library/qmakebuiltins.cpp12
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp169
-rw-r--r--src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro134
-rw-r--r--src/3rdparty/harfbuzz-ng/src/config.h17
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-coretext.cc46
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-coretext.h8
-rw-r--r--src/3rdparty/harfbuzz.pri121
-rw-r--r--src/3rdparty/harfbuzzng.pri6
-rw-r--r--src/3rdparty/sqlite/shell.c344
-rw-r--r--src/3rdparty/sqlite/sqlite3.c13910
-rw-r--r--src/3rdparty/sqlite/sqlite3.h100
-rw-r--r--src/3rdparty/xkbcommon.pri34
-rw-r--r--src/3rdparty/xkbcommon/NEWS86
-rw-r--r--src/3rdparty/xkbcommon/README47
-rw-r--r--src/3rdparty/xkbcommon/src/atom.c137
-rw-r--r--src/3rdparty/xkbcommon/src/atom.h7
-rw-r--r--src/3rdparty/xkbcommon/src/context-priv.c171
-rw-r--r--src/3rdparty/xkbcommon/src/context.c179
-rw-r--r--src/3rdparty/xkbcommon/src/context.h62
-rw-r--r--src/3rdparty/xkbcommon/src/keymap-priv.c121
-rw-r--r--src/3rdparty/xkbcommon/src/keymap.h29
-rw-r--r--src/3rdparty/xkbcommon/src/keysym-utf.c13
-rw-r--r--src/3rdparty/xkbcommon/src/keysym.c56
-rw-r--r--src/3rdparty/xkbcommon/src/keysym.h6
-rw-r--r--src/3rdparty/xkbcommon/src/ks_tables.h11765
-rw-r--r--src/3rdparty/xkbcommon/src/state.c20
-rw-r--r--src/3rdparty/xkbcommon/src/text.c8
-rw-r--r--src/3rdparty/xkbcommon/src/utils.c107
-rw-r--r--src/3rdparty/xkbcommon/src/utils.h95
-rw-r--r--src/3rdparty/xkbcommon/src/x11/util.c215
-rw-r--r--src/3rdparty/xkbcommon/src/x11/x11-keymap.c1146
-rw-r--r--src/3rdparty/xkbcommon/src/x11/x11-priv.h54
-rw-r--r--src/3rdparty/xkbcommon/src/x11/x11-state.c71
-rw-r--r--src/3rdparty/xkbcommon/src/xkb-keymap.c135
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/action.c91
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/ast-build.c318
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/ast-build.h58
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/ast.h124
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/compat.c61
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/expr.c170
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/include.c36
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/keycodes.c29
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/keymap-dump.c22
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/keymap.c30
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/keywords.c349
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/parser-priv.h15
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/parser.c738
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/parser.h18
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/rules.c243
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/scanner-utils.h145
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/scanner.c2982
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/symbols.c122
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/types.c13
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp-priv.h12
-rw-r--r--src/3rdparty/xkbcommon/src/xkbcomp/xkbcomp.c38
-rw-r--r--src/3rdparty/xkbcommon/xkbcommon/xkbcommon-keysyms.h8
-rw-r--r--src/3rdparty/xkbcommon/xkbcommon/xkbcommon-names.h1
-rw-r--r--src/3rdparty/xkbcommon/xkbcommon/xkbcommon-x11.h166
-rw-r--r--src/3rdparty/xkbcommon/xkbcommon/xkbcommon.h187
-rw-r--r--src/3rdparty/xkbcommon/xkbcommon/xkbcommon_workaround.h105
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java2
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java3
-rw-r--r--src/android/java/java.pro14
-rw-r--r--src/android/java/res/layout/splash.xml2
-rw-r--r--src/angle/patches/0014-ANGLE-D3D11-Fix-internal-index-buffer-for-level-9-ha.patch256
-rw-r--r--src/angle/src/d3dcompiler/main.cpp48
-rw-r--r--src/concurrent/doc/src/qtconcurrent-module.qdoc14
-rw-r--r--src/concurrent/qtconcurrentiteratekernel.h2
-rw-r--r--src/corelib/arch/qatomic_armv6.h16
-rw-r--r--src/corelib/doc/qtcore.qdocconf3
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_thread_qthread.cpp7
-rw-r--r--src/corelib/global/qglobal.cpp4
-rw-r--r--src/corelib/global/qglobal.h7
-rw-r--r--src/corelib/global/qlibraryinfo.cpp4
-rw-r--r--src/corelib/global/qlogging.cpp12
-rw-r--r--src/corelib/global/qnamespace.h2
-rw-r--r--src/corelib/global/qnamespace.qdoc3
-rw-r--r--src/corelib/io/io.pri2
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp48
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp14
-rw-r--r--src/corelib/io/qfilesystemwatcher_inotify.cpp9
-rw-r--r--src/corelib/io/qloggingregistry.cpp11
-rw-r--r--src/corelib/io/qloggingregistry_p.h1
-rw-r--r--src/corelib/io/qprocess.cpp6
-rw-r--r--src/corelib/io/qprocess_p.h5
-rw-r--r--src/corelib/io/qprocess_unix.cpp85
-rw-r--r--src/corelib/io/qsettings.cpp13
-rw-r--r--src/corelib/io/qstandardpaths_winrt.cpp1
-rw-r--r--src/corelib/kernel/qcore_unix.cpp43
-rw-r--r--src/corelib/kernel/qcore_unix_p.h8
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp11
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h2
-rw-r--r--src/corelib/kernel/qjni.cpp16
-rw-r--r--src/corelib/kernel/qmetatype.h7
-rw-r--r--src/corelib/kernel/qobject_impl.h2
-rw-r--r--src/corelib/kernel/qtcore_eval.cpp2
-rw-r--r--src/corelib/tools/qcommandlineparser.cpp72
-rw-r--r--src/corelib/tools/qhash.h24
-rw-r--r--src/corelib/tools/qlist.h9
-rw-r--r--src/corelib/tools/qmap.h9
-rw-r--r--src/corelib/tools/qmargins.cpp12
-rw-r--r--src/corelib/tools/qrect.cpp4
-rw-r--r--src/corelib/tools/qregexp.cpp4
-rw-r--r--src/corelib/tools/qsharedpointer.cpp8
-rw-r--r--src/corelib/tools/qsharedpointer.h2
-rw-r--r--src/corelib/tools/qstring.h11
-rw-r--r--src/corelib/tools/qstringbuilder.h8
-rw-r--r--src/corelib/tools/qtimezoneprivate_mac.mm1
-rw-r--r--src/corelib/tools/qvector.h9
-rw-r--r--src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp2
-rw-r--r--src/gui/image/qjpeghandler.cpp1
-rw-r--r--src/gui/kernel/qevent.cpp10
-rw-r--r--src/gui/kernel/qguiapplication.cpp12
-rw-r--r--src/gui/kernel/qopenglcontext.cpp9
-rw-r--r--src/gui/kernel/qplatformtheme.h1
-rw-r--r--src/gui/kernel/qsurfaceformat.cpp12
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp477
-rw-r--r--src/gui/opengl/qopenglshaderprogram.cpp6
-rw-r--r--src/gui/opengl/qopengltextureblitter.cpp14
-rw-r--r--src/gui/opengl/qopengltextureglyphcache.cpp12
-rw-r--r--src/gui/painting/painting.pri4
-rw-r--r--src/gui/painting/qdrawhelper.cpp83
-rw-r--r--src/gui/painting/qdrawhelper_sse2.cpp7
-rw-r--r--src/gui/painting/qdrawhelper_x86_p.h3
-rw-r--r--src/gui/painting/qpagedpaintdevice.cpp273
-rw-r--r--src/gui/painting/qpagedpaintdevice.h160
-rw-r--r--src/gui/painting/qpagedpaintdevice_p.h10
-rw-r--r--src/gui/painting/qpagelayout.cpp971
-rw-r--r--src/gui/painting/qpagelayout.h155
-rw-r--r--src/gui/painting/qpagesize.cpp1882
-rw-r--r--src/gui/painting/qpagesize.h311
-rw-r--r--src/gui/painting/qpaintengine_blitter.cpp3
-rw-r--r--src/gui/painting/qpainter.cpp2
-rw-r--r--src/gui/painting/qpdf.cpp104
-rw-r--r--src/gui/painting/qpdf_p.h39
-rw-r--r--src/gui/painting/qpdfwriter.cpp231
-rw-r--r--src/gui/painting/qpdfwriter.h12
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp40
-rw-r--r--src/gui/painting/qregion.cpp2
-rw-r--r--src/gui/text/qcssparser_p.h2
-rw-r--r--src/gui/text/qfontdatabase.cpp91
-rw-r--r--src/gui/text/qfontengine_ft.cpp9
-rw-r--r--src/gui/text/qplatformfontdatabase.cpp32
-rw-r--r--src/gui/text/qplatformfontdatabase.h2
-rw-r--r--src/gui/text/qstatictext.cpp3
-rw-r--r--src/gui/text/qtextengine.cpp4
-rw-r--r--src/gui/text/text.pri2
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp4
-rw-r--r--src/network/access/qhttpnetworkreply.cpp4
-rw-r--r--src/network/access/qhttpnetworkrequest.cpp2
-rw-r--r--src/network/access/qnetworkreplynsurlconnectionimpl.mm1
-rw-r--r--src/network/kernel/qauthenticator.cpp11
-rw-r--r--src/network/socket/qlocalserver_tcp.cpp2
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp66
-rw-r--r--src/network/socket/qnativesocketengine_winrt.cpp4
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp10
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp3
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager_p.h1
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadersource_p.h5
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp17
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h9
-rw-r--r--src/opengl/qgl.cpp22
-rw-r--r--src/opengl/qglfunctions.cpp338
-rw-r--r--src/opengl/qglshaderprogram.cpp6
-rw-r--r--src/platformsupport/cglconvenience/cglconvenience.mm11
-rw-r--r--src/platformsupport/eglconvenience/eglconvenience.pri37
-rw-r--r--src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp1
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp189
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h1
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm49
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h1
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm31
-rw-r--r--src/plugins/bearer/corewlan/qcorewlanengine.mm2
-rw-r--r--src/plugins/bearer/corewlan/qcorewlanengine_10_6.mm2
-rw-r--r--src/plugins/platforminputcontexts/compose/compose.pro8
-rw-r--r--src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp20
-rw-r--r--src/plugins/platforminputcontexts/platforminputcontexts.pro5
-rw-r--r--src/plugins/platforms/android/androidjniinput.cpp27
-rw-r--r--src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp12
-rw-r--r--src/plugins/platforms/android/qandroidassetsfileenginehandler.h5
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp86
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.h7
-rw-r--r--src/plugins/platforms/android/qandroidplatformbackingstore.cpp21
-rw-r--r--src/plugins/platforms/android/qandroidplatformbackingstore.h3
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp3
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm157
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm28
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.mm18
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm22
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm6
-rw-r--r--src/plugins/platforms/cocoa/qcocoakeymapper.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoakeymapper.mm5
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm9
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm10
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.h9
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm23
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintdevice.h129
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintdevice.mm502
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintersupport.h10
-rw-r--r--src/plugins/platforms/cocoa/qcocoaprintersupport.mm104
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemsettings.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h15
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm92
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm12
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac.mm40
-rw-r--r--src/plugins/platforms/cocoa/qprintengine_mac.mm521
-rw-r--r--src/plugins/platforms/cocoa/qprintengine_mac_p.h26
-rw-r--r--src/plugins/platforms/cocoa/qt_mac_p.h2
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp51
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm62
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm4
-rw-r--r--src/plugins/platforms/ios/quiview_textinput.mm13
-rw-r--r--src/plugins/platforms/qnx/qblackberrytheme.cpp6
-rw-r--r--src/plugins/platforms/qnx/qqnxeglwindow.cpp5
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp2
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventthread.cpp6
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp18
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp13
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h1
-rw-r--r--src/plugins/platforms/winrt/qwinrtbackingstore.cpp32
-rw-r--r--src/plugins/platforms/winrt/qwinrtbackingstore.h2
-rw-r--r--src/plugins/platforms/winrt/qwinrtfontdatabase.cpp314
-rw-r--r--src/plugins/platforms/winrt/qwinrtfontdatabase.h19
-rw-r--r--src/plugins/platforms/winrt/qwinrtservices.cpp3
-rw-r--r--src/plugins/platforms/winrt/winrt.pro5
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp15
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp20
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp3
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp12
-rw-r--r--src/plugins/platforms/xcb/xcb-plugin.pro5
-rw-r--r--src/plugins/printsupport/cups/cups.pro4
-rw-r--r--src/plugins/printsupport/cups/qcupsprintengine.cpp328
-rw-r--r--src/plugins/printsupport/cups/qcupsprintengine_p.h16
-rw-r--r--src/plugins/printsupport/cups/qcupsprintersupport.cpp109
-rw-r--r--src/plugins/printsupport/cups/qcupsprintersupport_p.h37
-rw-r--r--src/plugins/printsupport/cups/qppdprintdevice.cpp503
-rw-r--r--src/plugins/printsupport/cups/qppdprintdevice.h124
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintdevice.cpp480
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintdevice.h114
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintersupport.cpp45
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintersupport.h14
-rw-r--r--src/plugins/printsupport/windows/windows.pro6
-rw-r--r--src/printsupport/dialogs/qpagesetupdialog_unix.cpp701
-rw-r--r--src/printsupport/dialogs/qpagesetupdialog_unix_p.h48
-rw-r--r--src/printsupport/dialogs/qpagesetupdialog_win.cpp52
-rw-r--r--src/printsupport/dialogs/qpagesetupwidget.ui14
-rw-r--r--src/printsupport/dialogs/qprintdialog_mac.mm44
-rw-r--r--src/printsupport/dialogs/qprintdialog_unix.cpp167
-rw-r--r--src/printsupport/kernel/kernel.pri5
-rw-r--r--src/printsupport/kernel/qcups.cpp481
-rw-r--r--src/printsupport/kernel/qcups_p.h68
-rw-r--r--src/printsupport/kernel/qpaintengine_alpha.cpp1
-rw-r--r--src/printsupport/kernel/qplatformprintdevice.cpp393
-rw-r--r--src/printsupport/kernel/qplatformprintdevice.h182
-rw-r--r--src/printsupport/kernel/qplatformprintersupport.cpp85
-rw-r--r--src/printsupport/kernel/qplatformprintersupport.h26
-rw-r--r--src/printsupport/kernel/qprint_p.h304
-rw-r--r--src/printsupport/kernel/qprintdevice.cpp255
-rw-r--r--src/printsupport/kernel/qprintdevice_p.h149
-rw-r--r--src/printsupport/kernel/qprintengine.h5
-rw-r--r--src/printsupport/kernel/qprintengine_pdf.cpp164
-rw-r--r--src/printsupport/kernel/qprintengine_pdf_p.h18
-rw-r--r--src/printsupport/kernel/qprintengine_win.cpp993
-rw-r--r--src/printsupport/kernel/qprintengine_win_p.h60
-rw-r--r--src/printsupport/kernel/qprinter.cpp713
-rw-r--r--src/printsupport/kernel/qprinter.h167
-rw-r--r--src/printsupport/kernel/qprinter_p.h5
-rw-r--r--src/printsupport/kernel/qprinterinfo.cpp255
-rw-r--r--src/printsupport/kernel/qprinterinfo.h27
-rw-r--r--src/printsupport/kernel/qprinterinfo_p.h23
-rw-r--r--src/printsupport/widgets/qcupsjobwidget.cpp4
-rw-r--r--src/printsupport/widgets/qcupsjobwidget_p.h4
-rw-r--r--src/sql/drivers/ibase/qsql_ibase.cpp35
-rw-r--r--src/sql/kernel/qsqlresult.cpp13
-rw-r--r--src/src.pro12
-rw-r--r--src/testlib/qtestcase.cpp11
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.cpp6
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp72
-rw-r--r--src/widgets/dialogs/qfiledialog_p.h2
-rw-r--r--src/widgets/dialogs/qmessagebox.cpp2
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp10
-rw-r--r--src/widgets/kernel/qapplication.cpp7
-rw-r--r--src/widgets/kernel/qapplication_qpa.cpp2
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp2
-rw-r--r--src/widgets/kernel/qtooltip.cpp23
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp6
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp14
-rw-r--r--src/widgets/kernel/qwidgetwindow_qpa_p.h1
-rw-r--r--src/widgets/styles/qcommonstyle.cpp8
-rw-r--r--src/widgets/styles/qfusionstyle.cpp196
-rw-r--r--src/widgets/styles/qgtkstyle.cpp19
-rw-r--r--src/widgets/styles/qgtkstyle_p.cpp256
-rw-r--r--src/widgets/styles/qgtkstyle_p_p.h61
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm28
-rw-r--r--src/widgets/styles/qstyle.cpp6
-rw-r--r--src/widgets/styles/qstyle_p.h4
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp8
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp13
-rw-r--r--src/widgets/styles/qwindowsxpstyle.cpp21
-rw-r--r--src/widgets/styles/qwindowsxpstyle_p_p.h1
-rw-r--r--src/widgets/widgets/qabstractscrollarea.cpp56
-rw-r--r--src/widgets/widgets/qcombobox.cpp2
-rw-r--r--src/widgets/widgets/qlineedit_p.cpp12
-rw-r--r--src/widgets/widgets/qlineedit_p.h3
-rw-r--r--src/widgets/widgets/qmainwindow.cpp14
-rw-r--r--src/widgets/widgets/qmenu.cpp22
-rw-r--r--src/widgets/widgets/qmenu_p.h4
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp11
-rw-r--r--src/widgets/widgets/qplaintextedit.h1
-rw-r--r--src/widgets/widgets/qtoolbarlayout.cpp37
-rw-r--r--src/widgets/widgets/qtoolbarlayout_p.h1
-rw-r--r--src/winmain/qtmain_winrt.cpp25
-rw-r--r--tests/auto/corelib/io/qfile/tst_qfile.cpp12
-rw-r--r--tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp4
-rw-r--r--tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp12
-rw-r--r--tests/auto/corelib/io/qresourceengine/qresourceengine.pro9
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp8
-rw-r--r--tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp1
-rw-r--r--tests/auto/corelib/tools/qchar/qchar.pro2
-rw-r--r--tests/auto/corelib/tools/qmessageauthenticationcode/qmessageauthenticationcode.pro1
-rw-r--r--tests/auto/gui/kernel/qwindow/tst_qwindow.cpp51
-rw-r--r--tests/auto/gui/painting/painting.pro3
-rw-r--r--tests/auto/gui/painting/qpagelayout/.gitignore1
-rw-r--r--tests/auto/gui/painting/qpagelayout/qpagelayout.pro9
-rw-r--r--tests/auto/gui/painting/qpagelayout/tst_qpagelayout.cpp277
-rw-r--r--tests/auto/gui/painting/qpagesize/.gitignore1
-rw-r--r--tests/auto/gui/painting/qpagesize/qpagesize.pro9
-rw-r--r--tests/auto/gui/painting/qpagesize/tst_qpagesize.cpp258
-rw-r--r--tests/auto/gui/painting/qpdfwriter/.gitignore1
-rw-r--r--tests/auto/gui/painting/qpdfwriter/qpdfwriter.pro9
-rw-r--r--tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp265
-rw-r--r--tests/auto/gui/qopengl/tst_qopengl.cpp38
-rw-r--r--tests/auto/gui/text/qstatictext/tst_qstatictext.cpp28
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp122
-rw-r--r--tests/auto/network/kernel/qauthenticator/tst_qauthenticator.cpp2
-rw-r--r--tests/auto/opengl/qgl/tst_qgl.cpp40
-rw-r--r--tests/auto/other/d3dcompiler/tst_d3dcompiler.cpp18
-rw-r--r--tests/auto/other/gestures/tst_gestures.cpp2
-rw-r--r--tests/auto/other/macgui/tst_macgui.cpp2
-rw-r--r--tests/auto/other/macnativeevents/tst_macnativeevents.cpp2
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp47
-rw-r--r--tests/auto/printsupport/kernel/kernel.pro1
-rw-r--r--tests/auto/printsupport/kernel/qprintdevice/.gitignore1
-rw-r--r--tests/auto/printsupport/kernel/qprintdevice/qprintdevice.pro9
-rw-r--r--tests/auto/printsupport/kernel/qprintdevice/tst_qprintdevice.cpp111
-rw-r--r--tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp462
-rw-r--r--tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp94
-rw-r--r--tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp23
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp93
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp2
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp31
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp2
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/qabstractitemview.pro1
-rw-r--r--tests/auto/widgets/itemviews/qcolumnview/qcolumnview.pro1
-rw-r--r--tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp3
-rw-r--r--tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp32
-rw-r--r--tests/auto/widgets/util/qscroller/tst_qscroller.cpp2
-rw-r--r--tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp9
-rw-r--r--tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp4
-rw-r--r--tests/manual/manual.pro1
-rw-r--r--tests/manual/qopenglwidget/openglwidget/openglwidget.cpp9
-rw-r--r--tests/manual/qpainfo/main.cpp232
-rw-r--r--tests/manual/qpainfo/qpainfo.pro7
-rw-r--r--tests/manual/qprintdevice_dump/main.cpp181
-rw-r--r--tests/manual/qprintdevice_dump/qprintdevice_dump.pro6
411 files changed, 34270 insertions, 21840 deletions
diff --git a/config.tests/unix/cups/cups.cpp b/config.tests/unix/cups/cups.cpp
index bd8e85a7ce..9170b4003c 100644
--- a/config.tests/unix/cups/cups.cpp
+++ b/config.tests/unix/cups/cups.cpp
@@ -43,7 +43,7 @@
int main(int, char **)
{
- cups_dest_t *d;
- cupsGetDests(&d);
+ // CUPS 1.4 test
+ cupsGetNamedDest(CUPS_HTTP_DEFAULT, NULL, NULL);
return 0;
}
diff --git a/configure b/configure
index 1c1af57451..96273193a6 100755
--- a/configure
+++ b/configure
@@ -671,7 +671,6 @@ CFG_LARGEFILE=auto
CFG_OPENSSL=auto
CFG_PRECOMPILE=auto
CFG_SEPARATE_DEBUG_INFO=no
-CFG_SEPARATE_DEBUG_INFO_NOCOPY=no
CFG_REDUCE_EXPORTS=auto
CFG_SSE2=auto
CFG_SSE3=auto
@@ -1493,9 +1492,6 @@ while [ "$#" -gt 0 ]; do
separate-debug-info)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
CFG_SEPARATE_DEBUG_INFO="$VAL"
- elif [ "$VAL" = "nocopy" ] ; then
- CFG_SEPARATE_DEBUG_INFO="yes"
- CFG_SEPARATE_DEBUG_INFO_NOCOPY="yes"
else
UNKNOWN_OPT=yes
fi
@@ -3172,7 +3168,7 @@ if [ "$XPLATFORM_MAC" = "no" -a "$CFG_DEBUG_RELEASE" = "yes" ]; then
echo
fi
-if [ "$CFG_XCB" != "no" ] && [ "$CFG_XKBCOMMON" = "no" ]; then
+if ( [ "$CFG_XCB" = "system" ] || [ "$CFG_XCB" = "qt" ] ) && [ "$CFG_XKBCOMMON" = "no" ]; then
echo "Error: -no-xkbcommon is not supported on XCB platform plugin."
exit 101
fi
@@ -3376,9 +3372,10 @@ if [ "$XPLATFORM_IOS" = "yes" ]; then
fi
fi
-# disable GTK style support auto-detection on Mac
-if [ "$XPLATFORM_MAC" = "yes" ] && [ "$CFG_QGTKSTYLE" = "auto" ]; then
- CFG_QGTKSTYLE=no
+# disable XCB and GTK support auto-detection on Mac
+if [ "$XPLATFORM_MAC" = "yes" ]; then
+ [ "$CFG_XCB" = "auto" ] && CFG_XCB=no
+ [ "$CFG_QGTKSTYLE" = "auto" ] && CFG_QGTKSTYLE=no
fi
QMAKE_CONF_COMPILER=`getXQMakeConf QMAKE_CXX`
@@ -3441,21 +3438,21 @@ if [ "$CFG_PRECOMPILE" = "auto" ]; then
fi
# auto-detect support for separate debug info in objcopy
-if [ "$CFG_SEPARATE_DEBUG_INFO" != "no" ] && [ "$CFG_SHARED" = "yes" ]; then
+if [ "$CFG_SEPARATE_DEBUG_INFO" = "yes" ]; then
+ if [ "$CFG_SHARED" = "no" ]; then
+ echo "ERROR: -separate-debug-info is incompatible with -static"
+ exit 1
+ fi
+ if [ "$CFG_DEBUG" = "no" -a "$CFG_DEBUG_RELEASE" = "no" -a "$CFG_FORCEDEBUGINFO" = "no" ]; then
+ echo "ERROR: -separate-debug-info needs -debug, -debug-and-release, or -force-debug-info"
+ exit 1
+ fi
TEST_OBJCOPY=`getXQMakeConf QMAKE_OBJCOPY`
COMPILER_WITH_FLAGS="$TEST_COMPILER $TEST_COMPILER_CXXFLAGS"
if "$unixtests/objcopy.test" "$COMPILER_WITH_FLAGS" "$TEST_OBJCOPY" "$OPT_VERBOSE"; then
- CFG_SEPARATE_DEBUG_INFO=no
- else
- case "$PLATFORM" in
- hpux-*)
- # binutils on HP-UX is buggy; default to no.
- CFG_SEPARATE_DEBUG_INFO=no
- ;;
- *)
- CFG_SEPARATE_DEBUG_INFO=yes
- ;;
- esac
+ echo "ERROR: -separate-debug-info was requested but this binutils does not support it."
+ echo "Re-run configure with -v for more information"
+ exit 1
fi
fi
@@ -5213,26 +5210,30 @@ if [ "$CFG_XCB" != "no" ]; then
fi
QMakeVar set QMAKE_X11_PREFIX "$QMAKE_X11_PREFIX"
- if compileTest qpa/xcb "xcb" $QMAKE_CFLAGS_XCB $QMAKE_LIBS_XCB; then
+ if [ "$CFG_XKBCOMMON" != no ] && compileTest qpa/xcb "xcb" $QMAKE_CFLAGS_XCB $QMAKE_LIBS_XCB; then
+ QT_CONFIG="$QT_CONFIG xcb-plugin"
if [ "$CFG_XCB" = "qt" ]; then
QT_CONFIG="$QT_CONFIG xcb-qt"
else
CFG_XCB="system"
-
if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xcb >= 1.5" 2>/dev/null; then
XCB_PACKAGES="xcb xcb-shm xcb-sync xcb-xfixes xcb-randr xcb-image xcb-keysyms xcb-icccm xcb-shape"
QMAKE_CFLAGS_XCB="`$PKG_CONFIG --cflags $XCB_PACKAGES 2>/dev/null`"
QMAKE_LIBS_XCB="`$PKG_CONFIG --libs $XCB_PACKAGES 2>/dev/null`"
- # for xcb-xkb tests
+ fi
+
+ # libxcb version 1.10 was the first version that enables xcb-xkb by default,
+ # therefore the minimal xcb-xkb version we support is 1.10
+ CFG_XKB=no
+ if $PKG_CONFIG --exists "xcb-xkb >= 1.10" 2>/dev/null; then
QMAKE_CFLAGS_XKB="`$PKG_CONFIG --cflags xcb xcb-xkb 2>/dev/null`"
QMAKE_LIBS_XKB="`$PKG_CONFIG --libs xcb xcb-xkb 2>/dev/null`"
+ if compileTest qpa/xcb-xkb "xcb-xkb" $QMAKE_CFLAGS_XKB $QMAKE_LIBS_XKB; then
+ CFG_XKB=yes
+ fi
fi
-
- if compileTest qpa/xcb-xkb "xcb-xkb" $QMAKE_CFLAGS_XKB $QMAKE_LIBS_XKB; then
- CFG_XKB=yes
- else
- CFG_XKB=no
+ if [ "$CFG_XKB" = "no" ]; then
QMakeVar add DEFINES QT_NO_XKB
fi
@@ -5328,52 +5329,45 @@ fi
# Detect libxkbcommon
ORIG_CFG_XKBCOMMON="$CFG_XKBCOMMON"
-if [ "$CFG_XKBCOMMON" != "qt" ]; then
- # currently only xcb platform plugin requires xkbcommon, for other platforms it can be set to 'no'
- if [ "$CFG_XKBCOMMON" != "no" ]; then
- if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xkbcommon >= 0.2.0" 2>/dev/null; then
- QMAKE_CFLAGS_XKBCOMMON="`$PKG_CONFIG --cflags xkbcommon 2>/dev/null`"
- QMAKE_LIBS_XKBCOMMON="`$PKG_CONFIG --libs xkbcommon 2>/dev/null`"
- QMAKE_VERSION_XKBCOMMON="`$PKG_CONFIG --modversion xkbcommon 2>/dev/null`"
+# currently only xcb platform plugin supports building xkbcommon
+if [ "$CFG_XCB" != "no" ]; then
+ if [ "$CFG_XKBCOMMON" = "auto" ] || [ "$CFG_XKBCOMMON" = "system" ]; then
+ if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xkbcommon xkbcommon-x11 >= 0.4.0" 2>/dev/null; then
+ QMAKE_CFLAGS_XKBCOMMON="`$PKG_CONFIG --cflags xkbcommon xkbcommon-x11 2>/dev/null`"
+ QMAKE_LIBS_XKBCOMMON="`$PKG_CONFIG --libs xkbcommon xkbcommon-x11 2>/dev/null`"
QMakeVar set QMAKE_CFLAGS_XKBCOMMON "$QMAKE_CFLAGS_XKBCOMMON"
QMakeVar set QMAKE_LIBS_XKBCOMMON "$QMAKE_LIBS_XKBCOMMON"
- QMakeVar set QMAKE_VERSION_XKBCOMMON "$QMAKE_VERSION_XKBCOMMON"
CFG_XKBCOMMON=system
else
- CFG_XKBCOMMON=no
- fi
-
- if [ "$CFG_XCB" != "no" ] && [ "$CFG_XKBCOMMON" = "no" ]; then
# use the bundled version instead
CFG_XKBCOMMON=qt
fi
fi
-fi
-
-if [ "$CFG_XKBCOMMON" = "qt" ]; then
- QT_CONFIG="$QT_CONFIG xkbcommon-qt"
- # detect XKB config root
- if [ "$CFG_XKB_CONFIG_ROOT" = "auto" ]; then
- if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xkeyboard-config" 2> /dev/null; then
- CFG_XKB_CONFIG_ROOT="`$PKG_CONFIG --variable=xkb_base xkeyboard-config`"
- else
- # search for xkb configs in most probable locations
- if [ -d "/usr/share/X11/xkb" ]; then
- # Linux
- CFG_XKB_CONFIG_ROOT="/usr/share/X11/xkb"
- elif [ -d "/usr/local/share/X11/xkb" ]; then
- # BSD UNIX
- CFG_XKB_CONFIG_ROOT="/usr/local/share/X11/xkb"
+ if [ "$CFG_XKBCOMMON" = "qt" ]; then
+ QT_CONFIG="$QT_CONFIG xkbcommon-qt"
+ # detect XKB config root
+ if [ "$CFG_XKB_CONFIG_ROOT" = "auto" ]; then
+ if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "xkeyboard-config" 2> /dev/null; then
+ CFG_XKB_CONFIG_ROOT="`$PKG_CONFIG --variable=xkb_base xkeyboard-config`"
+ else
+ # search for xkb configs in most probable locations
+ if [ -d "/usr/share/X11/xkb" ]; then
+ # Linux
+ CFG_XKB_CONFIG_ROOT="/usr/share/X11/xkb"
+ elif [ -d "/usr/local/share/X11/xkb" ]; then
+ # BSD UNIX
+ CFG_XKB_CONFIG_ROOT="/usr/local/share/X11/xkb"
+ fi
fi
fi
+ QMakeVar set QMAKE_XKB_CONFIG_ROOT "$CFG_XKB_CONFIG_ROOT"
+ if [ "$CFG_XKB_CONFIG_ROOT" = "auto" ]; then
+ CFG_XKB_CONFIG_ROOT="not found"
+ fi
fi
- QMakeVar set QMAKE_XKB_CONFIG_ROOT "$CFG_XKB_CONFIG_ROOT"
- if [ "$CFG_XKB_CONFIG_ROOT" = "auto" ]; then
- CFG_XKB_CONFIG_ROOT="not found"
- fi
-elif [ "$CFG_XKBCOMMON" = "no" ]; then
- QMakeVar add DEFINES QT_NO_XKBCOMMON
+else
+ CFG_XKBCOMMON=no
fi
# EGL Support
@@ -5411,7 +5405,7 @@ if [ "$CFG_EGL" != "no" ]; then
fi
if [ "$CFG_EGLFS" != "no" ]; then
- if [ "$XPLATFORM_QNX" = "no" ]; then
+ if [ "$XPLATFORM_QNX" = "no" ] && [ "$CFG_OPENGL" != "no" ]; then
CFG_EGLFS="$CFG_EGL"
else
CFG_EGLFS="no"
@@ -5842,13 +5836,8 @@ fi
[ "$CFG_STRIP" = "no" ] && QMAKE_CONFIG="$QMAKE_CONFIG nostrip"
[ "$CFG_PRECOMPILE" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG precompile_header"
if [ "$CFG_SEPARATE_DEBUG_INFO" = "yes" ]; then
- QMakeVar add QMAKE_CFLAGS -g
- QMakeVar add QMAKE_CXXFLAGS -g
QT_CONFIG="$QT_CONFIG separate_debug_info"
fi
-if [ "$CFG_SEPARATE_DEBUG_INFO_NOCOPY" = "yes" ] ; then
- QT_CONFIG="$QT_CONFIG separate_debug_info_nocopy"
-fi
[ "$CFG_SSE2" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse2"
[ "$CFG_SSE3" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse3"
[ "$CFG_SSSE3" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG ssse3"
@@ -6852,7 +6841,7 @@ if [ "$CFG_OPENSSL" = "linked" ] && [ "$OPENSSL_LIBS" = "" ]; then
echo
fi
if [ "$ORIG_CFG_XKBCOMMON" != qt ] && [ "$CFG_XKBCOMMON" = qt ]; then
- echo "NOTE: libxkbcommon 0.2.0 (or higher) not found on the system, will use "
+ echo "NOTE: libxkbcommon and libxkbcommon-x11 0.4.0 or higher not found on the system, will use "
echo "the bundled version from 3rd party directory."
fi
if [ "$CFG_XKBCOMMON" = "qt" ] && [ "$CFG_XKB_CONFIG_ROOT" = "not found" ]; then
diff --git a/dist/changes-5.3.0 b/dist/changes-5.3.0
index 35fc9cabb0..cb2c3608f0 100644
--- a/dist/changes-5.3.0
+++ b/dist/changes-5.3.0
@@ -16,6 +16,14 @@ Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
+* Platform deprecation notice *
+****************************************************************************
+
+ - The support for deployment on OS X 10.6 (Snow Leopard) is deprecated
+ in Qt 5.3, and will be removed in Qt 5.4. The platform is currently
+ not tested, and most likely has issues that are not fully documented.
+
+****************************************************************************
* Library *
****************************************************************************
@@ -34,3 +42,12 @@ QtGui
- Added setSwapInterval() to QSurfaceFormat. Platforms that support
setting the swap interval are now defaulting to the value of 1,
meaning vsync is enabled.
+
+QtSql
+-----
+
+ - QSqlQuery::isNull(field) now correctly returns true for "no such field".
+ - QSqlQuery::isNull(fieldname) is a new overload.
+ - QSQLITE: Empty database name now opens in-memory database.
+ - QSqlError: Now handles alphanumeric error codes. Used by QPSQL.
+ Old numeric code is deprecated.
diff --git a/doc/global/qt-cpp-defines.qdocconf b/doc/global/qt-cpp-defines.qdocconf
index b2205f54ac..351bd4312b 100644
--- a/doc/global/qt-cpp-defines.qdocconf
+++ b/doc/global/qt-cpp-defines.qdocconf
@@ -130,6 +130,8 @@ Cpp.ignoredirectives += \
Q_DECLARE_SHARED \
Q_DECLARE_TR_FUNCTIONS \
Q_DECLARE_TYPEINFO \
+ Q_DECL_NOEXCEPT_EXPR \
+ QT_DEPRECATED_X \
Q_DISABLE_COPY \
Q_DUMMY_COMPARISON_OPERATOR \
Q_ENUMS \
diff --git a/examples/gui/analogclock/main.cpp b/examples/gui/analogclock/main.cpp
index e33aba83fd..1e10fcd07b 100644
--- a/examples/gui/analogclock/main.cpp
+++ b/examples/gui/analogclock/main.cpp
@@ -156,5 +156,5 @@ int main(int argc, char **argv)
AnalogClockWindow clock;
clock.show();
- app.exec();
+ return app.exec();
}
diff --git a/examples/network/dnslookup/dnslookup.cpp b/examples/network/dnslookup/dnslookup.cpp
index 202a5f9580..003a3e3028 100644
--- a/examples/network/dnslookup/dnslookup.cpp
+++ b/examples/network/dnslookup/dnslookup.cpp
@@ -45,71 +45,114 @@
#include <QHostAddress>
#include <QStringList>
#include <QTimer>
+#include <QCommandLineParser>
+#include <QCommandLineOption>
#include <stdio.h>
-static void usage() {
- printf("Qt DNS example - performs DNS lookups\n"
- "Usage: dnslookup [-t <type>] [-s nameserver] name\n\n");
+static int typeFromParameter(const QString &type)
+{
+ if (type == "a")
+ return QDnsLookup::A;
+ if (type == "aaaa")
+ return QDnsLookup::AAAA;
+ if (type == "any")
+ return QDnsLookup::ANY;
+ if (type == "cname")
+ return QDnsLookup::CNAME;
+ if (type == "mx")
+ return QDnsLookup::MX;
+ if (type == "ns")
+ return QDnsLookup::NS;
+ if (type == "ptr")
+ return QDnsLookup::PTR;
+ if (type == "srv")
+ return QDnsLookup::SRV;
+ if (type == "txt")
+ return QDnsLookup::TXT;
+ return -1;
}
-DnsManager::DnsManager()
+//! [0]
+
+enum CommandLineParseResult
{
- dns = new QDnsLookup(this);
- connect(dns, SIGNAL(finished()), this, SLOT(showResults()));
-}
+ CommandLineOk,
+ CommandLineError,
+ CommandLineVersionRequested,
+ CommandLineHelpRequested
+};
-void DnsManager::execute()
+CommandLineParseResult parseCommandLine(QCommandLineParser &parser, DnsQuery *query, QString *errorMessage)
{
- QStringList args = QCoreApplication::instance()->arguments();
- args.takeFirst();
+ parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
+ const QCommandLineOption nameServerOption("n", "The name server to use.", "nameserver");
+ parser.addOption(nameServerOption);
+ const QCommandLineOption typeOption("t", "The lookup type.", "type");
+ parser.addOption(typeOption);
+ parser.addPositionalArgument("name", "The name to look up.");
+ const QCommandLineOption helpOption = parser.addHelpOption();
+ const QCommandLineOption versionOption = parser.addVersionOption();
+
+ if (!parser.parse(QCoreApplication::arguments())) {
+ *errorMessage = parser.errorText();
+ return CommandLineError;
+ }
- // lookup type
- dns->setType(QDnsLookup::A);
- if (args.size() > 1 && args.first() == "-t") {
- args.takeFirst();
- const QString type = args.takeFirst().toLower();
- if (type == "a")
- dns->setType(QDnsLookup::A);
- else if (type == "aaaa")
- dns->setType(QDnsLookup::AAAA);
- else if (type == "any")
- dns->setType(QDnsLookup::ANY);
- else if (type == "cname")
- dns->setType(QDnsLookup::CNAME);
- else if (type == "mx")
- dns->setType(QDnsLookup::MX);
- else if (type == "ns")
- dns->setType(QDnsLookup::NS);
- else if (type == "ptr")
- dns->setType(QDnsLookup::PTR);
- else if (type == "srv")
- dns->setType(QDnsLookup::SRV);
- else if (type == "txt")
- dns->setType(QDnsLookup::TXT);
- else {
- printf("Bad record type: %s\n", qPrintable(type));
- QCoreApplication::instance()->quit();
- return;
+ if (parser.isSet(versionOption))
+ return CommandLineVersionRequested;
+
+ if (parser.isSet(helpOption))
+ return CommandLineHelpRequested;
+
+ if (parser.isSet(nameServerOption)) {
+ const QString nameserver = parser.value(nameServerOption);
+ query->nameServer = QHostAddress(nameserver);
+ if (query->nameServer.isNull() || query->nameServer.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
+ *errorMessage = "Bad nameserver address: " + nameserver;
+ return CommandLineError;
}
}
- if (args.size() > 1 && args.first() == "-s") {
- args.takeFirst();
- const QString ns = args.takeFirst();
- QHostAddress nameserver(ns);
- if (nameserver.isNull() || nameserver.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
- printf("Bad nameserver address: %s\n", qPrintable(ns));
- QCoreApplication::instance()->quit();
- return;
+
+ if (parser.isSet(typeOption)) {
+ const QString typeParameter = parser.value(typeOption);
+ const int type = typeFromParameter(typeParameter.toLower());
+ if (type < 0) {
+ *errorMessage = "Bad record type: " + typeParameter;
+ return CommandLineError;
}
- dns->setNameserver(nameserver);
+ query->type = static_cast<QDnsLookup::Type>(type);
}
- if (args.isEmpty()) {
- usage();
- QCoreApplication::instance()->quit();
- return;
+
+ const QStringList positionalArguments = parser.positionalArguments();
+ if (positionalArguments.isEmpty()) {
+ *errorMessage = "Argument 'name' missing.";
+ return CommandLineError;
+ }
+ if (positionalArguments.size() > 1) {
+ *errorMessage = "Several 'name' arguments specified.";
+ return CommandLineError;
}
- dns->setName(args.takeFirst());
+ query->name = positionalArguments.first();
+
+ return CommandLineOk;
+}
+
+//! [0]
+
+DnsManager::DnsManager()
+{
+ dns = new QDnsLookup(this);
+ connect(dns, SIGNAL(finished()), this, SLOT(showResults()));
+}
+
+void DnsManager::execute()
+{
+ // lookup type
+ dns->setType(query.type);
+ if (!query.nameServer.isNull())
+ dns->setNameserver(query.nameServer);
+ dns->setName(query.name);
dns->lookup();
}
@@ -159,7 +202,33 @@ int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
+//! [1]
+ QCoreApplication::setApplicationVersion(QT_VERSION_STR);
+ QCoreApplication::setApplicationName(QCoreApplication::translate("QDnsLookupExample", "DNS Lookup Example"));
+ QCommandLineParser parser;
+ parser.setApplicationDescription(QCoreApplication::translate("QDnsLookupExample", "An example demonstrating the class QDnsLookup."));
+ DnsQuery query;
+ QString errorMessage;
+ switch (parseCommandLine(parser, &query, &errorMessage)) {
+ case CommandLineOk:
+ break;
+ case CommandLineError:
+ fputs(qPrintable(errorMessage), stderr);
+ fputs("\n\n", stderr);
+ fputs(qPrintable(parser.helpText()), stderr);
+ return 1;
+ case CommandLineVersionRequested:
+ printf("%s %s\n", qPrintable(QCoreApplication::applicationName()),
+ qPrintable(QCoreApplication::applicationVersion()));
+ return 0;
+ case CommandLineHelpRequested:
+ parser.showHelp();
+ Q_UNREACHABLE();
+ }
+//! [1]
+
DnsManager manager;
+ manager.setQuery(query);
QTimer::singleShot(0, &manager, SLOT(execute()));
return app.exec();
diff --git a/examples/network/dnslookup/dnslookup.h b/examples/network/dnslookup/dnslookup.h
index d76756bad0..4d0232be8a 100644
--- a/examples/network/dnslookup/dnslookup.h
+++ b/examples/network/dnslookup/dnslookup.h
@@ -38,11 +38,21 @@
**
****************************************************************************/
-#include <QObject>
+#include <QDnsLookup>
+#include <QHostAddress>
-QT_BEGIN_NAMESPACE
-class QDnsLookup;
-QT_END_NAMESPACE
+//! [0]
+
+struct DnsQuery
+{
+ DnsQuery() : type(QDnsLookup::A) {}
+
+ QDnsLookup::Type type;
+ QHostAddress nameServer;
+ QString name;
+};
+
+//! [0]
class DnsManager : public QObject
{
@@ -50,6 +60,7 @@ class DnsManager : public QObject
public:
DnsManager();
+ void setQuery(const DnsQuery &q) { query = q; }
public slots:
void execute();
@@ -57,5 +68,6 @@ public slots:
private:
QDnsLookup *dns;
+ DnsQuery query;
};
diff --git a/examples/opengl/contextinfo/renderwindow.cpp b/examples/opengl/contextinfo/renderwindow.cpp
index 85fb19bd1a..af51de1d67 100644
--- a/examples/opengl/contextinfo/renderwindow.cpp
+++ b/examples/opengl/contextinfo/renderwindow.cpp
@@ -174,7 +174,7 @@ void RenderWindow::setupVertexAttribs()
void RenderWindow::render()
{
if (!m_context->makeCurrent(this)) {
- qWarning("makeCurrent() failed");
+ emit error(tr("makeCurrent() failed"));
return;
}
@@ -216,5 +216,10 @@ void RenderWindow::render()
m_context->swapBuffers(this);
m_angle += 1.0f;
- QTimer::singleShot(0, this, SLOT(render()));
+
+ // Instead of 0 wait a few more milliseconds before rendering again. This is
+ // only here to make the UI widgets more responsive on slower machines. We
+ // can afford it since our rendering is so lightweight.
+ const int interval = 5;
+ QTimer::singleShot(interval, this, SLOT(render()));
}
diff --git a/examples/opengl/contextinfo/widget.cpp b/examples/opengl/contextinfo/widget.cpp
index ff78639e24..4ab62ec2d2 100644
--- a/examples/opengl/contextinfo/widget.cpp
+++ b/examples/opengl/contextinfo/widget.cpp
@@ -275,6 +275,7 @@ void Widget::start()
addRenderWindow();
return;
}
+ m_surface = renderWindow;
renderWindow->setForceGLSL110(forceGLSL110);
connect(renderWindow, &RenderWindow::ready, this, &Widget::renderWindowReady);
@@ -284,12 +285,8 @@ void Widget::start()
addRenderWindow();
}
-void Widget::renderWindowReady()
+void Widget::printFormat(const QSurfaceFormat &format)
{
- QOpenGLContext *context = QOpenGLContext::currentContext();
- Q_ASSERT(context);
- const QSurfaceFormat format = context->format();
-
m_output->append(tr("OpenGL version: %1.%2").arg(format.majorVersion()).arg(format.minorVersion()));
for (size_t i = 0; i < sizeof(profiles) / sizeof(Profile); ++i)
@@ -310,6 +307,21 @@ void Widget::renderWindowReady()
break;
}
+ m_output->append(tr("Depth buffer size: %1").arg(QString::number(format.depthBufferSize())));
+ m_output->append(tr("Stencil buffer size: %1").arg(QString::number(format.stencilBufferSize())));
+ m_output->append(tr("Samples: %1").arg(QString::number(format.samples())));
+ m_output->append(tr("Red buffer size: %1").arg(QString::number(format.redBufferSize())));
+ m_output->append(tr("Green buffer size: %1").arg(QString::number(format.greenBufferSize())));
+ m_output->append(tr("Blue buffer size: %1").arg(QString::number(format.blueBufferSize())));
+ m_output->append(tr("Alpha buffer size: %1").arg(QString::number(format.alphaBufferSize())));
+ m_output->append(tr("Swap interval: %1").arg(QString::number(format.swapInterval())));
+}
+
+void Widget::renderWindowReady()
+{
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ Q_ASSERT(context);
+
QString vendor, renderer, version, glslVersion;
const GLubyte *p;
QOpenGLFunctions *f = context->functions();
@@ -322,22 +334,21 @@ void Widget::renderWindowReady()
if ((p = f->glGetString(GL_SHADING_LANGUAGE_VERSION)))
glslVersion = QString::fromLatin1(reinterpret_cast<const char *>(p));
- m_output->append(tr("\nVendor: %1").arg(vendor));
+ m_output->append(tr("*** Context information ***"));
+ m_output->append(tr("Vendor: %1").arg(vendor));
m_output->append(tr("Renderer: %1").arg(renderer));
m_output->append(tr("OpenGL version: %1").arg(version));
m_output->append(tr("GLSL version: %1").arg(glslVersion));
- m_output->append(tr("\nDepth buffer size: %1").arg(QString::number(format.depthBufferSize())));
- m_output->append(tr("Stencil buffer size: %1").arg(QString::number(format.stencilBufferSize())));
- m_output->append(tr("Samples: %1").arg(QString::number(format.samples())));
- m_output->append(tr("Red buffer size: %1").arg(QString::number(format.redBufferSize())));
- m_output->append(tr("Green buffer size: %1").arg(QString::number(format.greenBufferSize())));
- m_output->append(tr("Blue buffer size: %1").arg(QString::number(format.blueBufferSize())));
- m_output->append(tr("Alpha buffer size: %1").arg(QString::number(format.alphaBufferSize())));
- m_output->append(tr("Swap interval: %1").arg(QString::number(format.swapInterval())));
+ m_output->append(tr("\n*** QSurfaceFormat from context ***"));
+ printFormat(context->format());
+
+ m_output->append(tr("\n*** QSurfaceFormat from window surface ***"));
+ printFormat(m_surface->format());
+ m_output->append(tr("\n*** Qt build information ***"));
const char *gltype[] = { "Desktop", "GLES 2", "GLES 1" };
- m_output->append(tr("\nQt OpenGL configuration: %1")
+ m_output->append(tr("Qt OpenGL configuration: %1")
.arg(QString::fromLatin1(gltype[QOpenGLContext::openGLModuleType()])));
m_output->append(tr("Qt OpenGL library handle: %1")
.arg(QString::number(qintptr(QOpenGLContext::openGLModuleHandle()), 16)));
diff --git a/examples/opengl/contextinfo/widget.h b/examples/opengl/contextinfo/widget.h
index dcae66dac0..ad664178e4 100644
--- a/examples/opengl/contextinfo/widget.h
+++ b/examples/opengl/contextinfo/widget.h
@@ -46,6 +46,8 @@
QT_FORWARD_DECLARE_CLASS(QComboBox)
QT_FORWARD_DECLARE_CLASS(QTextEdit)
QT_FORWARD_DECLARE_CLASS(QVBoxLayout)
+QT_FORWARD_DECLARE_CLASS(QSurfaceFormat)
+QT_FORWARD_DECLARE_CLASS(QSurface)
class Widget : public QWidget
{
@@ -65,6 +67,7 @@ private:
void addOptions(QLayout *layout);
void addRenderableTypes(QLayout *layout);
void addRenderWindow();
+ void printFormat(const QSurfaceFormat &format);
QComboBox *m_version;
QLayout *m_profiles;
@@ -74,6 +77,7 @@ private:
QTextEdit *m_extensions;
QVBoxLayout *m_renderWindowLayout;
QWidget *m_renderWindowContainer;
+ QSurface *m_surface;
};
#endif // WIDGET_H
diff --git a/examples/opengl/cube/mainwidget.cpp b/examples/opengl/cube/mainwidget.cpp
index 8c87de6736..5c1cd28b54 100644
--- a/examples/opengl/cube/mainwidget.cpp
+++ b/examples/opengl/cube/mainwidget.cpp
@@ -43,7 +43,6 @@
#include <QMouseEvent>
#include <math.h>
-#include <locale.h>
MainWidget::MainWidget(QWidget *parent) :
QGLWidget(parent),
@@ -126,9 +125,6 @@ void MainWidget::initializeGL()
//! [3]
void MainWidget::initShaders()
{
- // Override system locale until shaders are compiled
- setlocale(LC_NUMERIC, "C");
-
// Compile vertex shader
if (!program.addShaderFromSourceFile(QGLShader::Vertex, ":/vshader.glsl"))
close();
@@ -144,9 +140,6 @@ void MainWidget::initShaders()
// Bind shader pipeline for use
if (!program.bind())
close();
-
- // Restore system locale
- setlocale(LC_ALL, "");
}
//! [3]
diff --git a/examples/widgets/mainwindows/application/mainwindow.cpp b/examples/widgets/mainwindows/application/mainwindow.cpp
index 8bdd0303de..a5a0def0a6 100644
--- a/examples/widgets/mainwindows/application/mainwindow.cpp
+++ b/examples/widgets/mainwindows/application/mainwindow.cpp
@@ -118,11 +118,16 @@ bool MainWindow::save()
bool MainWindow::saveAs()
//! [11] //! [12]
{
- QString fileName = QFileDialog::getSaveFileName(this);
- if (fileName.isEmpty())
+ QFileDialog dialog(this);
+ dialog.setWindowModality(Qt::WindowModal);
+ dialog.setAcceptMode(QFileDialog::AcceptSave);
+ dialog.exec();
+ QStringList files = dialog.selectedFiles();
+
+ if (files.isEmpty())
return false;
- return saveFile(fileName);
+ return saveFile(files.at(0));
}
//! [12]
diff --git a/mkspecs/android-g++/qmake.conf b/mkspecs/android-g++/qmake.conf
index e3fa924e23..732d415f9a 100644
--- a/mkspecs/android-g++/qmake.conf
+++ b/mkspecs/android-g++/qmake.conf
@@ -107,11 +107,15 @@ equals(ANDROID_TARGET_ARCH, x86) {
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = -g -gdwarf-2 -O2
QMAKE_CFLAGS_DEBUG = -g -gdwarf-2 -fno-omit-frame-pointer
} else { # arm
- QMAKE_CFLAGS_RELEASE = -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64
- QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = -g -gdwarf-2 -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64
+ QMAKE_CFLAGS_RELEASE = -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64
+ QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO = -g -gdwarf-2 -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64
QMAKE_CFLAGS_DEBUG = -g -gdwarf-2 -marm -O0 -fno-omit-frame-pointer
- equals(ANDROID_TARGET_ARCH, armeabi): equals(NDK_TOOLCHAIN_VERSION, 4.8): \
+ equals(ANDROID_TARGET_ARCH, armeabi): equals(NDK_TOOLCHAIN_VERSION, 4.8) {
DEFINES += QT_OS_ANDROID_GCC_48_WORKAROUND
+ } else {
+ QMAKE_CFLAGS_RELEASE += -mthumb
+ QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -mthumb
+ }
}
QMAKE_CFLAGS_SHLIB = -fPIC
diff --git a/mkspecs/common/winrt_winphone/manifests/8.0/AppxManifest.xml.in b/mkspecs/common/winrt_winphone/manifests/8.0/AppxManifest.xml.in
index 42bac8b8b1..6583bf0643 100644
--- a/mkspecs/common/winrt_winphone/manifests/8.0/AppxManifest.xml.in
+++ b/mkspecs/common/winrt_winphone/manifests/8.0/AppxManifest.xml.in
@@ -32,8 +32,6 @@
<SplashScreen Image=\"$${WINRT_MANIFEST.logo_splash}\" />
</VisualElements>
</Application>
- </Applications>
- <Capabilities>$${WINRT_MANIFEST.capabilities}</Capabilities>
- <Dependencies>$${WINRT_MANIFEST.dependencies}</Dependencies>
+ </Applications>$${WINRT_MANIFEST.capabilities}$${WINRT_MANIFEST.dependencies}
</Package>
<!-- Generated by qmake using the $$[QMAKE_XSPEC] mkspec. -->
diff --git a/mkspecs/common/winrt_winphone/manifests/8.0/WMAppManifest.xml.in b/mkspecs/common/winrt_winphone/manifests/8.0/WMAppManifest.xml.in
index 968f42fa06..5efb9c7b06 100644
--- a/mkspecs/common/winrt_winphone/manifests/8.0/WMAppManifest.xml.in
+++ b/mkspecs/common/winrt_winphone/manifests/8.0/WMAppManifest.xml.in
@@ -11,8 +11,7 @@
Description=\"$${WINRT_MANIFEST.description}\"
Publisher=\"$${WINRT_MANIFEST.publisher}\"
PublisherID=\"$${WINRT_MANIFEST.publisherid}\">
- <IconPath IsRelative=\"true\" IsResource=\"false\">$${WINRT_MANIFEST.logo_medium}</IconPath>
- <Capabilities>$${WINRT_MANIFEST.capabilities}</Capabilities>
+ <IconPath IsRelative=\"true\" IsResource=\"false\">$${WINRT_MANIFEST.logo_medium}</IconPath>$${WINRT_MANIFEST.capabilities}
<Tasks>
<DefaultTask
Name=\"_default\"
diff --git a/mkspecs/common/winrt_winphone/manifests/8.1/AppxManifest.xml.in b/mkspecs/common/winrt_winphone/manifests/8.1/AppxManifest.xml.in
index fcc4d75b0f..5587ace390 100644
--- a/mkspecs/common/winrt_winphone/manifests/8.1/AppxManifest.xml.in
+++ b/mkspecs/common/winrt_winphone/manifests/8.1/AppxManifest.xml.in
@@ -37,8 +37,6 @@
<v2:SplashScreen Image=\"$${WINRT_MANIFEST.logo_splash}\" />
</v2:VisualElements>
</Application>
- </Applications>
- <Capabilities>$${WINRT_MANIFEST.capabilities}</Capabilities>
- <Dependencies>$${WINRT_MANIFEST.dependencies}</Dependencies>
+ </Applications>$${WINRT_MANIFEST.capabilities}$${WINRT_MANIFEST.dependencies}
</Package>
<!-- Generated by qmake using the $$[QMAKE_XSPEC] mkspec. -->
diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf
index 051420e4f1..6cd848b405 100644
--- a/mkspecs/features/qt_common.prf
+++ b/mkspecs/features/qt_common.prf
@@ -19,7 +19,6 @@ contains(TEMPLATE, .*lib) {
unix:contains(QT_CONFIG, reduce_relocations): CONFIG += bsymbolic_functions
contains(QT_CONFIG, largefile): CONFIG += largefile
contains(QT_CONFIG, separate_debug_info): CONFIG += separate_debug_info
- contains(QT_CONFIG, separate_debug_info_nocopy): CONFIG += separate_debug_info_nocopy
}
warnings_are_errors:warning_clean {
diff --git a/mkspecs/features/qt_plugin.prf b/mkspecs/features/qt_plugin.prf
index f710bbff43..ba12b9c1cd 100644
--- a/mkspecs/features/qt_plugin.prf
+++ b/mkspecs/features/qt_plugin.prf
@@ -55,12 +55,11 @@ load(qt_common)
wince*:LIBS += $$QMAKE_LIBS_GUI
QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
-unix|mingw {
- !isEmpty(_QMAKE_SUPER_CACHE_): \
- rplbase = $$dirname(_QMAKE_SUPER_CACHE_)/[^/][^/]*
- else: \
- rplbase = $$MODULE_BASE_OUTDIR
- lib_replace.match = $$rplbase/lib
- lib_replace.replace = $$[QT_INSTALL_LIBS/raw]
- QMAKE_PRL_INSTALL_REPLACE += lib_replace
-}
+!isEmpty(_QMAKE_SUPER_CACHE_): \
+ rplbase = $$dirname(_QMAKE_SUPER_CACHE_)/[^/][^/]*
+else: \
+ rplbase = $$MODULE_BASE_OUTDIR
+lib_replace.match = $$rplbase/lib
+lib_replace.replace = $$[QT_INSTALL_LIBS/raw]
+lib_replace.CONFIG = path
+QMAKE_PRL_INSTALL_REPLACE += lib_replace
diff --git a/mkspecs/features/testcase.prf b/mkspecs/features/testcase.prf
index 10f421a8e2..40ec7cff30 100644
--- a/mkspecs/features/testcase.prf
+++ b/mkspecs/features/testcase.prf
@@ -134,6 +134,28 @@ contains(INSTALLS, target) {
INSTALLS += $$tdi
}
+ # Install GENERATED_TESTDATA.
+ # Logic is copied from the TESTDATA installation, only difference being that
+ # INSTALL target is added with CONFIG = no_check_exist
+ for(file, GENERATED_TESTDATA) {
+ tnam = $$file
+ tnam ~= s,\\.\\.,dotdot,
+ tnam ~= s,[?*],wildcard,
+ tnam ~= s,[^A-Za-z0-9],_,
+ tdi = testdata_$$tnam
+ tdif = $${tdi}.files
+ tdip = $${tdi}.path
+ tdic = $${tdi}.CONFIG
+
+ $$tdif = $$file
+ $$tdic = no_check_exist
+
+ file = $$replace(file, ^(\\.\\./)+, )
+ $$tdip = $${target.path}/$$dirname(file)
+
+ INSTALLS += $$tdi
+ }
+
# TEST_HELPER_INSTALLS specifies additional test helper executables for installation.
#
# Typical usage is:
diff --git a/mkspecs/features/unix/separate_debug_info.prf b/mkspecs/features/unix/separate_debug_info.prf
index c5ff6dcba3..394d5f42bc 100644
--- a/mkspecs/features/unix/separate_debug_info.prf
+++ b/mkspecs/features/unix/separate_debug_info.prf
@@ -1,5 +1,5 @@
-!separate_debug_info_nocopy:have_target:!static:!isEmpty(QMAKE_OBJCOPY) {
+have_target:!static:!isEmpty(QMAKE_OBJCOPY) {
qnx {
debug_info_suffix = sym
debug_info_keep = --keep-file-symbols
diff --git a/mkspecs/features/winrt/package_manifest.prf b/mkspecs/features/winrt/package_manifest.prf
index 969a6780ce..a959bc5480 100644
--- a/mkspecs/features/winrt/package_manifest.prf
+++ b/mkspecs/features/winrt/package_manifest.prf
@@ -39,8 +39,13 @@
manifest_file.input = $$WINRT_MANIFEST
- load(resolve_target)
- BUILD_DIR = $$dirname(QMAKE_RESOLVED_TARGET)
+ contains(TEMPLATE, "vc.*") {
+ BUILD_DIR = $$OUT_PWD
+ } else {
+ load(resolve_target)
+ BUILD_DIR = $$dirname(QMAKE_RESOLVED_TARGET)
+ }
+
winphone: \
manifest_file.output = $$BUILD_DIR/WMAppManifest.xml
else: contains(TEMPLATE, "vc.*"): \
@@ -87,16 +92,28 @@
winphone: INDENT = "$$escape_expand(\\r\\n) "
else: INDENT = "$$escape_expand(\\r\\n) "
+
# Capabilities are given as a string list and may change with the configuration (network, sensors, etc.)
WINRT_MANIFEST.capabilities = $$unique(WINRT_MANIFEST.capabilities)
- for(CAPABILITY, WINRT_MANIFEST.capabilities): \
- MANIFEST_CAPABILITIES += " <Capability Name=\"$$CAPABILITY\" />"
- WINRT_MANIFEST.capabilities = $$join(MANIFEST_CAPABILITIES, $$INDENT, $$INDENT, $$INDENT)
+ !isEmpty(WINRT_MANIFEST.capabilities)|winphone {
+ MANIFEST_CAPABILITIES += "<Capabilities>"
+ for(CAPABILITY, WINRT_MANIFEST.capabilities): \
+ MANIFEST_CAPABILITIES += " <Capability Name=\"$$CAPABILITY\" />"
+ MANIFEST_CAPABILITIES += "</Capabilities>"
+
+ WINRT_MANIFEST.capabilities = $$join(MANIFEST_CAPABILITIES, $$INDENT, $$INDENT)
+ }
+
# Dependencies are given as a string list. The CRT dependency is added automatically above.
WINRT_MANIFEST.dependencies = $$unique(WINRT_MANIFEST.dependencies)
- for(DEPENDENCY, WINRT_MANIFEST.dependencies): \
- MANIFEST_DEPENDENCIES += " <PackageDependency Name=\"$$DEPENDENCY\" />"
- WINRT_MANIFEST.dependencies = $$join(MANIFEST_DEPENDENCIES, $$INDENT, $$INDENT, $$INDENT)
+ !isEmpty(WINRT_MANIFEST.dependencies) {
+ MANIFEST_DEPENDENCIES += "<Dependencies>"
+ for(DEPENDENCY, WINRT_MANIFEST.dependencies): \
+ MANIFEST_DEPENDENCIES += " <PackageDependency Name=\"$$DEPENDENCY\" />"
+ MANIFEST_DEPENDENCIES += "</Dependencies>"
+
+ WINRT_MANIFEST.dependencies = $$join(MANIFEST_DEPENDENCIES, $$INDENT, $$INDENT)
+ }
# Provide default icons where needed
isEmpty(WINRT_ASSETS_PATH): WINRT_ASSETS_PATH = $$[QT_HOST_DATA/get]/mkspecs/common/winrt_winphone/assets
diff --git a/mkspecs/macx-ios-clang/features/default_post.prf b/mkspecs/macx-ios-clang/features/default_post.prf
index 28ad095da7..8b339dacdc 100644
--- a/mkspecs/macx-ios-clang/features/default_post.prf
+++ b/mkspecs/macx-ios-clang/features/default_post.prf
@@ -71,6 +71,7 @@ equals(TEMPLATE, app) {
distclean.depends = xcode_distclean
QMAKE_EXTRA_TARGETS += distclean
+ mkpath($$OUT_PWD)|error("Aborting.")
args =
for(arg, QMAKE_ARGS): \
args += $$system_quote($$arg)
diff --git a/mkspecs/win32-msvc2005/qmake.conf b/mkspecs/win32-msvc2005/qmake.conf
index 4a0fab761e..d89bfba958 100644
--- a/mkspecs/win32-msvc2005/qmake.conf
+++ b/mkspecs/win32-msvc2005/qmake.conf
@@ -8,6 +8,7 @@ MAKEFILE_GENERATOR = MSVC.NET
QMAKE_PLATFORM = win32
CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe
DEFINES += UNICODE WIN32
+MSVC_VER = 8.0
QMAKE_COMPILER_DEFINES += _MSC_VER=1400 _WIN32
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += WIN64
diff --git a/mkspecs/win32-msvc2008/qmake.conf b/mkspecs/win32-msvc2008/qmake.conf
index 8fd6eb0c7d..35693d0356 100644
--- a/mkspecs/win32-msvc2008/qmake.conf
+++ b/mkspecs/win32-msvc2008/qmake.conf
@@ -8,6 +8,7 @@ MAKEFILE_GENERATOR = MSVC.NET
QMAKE_PLATFORM = win32
CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe
DEFINES += UNICODE WIN32
+MSVC_VER = 9.0
QMAKE_COMPILER_DEFINES += _MSC_VER=1500 _WIN32
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += WIN64
diff --git a/mkspecs/win32-msvc2010/qmake.conf b/mkspecs/win32-msvc2010/qmake.conf
index 07422abb0a..f24da2d5c6 100644
--- a/mkspecs/win32-msvc2010/qmake.conf
+++ b/mkspecs/win32-msvc2010/qmake.conf
@@ -8,6 +8,7 @@ MAKEFILE_GENERATOR = MSBUILD
QMAKE_PLATFORM = win32
CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe
DEFINES += UNICODE WIN32
+MSVC_VER = 10.0
QMAKE_COMPILER_DEFINES += _MSC_VER=1600 _WIN32
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += WIN64
diff --git a/mkspecs/win32-msvc2012/qmake.conf b/mkspecs/win32-msvc2012/qmake.conf
index 45054862ba..18ffc27711 100644
--- a/mkspecs/win32-msvc2012/qmake.conf
+++ b/mkspecs/win32-msvc2012/qmake.conf
@@ -8,6 +8,7 @@ MAKEFILE_GENERATOR = MSBUILD
QMAKE_PLATFORM = win32
CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe
DEFINES += UNICODE WIN32
+MSVC_VER = 11.0
QMAKE_COMPILER_DEFINES += _MSC_VER=1700 _WIN32
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += WIN64
diff --git a/mkspecs/win32-msvc2013/qmake.conf b/mkspecs/win32-msvc2013/qmake.conf
index 9fc69e4d1a..ad46a2fb72 100644
--- a/mkspecs/win32-msvc2013/qmake.conf
+++ b/mkspecs/win32-msvc2013/qmake.conf
@@ -8,6 +8,7 @@ MAKEFILE_GENERATOR = MSBUILD
QMAKE_PLATFORM = win32
CONFIG += incremental flat precompile_header autogen_precompile_source debug_and_release debug_and_release_target embed_manifest_dll embed_manifest_exe
DEFINES += UNICODE WIN32
+MSVC_VER = 12.0
QMAKE_COMPILER_DEFINES += _MSC_VER=1800 _WIN32
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += WIN64
diff --git a/mkspecs/winphone-arm-msvc2012/qmake.conf b/mkspecs/winphone-arm-msvc2012/qmake.conf
index c4e3d2bab7..72961c320d 100644
--- a/mkspecs/winphone-arm-msvc2012/qmake.conf
+++ b/mkspecs/winphone-arm-msvc2012/qmake.conf
@@ -7,11 +7,11 @@
include(../common/winrt_winphone/qmake.conf)
QMAKE_COMPILER_DEFINES += _MSC_VER=1700
QMAKE_PLATFORM = winphone $$QMAKE_PLATFORM
-DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP ARM __ARM__ __arm__ QT_NO_CURSOR
+DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP ARM __ARM__ __arm__
QMAKE_LFLAGS += /MACHINE:ARM
-QMAKE_LIBS += WindowsPhoneCore.lib PhoneAppModelHost.lib ws2_32.lib
+QMAKE_LIBS += WindowsPhoneCore.lib PhoneAppModelHost.lib
VCPROJ_ARCH = ARM
MSVC_VER = 11.0
diff --git a/mkspecs/winphone-x86-msvc2012/qmake.conf b/mkspecs/winphone-x86-msvc2012/qmake.conf
index 4b8a92ea3b..f7838d187a 100644
--- a/mkspecs/winphone-x86-msvc2012/qmake.conf
+++ b/mkspecs/winphone-x86-msvc2012/qmake.conf
@@ -7,11 +7,11 @@
include(../common/winrt_winphone/qmake.conf)
QMAKE_COMPILER_DEFINES += _MSC_VER=1700
QMAKE_PLATFORM = winphone $$QMAKE_PLATFORM
-DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP X86 __X86__ __x86__ QT_NO_CURSOR
+DEFINES += WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP X86 __X86__ __x86__
QMAKE_LFLAGS += /MACHINE:X86
-QMAKE_LIBS += WindowsPhoneCore.lib PhoneAppModelHost.lib ws2_32.lib
+QMAKE_LIBS += WindowsPhoneCore.lib PhoneAppModelHost.lib
VCPROJ_ARCH = Win32
MSVC_VER = 11.0
diff --git a/qmake/doc/snippets/qmake/qtconfiguration.pro b/qmake/doc/snippets/qmake/qtconfiguration.pro
index 55e13be352..fe3667144e 100644
--- a/qmake/doc/snippets/qmake/qtconfiguration.pro
+++ b/qmake/doc/snippets/qmake/qtconfiguration.pro
@@ -10,7 +10,7 @@ message(Binary files (executables): $$[QT_INSTALL_BINS])
message(Plugins: $$[QT_INSTALL_PLUGINS])
message(Data files: $$[QT_INSTALL_DATA])
message(Translation files: $$[QT_INSTALL_TRANSLATIONS])
-message(Settings: $$[QT_INSTALL_SETTINGS])
+message(Settings: $$[QT_INSTALL_CONFIGURATION])
message(Examples: $$[QT_INSTALL_EXAMPLES])
#! [0]
diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc
index 958550ce91..01313b405f 100644
--- a/qmake/doc/src/qmake-manual.qdoc
+++ b/qmake/doc/src/qmake-manual.qdoc
@@ -2559,6 +2559,13 @@
See also \l{infile(filename, var, val)}{infile()}.
+ \section2 getenv(variablename)
+
+ Returns the value of the environment variable \c variablename.
+ This is mostly equivalent to the \c $$(variablename) syntax.
+ The \c getenv function, however, supports environment variables with
+ parentheses in their name.
+
\section2 join(variablename, glue, before, after)
Joins the value of \c variablename with \c glue. If this value is
diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp
index b588e68e83..b8a564968d 100644
--- a/qmake/generators/win32/msvc_nmake.cpp
+++ b/qmake/generators/win32/msvc_nmake.cpp
@@ -416,8 +416,9 @@ void NmakeMakefileGenerator::init()
}
if (project->isActiveConfig("debug_info")) {
QString pdbfile = project->first("DESTDIR") + project->first("TARGET") + version + ".pdb";
- project->values("QMAKE_CFLAGS").append("/Fd" + pdbfile);
- project->values("QMAKE_CXXFLAGS").append("/Fd" + pdbfile);
+ QString escapedPdbFile = escapeFilePath(pdbfile);
+ project->values("QMAKE_CFLAGS").append("/Fd" + escapedPdbFile);
+ project->values("QMAKE_CXXFLAGS").append("/Fd" + escapedPdbFile);
project->values("QMAKE_DISTCLEAN").append(pdbfile);
}
if (project->isActiveConfig("debug")) {
diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp
index 96de34fd14..36f808197a 100644
--- a/qmake/library/qmakebuiltins.cpp
+++ b/qmake/library/qmakebuiltins.cpp
@@ -99,7 +99,7 @@ enum ExpandFunc {
E_UPPER, E_LOWER, E_TITLE, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE,
E_REPLACE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS,
E_SHADOWED, E_ABSOLUTE_PATH, E_RELATIVE_PATH, E_CLEAN_PATH,
- E_SYSTEM_PATH, E_SHELL_PATH, E_SYSTEM_QUOTE, E_SHELL_QUOTE
+ E_SYSTEM_PATH, E_SHELL_PATH, E_SYSTEM_QUOTE, E_SHELL_QUOTE, E_GETENV
};
enum TestFunc {
@@ -156,6 +156,7 @@ void QMakeEvaluator::initFunctionStatics()
{ "shell_path", E_SHELL_PATH },
{ "system_quote", E_SYSTEM_QUOTE },
{ "shell_quote", E_SHELL_QUOTE },
+ { "getenv", E_GETENV },
};
for (unsigned i = 0; i < sizeof(expandInits)/sizeof(expandInits[0]); ++i)
statics.expands.insert(ProKey(expandInits[i].name), expandInits[i].func);
@@ -1090,6 +1091,15 @@ ProStringList QMakeEvaluator::evaluateBuiltinExpand(
ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0)));
}
break;
+ case E_GETENV:
+ if (args.count() != 1) {
+ evalError(fL1S("getenv(arg) requires one argument."));
+ } else {
+ const ProString &var = args.at(0);
+ const ProString &val = ProString(m_option->getEnv(var.toQString(m_tmp1)));
+ ret << val;
+ }
+ break;
default:
evalError(fL1S("Function '%1' is not implemented.").arg(func.toQString(m_tmp1)));
break;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp
index 31d976dec4..2de477b3bc 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp
@@ -1137,6 +1137,84 @@ void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLv
}
}
+template<typename T>
+static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *data)
+{
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+ data[count] = 0;
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLubyte*>(indices)[i];
+ }
+ data[count] = static_cast<const GLubyte*>(indices)[0];
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLushort*>(indices)[i];
+ }
+ data[count] = static_cast<const GLushort*>(indices)[0];
+ break;
+ case GL_UNSIGNED_INT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLuint*>(indices)[i];
+ }
+ data[count] = static_cast<const GLuint*>(indices)[0];
+ break;
+ default: UNREACHABLE();
+ }
+}
+
+template<typename T>
+static void fillTriangleFanIndices(GLenum type, unsigned int numTris, const GLvoid *indices, T *data)
+{
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = 0;
+ data[i*3 + 1] = i + 1;
+ data[i*3 + 2] = i + 2;
+ }
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
+ }
+ break;
+ default: UNREACHABLE();
+ }
+}
+
void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
{
// Get the raw indices for an indexed draw
@@ -1148,10 +1226,12 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
indices = static_cast<const GLubyte*>(storage->getData()) + offset;
}
+ const int indexType = get32BitIndexSupport() ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
+
if (!mLineLoopIB)
{
mLineLoopIB = new StreamingIndexBufferInterface(this);
- if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
+ if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType))
{
delete mLineLoopIB;
mLineLoopIB = NULL;
@@ -1171,7 +1251,7 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
}
const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
- if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
+ if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, indexType))
{
ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
return gl::error(GL_OUT_OF_MEMORY);
@@ -1185,42 +1265,12 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
return gl::error(GL_OUT_OF_MEMORY);
}
- unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
+ if (indexType == GL_UNSIGNED_SHORT)
+ fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned short*>(mappedMemory));
+ else
+ fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned int*>(mappedMemory));
unsigned int indexBufferOffset = offset;
- switch (type)
- {
- case GL_NONE: // Non-indexed draw
- for (int i = 0; i < count; i++)
- {
- data[i] = i;
- }
- data[count] = 0;
- break;
- case GL_UNSIGNED_BYTE:
- for (int i = 0; i < count; i++)
- {
- data[i] = static_cast<const GLubyte*>(indices)[i];
- }
- data[count] = static_cast<const GLubyte*>(indices)[0];
- break;
- case GL_UNSIGNED_SHORT:
- for (int i = 0; i < count; i++)
- {
- data[i] = static_cast<const GLushort*>(indices)[i];
- }
- data[count] = static_cast<const GLushort*>(indices)[0];
- break;
- case GL_UNSIGNED_INT:
- for (int i = 0; i < count; i++)
- {
- data[i] = static_cast<const GLuint*>(indices)[i];
- }
- data[count] = static_cast<const GLuint*>(indices)[0];
- break;
- default: UNREACHABLE();
- }
-
if (!mLineLoopIB->unmapBuffer())
{
ERR("Could not unmap index buffer for GL_LINE_LOOP.");
@@ -1251,10 +1301,12 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
indices = static_cast<const GLubyte*>(storage->getData()) + offset;
}
+ const int indexType = get32BitIndexSupport() ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
+
if (!mTriangleFanIB)
{
mTriangleFanIB = new StreamingIndexBufferInterface(this);
- if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
+ if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType))
{
delete mTriangleFanIB;
mTriangleFanIB = NULL;
@@ -1276,7 +1328,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
}
const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int);
- if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
+ if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType))
{
ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN.");
return gl::error(GL_OUT_OF_MEMORY);
@@ -1290,45 +1342,12 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
return gl::error(GL_OUT_OF_MEMORY);
}
- unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
+ if (indexType == GL_UNSIGNED_SHORT)
+ fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned short*>(mappedMemory));
+ else
+ fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned int*>(mappedMemory));
unsigned int indexBufferOffset = offset;
- switch (type)
- {
- case GL_NONE: // Non-indexed draw
- for (unsigned int i = 0; i < numTris; i++)
- {
- data[i*3 + 0] = 0;
- data[i*3 + 1] = i + 1;
- data[i*3 + 2] = i + 2;
- }
- break;
- case GL_UNSIGNED_BYTE:
- for (unsigned int i = 0; i < numTris; i++)
- {
- data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0];
- data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
- data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
- }
- break;
- case GL_UNSIGNED_SHORT:
- for (unsigned int i = 0; i < numTris; i++)
- {
- data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
- data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
- data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
- }
- break;
- case GL_UNSIGNED_INT:
- for (unsigned int i = 0; i < numTris; i++)
- {
- data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
- data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
- data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
- }
- break;
- default: UNREACHABLE();
- }
if (!mTriangleFanIB->unmapBuffer())
{
diff --git a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
new file mode 100644
index 0000000000..7d997d7d8b
--- /dev/null
+++ b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
@@ -0,0 +1,134 @@
+TARGET = qtharfbuzzng
+TEMPLATE = lib
+
+CONFIG += \
+ static \
+ hide_symbols \
+ exceptions_off rtti_off
+CONFIG -= qt
+
+DESTDIR = $$QT_BUILD_TREE/lib
+
+DEFINES += HAVE_CONFIG_H
+HEADERS += $$PWD/src/config.h
+
+INCLUDEPATH += $$PWD/include
+
+SOURCES += \
+ $$PWD/src/hb-blob.cc \
+ $$PWD/src/hb-buffer.cc \
+ $$PWD/src/hb-buffer-serialize.cc \
+ $$PWD/src/hb-common.cc \
+ $$PWD/src/hb-face.cc \
+ $$PWD/src/hb-font.cc \
+ $$PWD/src/hb-ot-tag.cc \
+ $$PWD/src/hb-set.cc \
+ $$PWD/src/hb-shape.cc \
+ $$PWD/src/hb-shape-plan.cc \
+ $$PWD/src/hb-shaper.cc \
+ $$PWD/src/hb-unicode.cc \
+ $$PWD/src/hb-warning.cc
+
+HEADERS += \
+ $$PWD/src/hb-atomic-private.hh \
+ $$PWD/src/hb-buffer-private.hh \
+ $$PWD/src/hb-buffer-deserialize-json.hh \
+ $$PWD/src/hb-buffer-deserialize-text.hh \
+ $$PWD/src/hb-cache-private.hh \
+ $$PWD/src/hb-face-private.hh \
+ $$PWD/src/hb-font-private.hh \
+ $$PWD/src/hb-mutex-private.hh \
+ $$PWD/src/hb-object-private.hh \
+ $$PWD/src/hb-open-file-private.hh \
+ $$PWD/src/hb-open-type-private.hh \
+ $$PWD/src/hb-ot-head-table.hh \
+ $$PWD/src/hb-ot-hhea-table.hh \
+ $$PWD/src/hb-ot-hmtx-table.hh \
+ $$PWD/src/hb-ot-maxp-table.hh \
+ $$PWD/src/hb-ot-name-table.hh \
+ $$PWD/src/hb-private.hh \
+ $$PWD/src/hb-set-private.hh \
+ $$PWD/src/hb-shape-plan-private.hh \
+ $$PWD/src/hb-shaper-impl-private.hh \
+ $$PWD/src/hb-shaper-list.hh \
+ $$PWD/src/hb-shaper-private.hh \
+ $$PWD/src/hb-unicode-private.hh \
+ $$PWD/src/hb-utf-private.hh
+
+HEADERS += \
+ $$PWD/src/hb.h \
+ $$PWD/src/hb-blob.h \
+ $$PWD/src/hb-buffer.h \
+ $$PWD/src/hb-common.h \
+ $$PWD/src/hb-face.h \
+ $$PWD/src/hb-font.h \
+ $$PWD/src/hb-set.h \
+ $$PWD/src/hb-shape.h \
+ $$PWD/src/hb-shape-plan.h \
+ $$PWD/src/hb-unicode.h \
+ $$PWD/src/hb-version.h
+
+# Open Type
+SOURCES += \
+ $$PWD/src/hb-ot-layout.cc \
+ $$PWD/src/hb-ot-map.cc \
+ $$PWD/src/hb-ot-shape.cc \
+ $$PWD/src/hb-ot-shape-complex-arabic.cc \
+ $$PWD/src/hb-ot-shape-complex-default.cc \
+ $$PWD/src/hb-ot-shape-complex-hangul.cc \
+ $$PWD/src/hb-ot-shape-complex-hebrew.cc \
+ $$PWD/src/hb-ot-shape-complex-indic.cc \
+ $$PWD/src/hb-ot-shape-complex-indic-table.cc \
+ $$PWD/src/hb-ot-shape-complex-myanmar.cc \
+ $$PWD/src/hb-ot-shape-complex-sea.cc \
+ $$PWD/src/hb-ot-shape-complex-thai.cc \
+ $$PWD/src/hb-ot-shape-complex-tibetan.cc \
+ $$PWD/src/hb-ot-shape-fallback.cc \
+ $$PWD/src/hb-ot-shape-normalize.cc
+
+HEADERS += \
+ $$PWD/src/hb-ot-layout-common-private.hh \
+ $$PWD/src/hb-ot-layout-gdef-table.hh \
+ $$PWD/src/hb-ot-layout-gpos-table.hh \
+ $$PWD/src/hb-ot-layout-gsubgpos-private.hh \
+ $$PWD/src/hb-ot-layout-gsub-table.hh \
+ $$PWD/src/hb-ot-layout-jstf-table.hh \
+ $$PWD/src/hb-ot-layout-private.hh \
+ $$PWD/src/hb-ot-map-private.hh \
+ $$PWD/src/hb-ot-shape-complex-arabic-fallback.hh \
+ $$PWD/src/hb-ot-shape-complex-arabic-table.hh \
+ $$PWD/src/hb-ot-shape-complex-indic-machine.hh \
+ $$PWD/src/hb-ot-shape-complex-indic-private.hh \
+ $$PWD/src/hb-ot-shape-complex-myanmar-machine.hh \
+ $$PWD/src/hb-ot-shape-complex-private.hh \
+ $$PWD/src/hb-ot-shape-complex-sea-machine.hh \
+ $$PWD/src/hb-ot-shape-fallback-private.hh \
+ $$PWD/src/hb-ot-shape-normalize-private.hh \
+ $$PWD/src/hb-ot-shape-private.hh
+
+HEADERS += \
+ $$PWD/src/hb-ot.h \
+ $$PWD/src/hb-ot-layout.h \
+ $$PWD/src/hb-ot-shape.h \
+ $$PWD/src/hb-ot-tag.h
+
+mac {
+ # Apple Advanced Typography
+ DEFINES += HAVE_CORETEXT
+
+ SOURCES += \
+ $$PWD/src/hb-coretext.cc
+
+ HEADERS += \
+ $$PWD/src/hb-coretext.h
+
+ ios: \
+ # On iOS CoreText and CoreGraphics are stand-alone frameworks
+ LIBS_PRIVATE += -framework CoreText -framework CoreGraphics
+ else: \
+ # On Mac OS they are part of the ApplicationServices umbrella framework,
+ # even in 10.8 where they were also made available stand-alone.
+ LIBS_PRIVATE += -framework ApplicationServices
+}
+
+TARGET = $$TARGET$$qtPlatformTargetSuffix()
diff --git a/src/3rdparty/harfbuzz-ng/src/config.h b/src/3rdparty/harfbuzz-ng/src/config.h
index db706987fe..cb68ab0e5b 100644
--- a/src/3rdparty/harfbuzz-ng/src/config.h
+++ b/src/3rdparty/harfbuzz-ng/src/config.h
@@ -2,29 +2,14 @@
#define HB_CONFIG_H
#define HAVE_OT
+#define HAVE_ATEXIT
#define HB_NO_MT
#define HB_NO_UNICODE_FUNCS
#define HB_DISABLE_DEPRECATED
-#include <QtCore/qglobal.h>
-
-#ifndef HB_INTERNAL
-# define HB_INTERNAL Q_DECL_HIDDEN
-#endif
-
-#if !defined(QT_NO_DEBUG)
-# define NDEBUG
-#endif
-
// because strdup() is not part of strict Posix, declare it here
extern "C" char *strdup(const char *src);
-#ifndef HAVE_ATEXIT
-# define HAVE_ATEXIT 1
-# include <QtCore/qcoreapplication.h>
-# define atexit qAddPostRoutine
-#endif
-
#endif /* HB_CONFIG_H */
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
index 5a34eddecc..40c06371bd 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
+++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
@@ -32,7 +32,6 @@
#include "hb-coretext.h"
#include "hb-face-private.hh"
-#include <private/qfontengine_p.h>
#ifndef HB_DEBUG_CORETEXT
@@ -44,6 +43,19 @@ HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face)
HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font)
+typedef bool (*qt_get_font_table_func_t) (void *user_data, unsigned int tag, unsigned char *buffer, unsigned int *length);
+
+struct FontEngineFaceData {
+ void *user_data;
+ qt_get_font_table_func_t get_font_table;
+};
+
+struct CoreTextFontEngineData {
+ CTFontRef ctFont;
+ CGFontRef cgFont;
+};
+
+
/*
* shaper face data
*/
@@ -83,25 +95,11 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face)
if (unlikely (!data))
return NULL;
- QFontEngine *fe = (QFontEngine *) ((QFontEngine::FaceData *) face->user_data)->user_data;
- if (fe->type () == QFontEngine::Mac)
- {
- data->cg_font = (CGFontRef) fe->userData ().value<void *> ();
- if (likely (data->cg_font))
- CFRetain (data->cg_font);
- }
- else
- {
- hb_blob_t *blob = hb_face_reference_blob (face);
- unsigned int blob_length;
- const char *blob_data = hb_blob_get_data (blob, &blob_length);
- if (unlikely (!blob_length))
- DEBUG_MSG (CORETEXT, face, "Face has empty blob");
-
- CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data);
- data->cg_font = CGFontCreateWithDataProvider (provider);
- CGDataProviderRelease (provider);
- }
+ FontEngineFaceData *fontEngineFaceData = (FontEngineFaceData *) face->user_data;
+ CoreTextFontEngineData *coreTextFontEngineData = (CoreTextFontEngineData *) fontEngineFaceData->user_data;
+ data->cg_font = coreTextFontEngineData->cgFont;
+ if (likely (data->cg_font))
+ CFRetain (data->cg_font);
if (unlikely (!data->cg_font)) {
DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed");
@@ -146,9 +144,13 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
return NULL;
hb_face_t *face = font->face;
- hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
- data->ct_font = CTFontCreateWithGraphicsFont (face_data->cg_font, font->y_scale / 64, NULL, NULL);
+ FontEngineFaceData *fontEngineFaceData = (FontEngineFaceData *) face->user_data;
+ CoreTextFontEngineData *coreTextFontEngineData = (CoreTextFontEngineData *) fontEngineFaceData->user_data;
+ data->ct_font = coreTextFontEngineData->ctFont;
+ if (likely (data->ct_font))
+ CFRetain (data->ct_font);
+
if (unlikely (!data->ct_font)) {
DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed");
free (data);
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.h b/src/3rdparty/harfbuzz-ng/src/hb-coretext.h
index bcf1de7141..aa4bf69a52 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.h
+++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.h
@@ -29,7 +29,13 @@
#include "hb.h"
-#include <ApplicationServices/ApplicationServices.h>
+#include <TargetConditionals.h>
+#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+# include <CoreText/CoreText.h>
+# include <CoreGraphics/CoreGraphics.h>
+#else
+# include <ApplicationServices/ApplicationServices.h>
+#endif
HB_BEGIN_DECLS
diff --git a/src/3rdparty/harfbuzz.pri b/src/3rdparty/harfbuzz.pri
deleted file mode 100644
index e61ee7eab6..0000000000
--- a/src/3rdparty/harfbuzz.pri
+++ /dev/null
@@ -1,121 +0,0 @@
-contains(QT_CONFIG, harfbuzz) {
- QT_HARFBUZZ_DIR = $$QT_SOURCE_TREE/src/3rdparty/harfbuzz-ng
-
- INCLUDEPATH += $$QT_HARFBUZZ_DIR/include
-
- SOURCES += \
- $$QT_HARFBUZZ_DIR/src/hb-blob.cc \
- $$QT_HARFBUZZ_DIR/src/hb-buffer.cc \
- $$QT_HARFBUZZ_DIR/src/hb-buffer-serialize.cc \
- $$QT_HARFBUZZ_DIR/src/hb-common.cc \
- $$QT_HARFBUZZ_DIR/src/hb-face.cc \
- $$QT_HARFBUZZ_DIR/src/hb-font.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-tag.cc \
- $$QT_HARFBUZZ_DIR/src/hb-set.cc \
- $$QT_HARFBUZZ_DIR/src/hb-shape.cc \
- $$QT_HARFBUZZ_DIR/src/hb-shape-plan.cc \
- $$QT_HARFBUZZ_DIR/src/hb-shaper.cc \
- $$QT_HARFBUZZ_DIR/src/hb-unicode.cc \
- $$QT_HARFBUZZ_DIR/src/hb-warning.cc
-
- HEADERS += \
- $$QT_HARFBUZZ_DIR/src/hb-atomic-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-buffer-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-buffer-deserialize-json.hh \
- $$QT_HARFBUZZ_DIR/src/hb-buffer-deserialize-text.hh \
- $$QT_HARFBUZZ_DIR/src/hb-cache-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-face-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-font-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-mutex-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-object-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-open-file-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-open-type-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-head-table.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-hhea-table.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-hmtx-table.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-maxp-table.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-name-table.hh \
- $$QT_HARFBUZZ_DIR/src/hb-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-set-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-shape-plan-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-shaper-impl-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-shaper-list.hh \
- $$QT_HARFBUZZ_DIR/src/hb-shaper-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-unicode-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-utf-private.hh
-
- HEADERS += \
- $$QT_HARFBUZZ_DIR/src/hb.h \
- $$QT_HARFBUZZ_DIR/src/hb-blob.h \
- $$QT_HARFBUZZ_DIR/src/hb-buffer.h \
- $$QT_HARFBUZZ_DIR/src/hb-common.h \
- $$QT_HARFBUZZ_DIR/src/hb-face.h \
- $$QT_HARFBUZZ_DIR/src/hb-font.h \
- $$QT_HARFBUZZ_DIR/src/hb-set.h \
- $$QT_HARFBUZZ_DIR/src/hb-shape.h \
- $$QT_HARFBUZZ_DIR/src/hb-shape-plan.h \
- $$QT_HARFBUZZ_DIR/src/hb-unicode.h \
- $$QT_HARFBUZZ_DIR/src/hb-version.h
-
- # Open Type
- SOURCES += \
- $$QT_HARFBUZZ_DIR/src/hb-ot-layout.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-map.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-arabic.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-default.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-hangul.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-hebrew.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-indic.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-indic-table.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-myanmar.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-sea.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-thai.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-tibetan.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-fallback.cc \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-normalize.cc
-
- HEADERS += \
- $$QT_HARFBUZZ_DIR/src/hb-ot-layout-common-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-layout-gdef-table.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-layout-gpos-table.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-layout-gsubgpos-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-layout-gsub-table.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-layout-jstf-table.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-layout-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-map-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-arabic-fallback.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-arabic-table.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-indic-machine.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-indic-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-myanmar-machine.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-complex-sea-machine.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-fallback-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-normalize-private.hh \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape-private.hh
-
- HEADERS += \
- $$QT_HARFBUZZ_DIR/src/hb-ot.h \
- $$QT_HARFBUZZ_DIR/src/hb-ot-layout.h \
- $$QT_HARFBUZZ_DIR/src/hb-ot-shape.h \
- $$QT_HARFBUZZ_DIR/src/hb-ot-tag.h
-
- mac {
- # Apple Advanced Typography
- SOURCES += \
- $$QT_HARFBUZZ_DIR/src/hb-coretext.cc
-
- HEADERS += \
- $$QT_HARFBUZZ_DIR/src/hb-coretext.h
-
- DEFINES += HAVE_CORETEXT
- }
-
- DEFINES += HAVE_CONFIG_H
- QT += core-private
-
- TR_EXCLUDE += $$QT_HARFBUZZ_DIR/*
-} else:contains(QT_CONFIG, system-harfbuzz) {
- LIBS_PRIVATE += -lharfbuzz
-}
diff --git a/src/3rdparty/harfbuzzng.pri b/src/3rdparty/harfbuzzng.pri
new file mode 100644
index 0000000000..74433688f6
--- /dev/null
+++ b/src/3rdparty/harfbuzzng.pri
@@ -0,0 +1,6 @@
+contains(QT_CONFIG, harfbuzz) {
+ INCLUDEPATH += $$PWD/harfbuzz-ng/include
+ LIBS_PRIVATE += -L$$QT_BUILD_TREE/lib -lqtharfbuzzng$$qtPlatformTargetSuffix()
+} else:contains(QT_CONFIG, system-harfbuzz) {
+ LIBS_PRIVATE += -lharfbuzz
+}
diff --git a/src/3rdparty/sqlite/shell.c b/src/3rdparty/sqlite/shell.c
index 480ec5b455..2cff102e91 100644
--- a/src/3rdparty/sqlite/shell.c
+++ b/src/3rdparty/sqlite/shell.c
@@ -45,14 +45,17 @@
# include <sys/types.h>
#endif
-#ifdef HAVE_EDITLINE
-# include <editline/editline.h>
-#endif
-#if defined(HAVE_READLINE) && HAVE_READLINE==1
+#if defined(HAVE_READLINE) && HAVE_READLINE!=0
# include <readline/readline.h>
# include <readline/history.h>
+#else
+# undef HAVE_READLINE
+#endif
+#if defined(HAVE_EDITLINE) && !defined(HAVE_READLINE)
+# define HAVE_READLINE 1
+# include <editline/readline.h>
#endif
-#if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1)
+#if !defined(HAVE_READLINE)
# define add_history(X)
# define read_history(X)
# define write_history(X)
@@ -62,7 +65,9 @@
#if defined(_WIN32) || defined(WIN32)
# include <io.h>
#define isatty(h) _isatty(h)
-#define access(f,m) _access((f),(m))
+#ifndef access
+# define access(f,m) _access((f),(m))
+#endif
#undef popen
#define popen _popen
#undef pclose
@@ -413,7 +418,7 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
zResult = local_getline(zPrior, in);
}else{
zPrompt = isContinuation ? continuePrompt : mainPrompt;
-#if defined(HAVE_READLINE) && HAVE_READLINE==1
+#if defined(HAVE_READLINE)
free(zPrior);
zResult = readline(zPrompt);
if( zResult && *zResult ) add_history(zResult);
@@ -441,6 +446,7 @@ struct previous_mode_data {
struct callback_data {
sqlite3 *db; /* The database */
int echoOn; /* True to echo input commands */
+ int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL statement */
int statsOn; /* True to display memory stats before each finalize */
int cnt; /* Number of records displayed so far */
FILE *out; /* Write results here */
@@ -597,6 +603,7 @@ static void output_c_string(FILE *out, const char *z){
*/
static void output_html_string(FILE *out, const char *z){
int i;
+ if( z==0 ) z = "";
while( *z ){
for(i=0; z[i]
&& z[i]!='<'
@@ -1004,7 +1011,7 @@ static int run_table_dump_query(
int nResult;
int i;
const char *z;
- rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
+ rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
if( rc!=SQLITE_OK || !pSelect ){
fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
@@ -1176,7 +1183,8 @@ static int str_in_array(const char *zStr, const char **azArray){
**
** * For each "Goto", if the jump destination is earlier in the program
** and ends on one of:
-** Yield SeekGt SeekLt RowSetRead
+** Yield SeekGt SeekLt RowSetRead Rewind
+** or if the P1 parameter is one instead of zero,
** then indent all opcodes between the earlier instruction
** and "Goto" by 2 spaces.
*/
@@ -1188,7 +1196,7 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
int iOp; /* Index of operation in p->aiIndent[] */
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
- const char *azYield[] = { "Yield", "SeekLt", "SeekGt", "RowSetRead", 0 };
+ const char *azYield[] = { "Yield", "SeekLt", "SeekGt", "RowSetRead", "Rewind", 0 };
const char *azGoto[] = { "Goto", 0 };
/* Try to figure out if this is really an EXPLAIN statement. If this
@@ -1224,8 +1232,10 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
if( str_in_array(zOp, azNext) ){
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
}
- if( str_in_array(zOp, azGoto) && p2op<p->nIndent && abYield[p2op] ){
- for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
+ if( str_in_array(zOp, azGoto) && p2op<p->nIndent
+ && (abYield[p2op] || sqlite3_column_int(pSql, 2))
+ ){
+ for(i=p2op+1; i<iOp; i++) p->aiIndent[i] += 2;
}
}
@@ -1296,6 +1306,23 @@ static int shell_exec(
fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
}
+ /* Show the EXPLAIN QUERY PLAN if .eqp is on */
+ if( pArg && pArg->autoEQP ){
+ sqlite3_stmt *pExplain;
+ char *zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", sqlite3_sql(pStmt));
+ rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
+ if( rc==SQLITE_OK ){
+ while( sqlite3_step(pExplain)==SQLITE_ROW ){
+ fprintf(pArg->out,"--EQP-- %d,", sqlite3_column_int(pExplain, 0));
+ fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1));
+ fprintf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2));
+ fprintf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
+ }
+ }
+ sqlite3_finalize(pExplain);
+ sqlite3_free(zEQP);
+ }
+
/* Output TESTCTRL_EXPLAIN text of requested */
if( pArg && pArg->mode==MODE_Explain ){
const char *zExplain = 0;
@@ -1452,7 +1479,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
zTableInfo = appendText(zTableInfo, zTable, '"');
zTableInfo = appendText(zTableInfo, ");", 0);
- rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0);
+ rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0);
free(zTableInfo);
if( rc!=SQLITE_OK || !pTableInfo ){
return 1;
@@ -1542,6 +1569,7 @@ static int run_schema_dump_query(
static char zHelp[] =
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
".bail ON|OFF Stop after hitting an error. Default OFF\n"
+ ".clone NEWDB Clone data into NEWDB from the existing database\n"
".databases List names and files of attached databases\n"
".dump ?TABLE? ... Dump the database in an SQL text format\n"
" If TABLE specified, only dump tables matching\n"
@@ -1581,6 +1609,7 @@ static char zHelp[] =
".quit Exit this program\n"
".read FILENAME Execute SQL in FILENAME\n"
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
+ ".save FILE Write in-memory database into FILE\n"
".schema ?TABLE? Show the CREATE statements\n"
" If TABLE specified, only show tables matching\n"
" LIKE pattern TABLE.\n"
@@ -1836,7 +1865,7 @@ static void csv_append_char(CSVReader *p, int c){
** + Report syntax errors on stderr
*/
static char *csv_read_one_field(CSVReader *p){
- int c, pc;
+ int c, pc, ppc;
int cSep = p->cSeparator;
p->n = 0;
c = fgetc(p->in);
@@ -1847,7 +1876,7 @@ static char *csv_read_one_field(CSVReader *p){
if( c=='"' ){
int startLine = p->nLine;
int cQuote = c;
- pc = 0;
+ pc = ppc = 0;
while( 1 ){
c = fgetc(p->in);
if( c=='\n' ) p->nLine++;
@@ -1859,7 +1888,7 @@ static char *csv_read_one_field(CSVReader *p){
}
if( (c==cSep && pc==cQuote)
|| (c=='\n' && pc==cQuote)
- || (c=='\n' && pc=='\r' && p->n>=2 && p->z[p->n-2]==cQuote)
+ || (c=='\n' && pc=='\r' && ppc==cQuote)
|| (c==EOF && pc==cQuote)
){
do{ p->n--; }while( p->z[p->n]!=cQuote );
@@ -1877,6 +1906,7 @@ static char *csv_read_one_field(CSVReader *p){
break;
}
csv_append_char(p, c);
+ ppc = pc;
pc = c;
}
}else{
@@ -1886,7 +1916,7 @@ static char *csv_read_one_field(CSVReader *p){
}
if( c=='\n' ){
p->nLine++;
- if( p->n>1 && p->z[p->n-1]=='\r' ) p->n--;
+ if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
}
p->cTerm = c;
}
@@ -1895,6 +1925,219 @@ static char *csv_read_one_field(CSVReader *p){
}
/*
+** Try to transfer data for table zTable. If an error is seen while
+** moving forward, try to go backwards. The backwards movement won't
+** work for WITHOUT ROWID tables.
+*/
+static void tryToCloneData(
+ struct callback_data *p,
+ sqlite3 *newDb,
+ const char *zTable
+){
+ sqlite3_stmt *pQuery = 0;
+ sqlite3_stmt *pInsert = 0;
+ char *zQuery = 0;
+ char *zInsert = 0;
+ int rc;
+ int i, j, n;
+ int nTable = (int)strlen(zTable);
+ int k = 0;
+ int cnt = 0;
+ const int spinRate = 10000;
+
+ zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
+ rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
+ if( rc ){
+ fprintf(stderr, "Error %d: %s on [%s]\n",
+ sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
+ zQuery);
+ goto end_data_xfer;
+ }
+ n = sqlite3_column_count(pQuery);
+ zInsert = sqlite3_malloc(200 + nTable + n*3);
+ if( zInsert==0 ){
+ fprintf(stderr, "out of memory\n");
+ goto end_data_xfer;
+ }
+ sqlite3_snprintf(200+nTable,zInsert,
+ "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
+ i = (int)strlen(zInsert);
+ for(j=1; j<n; j++){
+ memcpy(zInsert+i, ",?", 2);
+ i += 2;
+ }
+ memcpy(zInsert+i, ");", 3);
+ rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
+ if( rc ){
+ fprintf(stderr, "Error %d: %s on [%s]\n",
+ sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
+ zQuery);
+ goto end_data_xfer;
+ }
+ for(k=0; k<2; k++){
+ while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
+ for(i=0; i<n; i++){
+ switch( sqlite3_column_type(pQuery, i) ){
+ case SQLITE_NULL: {
+ sqlite3_bind_null(pInsert, i+1);
+ break;
+ }
+ case SQLITE_INTEGER: {
+ sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
+ break;
+ }
+ case SQLITE_FLOAT: {
+ sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
+ break;
+ }
+ case SQLITE_TEXT: {
+ sqlite3_bind_text(pInsert, i+1,
+ (const char*)sqlite3_column_text(pQuery,i),
+ -1, SQLITE_STATIC);
+ break;
+ }
+ case SQLITE_BLOB: {
+ sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
+ sqlite3_column_bytes(pQuery,i),
+ SQLITE_STATIC);
+ break;
+ }
+ }
+ } /* End for */
+ rc = sqlite3_step(pInsert);
+ if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
+ fprintf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
+ sqlite3_errmsg(newDb));
+ }
+ sqlite3_reset(pInsert);
+ cnt++;
+ if( (cnt%spinRate)==0 ){
+ printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
+ fflush(stdout);
+ }
+ } /* End while */
+ if( rc==SQLITE_DONE ) break;
+ sqlite3_finalize(pQuery);
+ sqlite3_free(zQuery);
+ zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
+ zTable);
+ rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
+ if( rc ){
+ fprintf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
+ break;
+ }
+ } /* End for(k=0...) */
+
+end_data_xfer:
+ sqlite3_finalize(pQuery);
+ sqlite3_finalize(pInsert);
+ sqlite3_free(zQuery);
+ sqlite3_free(zInsert);
+}
+
+
+/*
+** Try to transfer all rows of the schema that match zWhere. For
+** each row, invoke xForEach() on the object defined by that row.
+** If an error is encountered while moving forward through the
+** sqlite_master table, try again moving backwards.
+*/
+static void tryToCloneSchema(
+ struct callback_data *p,
+ sqlite3 *newDb,
+ const char *zWhere,
+ void (*xForEach)(struct callback_data*,sqlite3*,const char*)
+){
+ sqlite3_stmt *pQuery = 0;
+ char *zQuery = 0;
+ int rc;
+ const unsigned char *zName;
+ const unsigned char *zSql;
+ char *zErrMsg = 0;
+
+ zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
+ " WHERE %s", zWhere);
+ rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
+ if( rc ){
+ fprintf(stderr, "Error: (%d) %s on [%s]\n",
+ sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
+ zQuery);
+ goto end_schema_xfer;
+ }
+ while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
+ zName = sqlite3_column_text(pQuery, 0);
+ zSql = sqlite3_column_text(pQuery, 1);
+ printf("%s... ", zName); fflush(stdout);
+ sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
+ if( zErrMsg ){
+ fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
+ sqlite3_free(zErrMsg);
+ zErrMsg = 0;
+ }
+ if( xForEach ){
+ xForEach(p, newDb, (const char*)zName);
+ }
+ printf("done\n");
+ }
+ if( rc!=SQLITE_DONE ){
+ sqlite3_finalize(pQuery);
+ sqlite3_free(zQuery);
+ zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
+ " WHERE %s ORDER BY rowid DESC", zWhere);
+ rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
+ if( rc ){
+ fprintf(stderr, "Error: (%d) %s on [%s]\n",
+ sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
+ zQuery);
+ goto end_schema_xfer;
+ }
+ while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
+ zName = sqlite3_column_text(pQuery, 0);
+ zSql = sqlite3_column_text(pQuery, 1);
+ printf("%s... ", zName); fflush(stdout);
+ sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
+ if( zErrMsg ){
+ fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
+ sqlite3_free(zErrMsg);
+ zErrMsg = 0;
+ }
+ if( xForEach ){
+ xForEach(p, newDb, (const char*)zName);
+ }
+ printf("done\n");
+ }
+ }
+end_schema_xfer:
+ sqlite3_finalize(pQuery);
+ sqlite3_free(zQuery);
+}
+
+/*
+** Open a new database file named "zNewDb". Try to recover as much information
+** as possible out of the main database (which might be corrupt) and write it
+** into zNewDb.
+*/
+static void tryToClone(struct callback_data *p, const char *zNewDb){
+ int rc;
+ sqlite3 *newDb = 0;
+ if( access(zNewDb,0)==0 ){
+ fprintf(stderr, "File \"%s\" already exists.\n", zNewDb);
+ return;
+ }
+ rc = sqlite3_open(zNewDb, &newDb);
+ if( rc ){
+ fprintf(stderr, "Cannot create output database: %s\n",
+ sqlite3_errmsg(newDb));
+ }else{
+ sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
+ tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
+ tryToCloneSchema(p, newDb, "type!='table'", 0);
+ sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
+ }
+ sqlite3_close(newDb);
+}
+
+/*
** If an input line begins with "." then invoke this routine to
** process that line.
**
@@ -1936,7 +2179,9 @@ static int do_meta_command(char *zLine, struct callback_data *p){
if( nArg==0 ) return 0; /* no tokens, no error */
n = strlen30(azArg[0]);
c = azArg[0][0];
- if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 ){
+ if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
+ || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
+ ){
const char *zDestFile = 0;
const char *zDb = 0;
sqlite3 *pDest;
@@ -2001,6 +2246,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
test_breakpoint();
}else
+ if( c=='c' && strncmp(azArg[0], "clone", n)==0 && nArg>1 && nArg<3 ){
+ tryToClone(p, azArg[1]);
+ }else
+
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){
struct callback_data data;
char *zErrMsg = 0;
@@ -2073,6 +2322,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
p->echoOn = booleanValue(azArg[1]);
}else
+ if( c=='e' && strncmp(azArg[0], "eqp", n)==0 && nArg>1 && nArg<3 ){
+ p->autoEQP = booleanValue(azArg[1]);
+ }else
+
if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
rc = 2;
@@ -2173,7 +2426,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
return 1;
}
nByte = strlen30(zSql);
- rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
char cSep = '(';
@@ -2199,7 +2452,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
xCloser(sCsv.in);
return 1;
}
- rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
}
sqlite3_free(zSql);
if( rc ){
@@ -2226,7 +2479,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}
zSql[j++] = ')';
zSql[j] = 0;
- rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
@@ -2645,6 +2898,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){
int i;
fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off");
+ fprintf(p->out,"%9.9s: %s\n","eqp", p->autoEQP ? "on" : "off");
fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off");
fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off");
fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]);
@@ -3037,7 +3291,10 @@ static int process_input(struct callback_data *p, FILE *in){
seenInterrupt = 0;
}
lineno++;
- if( nSql==0 && _all_whitespace(zLine) ) continue;
+ if( nSql==0 && _all_whitespace(zLine) ){
+ if( p->echoOn ) printf("%s\n", zLine);
+ continue;
+ }
if( zLine && zLine[0]=='.' && nSql==0 ){
if( p->echoOn ) printf("%s\n", zLine);
rc = do_meta_command(zLine, p);
@@ -3099,6 +3356,7 @@ static int process_input(struct callback_data *p, FILE *in){
}
nSql = 0;
}else if( nSql && _all_whitespace(zSql) ){
+ if( p->echoOn ) printf("%s\n", zSql);
nSql = 0;
}
}
@@ -3277,6 +3535,26 @@ static void main_init(struct callback_data *data) {
}
/*
+** Output text to the console in a font that attracts extra attention.
+*/
+#ifdef _WIN32
+static void printBold(const char *zText){
+ HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
+ CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
+ GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
+ SetConsoleTextAttribute(out,
+ FOREGROUND_RED|FOREGROUND_INTENSITY
+ );
+ printf("%s", zText);
+ SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
+}
+#else
+static void printBold(const char *zText){
+ printf("\033[1m%s\033[0m", zText);
+}
+#endif
+
+/*
** Get the argument to an --option. Throw an error and die if no argument
** is available.
*/
@@ -3296,12 +3574,15 @@ int main(int argc, char **argv){
char *zFirstCmd = 0;
int i;
int rc = 0;
+ int warnInmemoryDb = 0;
+#if USE_SYSTEM_SQLITE+0!=1
if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
sqlite3_sourceid(), SQLITE_SOURCE_ID);
exit(1);
}
+#endif
Argv0 = argv[0];
main_init(&data);
stdin_is_interactive = isatty(0);
@@ -3390,10 +3671,16 @@ int main(int argc, char **argv){
if( data.zDbFilename==0 ){
#ifndef SQLITE_OMIT_MEMORYDB
data.zDbFilename = ":memory:";
+ warnInmemoryDb = argc==1;
#else
fprintf(stderr,"%s: Error: no database filename specified\n", Argv0);
return 1;
#endif
+#ifdef SQLITE_SHELL_DBNAME_PROC
+ { extern void SQLITE_SHELL_DBNAME_PROC(const char**);
+ SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename);
+ warnInmemoryDb = 0; }
+#endif
}
data.out = stdout;
@@ -3449,6 +3736,8 @@ int main(int argc, char **argv){
data.showHeader = 0;
}else if( strcmp(z,"-echo")==0 ){
data.echoOn = 1;
+ }else if( strcmp(z,"-eqp")==0 ){
+ data.autoEQP = 1;
}else if( strcmp(z,"-stats")==0 ){
data.statsOn = 1;
}else if( strcmp(z,"-bail")==0 ){
@@ -3526,10 +3815,15 @@ int main(int argc, char **argv){
int nHistory;
printf(
"SQLite version %s %.19s\n" /*extra-version-info*/
- "Enter \".help\" for instructions\n"
- "Enter SQL statements terminated with a \";\"\n",
+ "Enter \".help\" for usage hints.\n",
sqlite3_libversion(), sqlite3_sourceid()
);
+ if( warnInmemoryDb ){
+ printf("Connected to a ");
+ printBold("transient in-memory database");
+ printf(".\nUse \".open FILENAME\" to reopen on a "
+ "persistent database.\n");
+ }
zHome = find_home_dir();
if( zHome ){
nHistory = strlen30(zHome) + 20;
@@ -3537,7 +3831,7 @@ int main(int argc, char **argv){
sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
}
}
-#if defined(HAVE_READLINE) && HAVE_READLINE==1
+#if defined(HAVE_READLINE)
if( zHistory ) read_history(zHistory);
#endif
rc = process_input(&data, 0);
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
index 9c73927982..a2e37dd48e 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.8.2. By combining all the individual C code files into this
+** version 3.8.4.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
@@ -25,6 +25,93 @@
#ifndef SQLITE_API
# define SQLITE_API
#endif
+/************** Begin file sqliteInt.h ***************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** Internal interface definitions for SQLite.
+**
+*/
+#ifndef _SQLITEINT_H_
+#define _SQLITEINT_H_
+
+/*
+** These #defines should enable >2GB file support on POSIX if the
+** underlying operating system supports it. If the OS lacks
+** large file support, or if the OS is windows, these should be no-ops.
+**
+** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any
+** system #includes. Hence, this block of code must be the very first
+** code in all source files.
+**
+** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
+** on the compiler command line. This is necessary if you are compiling
+** on a recent machine (ex: Red Hat 7.2) but you want your code to work
+** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2
+** without this option, LFS is enable. But LFS does not exist in the kernel
+** in Red Hat 6.0, so the code won't work. Hence, for maximum binary
+** portability you should omit LFS.
+**
+** The previous paragraph was written in 2005. (This paragraph is written
+** on 2008-11-28.) These days, all Linux kernels support large files, so
+** you should probably leave LFS enabled. But some embedded platforms might
+** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
+**
+** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later.
+*/
+#ifndef SQLITE_DISABLE_LFS
+# define _LARGE_FILE 1
+# ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 64
+# endif
+# define _LARGEFILE_SOURCE 1
+#endif
+
+/*
+** For MinGW, check to see if we can include the header file containing its
+** version information, among other things. Normally, this internal MinGW
+** header file would [only] be included automatically by other MinGW header
+** files; however, the contained version information is now required by this
+** header file to work around binary compatibility issues (see below) and
+** this is the only known way to reliably obtain it. This entire #if block
+** would be completely unnecessary if there was any other way of detecting
+** MinGW via their preprocessor (e.g. if they customized their GCC to define
+** some MinGW-specific macros). When compiling for MinGW, either the
+** _HAVE_MINGW_H or _HAVE__MINGW_H (note the extra underscore) macro must be
+** defined; otherwise, detection of conditions specific to MinGW will be
+** disabled.
+*/
+#if defined(_HAVE_MINGW_H)
+# include "mingw.h"
+#elif defined(_HAVE__MINGW_H)
+# include "_mingw.h"
+#endif
+
+/*
+** For MinGW version 4.x (and higher), check to see if the _USE_32BIT_TIME_T
+** define is required to maintain binary compatibility with the MSVC runtime
+** library in use (e.g. for Windows XP).
+*/
+#if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \
+ defined(_WIN32) && !defined(_WIN64) && \
+ defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \
+ defined(__MSVCRT__)
+# define _USE_32BIT_TIME_T
+#endif
+
+/* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear
+** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for
+** MinGW.
+*/
+/************** Include sqlite3.h in the middle of sqliteInt.h ***************/
/************** Begin file sqlite3.h *****************************************/
/*
** 2001 September 15
@@ -135,9 +222,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.8.2"
-#define SQLITE_VERSION_NUMBER 3008002
-#define SQLITE_SOURCE_ID "2013-12-06 14:53:30 27392118af4c38c5203a04b8013e1afdb1cebd0d"
+#define SQLITE_VERSION "3.8.4.1"
+#define SQLITE_VERSION_NUMBER 3008004
+#define SQLITE_SOURCE_ID "2014-03-11 15:27:36 018d317b1257ce68a92908b05c9c7cf1494050d0"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -519,6 +606,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
+#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8))
#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8))
@@ -586,7 +674,8 @@ SQLITE_API int sqlite3_exec(
** after reboot following a crash or power loss, the only bytes in a
** file that were written at the application level might have changed
** and that adjacent bytes, even bytes within the same sector are
-** guaranteed to be unchanged.
+** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
+** flag indicate that a file cannot be deleted when open.
*/
#define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002
@@ -817,15 +906,29 @@ struct sqlite3_io_methods {
** additional information.
**
** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
-** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
-** SQLite and sent to all VFSes in place of a call to the xSync method
-** when the database connection has [PRAGMA synchronous] set to OFF.)^
-** Some specialized VFSes need this signal in order to operate correctly
-** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
-** VFSes do not need this signal and should silently ignore this opcode.
-** Applications should not call [sqlite3_file_control()] with this
-** opcode as doing so may disrupt the operation of the specialized VFSes
-** that do require it.
+** No longer in use.
+**
+** <li>[[SQLITE_FCNTL_SYNC]]
+** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and
+** sent to the VFS immediately before the xSync method is invoked on a
+** database file descriptor. Or, if the xSync method is not invoked
+** because the user has configured SQLite with
+** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place
+** of the xSync method. In most cases, the pointer argument passed with
+** this file-control is NULL. However, if the database file is being synced
+** as part of a multi-database commit, the argument points to a nul-terminated
+** string containing the transactions master-journal file name. VFSes that
+** do not need this signal should silently ignore this opcode. Applications
+** should not call [sqlite3_file_control()] with this opcode as doing so may
+** disrupt the operation of the specialized VFSes that do require it.
+**
+** <li>[[SQLITE_FCNTL_COMMIT_PHASETWO]]
+** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite
+** and sent to the VFS after a transaction has been committed immediately
+** but before the database is unlocked. VFSes that do not need this signal
+** should silently ignore this opcode. Applications should not call
+** [sqlite3_file_control()] with this opcode as doing so may disrupt the
+** operation of the specialized VFSes that do require it.
**
** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
@@ -949,6 +1052,12 @@ struct sqlite3_io_methods {
** SQLite stack may generate instances of this file control if
** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled.
**
+** <li>[[SQLITE_FCNTL_HAS_MOVED]]
+** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
+** pointer to an integer and it writes a boolean into that integer depending
+** on whether or not the file has been renamed, moved, or deleted since it
+** was first opened.
+**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -969,6 +1078,9 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_TEMPFILENAME 16
#define SQLITE_FCNTL_MMAP_SIZE 18
#define SQLITE_FCNTL_TRACE 19
+#define SQLITE_FCNTL_HAS_MOVED 20
+#define SQLITE_FCNTL_SYNC 21
+#define SQLITE_FCNTL_COMMIT_PHASETWO 22
/*
** CAPI3REF: Mutex Handle
@@ -2403,11 +2515,13 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
** applications to access the same PRNG for other purposes.
**
** ^A call to this routine stores N bytes of randomness into buffer P.
+** ^If N is less than one, then P can be a NULL pointer.
**
-** ^The first time this routine is invoked (either internally or by
-** the application) the PRNG is seeded using randomness obtained
-** from the xRandomness method of the default [sqlite3_vfs] object.
-** ^On all subsequent invocations, the pseudo-randomness is generated
+** ^If this routine has not been previously called or if the previous
+** call had N less than one, then the PRNG is seeded using randomness
+** obtained from the xRandomness method of the default [sqlite3_vfs] object.
+** ^If the previous call to this routine had an N of 1 or more then
+** the pseudo-randomness is generated
** internally and without recourse to the [sqlite3_vfs] xRandomness
** method.
*/
@@ -2567,6 +2681,7 @@ SQLITE_API int sqlite3_set_authorizer(
#define SQLITE_FUNCTION 31 /* NULL Function Name */
#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */
#define SQLITE_COPY 0 /* No longer used */
+#define SQLITE_RECURSIVE 33 /* NULL NULL */
/*
** CAPI3REF: Tracing And Profiling Functions
@@ -3985,15 +4100,24 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
**
** ^The fourth parameter, eTextRep, specifies what
** [SQLITE_UTF8 | text encoding] this SQL function prefers for
-** its parameters. Every SQL function implementation must be able to work
-** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be
-** more efficient with one encoding than another. ^An application may
-** invoke sqlite3_create_function() or sqlite3_create_function16() multiple
-** times with the same function but with different values of eTextRep.
+** its parameters. The application should set this parameter to
+** [SQLITE_UTF16LE] if the function implementation invokes
+** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the
+** implementation invokes [sqlite3_value_text16be()] on an input, or
+** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8]
+** otherwise. ^The same SQL function may be registered multiple times using
+** different preferred text encodings, with different implementations for
+** each encoding.
** ^When multiple implementations of the same function are available, SQLite
** will pick the one that involves the least amount of data conversion.
-** If there is only a single implementation which does not care what text
-** encoding is used, then the fourth argument should be [SQLITE_ANY].
+**
+** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC]
+** to signal that the function will always return the same result given
+** the same inputs within a single SQL statement. Most SQL functions are
+** deterministic. The built-in [random()] SQL function is an example of a
+** function that is not deterministic. The SQLite query planner is able to
+** perform additional optimizations on deterministic functions, so use
+** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
**
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
** function can gain access to this pointer using [sqlite3_user_data()].)^
@@ -4079,10 +4203,20 @@ SQLITE_API int sqlite3_create_function_v2(
#define SQLITE_UTF16LE 2
#define SQLITE_UTF16BE 3
#define SQLITE_UTF16 4 /* Use native byte order */
-#define SQLITE_ANY 5 /* sqlite3_create_function only */
+#define SQLITE_ANY 5 /* Deprecated */
#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
/*
+** CAPI3REF: Function Flags
+**
+** These constants may be ORed together with the
+** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
+** to [sqlite3_create_function()], [sqlite3_create_function16()], or
+** [sqlite3_create_function_v2()].
+*/
+#define SQLITE_DETERMINISTIC 0x800
+
+/*
** CAPI3REF: Deprecated Functions
** DEPRECATED
**
@@ -6103,7 +6237,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
-#define SQLITE_TESTCTRL_LAST 20
+#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
+#define SQLITE_TESTCTRL_LAST 21
/*
** CAPI3REF: SQLite Runtime Status
@@ -7366,50 +7501,7 @@ struct sqlite3_rtree_geometry {
/************** End of sqlite3.h *********************************************/
-/************** Begin file sqliteInt.h ***************************************/
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** Internal interface definitions for SQLite.
-**
-*/
-#ifndef _SQLITEINT_H_
-#define _SQLITEINT_H_
-
-/*
-** These #defines should enable >2GB file support on POSIX if the
-** underlying operating system supports it. If the OS lacks
-** large file support, or if the OS is windows, these should be no-ops.
-**
-** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any
-** system #includes. Hence, this block of code must be the very first
-** code in all source files.
-**
-** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
-** on the compiler command line. This is necessary if you are compiling
-** on a recent machine (ex: Red Hat 7.2) but you want your code to work
-** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2
-** without this option, LFS is enable. But LFS does not exist in the kernel
-** in Red Hat 6.0, so the code won't work. Hence, for maximum binary
-** portability you should omit LFS.
-**
-** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later.
-*/
-#ifndef SQLITE_DISABLE_LFS
-# define _LARGE_FILE 1
-# ifndef _FILE_OFFSET_BITS
-# define _FILE_OFFSET_BITS 64
-# endif
-# define _LARGEFILE_SOURCE 1
-#endif
+/************** Continuing where we left off in sqliteInt.h ******************/
/*
** Include the configuration header output by 'configure' if we're using the
@@ -7996,163 +8088,165 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
/************** Continuing where we left off in sqliteInt.h ******************/
/************** Include parse.h in the middle of sqliteInt.h *****************/
/************** Begin file parse.h *******************************************/
-#define TK_SEMI 1
-#define TK_EXPLAIN 2
-#define TK_QUERY 3
-#define TK_PLAN 4
-#define TK_BEGIN 5
-#define TK_TRANSACTION 6
-#define TK_DEFERRED 7
-#define TK_IMMEDIATE 8
-#define TK_EXCLUSIVE 9
-#define TK_COMMIT 10
-#define TK_END 11
-#define TK_ROLLBACK 12
-#define TK_SAVEPOINT 13
-#define TK_RELEASE 14
-#define TK_TO 15
-#define TK_TABLE 16
-#define TK_CREATE 17
-#define TK_IF 18
-#define TK_NOT 19
-#define TK_EXISTS 20
-#define TK_TEMP 21
-#define TK_LP 22
-#define TK_RP 23
-#define TK_AS 24
-#define TK_WITHOUT 25
-#define TK_COMMA 26
-#define TK_ID 27
-#define TK_INDEXED 28
-#define TK_ABORT 29
-#define TK_ACTION 30
-#define TK_AFTER 31
-#define TK_ANALYZE 32
-#define TK_ASC 33
-#define TK_ATTACH 34
-#define TK_BEFORE 35
-#define TK_BY 36
-#define TK_CASCADE 37
-#define TK_CAST 38
-#define TK_COLUMNKW 39
-#define TK_CONFLICT 40
-#define TK_DATABASE 41
-#define TK_DESC 42
-#define TK_DETACH 43
-#define TK_EACH 44
-#define TK_FAIL 45
-#define TK_FOR 46
-#define TK_IGNORE 47
-#define TK_INITIALLY 48
-#define TK_INSTEAD 49
-#define TK_LIKE_KW 50
-#define TK_MATCH 51
-#define TK_NO 52
-#define TK_KEY 53
-#define TK_OF 54
-#define TK_OFFSET 55
-#define TK_PRAGMA 56
-#define TK_RAISE 57
-#define TK_REPLACE 58
-#define TK_RESTRICT 59
-#define TK_ROW 60
-#define TK_TRIGGER 61
-#define TK_VACUUM 62
-#define TK_VIEW 63
-#define TK_VIRTUAL 64
-#define TK_REINDEX 65
-#define TK_RENAME 66
-#define TK_CTIME_KW 67
-#define TK_ANY 68
-#define TK_OR 69
-#define TK_AND 70
-#define TK_IS 71
-#define TK_BETWEEN 72
-#define TK_IN 73
-#define TK_ISNULL 74
-#define TK_NOTNULL 75
-#define TK_NE 76
-#define TK_EQ 77
-#define TK_GT 78
-#define TK_LE 79
-#define TK_LT 80
-#define TK_GE 81
-#define TK_ESCAPE 82
-#define TK_BITAND 83
-#define TK_BITOR 84
-#define TK_LSHIFT 85
-#define TK_RSHIFT 86
-#define TK_PLUS 87
-#define TK_MINUS 88
-#define TK_STAR 89
-#define TK_SLASH 90
-#define TK_REM 91
-#define TK_CONCAT 92
-#define TK_COLLATE 93
-#define TK_BITNOT 94
-#define TK_STRING 95
-#define TK_JOIN_KW 96
-#define TK_CONSTRAINT 97
-#define TK_DEFAULT 98
-#define TK_NULL 99
-#define TK_PRIMARY 100
-#define TK_UNIQUE 101
-#define TK_CHECK 102
-#define TK_REFERENCES 103
-#define TK_AUTOINCR 104
-#define TK_ON 105
-#define TK_INSERT 106
-#define TK_DELETE 107
-#define TK_UPDATE 108
-#define TK_SET 109
-#define TK_DEFERRABLE 110
-#define TK_FOREIGN 111
-#define TK_DROP 112
-#define TK_UNION 113
-#define TK_ALL 114
-#define TK_EXCEPT 115
-#define TK_INTERSECT 116
-#define TK_SELECT 117
-#define TK_DISTINCT 118
-#define TK_DOT 119
-#define TK_FROM 120
-#define TK_JOIN 121
-#define TK_USING 122
-#define TK_ORDER 123
-#define TK_GROUP 124
-#define TK_HAVING 125
-#define TK_LIMIT 126
-#define TK_WHERE 127
-#define TK_INTO 128
-#define TK_VALUES 129
-#define TK_INTEGER 130
-#define TK_FLOAT 131
-#define TK_BLOB 132
-#define TK_REGISTER 133
-#define TK_VARIABLE 134
-#define TK_CASE 135
-#define TK_WHEN 136
-#define TK_THEN 137
-#define TK_ELSE 138
-#define TK_INDEX 139
-#define TK_ALTER 140
-#define TK_ADD 141
-#define TK_TO_TEXT 142
-#define TK_TO_BLOB 143
-#define TK_TO_NUMERIC 144
-#define TK_TO_INT 145
-#define TK_TO_REAL 146
-#define TK_ISNOT 147
-#define TK_END_OF_FILE 148
-#define TK_ILLEGAL 149
-#define TK_SPACE 150
-#define TK_UNCLOSED_STRING 151
-#define TK_FUNCTION 152
-#define TK_COLUMN 153
-#define TK_AGG_FUNCTION 154
-#define TK_AGG_COLUMN 155
-#define TK_UMINUS 156
-#define TK_UPLUS 157
+#define TK_SEMI 1
+#define TK_EXPLAIN 2
+#define TK_QUERY 3
+#define TK_PLAN 4
+#define TK_BEGIN 5
+#define TK_TRANSACTION 6
+#define TK_DEFERRED 7
+#define TK_IMMEDIATE 8
+#define TK_EXCLUSIVE 9
+#define TK_COMMIT 10
+#define TK_END 11
+#define TK_ROLLBACK 12
+#define TK_SAVEPOINT 13
+#define TK_RELEASE 14
+#define TK_TO 15
+#define TK_TABLE 16
+#define TK_CREATE 17
+#define TK_IF 18
+#define TK_NOT 19
+#define TK_EXISTS 20
+#define TK_TEMP 21
+#define TK_LP 22
+#define TK_RP 23
+#define TK_AS 24
+#define TK_WITHOUT 25
+#define TK_COMMA 26
+#define TK_ID 27
+#define TK_INDEXED 28
+#define TK_ABORT 29
+#define TK_ACTION 30
+#define TK_AFTER 31
+#define TK_ANALYZE 32
+#define TK_ASC 33
+#define TK_ATTACH 34
+#define TK_BEFORE 35
+#define TK_BY 36
+#define TK_CASCADE 37
+#define TK_CAST 38
+#define TK_COLUMNKW 39
+#define TK_CONFLICT 40
+#define TK_DATABASE 41
+#define TK_DESC 42
+#define TK_DETACH 43
+#define TK_EACH 44
+#define TK_FAIL 45
+#define TK_FOR 46
+#define TK_IGNORE 47
+#define TK_INITIALLY 48
+#define TK_INSTEAD 49
+#define TK_LIKE_KW 50
+#define TK_MATCH 51
+#define TK_NO 52
+#define TK_KEY 53
+#define TK_OF 54
+#define TK_OFFSET 55
+#define TK_PRAGMA 56
+#define TK_RAISE 57
+#define TK_RECURSIVE 58
+#define TK_REPLACE 59
+#define TK_RESTRICT 60
+#define TK_ROW 61
+#define TK_TRIGGER 62
+#define TK_VACUUM 63
+#define TK_VIEW 64
+#define TK_VIRTUAL 65
+#define TK_WITH 66
+#define TK_REINDEX 67
+#define TK_RENAME 68
+#define TK_CTIME_KW 69
+#define TK_ANY 70
+#define TK_OR 71
+#define TK_AND 72
+#define TK_IS 73
+#define TK_BETWEEN 74
+#define TK_IN 75
+#define TK_ISNULL 76
+#define TK_NOTNULL 77
+#define TK_NE 78
+#define TK_EQ 79
+#define TK_GT 80
+#define TK_LE 81
+#define TK_LT 82
+#define TK_GE 83
+#define TK_ESCAPE 84
+#define TK_BITAND 85
+#define TK_BITOR 86
+#define TK_LSHIFT 87
+#define TK_RSHIFT 88
+#define TK_PLUS 89
+#define TK_MINUS 90
+#define TK_STAR 91
+#define TK_SLASH 92
+#define TK_REM 93
+#define TK_CONCAT 94
+#define TK_COLLATE 95
+#define TK_BITNOT 96
+#define TK_STRING 97
+#define TK_JOIN_KW 98
+#define TK_CONSTRAINT 99
+#define TK_DEFAULT 100
+#define TK_NULL 101
+#define TK_PRIMARY 102
+#define TK_UNIQUE 103
+#define TK_CHECK 104
+#define TK_REFERENCES 105
+#define TK_AUTOINCR 106
+#define TK_ON 107
+#define TK_INSERT 108
+#define TK_DELETE 109
+#define TK_UPDATE 110
+#define TK_SET 111
+#define TK_DEFERRABLE 112
+#define TK_FOREIGN 113
+#define TK_DROP 114
+#define TK_UNION 115
+#define TK_ALL 116
+#define TK_EXCEPT 117
+#define TK_INTERSECT 118
+#define TK_SELECT 119
+#define TK_VALUES 120
+#define TK_DISTINCT 121
+#define TK_DOT 122
+#define TK_FROM 123
+#define TK_JOIN 124
+#define TK_USING 125
+#define TK_ORDER 126
+#define TK_GROUP 127
+#define TK_HAVING 128
+#define TK_LIMIT 129
+#define TK_WHERE 130
+#define TK_INTO 131
+#define TK_INTEGER 132
+#define TK_FLOAT 133
+#define TK_BLOB 134
+#define TK_VARIABLE 135
+#define TK_CASE 136
+#define TK_WHEN 137
+#define TK_THEN 138
+#define TK_ELSE 139
+#define TK_INDEX 140
+#define TK_ALTER 141
+#define TK_ADD 142
+#define TK_TO_TEXT 143
+#define TK_TO_BLOB 144
+#define TK_TO_NUMERIC 145
+#define TK_TO_INT 146
+#define TK_TO_REAL 147
+#define TK_ISNOT 148
+#define TK_END_OF_FILE 149
+#define TK_ILLEGAL 150
+#define TK_SPACE 151
+#define TK_UNCLOSED_STRING 152
+#define TK_FUNCTION 153
+#define TK_COLUMN 154
+#define TK_AGG_FUNCTION 155
+#define TK_AGG_COLUMN 156
+#define TK_UMINUS 157
+#define TK_UPLUS 158
+#define TK_REGISTER 159
/************** End of parse.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
@@ -8583,6 +8677,7 @@ typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
typedef struct Parse Parse;
+typedef struct PrintfArguments PrintfArguments;
typedef struct RowSet RowSet;
typedef struct Savepoint Savepoint;
typedef struct Select Select;
@@ -8600,6 +8695,7 @@ typedef struct VTable VTable;
typedef struct VtabCtx VtabCtx;
typedef struct Walker Walker;
typedef struct WhereInfo WhereInfo;
+typedef struct With With;
/*
** Defer sourcing vdbe.h and btree.h until after the "u8" and
@@ -8792,8 +8888,6 @@ SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor*, u32 *pAmt);
SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor*, u32 *pAmt);
SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
-SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor*, sqlite3_int64);
-SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor*);
SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);
@@ -8933,9 +9027,12 @@ struct VdbeOp {
char *zComment; /* Comment to improve readability */
#endif
#ifdef VDBE_PROFILE
- int cnt; /* Number of times this instruction was executed */
+ u32 cnt; /* Number of times this instruction was executed */
u64 cycles; /* Total time spent executing this instruction */
#endif
+#ifdef SQLITE_VDBE_COVERAGE
+ int iSrcLine; /* Source-code line that generated this opcode */
+#endif
};
typedef struct VdbeOp VdbeOp;
@@ -9045,139 +9142,143 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Gosub 17
#define OP_Return 18
#define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */
-#define OP_Yield 20
-#define OP_HaltIfNull 21 /* synopsis: if r[P3] null then halt */
-#define OP_Halt 22
-#define OP_Integer 23 /* synopsis: r[P2]=P1 */
-#define OP_Int64 24 /* synopsis: r[P2]=P4 */
-#define OP_String 25 /* synopsis: r[P2]='P4' (len=P1) */
-#define OP_Null 26 /* synopsis: r[P2..P3]=NULL */
-#define OP_Blob 27 /* synopsis: r[P2]=P4 (len=P1) */
-#define OP_Variable 28 /* synopsis: r[P2]=parameter(P1,P4) */
-#define OP_Move 29 /* synopsis: r[P2@P3]=r[P1@P3] */
-#define OP_Copy 30 /* synopsis: r[P2@P3]=r[P1@P3] */
-#define OP_SCopy 31 /* synopsis: r[P2]=r[P1] */
-#define OP_ResultRow 32 /* synopsis: output=r[P1@P2] */
-#define OP_CollSeq 33
-#define OP_AddImm 34 /* synopsis: r[P1]=r[P1]+P2 */
-#define OP_MustBeInt 35
-#define OP_RealAffinity 36
-#define OP_Permutation 37
-#define OP_Compare 38
-#define OP_Jump 39
-#define OP_Once 40
-#define OP_If 41
-#define OP_IfNot 42
-#define OP_Column 43 /* synopsis: r[P3]=PX */
-#define OP_Affinity 44 /* synopsis: affinity(r[P1@P2]) */
-#define OP_MakeRecord 45 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
-#define OP_Count 46 /* synopsis: r[P2]=count() */
-#define OP_ReadCookie 47
-#define OP_SetCookie 48
-#define OP_VerifyCookie 49
-#define OP_OpenRead 50 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenWrite 51 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenAutoindex 52 /* synopsis: nColumn=P2 */
-#define OP_OpenEphemeral 53 /* synopsis: nColumn=P2 */
-#define OP_SorterOpen 54
-#define OP_OpenPseudo 55 /* synopsis: content in r[P2@P3] */
-#define OP_Close 56
-#define OP_SeekLt 57 /* synopsis: key=r[P3@P4] */
-#define OP_SeekLe 58 /* synopsis: key=r[P3@P4] */
-#define OP_SeekGe 59 /* synopsis: key=r[P3@P4] */
-#define OP_SeekGt 60 /* synopsis: key=r[P3@P4] */
-#define OP_Seek 61 /* synopsis: intkey=r[P2] */
-#define OP_NoConflict 62 /* synopsis: key=r[P3@P4] */
-#define OP_NotFound 63 /* synopsis: key=r[P3@P4] */
-#define OP_Found 64 /* synopsis: key=r[P3@P4] */
-#define OP_NotExists 65 /* synopsis: intkey=r[P3] */
-#define OP_Sequence 66 /* synopsis: r[P2]=rowid */
-#define OP_NewRowid 67 /* synopsis: r[P2]=rowid */
-#define OP_Insert 68 /* synopsis: intkey=r[P3] data=r[P2] */
-#define OP_Or 69 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
-#define OP_And 70 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
-#define OP_InsertInt 71 /* synopsis: intkey=P3 data=r[P2] */
-#define OP_Delete 72
-#define OP_ResetCount 73
-#define OP_IsNull 74 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
-#define OP_NotNull 75 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
-#define OP_Ne 76 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */
-#define OP_Eq 77 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */
-#define OP_Gt 78 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */
-#define OP_Le 79 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */
-#define OP_Lt 80 /* same as TK_LT, synopsis: if r[P1]<r[P3] goto P2 */
-#define OP_Ge 81 /* same as TK_GE, synopsis: if r[P1]>=r[P3] goto P2 */
-#define OP_SorterCompare 82 /* synopsis: if key(P1)!=rtrim(r[P3],P4) goto P2 */
-#define OP_BitAnd 83 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
-#define OP_BitOr 84 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
-#define OP_ShiftLeft 85 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
-#define OP_ShiftRight 86 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
-#define OP_Add 87 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
-#define OP_Subtract 88 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
-#define OP_Multiply 89 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
-#define OP_Divide 90 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
-#define OP_Remainder 91 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
-#define OP_Concat 92 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
-#define OP_SorterData 93 /* synopsis: r[P2]=data */
-#define OP_BitNot 94 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
-#define OP_String8 95 /* same as TK_STRING, synopsis: r[P2]='P4' */
-#define OP_RowKey 96 /* synopsis: r[P2]=key */
-#define OP_RowData 97 /* synopsis: r[P2]=data */
-#define OP_Rowid 98 /* synopsis: r[P2]=rowid */
-#define OP_NullRow 99
-#define OP_Last 100
-#define OP_SorterSort 101
-#define OP_Sort 102
-#define OP_Rewind 103
-#define OP_SorterInsert 104
-#define OP_IdxInsert 105 /* synopsis: key=r[P2] */
-#define OP_IdxDelete 106 /* synopsis: key=r[P2@P3] */
-#define OP_IdxRowid 107 /* synopsis: r[P2]=rowid */
-#define OP_IdxLT 108 /* synopsis: key=r[P3@P4] */
-#define OP_IdxGE 109 /* synopsis: key=r[P3@P4] */
-#define OP_Destroy 110
-#define OP_Clear 111
-#define OP_CreateIndex 112 /* synopsis: r[P2]=root iDb=P1 */
-#define OP_CreateTable 113 /* synopsis: r[P2]=root iDb=P1 */
-#define OP_ParseSchema 114
-#define OP_LoadAnalysis 115
-#define OP_DropTable 116
-#define OP_DropIndex 117
-#define OP_DropTrigger 118
-#define OP_IntegrityCk 119
-#define OP_RowSetAdd 120 /* synopsis: rowset(P1)=r[P2] */
-#define OP_RowSetRead 121 /* synopsis: r[P3]=rowset(P1) */
-#define OP_RowSetTest 122 /* synopsis: if r[P3] in rowset(P1) goto P2 */
-#define OP_Program 123
-#define OP_Param 124
-#define OP_FkCounter 125 /* synopsis: fkctr[P1]+=P2 */
-#define OP_FkIfZero 126 /* synopsis: if fkctr[P1]==0 goto P2 */
-#define OP_MemMax 127 /* synopsis: r[P1]=max(r[P1],r[P2]) */
-#define OP_IfPos 128 /* synopsis: if r[P1]>0 goto P2 */
-#define OP_IfNeg 129 /* synopsis: if r[P1]<0 goto P2 */
-#define OP_IfZero 130 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2 */
-#define OP_Real 131 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
-#define OP_AggFinal 132 /* synopsis: accum=r[P1] N=P2 */
-#define OP_IncrVacuum 133
-#define OP_Expire 134
-#define OP_TableLock 135 /* synopsis: iDb=P1 root=P2 write=P3 */
-#define OP_VBegin 136
-#define OP_VCreate 137
-#define OP_VDestroy 138
-#define OP_VOpen 139
-#define OP_VColumn 140 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VNext 141
-#define OP_ToText 142 /* same as TK_TO_TEXT */
-#define OP_ToBlob 143 /* same as TK_TO_BLOB */
-#define OP_ToNumeric 144 /* same as TK_TO_NUMERIC */
-#define OP_ToInt 145 /* same as TK_TO_INT */
-#define OP_ToReal 146 /* same as TK_TO_REAL */
-#define OP_VRename 147
-#define OP_Pagecount 148
-#define OP_MaxPgcnt 149
-#define OP_Trace 150
-#define OP_Noop 151
-#define OP_Explain 152
+#define OP_InitCoroutine 20
+#define OP_EndCoroutine 21
+#define OP_Yield 22
+#define OP_HaltIfNull 23 /* synopsis: if r[P3]=null halt */
+#define OP_Halt 24
+#define OP_Integer 25 /* synopsis: r[P2]=P1 */
+#define OP_Int64 26 /* synopsis: r[P2]=P4 */
+#define OP_String 27 /* synopsis: r[P2]='P4' (len=P1) */
+#define OP_Null 28 /* synopsis: r[P2..P3]=NULL */
+#define OP_SoftNull 29 /* synopsis: r[P1]=NULL */
+#define OP_Blob 30 /* synopsis: r[P2]=P4 (len=P1) */
+#define OP_Variable 31 /* synopsis: r[P2]=parameter(P1,P4) */
+#define OP_Move 32 /* synopsis: r[P2@P3]=r[P1@P3] */
+#define OP_Copy 33 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
+#define OP_SCopy 34 /* synopsis: r[P2]=r[P1] */
+#define OP_ResultRow 35 /* synopsis: output=r[P1@P2] */
+#define OP_CollSeq 36
+#define OP_AddImm 37 /* synopsis: r[P1]=r[P1]+P2 */
+#define OP_MustBeInt 38
+#define OP_RealAffinity 39
+#define OP_Permutation 40
+#define OP_Compare 41
+#define OP_Jump 42
+#define OP_Once 43
+#define OP_If 44
+#define OP_IfNot 45
+#define OP_Column 46 /* synopsis: r[P3]=PX */
+#define OP_Affinity 47 /* synopsis: affinity(r[P1@P2]) */
+#define OP_MakeRecord 48 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
+#define OP_Count 49 /* synopsis: r[P2]=count() */
+#define OP_ReadCookie 50
+#define OP_SetCookie 51
+#define OP_OpenRead 52 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenWrite 53 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenAutoindex 54 /* synopsis: nColumn=P2 */
+#define OP_OpenEphemeral 55 /* synopsis: nColumn=P2 */
+#define OP_SorterOpen 56
+#define OP_OpenPseudo 57 /* synopsis: P3 columns in r[P2] */
+#define OP_Close 58
+#define OP_SeekLT 59
+#define OP_SeekLE 60
+#define OP_SeekGE 61
+#define OP_SeekGT 62
+#define OP_Seek 63 /* synopsis: intkey=r[P2] */
+#define OP_NoConflict 64 /* synopsis: key=r[P3@P4] */
+#define OP_NotFound 65 /* synopsis: key=r[P3@P4] */
+#define OP_Found 66 /* synopsis: key=r[P3@P4] */
+#define OP_NotExists 67 /* synopsis: intkey=r[P3] */
+#define OP_Sequence 68 /* synopsis: r[P2]=rowid */
+#define OP_NewRowid 69 /* synopsis: r[P2]=rowid */
+#define OP_Insert 70 /* synopsis: intkey=r[P3] data=r[P2] */
+#define OP_Or 71 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
+#define OP_And 72 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
+#define OP_InsertInt 73 /* synopsis: intkey=P3 data=r[P2] */
+#define OP_Delete 74
+#define OP_ResetCount 75
+#define OP_IsNull 76 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
+#define OP_NotNull 77 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
+#define OP_Ne 78 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */
+#define OP_Eq 79 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */
+#define OP_Gt 80 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */
+#define OP_Le 81 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */
+#define OP_Lt 82 /* same as TK_LT, synopsis: if r[P1]<r[P3] goto P2 */
+#define OP_Ge 83 /* same as TK_GE, synopsis: if r[P1]>=r[P3] goto P2 */
+#define OP_SorterCompare 84 /* synopsis: if key(P1)!=rtrim(r[P3],P4) goto P2 */
+#define OP_BitAnd 85 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr 86 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft 87 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
+#define OP_ShiftRight 88 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
+#define OP_Add 89 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract 90 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply 91 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide 92 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder 93 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat 94 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
+#define OP_SorterData 95 /* synopsis: r[P2]=data */
+#define OP_BitNot 96 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
+#define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */
+#define OP_RowKey 98 /* synopsis: r[P2]=key */
+#define OP_RowData 99 /* synopsis: r[P2]=data */
+#define OP_Rowid 100 /* synopsis: r[P2]=rowid */
+#define OP_NullRow 101
+#define OP_Last 102
+#define OP_SorterSort 103
+#define OP_Sort 104
+#define OP_Rewind 105
+#define OP_SorterInsert 106
+#define OP_IdxInsert 107 /* synopsis: key=r[P2] */
+#define OP_IdxDelete 108 /* synopsis: key=r[P2@P3] */
+#define OP_IdxRowid 109 /* synopsis: r[P2]=rowid */
+#define OP_IdxLE 110 /* synopsis: key=r[P3@P4] */
+#define OP_IdxGT 111 /* synopsis: key=r[P3@P4] */
+#define OP_IdxLT 112 /* synopsis: key=r[P3@P4] */
+#define OP_IdxGE 113 /* synopsis: key=r[P3@P4] */
+#define OP_Destroy 114
+#define OP_Clear 115
+#define OP_CreateIndex 116 /* synopsis: r[P2]=root iDb=P1 */
+#define OP_CreateTable 117 /* synopsis: r[P2]=root iDb=P1 */
+#define OP_ParseSchema 118
+#define OP_LoadAnalysis 119
+#define OP_DropTable 120
+#define OP_DropIndex 121
+#define OP_DropTrigger 122
+#define OP_IntegrityCk 123
+#define OP_RowSetAdd 124 /* synopsis: rowset(P1)=r[P2] */
+#define OP_RowSetRead 125 /* synopsis: r[P3]=rowset(P1) */
+#define OP_RowSetTest 126 /* synopsis: if r[P3] in rowset(P1) goto P2 */
+#define OP_Program 127
+#define OP_Param 128
+#define OP_FkCounter 129 /* synopsis: fkctr[P1]+=P2 */
+#define OP_FkIfZero 130 /* synopsis: if fkctr[P1]==0 goto P2 */
+#define OP_MemMax 131 /* synopsis: r[P1]=max(r[P1],r[P2]) */
+#define OP_IfPos 132 /* synopsis: if r[P1]>0 goto P2 */
+#define OP_Real 133 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
+#define OP_IfNeg 134 /* synopsis: if r[P1]<0 goto P2 */
+#define OP_IfZero 135 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2 */
+#define OP_AggFinal 136 /* synopsis: accum=r[P1] N=P2 */
+#define OP_IncrVacuum 137
+#define OP_Expire 138
+#define OP_TableLock 139 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 140
+#define OP_VCreate 141
+#define OP_VDestroy 142
+#define OP_ToText 143 /* same as TK_TO_TEXT */
+#define OP_ToBlob 144 /* same as TK_TO_BLOB */
+#define OP_ToNumeric 145 /* same as TK_TO_NUMERIC */
+#define OP_ToInt 146 /* same as TK_TO_INT */
+#define OP_ToReal 147 /* same as TK_TO_REAL */
+#define OP_VOpen 148
+#define OP_VColumn 149 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VNext 150
+#define OP_VRename 151
+#define OP_Pagecount 152
+#define OP_MaxPgcnt 153
+#define OP_Init 154 /* synopsis: Start at P2 */
+#define OP_Noop 155
+#define OP_Explain 156
/* Properties such as "out2" or "jump" that are specified in
@@ -9194,24 +9295,24 @@ typedef struct VdbeOpList VdbeOpList;
#define OPFLG_INITIALIZER {\
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,\
/* 8 */ 0x01, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,\
-/* 16 */ 0x01, 0x01, 0x04, 0x24, 0x04, 0x10, 0x00, 0x02,\
-/* 24 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x20,\
-/* 32 */ 0x00, 0x00, 0x04, 0x05, 0x04, 0x00, 0x00, 0x01,\
-/* 40 */ 0x01, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x02,\
-/* 48 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 56 */ 0x00, 0x11, 0x11, 0x11, 0x11, 0x08, 0x11, 0x11,\
-/* 64 */ 0x11, 0x11, 0x02, 0x02, 0x00, 0x4c, 0x4c, 0x00,\
-/* 72 */ 0x00, 0x00, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15,\
-/* 80 */ 0x15, 0x15, 0x00, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
-/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00, 0x24, 0x02,\
-/* 96 */ 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,\
-/* 104 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\
-/* 112 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 120 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\
-/* 128 */ 0x05, 0x05, 0x05, 0x02, 0x00, 0x01, 0x00, 0x00,\
-/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x04,\
-/* 144 */ 0x04, 0x04, 0x04, 0x00, 0x02, 0x02, 0x00, 0x00,\
-/* 152 */ 0x00,}
+/* 16 */ 0x01, 0x01, 0x04, 0x24, 0x01, 0x04, 0x05, 0x10,\
+/* 24 */ 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\
+/* 32 */ 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x05, 0x04,\
+/* 40 */ 0x00, 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00,\
+/* 48 */ 0x00, 0x02, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00,\
+/* 56 */ 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x08,\
+/* 64 */ 0x11, 0x11, 0x11, 0x11, 0x02, 0x02, 0x00, 0x4c,\
+/* 72 */ 0x4c, 0x00, 0x00, 0x00, 0x05, 0x05, 0x15, 0x15,\
+/* 80 */ 0x15, 0x15, 0x15, 0x15, 0x00, 0x4c, 0x4c, 0x4c,\
+/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00,\
+/* 96 */ 0x24, 0x02, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01,\
+/* 104 */ 0x01, 0x01, 0x08, 0x08, 0x00, 0x02, 0x01, 0x01,\
+/* 112 */ 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00,\
+/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x45, 0x15, 0x01,\
+/* 128 */ 0x02, 0x00, 0x01, 0x08, 0x05, 0x02, 0x05, 0x05,\
+/* 136 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,\
+/* 144 */ 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x01, 0x00,\
+/* 152 */ 0x02, 0x02, 0x01, 0x00, 0x00,}
/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
@@ -9220,14 +9321,14 @@ typedef struct VdbeOpList VdbeOpList;
** Prototypes for the VDBE interface. See comments on the implementation
** for a description of what each of these routines does.
*/
-SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3*);
+SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse*);
SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int);
SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
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 sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
-SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
+SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
@@ -9235,6 +9336,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
+SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
@@ -9267,9 +9369,12 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
#endif
SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
-SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
+SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,const UnpackedRecord*,int);
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
+typedef int (*RecordCompare)(int,const void*,const UnpackedRecord*,int);
+SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
+
#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif
@@ -9297,6 +9402,43 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
# define VdbeModuleComment(X)
#endif
+/*
+** The VdbeCoverage macros are used to set a coverage testing point
+** for VDBE branch instructions. The coverage testing points are line
+** numbers in the sqlite3.c source file. VDBE branch coverage testing
+** only works with an amalagmation build. That's ok since a VDBE branch
+** coverage build designed for testing the test suite only. No application
+** should ever ship with VDBE branch coverage measuring turned on.
+**
+** VdbeCoverage(v) // Mark the previously coded instruction
+** // as a branch
+**
+** VdbeCoverageIf(v, conditional) // Mark previous if conditional true
+**
+** VdbeCoverageAlwaysTaken(v) // Previous branch is always taken
+**
+** VdbeCoverageNeverTaken(v) // Previous branch is never taken
+**
+** Every VDBE branch operation must be tagged with one of the macros above.
+** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and
+** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch()
+** routine in vdbe.c, alerting the developer to the missed tag.
+*/
+#ifdef SQLITE_VDBE_COVERAGE
+SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe*,int);
+# define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__)
+# define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__)
+# define VdbeCoverageAlwaysTaken(v) sqlite3VdbeSetLineNumber(v,2);
+# define VdbeCoverageNeverTaken(v) sqlite3VdbeSetLineNumber(v,1);
+# define VDBE_OFFSET_LINENO(x) (__LINE__+x)
+#else
+# define VdbeCoverage(v)
+# define VdbeCoverageIf(v,x)
+# define VdbeCoverageAlwaysTaken(v)
+# define VdbeCoverageNeverTaken(v)
+# define VDBE_OFFSET_LINENO(x) 0
+#endif
+
#endif
/************** End of vdbe.h ************************************************/
@@ -9441,6 +9583,7 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage
SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
SQLITE_PRIVATE void sqlite3PagerRef(DbPage*);
SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*);
+SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage*);
/* Operations on page references. */
SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*);
@@ -9455,7 +9598,7 @@ SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*);
SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int);
SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int);
SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*);
-SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager);
+SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster);
SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*);
SQLITE_PRIVATE int sqlite3PagerRollback(Pager*);
SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
@@ -10327,7 +10470,7 @@ struct sqlite3 {
#define SQLITE_ColumnCache 0x0002 /* Column cache */
#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
-#define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */
+/* not used 0x0010 // Was: SQLITE_IdxRealAsInt */
#define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */
#define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */
#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */
@@ -10353,8 +10496,7 @@ struct sqlite3 {
** Return true if it OK to factor constant expressions into the initialization
** code. The argument is a Parse object for the code generator.
*/
-#define ConstFactorOk(P) \
- ((P)->cookieGoto>0 && OptimizationEnabled((P)->db,SQLITE_FactorOutConst))
+#define ConstFactorOk(P) ((P)->okConstFactor)
/*
** Possible values for the sqlite.magic field.
@@ -10580,10 +10722,16 @@ struct CollSeq {
/*
** Additional bit values that can be ORed with an affinity without
** changing the affinity.
+**
+** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL.
+** It causes an assert() to fire if either operand to a comparison
+** operator is NULL. It is added to certain comparison operators to
+** prove that the operands are always NOT NULL.
*/
#define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */
#define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */
#define SQLITE_NULLEQ 0x80 /* NULL=NULL */
+#define SQLITE_NOTNULL 0x88 /* Assert that operands are never NULL */
/*
** An object of this type is created for each virtual table present in
@@ -10699,7 +10847,7 @@ struct Table {
};
/*
-** Allowed values for Tabe.tabFlags.
+** Allowed values for Table.tabFlags.
*/
#define TF_Readonly 0x01 /* Read-only system table */
#define TF_Ephemeral 0x02 /* An ephemeral table */
@@ -10842,19 +10990,19 @@ struct KeyInfo {
**
** This structure holds a record that has already been disassembled
** into its constituent fields.
+**
+** The r1 and r2 member variables are only used by the optimized comparison
+** functions vdbeRecordCompareInt() and vdbeRecordCompareString().
*/
struct UnpackedRecord {
KeyInfo *pKeyInfo; /* Collation and sort-order information */
u16 nField; /* Number of entries in apMem[] */
- u8 flags; /* Boolean settings. UNPACKED_... below */
+ i8 default_rc; /* Comparison result if keys are equal */
Mem *aMem; /* Values */
+ int r1; /* Value to return if (lhs > rhs) */
+ int r2; /* Value to return if (rhs < lhs) */
};
-/*
-** Allowed values of UnpackedRecord.flags
-*/
-#define UNPACKED_INCRKEY 0x01 /* Make this key an epsilon larger */
-#define UNPACKED_PREFIX_MATCH 0x02 /* A prefix match is considered OK */
/*
** Each SQL index is represented in memory by an
@@ -10959,6 +11107,7 @@ struct AggInfo {
int sortingIdx; /* Cursor number of the sorting index */
int sortingIdxPTab; /* Cursor number of pseudo-table */
int nSortingColumn; /* Number of columns in the sorting index */
+ int mnReg, mxReg; /* Range of registers allocated for aCol and aFunc */
ExprList *pGroupBy; /* The group by clause */
struct AggInfo_col { /* For each column used in source tables */
Table *pTab; /* Source table */
@@ -11251,6 +11400,7 @@ typedef u64 Bitmask;
** A bit in a Bitmask
*/
#define MASKBIT(n) (((Bitmask)1)<<(n))
+#define MASKBIT32(n) (((unsigned int)1)<<(n))
/*
** The following structure describes the FROM clause of a SELECT statement.
@@ -11272,8 +11422,8 @@ typedef u64 Bitmask;
** contains more than 63 columns and the 64-th or later column is used.
*/
struct SrcList {
- u8 nSrc; /* Number of tables or subqueries in the FROM clause */
- u8 nAlloc; /* Number of entries allocated in a[] below */
+ int nSrc; /* Number of tables or subqueries in the FROM clause */
+ u32 nAlloc; /* Number of entries allocated in a[] below */
struct SrcList_item {
Schema *pSchema; /* Schema to which this item is fixed */
char *zDatabase; /* Name of database holding this table */
@@ -11283,10 +11433,12 @@ struct SrcList {
Select *pSelect; /* A SELECT statement used in place of a table name */
int addrFillSub; /* Address of subroutine to manifest a subquery */
int regReturn; /* Register holding return address of addrFillSub */
+ int regResult; /* Registers holding results of a co-routine */
u8 jointype; /* Type of join between this able and the previous */
unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
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 */
#ifndef SQLITE_OMIT_EXPLAIN
u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
#endif
@@ -11410,9 +11562,9 @@ struct Select {
ExprList *pOrderBy; /* The ORDER BY clause */
Select *pPrior; /* Prior select in a compound select statement */
Select *pNext; /* Next select to the left in a compound */
- Select *pRightmost; /* Right-most select in a compound select statement */
Expr *pLimit; /* LIMIT expression. NULL means not used. */
Expr *pOffset; /* OFFSET expression. NULL means not used. */
+ With *pWith; /* WITH clause attached to this select. Or NULL. */
};
/*
@@ -11427,14 +11579,74 @@ struct Select {
#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
#define SF_UseSorter 0x0040 /* Sort using a sorter */
#define SF_Values 0x0080 /* Synthesized from VALUES clause */
-#define SF_Materialize 0x0100 /* Force materialization of views */
+#define SF_Materialize 0x0100 /* NOT USED */
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
+#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */
+#define SF_Compound 0x1000 /* Part of a compound query */
/*
-** The results of a select can be distributed in several ways. The
-** "SRT" prefix means "SELECT Result Type".
+** The results of a SELECT can be distributed in several ways, as defined
+** by one of the following macros. The "SRT" prefix means "SELECT Result
+** Type".
+**
+** SRT_Union Store results as a key in a temporary index
+** identified by pDest->iSDParm.
+**
+** SRT_Except Remove results from the temporary index pDest->iSDParm.
+**
+** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result
+** set is not empty.
+**
+** SRT_Discard Throw the results away. This is used by SELECT
+** statements within triggers whose only purpose is
+** the side-effects of functions.
+**
+** All of the above are free to ignore their ORDER BY clause. Those that
+** follow must honor the ORDER BY clause.
+**
+** SRT_Output Generate a row of output (using the OP_ResultRow
+** opcode) for each row in the result set.
+**
+** SRT_Mem Only valid if the result is a single column.
+** Store the first column of the first result row
+** in register pDest->iSDParm then abandon the rest
+** of the query. This destination implies "LIMIT 1".
+**
+** SRT_Set The result must be a single column. Store each
+** row of result as the key in table pDest->iSDParm.
+** Apply the affinity pDest->affSdst before storing
+** results. Used to implement "IN (SELECT ...)".
+**
+** SRT_EphemTab Create an temporary table pDest->iSDParm and store
+** the result there. The cursor is left open after
+** returning. This is like SRT_Table except that
+** this destination uses OP_OpenEphemeral to create
+** the table first.
+**
+** SRT_Coroutine Generate a co-routine that returns a new row of
+** results each time it is invoked. The entry point
+** of the co-routine is stored in register pDest->iSDParm
+** and the result row is stored in pDest->nDest registers
+** starting with pDest->iSdst.
+**
+** SRT_Table Store results in temporary table pDest->iSDParm.
+** This is like SRT_EphemTab except that the table
+** is assumed to already be open.
+**
+** SRT_DistTable Store results in a temporary table pDest->iSDParm.
+** But also use temporary table pDest->iSDParm+1 as
+** a record of all prior results and ignore any duplicate
+** rows. Name means: "Distinct Table".
+**
+** SRT_Queue Store results in priority queue pDest->iSDParm (really
+** an index). Append a sequence number so that all entries
+** are distinct.
+**
+** SRT_DistQueue Store results in priority queue pDest->iSDParm only if
+** the same record has never been stored before. The
+** index at pDest->iSDParm+1 hold all prior stores.
*/
#define SRT_Union 1 /* Store result as keys in an index */
#define SRT_Except 2 /* Remove result from a UNION index */
@@ -11447,20 +11659,24 @@ struct Select {
#define SRT_Output 5 /* Output each row of result */
#define SRT_Mem 6 /* Store result in a memory cell */
#define SRT_Set 7 /* Store results as keys in an index */
-#define SRT_Table 8 /* Store result as data with an automatic rowid */
-#define SRT_EphemTab 9 /* Create transient tab and store like SRT_Table */
-#define SRT_Coroutine 10 /* Generate a single row of result */
+#define SRT_EphemTab 8 /* Create transient tab and store like SRT_Table */
+#define SRT_Coroutine 9 /* Generate a single row of result */
+#define SRT_Table 10 /* Store result as data with an automatic rowid */
+#define SRT_DistTable 11 /* Like SRT_Table, but unique results only */
+#define SRT_Queue 12 /* Store result in an queue */
+#define SRT_DistQueue 13 /* Like SRT_Queue, but unique results only */
/*
** An instance of this object describes where to put of the results of
** a SELECT statement.
*/
struct SelectDest {
- u8 eDest; /* How to dispose of the results. On of SRT_* above. */
- char affSdst; /* Affinity used when eDest==SRT_Set */
- int iSDParm; /* A parameter used by the eDest disposal method */
- int iSdst; /* Base register where results are written */
- int nSdst; /* Number of registers allocated */
+ u8 eDest; /* How to dispose of the results. On of SRT_* above. */
+ char affSdst; /* Affinity used when eDest==SRT_Set */
+ int iSDParm; /* A parameter used by the eDest disposal method */
+ int iSdst; /* Base register where results are written */
+ int nSdst; /* Number of registers allocated */
+ ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */
};
/*
@@ -11546,12 +11762,12 @@ struct Parse {
u8 checkSchema; /* Causes schema cookie check after an error */
u8 nested; /* Number of nested calls to the parser/code generator */
u8 nTempReg; /* Number of temporary registers in aTempReg[] */
- u8 nTempInUse; /* Number of aTempReg[] currently checked out */
u8 nColCache; /* Number of entries in aColCache[] */
u8 iColCache; /* Next entry in aColCache[] to replace */
u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
u8 mayAbort; /* True if statement may throw an ABORT exception */
u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
+ u8 okConstFactor; /* OK to factor out constants */
int aTempReg[8]; /* Holding area for temporary registers */
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
@@ -11560,27 +11776,30 @@ struct Parse {
int nMem; /* Number of memory cells used so far */
int nSet; /* Number of sets used so far */
int nOnce; /* Number of OP_Once instructions so far */
+ int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
+ int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */
int ckBase; /* Base register of data during check constraints */
int iPartIdxTab; /* Table corresponding to a partial index */
int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
int iCacheCnt; /* Counter used to generate aColCache[].lru values */
+ int nLabel; /* Number of labels used */
+ int *aLabel; /* Space to hold the labels */
struct yColCache {
int iTable; /* Table cursor number */
- int iColumn; /* Table column number */
+ i16 iColumn; /* Table column number */
u8 tempReg; /* iReg is a temp register that needs to be freed */
int iLevel; /* Nesting level */
int iReg; /* Reg with value of this column. 0 means none. */
int lru; /* Least recently used entry has the smallest value */
} aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
ExprList *pConstExpr;/* Constant expressions */
+ Token constraintName;/* Name of the constraint currently being parsed */
yDbMask writeMask; /* Start a write transaction on these databases */
yDbMask cookieMask; /* Bitmask of schema verified databases */
- int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */
int regRowid; /* Register holding rowid of CREATE TABLE entry */
int regRoot; /* Register holding root page number for new objects */
int nMaxArg; /* Max args passed to user function by sub-program */
- Token constraintName;/* Name of the constraint currently being parsed */
#ifndef SQLITE_OMIT_SHARED_CACHE
int nTableLock; /* Number of locks in aTableLock */
TableLock *aTableLock; /* Required table locks for shared-cache mode */
@@ -11599,12 +11818,17 @@ struct Parse {
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
u8 disableTriggers; /* True to disable triggers */
- /* Above is constant between recursions. Below is reset before and after
- ** each recursion */
+ /************************************************************************
+ ** Above is constant between recursions. Below is reset before and after
+ ** each recursion. The boundary between these two regions is determined
+ ** using offsetof(Parse,nVar) so the nVar field must be the first field
+ ** in the recursive region.
+ ************************************************************************/
int nVar; /* Number of '?' variables seen in the SQL so far */
int nzVar; /* Number of available slots in azVar[] */
u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
+ u8 bFreeWith; /* True if pWith should be freed with parser */
u8 explain; /* True if the EXPLAIN flag is found on the query */
#ifndef SQLITE_OMIT_VIRTUALTABLE
u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
@@ -11630,6 +11854,7 @@ struct Parse {
#endif
Table *pZombieTab; /* List of Table objects to delete after code gen */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
+ With *pWith; /* Current WITH clause, or NULL */
};
/*
@@ -11749,7 +11974,7 @@ struct TriggerStep {
Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */
Token target; /* Target table for DELETE, UPDATE, INSERT */
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
- ExprList *pExprList; /* SET clause for UPDATE. VALUES clause for INSERT */
+ ExprList *pExprList; /* SET clause for UPDATE. */
IdList *pIdList; /* Column names for INSERT */
TriggerStep *pNext; /* Next in the link-list */
TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */
@@ -11845,6 +12070,13 @@ struct Sqlite3Config {
void(*xSqllog)(void*,sqlite3*,const char*, int);
void *pSqllogArg;
#endif
+#ifdef SQLITE_VDBE_COVERAGE
+ /* The following callback (if not NULL) is invoked on every VDBE branch
+ ** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE.
+ */
+ void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */
+ void *pVdbeBranchArg; /* 1st argument */
+#endif
};
/*
@@ -11871,9 +12103,9 @@ struct Sqlite3Config {
struct Walker {
int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */
int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */
+ void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */
Parse *pParse; /* Parser context. */
int walkerDepth; /* Number of subqueries */
- u8 bSelectDepthFirst; /* Do subqueries first */
union { /* Extra data for callback */
NameContext *pNC; /* Naming context */
int i; /* Integer value */
@@ -11898,6 +12130,21 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
#define WRC_Abort 2 /* Abandon the tree walk */
/*
+** An instance of this structure represents a set of one or more CTEs
+** (common table expressions) created by a single WITH clause.
+*/
+struct With {
+ int nCte; /* Number of CTEs in the WITH clause */
+ With *pOuter; /* Containing WITH clause, or NULL */
+ struct Cte { /* For each CTE in the WITH clause.... */
+ char *zName; /* Name of this CTE */
+ ExprList *pCols; /* List of explicit column names, or NULL */
+ Select *pSelect; /* The definition of this CTE */
+ const char *zErr; /* Error message for circular references */
+ } a[1];
+};
+
+/*
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
*/
@@ -12036,10 +12283,20 @@ SQLITE_PRIVATE int sqlite3IsNaN(double);
# define sqlite3IsNaN(X) 0
#endif
-SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);
-#ifndef SQLITE_OMIT_TRACE
-SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, const char*, ...);
-#endif
+/*
+** An instance of the following structure holds information about SQL
+** functions arguments that are the parameters to the printf() function.
+*/
+struct PrintfArguments {
+ int nArg; /* Total number of arguments */
+ int nUsed; /* Number of arguments used so far */
+ sqlite3_value **apArg; /* The argument values */
+};
+
+#define SQLITE_PRINTF_INTERNAL 0x01
+#define SQLITE_PRINTF_SQLFUNC 0x02
+SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, u32, const char*, va_list);
+SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, u32, const char*, ...);
SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...);
SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
@@ -12153,8 +12410,7 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse);
# define sqlite3AutoincrementBegin(X)
# define sqlite3AutoincrementEnd(X)
#endif
-SQLITE_PRIVATE int sqlite3CodeCoroutine(Parse*, Select*, SelectDest*);
-SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
+SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int);
SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
@@ -12201,11 +12457,12 @@ SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*, int);
SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int, int);
SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*);
SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int);
-SQLITE_PRIVATE int sqlite3ExprCode(Parse*, Expr*, int);
+SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
+SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8);
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int);
-SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse*, Expr*, int);
+SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, u8);
#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */
#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
@@ -12229,7 +12486,6 @@ SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
SQLITE_PRIVATE void sqlite3PrngSaveState(void);
SQLITE_PRIVATE void sqlite3PrngRestoreState(void);
-SQLITE_PRIVATE void sqlite3PrngResetState(void);
SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int);
SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int);
SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
@@ -12244,12 +12500,11 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*);
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*);
SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*);
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
-SQLITE_PRIVATE void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int);
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8);
SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*);
-SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*);
+SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
u8,u8,int,int*);
SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
@@ -12293,7 +12548,7 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, i
SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*);
SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
- ExprList*,Select*,u8);
+ Select*,u8);
SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8);
SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*);
SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*);
@@ -12388,7 +12643,7 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *, Index *);
-SQLITE_PRIVATE void sqlite3TableAffinityStr(Vdbe *, Table *);
+SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int);
SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2);
SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
@@ -12398,8 +12653,7 @@ SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) || \
- defined(SQLITE_DEBUG_OS_TRACE)
+#if defined(SQLITE_TEST)
SQLITE_PRIVATE const char *sqlite3ErrName(int);
#endif
@@ -12429,6 +12683,7 @@ SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
void(*)(void*));
+SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value*);
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*);
SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *);
SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
@@ -12494,6 +12749,7 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *);
SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, char*, int, int);
SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int);
+SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum*,const char*);
SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum*,int);
SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*);
SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum*);
@@ -12585,6 +12841,14 @@ SQLITE_PRIVATE const char *sqlite3JournalModename(int);
SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
#endif
+#ifndef SQLITE_OMIT_CTE
+SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*);
+SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*);
+SQLITE_PRIVATE void sqlite3WithPush(Parse*, With*, u8);
+#else
+#define sqlite3WithPush(x,y,z)
+#define sqlite3WithDelete(x,y)
+#endif
/* Declarations for functions in fkey.c. All of these are replaced by
** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
@@ -13192,6 +13456,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_COMPOUND_SELECT
"OMIT_COMPOUND_SELECT",
#endif
+#ifdef SQLITE_OMIT_CTE
+ "OMIT_CTE",
+#endif
#ifdef SQLITE_OMIT_DATETIME_FUNCS
"OMIT_DATETIME_FUNCS",
#endif
@@ -13483,7 +13750,6 @@ struct VdbeCursor {
Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
Bool isTable:1; /* True if a table requiring integer keys */
Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */
- Bool multiPseudo:1; /* Multi-register pseudo-cursor */
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
i64 seqCount; /* Sequence counter */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
@@ -13577,7 +13843,6 @@ struct Mem {
} u;
int n; /* Number of characters in string value, excluding '\0' */
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
- u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
#ifdef SQLITE_DEBUG
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
@@ -13604,9 +13869,10 @@ struct Mem {
#define MEM_Int 0x0004 /* Value is an integer */
#define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Blob 0x0010 /* Value is a BLOB */
+#define MEM_AffMask 0x001f /* Mask of affinity bits */
#define MEM_RowSet 0x0020 /* Value is a RowSet object */
#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
-#define MEM_Invalid 0x0080 /* Value is undefined */
+#define MEM_Undefined 0x0080 /* Value is undefined */
#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
#define MEM_TypeMask 0x01ff /* Mask of type bits */
@@ -13617,7 +13883,7 @@ struct Mem {
** string is \000 or \u0000 terminated
*/
#define MEM_Term 0x0200 /* String rep is nul terminated */
-#define MEM_Dyn 0x0400 /* Need to call sqliteFree() on Mem.z */
+#define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */
#define MEM_Static 0x0800 /* Mem.z points to a static string */
#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */
@@ -13638,7 +13904,7 @@ struct Mem {
** is for use inside assert() statements only.
*/
#ifdef SQLITE_DEBUG
-#define memIsValid(M) ((M)->flags & MEM_Invalid)==0
+#define memIsValid(M) ((M)->flags & MEM_Undefined)==0
#endif
/*
@@ -13720,12 +13986,9 @@ struct Vdbe {
Mem **apArg; /* Arguments to currently executing user function */
Mem *aColName; /* Column names to return */
Mem *pResultSet; /* Pointer to an array of results */
+ Parse *pParse; /* Parsing context used to create this Vdbe */
int nMem; /* Number of memory locations currently allocated */
int nOp; /* Number of instructions in the program */
- int nOpAlloc; /* Number of slots allocated for aOp[] */
- int nLabel; /* Number of labels used */
- int *aLabel; /* Space to hold the labels */
- u16 nResColumn; /* Number of columns in one row of the result set */
int nCursor; /* Number of slots in apCsr[] */
u32 magic; /* Magic number for sanity checking */
char *zErrMsg; /* Error message written here */
@@ -13738,6 +14001,7 @@ struct Vdbe {
u32 cacheCtr; /* VdbeCursor row cache generation counter */
int pc; /* The program counter */
int rc; /* Value to return */
+ u16 nResColumn; /* Number of columns in one row of the result set */
u8 errorAction; /* Recovery action to do in case of an error */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
bft explain:2; /* True if EXPLAIN present on SQL command */
@@ -13797,12 +14061,12 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*);
#endif
SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int);
-SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int);
+SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
-SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
+SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,const UnpackedRecord*,int*);
SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
@@ -13835,16 +14099,16 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);
+#define VdbeMemDynamic(X) \
+ (((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0)
#define VdbeMemRelease(X) \
- if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
- sqlite3VdbeMemReleaseExternal(X);
+ if( VdbeMemDynamic(X) ) sqlite3VdbeMemReleaseExternal(X);
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
-SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
@@ -13865,6 +14129,7 @@ SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
+SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem*);
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
@@ -15391,7 +15656,21 @@ SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
** routine has no return value since the return value would be meaningless.
*/
SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
- DO_OS_MALLOC_TEST(id);
+#ifdef SQLITE_TEST
+ if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){
+ /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
+ ** is using a regular VFS, it is called after the corresponding
+ ** transaction has been committed. Injecting a fault at this point
+ ** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM
+ ** but the transaction is committed anyway.
+ **
+ ** The core must call OsFileControl() though, not OsFileControlHint(),
+ ** as if a custom VFS (e.g. zipvfs) returns an error here, it probably
+ ** means the commit really has failed and an error should be returned
+ ** to the user. */
+ DO_OS_MALLOC_TEST(id);
+ }
+#endif
return id->pMethods->xFileControl(id, op, pArg);
}
SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
@@ -17603,6 +17882,12 @@ static void *memsys5MallocUnsafe(int nByte){
if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
+#ifdef SQLITE_DEBUG
+ /* Make sure the allocated memory does not assume that it is set to zero
+ ** or retains a value from a previous allocation */
+ memset(&mem5.zPool[i*mem5.szAtom], 0xAA, iFullSz);
+#endif
+
/* Return a pointer to the allocated memory. */
return (void*)&mem5.zPool[i*mem5.szAtom];
}
@@ -17660,6 +17945,13 @@ static void memsys5FreeUnsafe(void *pOld){
}
size *= 2;
}
+
+#ifdef SQLITE_DEBUG
+ /* Overwrite freed memory with the 0x55 bit pattern to verify that it is
+ ** not used after being freed */
+ memset(&mem5.zPool[iBlock*mem5.szAtom], 0x55, size);
+#endif
+
memsys5Link(iBlock, iLogsize);
}
@@ -19386,7 +19678,7 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
*/
#ifndef SQLITE_OMIT_LOOKASIDE
static int isLookaside(sqlite3 *db, void *p){
- return p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
+ return p>=db->lookaside.pStart && p<db->lookaside.pEnd;
}
#else
#define isLookaside(A,B) 0
@@ -19402,8 +19694,9 @@ SQLITE_PRIVATE int sqlite3MallocSize(void *p){
return sqlite3GlobalConfig.m.xSize(p);
}
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
- assert( db==0 || sqlite3_mutex_held(db->mutex) );
- if( db && isLookaside(db, p) ){
+ assert( db!=0 );
+ assert( sqlite3_mutex_held(db->mutex) );
+ if( isLookaside(db, p) ){
return db->lookaside.sz;
}else{
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
@@ -19887,6 +20180,31 @@ SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *pAccum, int N){
}
/*
+** Set the StrAccum object to an error mode.
+*/
+static void setStrAccumError(StrAccum *p, u8 eError){
+ p->accError = eError;
+ p->nAlloc = 0;
+}
+
+/*
+** Extra argument values from a PrintfArguments object
+*/
+static sqlite3_int64 getIntArg(PrintfArguments *p){
+ if( p->nArg<=p->nUsed ) return 0;
+ return sqlite3_value_int64(p->apArg[p->nUsed++]);
+}
+static double getDoubleArg(PrintfArguments *p){
+ if( p->nArg<=p->nUsed ) return 0.0;
+ return sqlite3_value_double(p->apArg[p->nUsed++]);
+}
+static char *getTextArg(PrintfArguments *p){
+ if( p->nArg<=p->nUsed ) return 0;
+ return (char*)sqlite3_value_text(p->apArg[p->nUsed++]);
+}
+
+
+/*
** On machines with a small stack size, you can redefine the
** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
*/
@@ -19899,10 +20217,10 @@ SQLITE_PRIVATE void sqlite3AppendSpace(StrAccum *pAccum, int N){
** Render a string given by "fmt" into the StrAccum object.
*/
SQLITE_PRIVATE void sqlite3VXPrintf(
- StrAccum *pAccum, /* Accumulate results here */
- int useExtended, /* Allow extended %-conversions */
- const char *fmt, /* Format string */
- va_list ap /* arguments */
+ StrAccum *pAccum, /* Accumulate results here */
+ u32 bFlags, /* SQLITE_PRINTF_* flags */
+ const char *fmt, /* Format string */
+ va_list ap /* arguments */
){
int c; /* Next character in the format string */
char *bufpt; /* Pointer to the conversion buffer */
@@ -19920,6 +20238,8 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
etByte flag_longlong; /* True if the "ll" flag is present */
etByte done; /* Loop termination flag */
etByte xtype = 0; /* Conversion paradigm */
+ u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */
+ u8 useIntern; /* Ok to use internal conversions (ex: %T) */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
sqlite_uint64 longvalue; /* Value for integer types */
LONGDOUBLE_TYPE realvalue; /* Value for real types */
@@ -19934,9 +20254,18 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
etByte flag_dp; /* True if decimal point should be shown */
etByte flag_rtz; /* True if trailing zeros should be removed */
#endif
+ PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
char buf[etBUFSIZE]; /* Conversion buffer */
bufpt = 0;
+ if( bFlags ){
+ if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){
+ pArgList = va_arg(ap, PrintfArguments*);
+ }
+ useIntern = bFlags & SQLITE_PRINTF_INTERNAL;
+ }else{
+ bArgList = useIntern = 0;
+ }
for(; (c=(*fmt))!=0; ++fmt){
if( c!='%' ){
int amt;
@@ -19968,7 +20297,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
/* Get the field width */
width = 0;
if( c=='*' ){
- width = va_arg(ap,int);
+ if( bArgList ){
+ width = (int)getIntArg(pArgList);
+ }else{
+ width = va_arg(ap,int);
+ }
if( width<0 ){
flag_leftjustify = 1;
width = -width;
@@ -19985,7 +20318,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
precision = 0;
c = *++fmt;
if( c=='*' ){
- precision = va_arg(ap,int);
+ if( bArgList ){
+ precision = (int)getIntArg(pArgList);
+ }else{
+ precision = va_arg(ap,int);
+ }
if( precision<0 ) precision = -precision;
c = *++fmt;
}else{
@@ -20016,7 +20353,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
for(idx=0; idx<ArraySize(fmtinfo); idx++){
if( c==fmtinfo[idx].fmttype ){
infop = &fmtinfo[idx];
- if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
+ if( useIntern || (infop->flags & FLAG_INTERN)==0 ){
xtype = infop->type;
}else{
return;
@@ -20056,7 +20393,9 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
case etRADIX:
if( infop->flags & FLAG_SIGNED ){
i64 v;
- if( flag_longlong ){
+ if( bArgList ){
+ v = getIntArg(pArgList);
+ }else if( flag_longlong ){
v = va_arg(ap,i64);
}else if( flag_long ){
v = va_arg(ap,long int);
@@ -20077,7 +20416,9 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
else prefix = 0;
}
}else{
- if( flag_longlong ){
+ if( bArgList ){
+ longvalue = (u64)getIntArg(pArgList);
+ }else if( flag_longlong ){
longvalue = va_arg(ap,u64);
}else if( flag_long ){
longvalue = va_arg(ap,unsigned long int);
@@ -20097,7 +20438,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
nOut = precision + 10;
zOut = zExtra = sqlite3Malloc( nOut );
if( zOut==0 ){
- pAccum->accError = STRACCUM_NOMEM;
+ setStrAccumError(pAccum, STRACCUM_NOMEM);
return;
}
}
@@ -20137,7 +20478,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
case etFLOAT:
case etEXP:
case etGENERIC:
- realvalue = va_arg(ap,double);
+ if( bArgList ){
+ realvalue = getDoubleArg(pArgList);
+ }else{
+ realvalue = va_arg(ap,double);
+ }
#ifdef SQLITE_OMIT_FLOATING_POINT
length = 0;
#else
@@ -20209,7 +20554,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){
bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 );
if( bufpt==0 ){
- pAccum->accError = STRACCUM_NOMEM;
+ setStrAccumError(pAccum, STRACCUM_NOMEM);
return;
}
}
@@ -20292,7 +20637,9 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
break;
case etSIZE:
- *(va_arg(ap,int*)) = pAccum->nChar;
+ if( !bArgList ){
+ *(va_arg(ap,int*)) = pAccum->nChar;
+ }
length = width = 0;
break;
case etPERCENT:
@@ -20301,7 +20648,12 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
length = 1;
break;
case etCHARX:
- c = va_arg(ap,int);
+ if( bArgList ){
+ bufpt = getTextArg(pArgList);
+ c = bufpt ? bufpt[0] : 0;
+ }else{
+ c = va_arg(ap,int);
+ }
buf[0] = (char)c;
if( precision>=0 ){
for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
@@ -20313,10 +20665,14 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
break;
case etSTRING:
case etDYNSTRING:
- bufpt = va_arg(ap,char*);
+ if( bArgList ){
+ bufpt = getTextArg(pArgList);
+ }else{
+ bufpt = va_arg(ap,char*);
+ }
if( bufpt==0 ){
bufpt = "";
- }else if( xtype==etDYNSTRING ){
+ }else if( xtype==etDYNSTRING && !bArgList ){
zExtra = bufpt;
}
if( precision>=0 ){
@@ -20332,7 +20688,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
int needQuote;
char ch;
char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
- char *escarg = va_arg(ap,char*);
+ char *escarg;
+
+ if( bArgList ){
+ escarg = getTextArg(pArgList);
+ }else{
+ escarg = va_arg(ap,char*);
+ }
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
k = precision;
@@ -20344,7 +20706,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
if( n>etBUFSIZE ){
bufpt = zExtra = sqlite3Malloc( n );
if( bufpt==0 ){
- pAccum->accError = STRACCUM_NOMEM;
+ setStrAccumError(pAccum, STRACCUM_NOMEM);
return;
}
}else{
@@ -20367,7 +20729,8 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
}
case etTOKEN: {
Token *pToken = va_arg(ap, Token*);
- if( pToken ){
+ assert( bArgList==0 );
+ if( pToken && pToken->n ){
sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
}
length = width = 0;
@@ -20377,12 +20740,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
SrcList *pSrc = va_arg(ap, SrcList*);
int k = va_arg(ap, int);
struct SrcList_item *pItem = &pSrc->a[k];
+ assert( bArgList==0 );
assert( k>=0 && k<pSrc->nSrc );
if( pItem->zDatabase ){
- sqlite3StrAccumAppend(pAccum, pItem->zDatabase, -1);
+ sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase);
sqlite3StrAccumAppend(pAccum, ".", 1);
}
- sqlite3StrAccumAppend(pAccum, pItem->zName, -1);
+ sqlite3StrAccumAppendAll(pAccum, pItem->zName);
length = width = 0;
break;
}
@@ -20413,7 +20777,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
sqlite3AppendSpace(pAccum, nspace);
}
}
- sqlite3_free(zExtra);
+ if( zExtra ) sqlite3_free(zExtra);
}/* End for loop over the format string */
} /* End of function */
@@ -20421,22 +20785,20 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
** Append N bytes of text from z to the StrAccum object.
*/
SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
- assert( z!=0 || N==0 );
- if( p->accError ){
- testcase(p->accError==STRACCUM_TOOBIG);
- testcase(p->accError==STRACCUM_NOMEM);
- return;
- }
- assert( p->zText!=0 || p->nChar==0 );
- if( N<=0 ){
- if( N==0 || z[0]==0 ) return;
- N = sqlite3Strlen30(z);
- }
+ assert( z!=0 );
+ assert( p->zText!=0 || p->nChar==0 || p->accError );
+ assert( N>=0 );
+ assert( p->accError==0 || p->nAlloc==0 );
if( p->nChar+N >= p->nAlloc ){
char *zNew;
+ if( p->accError ){
+ testcase(p->accError==STRACCUM_TOOBIG);
+ testcase(p->accError==STRACCUM_NOMEM);
+ return;
+ }
if( !p->useMalloc ){
- p->accError = STRACCUM_TOOBIG;
N = p->nAlloc - p->nChar - 1;
+ setStrAccumError(p, STRACCUM_TOOBIG);
if( N<=0 ){
return;
}
@@ -20446,7 +20808,7 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
szNew += N + 1;
if( szNew > p->mxAlloc ){
sqlite3StrAccumReset(p);
- p->accError = STRACCUM_TOOBIG;
+ setStrAccumError(p, STRACCUM_TOOBIG);
return;
}else{
p->nAlloc = (int)szNew;
@@ -20460,8 +20822,8 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
p->zText = zNew;
}else{
- p->accError = STRACCUM_NOMEM;
sqlite3StrAccumReset(p);
+ setStrAccumError(p, STRACCUM_NOMEM);
return;
}
}
@@ -20472,6 +20834,14 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
}
/*
+** Append the complete text of zero-terminated string z[] to the p string.
+*/
+SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){
+ sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z));
+}
+
+
+/*
** Finish off a string by making sure it is zero-terminated.
** Return a pointer to the resulting string. Return a NULL
** pointer if any kind of error was encountered.
@@ -20488,7 +20858,7 @@ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
if( p->zText ){
memcpy(p->zText, p->zBase, p->nChar+1);
}else{
- p->accError = STRACCUM_NOMEM;
+ setStrAccumError(p, STRACCUM_NOMEM);
}
}
}
@@ -20534,7 +20904,7 @@ SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list a
sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]);
acc.db = db;
- sqlite3VXPrintf(&acc, 1, zFormat, ap);
+ sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
if( acc.accError==STRACCUM_NOMEM ){
db->mallocFailed = 1;
@@ -20690,17 +21060,15 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
}
#endif
-#ifndef SQLITE_OMIT_TRACE
/*
** variable-argument wrapper around sqlite3VXPrintf().
*/
-SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){
+SQLITE_PRIVATE void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){
va_list ap;
va_start(ap,zFormat);
- sqlite3VXPrintf(p, 1, zFormat, ap);
+ sqlite3VXPrintf(p, bFlags, zFormat, ap);
va_end(ap);
}
-#endif
/************** End of printf.c **********************************************/
/************** Begin file random.c ******************************************/
@@ -20757,6 +21125,12 @@ SQLITE_API void sqlite3_randomness(int N, void *pBuf){
sqlite3_mutex_enter(mutex);
#endif
+ if( N<=0 ){
+ wsdPrng.isInit = 0;
+ sqlite3_mutex_leave(mutex);
+ return;
+ }
+
/* Initialize the state of the random number generator once,
** the first time this routine is called. The seed value does
** not need to contain a lot of randomness since we are not
@@ -20784,7 +21158,8 @@ SQLITE_API void sqlite3_randomness(int N, void *pBuf){
wsdPrng.isInit = 1;
}
- while( N-- ){
+ assert( N>0 );
+ do{
wsdPrng.i++;
t = wsdPrng.s[wsdPrng.i];
wsdPrng.j += t;
@@ -20792,7 +21167,7 @@ SQLITE_API void sqlite3_randomness(int N, void *pBuf){
wsdPrng.s[wsdPrng.j] = t;
t += wsdPrng.s[wsdPrng.i];
*(zBuf++) = wsdPrng.s[t];
- }
+ }while( --N );
sqlite3_mutex_leave(mutex);
}
@@ -20821,9 +21196,6 @@ SQLITE_PRIVATE void sqlite3PrngRestoreState(void){
sizeof(sqlite3Prng)
);
}
-SQLITE_PRIVATE void sqlite3PrngResetState(void){
- GLOBAL(struct sqlite3PrngType, sqlite3Prng).isInit = 0;
-}
#endif /* SQLITE_OMIT_BUILTIN_TEST */
/************** End of random.c **********************************************/
@@ -21145,7 +21517,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
sqlite3VdbeMemRelease(pMem);
pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
pMem->enc = desiredEnc;
- pMem->flags |= (MEM_Term|MEM_Dyn);
+ pMem->flags |= (MEM_Term);
pMem->z = (char*)zOut;
pMem->zMalloc = pMem->z;
@@ -21273,7 +21645,6 @@ SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 e
}
assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
- assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
assert( m.z || db->mallocFailed );
return m.z;
}
@@ -21475,18 +21846,17 @@ SQLITE_PRIVATE int sqlite3Strlen30(const char *z){
** to NULL.
*/
SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){
- if( db && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){
- db->errCode = err_code;
- if( zFormat ){
- char *z;
- va_list ap;
- va_start(ap, zFormat);
- z = sqlite3VMPrintf(db, zFormat, ap);
- va_end(ap);
- sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
- }else{
- sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
- }
+ assert( db!=0 );
+ db->errCode = err_code;
+ if( zFormat && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){
+ char *z;
+ va_list ap;
+ va_start(ap, zFormat);
+ z = sqlite3VMPrintf(db, zFormat, ap);
+ va_end(ap);
+ sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
+ }else if( db->pErr ){
+ sqlite3ValueSetNull(db->pErr);
}
}
@@ -22362,7 +22732,8 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v){
** Read or write a four-byte big-endian integer value.
*/
SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
- return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
+ testcase( p[0]&0x80 );
+ return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
}
SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
p[0] = (u8)(v>>24);
@@ -22483,13 +22854,12 @@ SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
testcase( iA>0 && LARGEST_INT64 - iA == iB );
testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 );
if( iA>0 && LARGEST_INT64 - iA < iB ) return 1;
- *pA += iB;
}else{
testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 );
testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 );
if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
- *pA += iB;
}
+ *pA += iB;
return 0;
}
SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
@@ -22513,9 +22883,18 @@ SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
iA0 = iA % TWOPOWER32;
iB1 = iB/TWOPOWER32;
iB0 = iB % TWOPOWER32;
- if( iA1*iB1 != 0 ) return 1;
- assert( iA1*iB0==0 || iA0*iB1==0 );
- r = iA1*iB0 + iA0*iB1;
+ if( iA1==0 ){
+ if( iB1==0 ){
+ *pA *= iB;
+ return 0;
+ }
+ r = iA0*iB1;
+ }else if( iB1==0 ){
+ r = iA1*iB0;
+ }else{
+ /* If both iA1 and iB1 are non-zero, overflow will result */
+ return 1;
+ }
testcase( r==(-TWOPOWER31)-1 );
testcase( r==(-TWOPOWER31) );
testcase( r==TWOPOWER31 );
@@ -22703,7 +23082,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){
** The hashing function.
*/
static unsigned int strHash(const char *z, int nKey){
- int h = 0;
+ unsigned int h = 0;
assert( nKey>=0 );
while( nKey > 0 ){
h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
@@ -22961,139 +23340,143 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 17 */ "Gosub" OpHelp(""),
/* 18 */ "Return" OpHelp(""),
/* 19 */ "Not" OpHelp("r[P2]= !r[P1]"),
- /* 20 */ "Yield" OpHelp(""),
- /* 21 */ "HaltIfNull" OpHelp("if r[P3] null then halt"),
- /* 22 */ "Halt" OpHelp(""),
- /* 23 */ "Integer" OpHelp("r[P2]=P1"),
- /* 24 */ "Int64" OpHelp("r[P2]=P4"),
- /* 25 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
- /* 26 */ "Null" OpHelp("r[P2..P3]=NULL"),
- /* 27 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
- /* 28 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
- /* 29 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
- /* 30 */ "Copy" OpHelp("r[P2@P3]=r[P1@P3]"),
- /* 31 */ "SCopy" OpHelp("r[P2]=r[P1]"),
- /* 32 */ "ResultRow" OpHelp("output=r[P1@P2]"),
- /* 33 */ "CollSeq" OpHelp(""),
- /* 34 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
- /* 35 */ "MustBeInt" OpHelp(""),
- /* 36 */ "RealAffinity" OpHelp(""),
- /* 37 */ "Permutation" OpHelp(""),
- /* 38 */ "Compare" OpHelp(""),
- /* 39 */ "Jump" OpHelp(""),
- /* 40 */ "Once" OpHelp(""),
- /* 41 */ "If" OpHelp(""),
- /* 42 */ "IfNot" OpHelp(""),
- /* 43 */ "Column" OpHelp("r[P3]=PX"),
- /* 44 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
- /* 45 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
- /* 46 */ "Count" OpHelp("r[P2]=count()"),
- /* 47 */ "ReadCookie" OpHelp(""),
- /* 48 */ "SetCookie" OpHelp(""),
- /* 49 */ "VerifyCookie" OpHelp(""),
- /* 50 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
- /* 51 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
- /* 52 */ "OpenAutoindex" OpHelp("nColumn=P2"),
- /* 53 */ "OpenEphemeral" OpHelp("nColumn=P2"),
- /* 54 */ "SorterOpen" OpHelp(""),
- /* 55 */ "OpenPseudo" OpHelp("content in r[P2@P3]"),
- /* 56 */ "Close" OpHelp(""),
- /* 57 */ "SeekLt" OpHelp("key=r[P3@P4]"),
- /* 58 */ "SeekLe" OpHelp("key=r[P3@P4]"),
- /* 59 */ "SeekGe" OpHelp("key=r[P3@P4]"),
- /* 60 */ "SeekGt" OpHelp("key=r[P3@P4]"),
- /* 61 */ "Seek" OpHelp("intkey=r[P2]"),
- /* 62 */ "NoConflict" OpHelp("key=r[P3@P4]"),
- /* 63 */ "NotFound" OpHelp("key=r[P3@P4]"),
- /* 64 */ "Found" OpHelp("key=r[P3@P4]"),
- /* 65 */ "NotExists" OpHelp("intkey=r[P3]"),
- /* 66 */ "Sequence" OpHelp("r[P2]=rowid"),
- /* 67 */ "NewRowid" OpHelp("r[P2]=rowid"),
- /* 68 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
- /* 69 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
- /* 70 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
- /* 71 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
- /* 72 */ "Delete" OpHelp(""),
- /* 73 */ "ResetCount" OpHelp(""),
- /* 74 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
- /* 75 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
- /* 76 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"),
- /* 77 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"),
- /* 78 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"),
- /* 79 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"),
- /* 80 */ "Lt" OpHelp("if r[P1]<r[P3] goto P2"),
- /* 81 */ "Ge" OpHelp("if r[P1]>=r[P3] goto P2"),
- /* 82 */ "SorterCompare" OpHelp("if key(P1)!=rtrim(r[P3],P4) goto P2"),
- /* 83 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
- /* 84 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
- /* 85 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
- /* 86 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
- /* 87 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
- /* 88 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
- /* 89 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
- /* 90 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
- /* 91 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
- /* 92 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
- /* 93 */ "SorterData" OpHelp("r[P2]=data"),
- /* 94 */ "BitNot" OpHelp("r[P1]= ~r[P1]"),
- /* 95 */ "String8" OpHelp("r[P2]='P4'"),
- /* 96 */ "RowKey" OpHelp("r[P2]=key"),
- /* 97 */ "RowData" OpHelp("r[P2]=data"),
- /* 98 */ "Rowid" OpHelp("r[P2]=rowid"),
- /* 99 */ "NullRow" OpHelp(""),
- /* 100 */ "Last" OpHelp(""),
- /* 101 */ "SorterSort" OpHelp(""),
- /* 102 */ "Sort" OpHelp(""),
- /* 103 */ "Rewind" OpHelp(""),
- /* 104 */ "SorterInsert" OpHelp(""),
- /* 105 */ "IdxInsert" OpHelp("key=r[P2]"),
- /* 106 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
- /* 107 */ "IdxRowid" OpHelp("r[P2]=rowid"),
- /* 108 */ "IdxLT" OpHelp("key=r[P3@P4]"),
- /* 109 */ "IdxGE" OpHelp("key=r[P3@P4]"),
- /* 110 */ "Destroy" OpHelp(""),
- /* 111 */ "Clear" OpHelp(""),
- /* 112 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"),
- /* 113 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"),
- /* 114 */ "ParseSchema" OpHelp(""),
- /* 115 */ "LoadAnalysis" OpHelp(""),
- /* 116 */ "DropTable" OpHelp(""),
- /* 117 */ "DropIndex" OpHelp(""),
- /* 118 */ "DropTrigger" OpHelp(""),
- /* 119 */ "IntegrityCk" OpHelp(""),
- /* 120 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
- /* 121 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
- /* 122 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
- /* 123 */ "Program" OpHelp(""),
- /* 124 */ "Param" OpHelp(""),
- /* 125 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
- /* 126 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
- /* 127 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
- /* 128 */ "IfPos" OpHelp("if r[P1]>0 goto P2"),
- /* 129 */ "IfNeg" OpHelp("if r[P1]<0 goto P2"),
- /* 130 */ "IfZero" OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"),
- /* 131 */ "Real" OpHelp("r[P2]=P4"),
- /* 132 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
- /* 133 */ "IncrVacuum" OpHelp(""),
- /* 134 */ "Expire" OpHelp(""),
- /* 135 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
- /* 136 */ "VBegin" OpHelp(""),
- /* 137 */ "VCreate" OpHelp(""),
- /* 138 */ "VDestroy" OpHelp(""),
- /* 139 */ "VOpen" OpHelp(""),
- /* 140 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 141 */ "VNext" OpHelp(""),
- /* 142 */ "ToText" OpHelp(""),
- /* 143 */ "ToBlob" OpHelp(""),
- /* 144 */ "ToNumeric" OpHelp(""),
- /* 145 */ "ToInt" OpHelp(""),
- /* 146 */ "ToReal" OpHelp(""),
- /* 147 */ "VRename" OpHelp(""),
- /* 148 */ "Pagecount" OpHelp(""),
- /* 149 */ "MaxPgcnt" OpHelp(""),
- /* 150 */ "Trace" OpHelp(""),
- /* 151 */ "Noop" OpHelp(""),
- /* 152 */ "Explain" OpHelp(""),
+ /* 20 */ "InitCoroutine" OpHelp(""),
+ /* 21 */ "EndCoroutine" OpHelp(""),
+ /* 22 */ "Yield" OpHelp(""),
+ /* 23 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
+ /* 24 */ "Halt" OpHelp(""),
+ /* 25 */ "Integer" OpHelp("r[P2]=P1"),
+ /* 26 */ "Int64" OpHelp("r[P2]=P4"),
+ /* 27 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
+ /* 28 */ "Null" OpHelp("r[P2..P3]=NULL"),
+ /* 29 */ "SoftNull" OpHelp("r[P1]=NULL"),
+ /* 30 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
+ /* 31 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
+ /* 32 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
+ /* 33 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
+ /* 34 */ "SCopy" OpHelp("r[P2]=r[P1]"),
+ /* 35 */ "ResultRow" OpHelp("output=r[P1@P2]"),
+ /* 36 */ "CollSeq" OpHelp(""),
+ /* 37 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
+ /* 38 */ "MustBeInt" OpHelp(""),
+ /* 39 */ "RealAffinity" OpHelp(""),
+ /* 40 */ "Permutation" OpHelp(""),
+ /* 41 */ "Compare" OpHelp(""),
+ /* 42 */ "Jump" OpHelp(""),
+ /* 43 */ "Once" OpHelp(""),
+ /* 44 */ "If" OpHelp(""),
+ /* 45 */ "IfNot" OpHelp(""),
+ /* 46 */ "Column" OpHelp("r[P3]=PX"),
+ /* 47 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
+ /* 48 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
+ /* 49 */ "Count" OpHelp("r[P2]=count()"),
+ /* 50 */ "ReadCookie" OpHelp(""),
+ /* 51 */ "SetCookie" OpHelp(""),
+ /* 52 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 53 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
+ /* 54 */ "OpenAutoindex" OpHelp("nColumn=P2"),
+ /* 55 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 56 */ "SorterOpen" OpHelp(""),
+ /* 57 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
+ /* 58 */ "Close" OpHelp(""),
+ /* 59 */ "SeekLT" OpHelp(""),
+ /* 60 */ "SeekLE" OpHelp(""),
+ /* 61 */ "SeekGE" OpHelp(""),
+ /* 62 */ "SeekGT" OpHelp(""),
+ /* 63 */ "Seek" OpHelp("intkey=r[P2]"),
+ /* 64 */ "NoConflict" OpHelp("key=r[P3@P4]"),
+ /* 65 */ "NotFound" OpHelp("key=r[P3@P4]"),
+ /* 66 */ "Found" OpHelp("key=r[P3@P4]"),
+ /* 67 */ "NotExists" OpHelp("intkey=r[P3]"),
+ /* 68 */ "Sequence" OpHelp("r[P2]=rowid"),
+ /* 69 */ "NewRowid" OpHelp("r[P2]=rowid"),
+ /* 70 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
+ /* 71 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
+ /* 72 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
+ /* 73 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
+ /* 74 */ "Delete" OpHelp(""),
+ /* 75 */ "ResetCount" OpHelp(""),
+ /* 76 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
+ /* 77 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
+ /* 78 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"),
+ /* 79 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"),
+ /* 80 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"),
+ /* 81 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"),
+ /* 82 */ "Lt" OpHelp("if r[P1]<r[P3] goto P2"),
+ /* 83 */ "Ge" OpHelp("if r[P1]>=r[P3] goto P2"),
+ /* 84 */ "SorterCompare" OpHelp("if key(P1)!=rtrim(r[P3],P4) goto P2"),
+ /* 85 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
+ /* 86 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
+ /* 87 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
+ /* 88 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
+ /* 89 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
+ /* 90 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
+ /* 91 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
+ /* 92 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
+ /* 93 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
+ /* 94 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
+ /* 95 */ "SorterData" OpHelp("r[P2]=data"),
+ /* 96 */ "BitNot" OpHelp("r[P1]= ~r[P1]"),
+ /* 97 */ "String8" OpHelp("r[P2]='P4'"),
+ /* 98 */ "RowKey" OpHelp("r[P2]=key"),
+ /* 99 */ "RowData" OpHelp("r[P2]=data"),
+ /* 100 */ "Rowid" OpHelp("r[P2]=rowid"),
+ /* 101 */ "NullRow" OpHelp(""),
+ /* 102 */ "Last" OpHelp(""),
+ /* 103 */ "SorterSort" OpHelp(""),
+ /* 104 */ "Sort" OpHelp(""),
+ /* 105 */ "Rewind" OpHelp(""),
+ /* 106 */ "SorterInsert" OpHelp(""),
+ /* 107 */ "IdxInsert" OpHelp("key=r[P2]"),
+ /* 108 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
+ /* 109 */ "IdxRowid" OpHelp("r[P2]=rowid"),
+ /* 110 */ "IdxLE" OpHelp("key=r[P3@P4]"),
+ /* 111 */ "IdxGT" OpHelp("key=r[P3@P4]"),
+ /* 112 */ "IdxLT" OpHelp("key=r[P3@P4]"),
+ /* 113 */ "IdxGE" OpHelp("key=r[P3@P4]"),
+ /* 114 */ "Destroy" OpHelp(""),
+ /* 115 */ "Clear" OpHelp(""),
+ /* 116 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"),
+ /* 117 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"),
+ /* 118 */ "ParseSchema" OpHelp(""),
+ /* 119 */ "LoadAnalysis" OpHelp(""),
+ /* 120 */ "DropTable" OpHelp(""),
+ /* 121 */ "DropIndex" OpHelp(""),
+ /* 122 */ "DropTrigger" OpHelp(""),
+ /* 123 */ "IntegrityCk" OpHelp(""),
+ /* 124 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
+ /* 125 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
+ /* 126 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
+ /* 127 */ "Program" OpHelp(""),
+ /* 128 */ "Param" OpHelp(""),
+ /* 129 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 130 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
+ /* 131 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
+ /* 132 */ "IfPos" OpHelp("if r[P1]>0 goto P2"),
+ /* 133 */ "Real" OpHelp("r[P2]=P4"),
+ /* 134 */ "IfNeg" OpHelp("if r[P1]<0 goto P2"),
+ /* 135 */ "IfZero" OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"),
+ /* 136 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
+ /* 137 */ "IncrVacuum" OpHelp(""),
+ /* 138 */ "Expire" OpHelp(""),
+ /* 139 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 140 */ "VBegin" OpHelp(""),
+ /* 141 */ "VCreate" OpHelp(""),
+ /* 142 */ "VDestroy" OpHelp(""),
+ /* 143 */ "ToText" OpHelp(""),
+ /* 144 */ "ToBlob" OpHelp(""),
+ /* 145 */ "ToNumeric" OpHelp(""),
+ /* 146 */ "ToInt" OpHelp(""),
+ /* 147 */ "ToReal" OpHelp(""),
+ /* 148 */ "VOpen" OpHelp(""),
+ /* 149 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 150 */ "VNext" OpHelp(""),
+ /* 151 */ "VRename" OpHelp(""),
+ /* 152 */ "Pagecount" OpHelp(""),
+ /* 153 */ "MaxPgcnt" OpHelp(""),
+ /* 154 */ "Init" OpHelp("Start at P2"),
+ /* 155 */ "Noop" OpHelp(""),
+ /* 156 */ "Explain" OpHelp(""),
};
return azName[i];
}
@@ -23186,32 +23569,6 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
#endif
/*
-** These #defines should enable >2GB file support on Posix if the
-** underlying operating system supports it. If the OS lacks
-** large file support, these should be no-ops.
-**
-** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
-** on the compiler command line. This is necessary if you are compiling
-** on a recent machine (ex: RedHat 7.2) but you want your code to work
-** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
-** without this option, LFS is enable. But LFS does not exist in the kernel
-** in RedHat 6.0, so the code won't work. Hence, for maximum binary
-** portability you should omit LFS.
-**
-** The previous paragraph was written in 2005. (This paragraph is written
-** on 2008-11-28.) These days, all Linux kernels support large files, so
-** you should probably leave LFS enabled. But some embedded platforms might
-** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
-*/
-#ifndef SQLITE_DISABLE_LFS
-# define _LARGE_FILE 1
-# ifndef _FILE_OFFSET_BITS
-# define _FILE_OFFSET_BITS 64
-# endif
-# define _LARGEFILE_SOURCE 1
-#endif
-
-/*
** standard include files.
*/
#include <sys/types.h>
@@ -23362,6 +23719,12 @@ struct unixFile {
#endif
};
+/* This variable holds the process id (pid) from when the xRandomness()
+** method was called. If xOpen() is called from a different process id,
+** indicating that a fork() has occurred, the PRNG will be reset.
+*/
+static int randomnessPid = 0;
+
/*
** Allowed values for the unixFile.ctrlFlags bitmask:
*/
@@ -24625,6 +24988,15 @@ static int findInodeInfo(
return SQLITE_OK;
}
+/*
+** Return TRUE if pFile has been renamed or unlinked since it was first opened.
+*/
+static int fileHasMoved(unixFile *pFile){
+ struct stat buf;
+ return pFile->pInode!=0 &&
+ (osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino);
+}
+
/*
** Check a unixFile that is a database. Verify the following:
@@ -24659,10 +25031,7 @@ static void verifyDbFile(unixFile *pFile){
pFile->ctrlFlags |= UNIXFILE_WARNED;
return;
}
- if( pFile->pInode!=0
- && ((rc = osStat(pFile->zPath, &buf))!=0
- || buf.st_ino!=pFile->pInode->fileId.ino)
- ){
+ if( fileHasMoved(pFile) ){
sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
pFile->ctrlFlags |= UNIXFILE_WARNED;
return;
@@ -27111,6 +27480,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
}
return SQLITE_OK;
}
+ case SQLITE_FCNTL_HAS_MOVED: {
+ *(int*)pArg = fileHasMoved(pFile);
+ return SQLITE_OK;
+ }
#if SQLITE_MAX_MMAP_SIZE>0
case SQLITE_FCNTL_MMAP_SIZE: {
i64 newLimit = *(i64*)pArg;
@@ -27391,7 +27764,7 @@ static int unixShmSystemLock(
#ifdef SQLITE_DEBUG
{ u16 mask;
OSTRACE(("SHM-LOCK "));
- mask = ofst>31 ? 0xffffffff : (1<<(ofst+n)) - (1<<ofst);
+ mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<<ofst);
if( rc==SQLITE_OK ){
if( lockType==F_UNLCK ){
OSTRACE(("unlock %d ok", ofst));
@@ -28142,10 +28515,10 @@ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
** may now be invalid and should be unmapped.
*/
static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
+#if SQLITE_MAX_MMAP_SIZE>0
unixFile *pFd = (unixFile *)fd; /* The underlying database file */
UNUSED_PARAMETER(iOff);
-#if SQLITE_MAX_MMAP_SIZE>0
/* If p==0 (unmap the entire file) then there must be no outstanding
** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
** then there must be at least one outstanding. */
@@ -28161,6 +28534,10 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
}
assert( pFd->nFetchOut>=0 );
+#else
+ UNUSED_PARAMETER(fd);
+ UNUSED_PARAMETER(p);
+ UNUSED_PARAMETER(iOff);
#endif
return SQLITE_OK;
}
@@ -28951,6 +29328,16 @@ static int unixOpen(
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
);
+ /* Detect a pid change and reset the PRNG. There is a race condition
+ ** here such that two or more threads all trying to open databases at
+ ** the same instant might all reset the PRNG. But multiple resets
+ ** are harmless.
+ */
+ if( randomnessPid!=getpid() ){
+ randomnessPid = getpid();
+ sqlite3_randomness(0,0);
+ }
+
memset(p, 0, sizeof(unixFile));
if( eType==SQLITE_OPEN_MAIN_DB ){
@@ -29338,18 +29725,18 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
** tests repeatable.
*/
memset(zBuf, 0, nBuf);
+ randomnessPid = getpid();
#if !defined(SQLITE_TEST)
{
- int pid, fd, got;
+ int fd, got;
fd = robust_open("/dev/urandom", O_RDONLY, 0);
if( fd<0 ){
time_t t;
time(&t);
memcpy(zBuf, &t, sizeof(t));
- pid = getpid();
- memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
- assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
- nBuf = sizeof(t) + sizeof(pid);
+ memcpy(&zBuf[sizeof(t)], &randomnessPid, sizeof(randomnessPid));
+ assert( sizeof(t)+sizeof(randomnessPid)<=(size_t)nBuf );
+ nBuf = sizeof(t) + sizeof(randomnessPid);
}else{
do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR );
robust_close(0, fd, __LINE__);
@@ -34087,7 +34474,7 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
return SQLITE_OK;
}
case SQLITE_FCNTL_VFSNAME: {
- *(char**)pArg = sqlite3_mprintf("win32");
+ *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
return SQLITE_OK;
}
@@ -34169,7 +34556,7 @@ static int winDeviceCharacteristics(sqlite3_file *id){
** During sqlite3_os_init() we do a GetSystemInfo()
** to get the granularity size.
*/
-SYSTEM_INFO winSysInfo;
+static SYSTEM_INFO winSysInfo;
#ifndef SQLITE_OMIT_WAL
@@ -34192,7 +34579,7 @@ static void winShmEnterMutex(void){
static void winShmLeaveMutex(void){
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
-#ifdef SQLITE_DEBUG
+#ifndef NDEBUG
static int winShmMutexHeld(void) {
return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
@@ -36103,15 +36490,29 @@ static int winFullPathname(
** Interfaces for opening a shared library, finding entry points
** within the shared library, and closing the shared library.
*/
-/*
-** Interfaces for opening a shared library, finding entry points
-** within the shared library, and closing the shared library.
-*/
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
HANDLE h;
+#if defined(__CYGWIN__)
+ int nFull = pVfs->mxPathname+1;
+ char *zFull = sqlite3MallocZero( nFull );
+ void *zConverted = 0;
+ if( zFull==0 ){
+ OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
+ return 0;
+ }
+ if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){
+ sqlite3_free(zFull);
+ OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
+ return 0;
+ }
+ zConverted = winConvertFromUtf8Filename(zFull);
+ sqlite3_free(zFull);
+#else
void *zConverted = winConvertFromUtf8Filename(zFilename);
UNUSED_PARAMETER(pVfs);
+#endif
if( zConverted==0 ){
+ OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
return 0;
}
if( osIsNT() ){
@@ -36126,6 +36527,7 @@ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
h = osLoadLibraryA((char*)zConverted);
}
#endif
+ OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)h));
sqlite3_free(zConverted);
return (void*)h;
}
@@ -36134,12 +36536,17 @@ static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut);
}
static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
+ FARPROC proc;
UNUSED_PARAMETER(pVfs);
- return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym);
+ proc = osGetProcAddressA((HANDLE)pH, zSym);
+ OSTRACE(("DLSYM handle=%p, symbol=%s, address=%p\n",
+ (void*)pH, zSym, (void*)proc));
+ return (void(*)(void))proc;
}
static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
UNUSED_PARAMETER(pVfs);
osFreeLibrary((HANDLE)pHandle);
+ OSTRACE(("DLCLOSE handle=%p\n", (void*)pHandle));
}
#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
#define winDlOpen 0
@@ -36835,7 +37242,8 @@ struct PCache {
int szCache; /* Configured cache size */
int szPage; /* Size of every page in this cache */
int szExtra; /* Size of extra space for each page */
- int bPurgeable; /* True if pages are on backing store */
+ u8 bPurgeable; /* True if pages are on backing store */
+ u8 eCreate; /* eCreate value for for xFetch() */
int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
void *pStress; /* Argument to xStress */
sqlite3_pcache *pCache; /* Pluggable cache module */
@@ -36902,6 +37310,10 @@ static void pcacheRemoveFromDirtyList(PgHdr *pPage){
}else{
assert( pPage==p->pDirty );
p->pDirty = pPage->pDirtyNext;
+ if( p->pDirty==0 && p->bPurgeable ){
+ assert( p->eCreate==1 );
+ p->eCreate = 2;
+ }
}
pPage->pDirtyNext = 0;
pPage->pDirtyPrev = 0;
@@ -36922,6 +37334,9 @@ static void pcacheAddToDirtyList(PgHdr *pPage){
if( pPage->pDirtyNext ){
assert( pPage->pDirtyNext->pDirtyPrev==0 );
pPage->pDirtyNext->pDirtyPrev = pPage;
+ }else if( p->bPurgeable ){
+ assert( p->eCreate==2 );
+ p->eCreate = 1;
}
p->pDirty = pPage;
if( !p->pDirtyTail ){
@@ -36991,6 +37406,7 @@ SQLITE_PRIVATE void sqlite3PcacheOpen(
p->szPage = szPage;
p->szExtra = szExtra;
p->bPurgeable = bPurgeable;
+ p->eCreate = 2;
p->xStress = xStress;
p->pStress = pStress;
p->szCache = 100;
@@ -37030,7 +37446,7 @@ SQLITE_PRIVATE int sqlite3PcacheFetch(
int createFlag, /* If true, create page if it does not exist already */
PgHdr **ppPage /* Write the page here */
){
- sqlite3_pcache_page *pPage = 0;
+ sqlite3_pcache_page *pPage;
PgHdr *pPgHdr = 0;
int eCreate;
@@ -37041,8 +37457,12 @@ SQLITE_PRIVATE int sqlite3PcacheFetch(
/* If the pluggable cache (sqlite3_pcache*) has not been allocated,
** allocate it now.
*/
- if( !pCache->pCache && createFlag ){
+ if( !pCache->pCache ){
sqlite3_pcache *p;
+ if( !createFlag ){
+ *ppPage = 0;
+ return SQLITE_OK;
+ }
p = sqlite3GlobalConfig.pcache2.xCreate(
pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
);
@@ -37053,11 +37473,16 @@ SQLITE_PRIVATE int sqlite3PcacheFetch(
pCache->pCache = p;
}
- eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty));
- if( pCache->pCache ){
- pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
- }
-
+ /* eCreate defines what to do if the page does not exist.
+ ** 0 Do not allocate a new page. (createFlag==0)
+ ** 1 Allocate a new page if doing so is inexpensive.
+ ** (createFlag==1 AND bPurgeable AND pDirty)
+ ** 2 Allocate a new page even it doing so is difficult.
+ ** (createFlag==1 AND !(bPurgeable AND pDirty)
+ */
+ eCreate = createFlag==0 ? 0 : pCache->eCreate;
+ assert( (createFlag*(1+(!pCache->bPurgeable||!pCache->pDirty)))==eCreate );
+ pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
if( !pPage && eCreate==1 ){
PgHdr *pPg;
@@ -37529,6 +37954,7 @@ struct PCache1 {
struct PgHdr1 {
sqlite3_pcache_page page;
unsigned int iKey; /* Key value (page number) */
+ u8 isPinned; /* Page in use, not on the LRU list */
PgHdr1 *pNext; /* Next in hash table chain */
PCache1 *pCache; /* Cache that currently owns this page */
PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
@@ -37857,34 +38283,32 @@ static int pcache1ResizeHash(PCache1 *p){
** LRU list, then this function is a no-op.
**
** The PGroup mutex must be held when this function is called.
-**
-** If pPage is NULL then this routine is a no-op.
*/
static void pcache1PinPage(PgHdr1 *pPage){
PCache1 *pCache;
PGroup *pGroup;
- if( pPage==0 ) return;
+ assert( pPage!=0 );
+ assert( pPage->isPinned==0 );
pCache = pPage->pCache;
pGroup = pCache->pGroup;
+ assert( pPage->pLruNext || pPage==pGroup->pLruTail );
+ assert( pPage->pLruPrev || pPage==pGroup->pLruHead );
assert( sqlite3_mutex_held(pGroup->mutex) );
- if( pPage->pLruNext || pPage==pGroup->pLruTail ){
- if( pPage->pLruPrev ){
- pPage->pLruPrev->pLruNext = pPage->pLruNext;
- }
- if( pPage->pLruNext ){
- pPage->pLruNext->pLruPrev = pPage->pLruPrev;
- }
- if( pGroup->pLruHead==pPage ){
- pGroup->pLruHead = pPage->pLruNext;
- }
- if( pGroup->pLruTail==pPage ){
- pGroup->pLruTail = pPage->pLruPrev;
- }
- pPage->pLruNext = 0;
- pPage->pLruPrev = 0;
- pPage->pCache->nRecyclable--;
+ if( pPage->pLruPrev ){
+ pPage->pLruPrev->pLruNext = pPage->pLruNext;
+ }else{
+ pGroup->pLruHead = pPage->pLruNext;
}
+ if( pPage->pLruNext ){
+ pPage->pLruNext->pLruPrev = pPage->pLruPrev;
+ }else{
+ pGroup->pLruTail = pPage->pLruPrev;
+ }
+ pPage->pLruNext = 0;
+ pPage->pLruPrev = 0;
+ pPage->isPinned = 1;
+ pCache->nRecyclable--;
}
@@ -37916,6 +38340,7 @@ static void pcache1EnforceMaxPage(PGroup *pGroup){
while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){
PgHdr1 *p = pGroup->pLruTail;
assert( p->pCache->pGroup==pGroup );
+ assert( p->isPinned==0 );
pcache1PinPage(p);
pcache1RemoveFromHash(p);
pcache1FreePage(p);
@@ -37943,7 +38368,7 @@ static void pcache1TruncateUnsafe(
if( pPage->iKey>=iLimit ){
pCache->nPage--;
*pp = pPage->pNext;
- pcache1PinPage(pPage);
+ if( !pPage->isPinned ) pcache1PinPage(pPage);
pcache1FreePage(pPage);
}else{
pp = &pPage->pNext;
@@ -38153,6 +38578,7 @@ static sqlite3_pcache_page *pcache1Fetch(
PGroup *pGroup;
PgHdr1 *pPage = 0;
+ assert( offsetof(PgHdr1,page)==0 );
assert( pCache->bPurgeable || createFlag!=1 );
assert( pCache->bPurgeable || pCache->nMin==0 );
assert( pCache->bPurgeable==0 || pCache->nMin==10 );
@@ -38166,8 +38592,11 @@ static sqlite3_pcache_page *pcache1Fetch(
}
/* Step 2: Abort if no existing page is found and createFlag is 0 */
- if( pPage || createFlag==0 ){
- pcache1PinPage(pPage);
+ if( pPage ){
+ if( !pPage->isPinned ) pcache1PinPage(pPage);
+ goto fetch_out;
+ }
+ if( createFlag==0 ){
goto fetch_out;
}
@@ -38208,6 +38637,7 @@ static sqlite3_pcache_page *pcache1Fetch(
)){
PCache1 *pOther;
pPage = pGroup->pLruTail;
+ assert( pPage->isPinned==0 );
pcache1RemoveFromHash(pPage);
pcache1PinPage(pPage);
pOther = pPage->pCache;
@@ -38244,6 +38674,7 @@ static sqlite3_pcache_page *pcache1Fetch(
pPage->pCache = pCache;
pPage->pLruPrev = 0;
pPage->pLruNext = 0;
+ pPage->isPinned = 1;
*(void **)pPage->page.pExtra = 0;
pCache->apHash[h] = pPage;
}
@@ -38253,7 +38684,7 @@ fetch_out:
pCache->iMaxKey = iKey;
}
pcache1LeaveMutex(pGroup);
- return &pPage->page;
+ return (sqlite3_pcache_page*)pPage;
}
@@ -38279,6 +38710,7 @@ static void pcache1Unpin(
*/
assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage );
+ assert( pPage->isPinned==1 );
if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
pcache1RemoveFromHash(pPage);
@@ -38294,6 +38726,7 @@ static void pcache1Unpin(
pGroup->pLruHead = pPage;
}
pCache->nRecyclable++;
+ pPage->isPinned = 0;
}
pcache1LeaveMutex(pCache->pGroup);
@@ -38420,6 +38853,7 @@ SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
nFree += sqlite3MemSize(p);
#endif
+ assert( p->isPinned==0 );
pcache1PinPage(p);
pcache1RemoveFromHash(p);
pcache1FreePage(p);
@@ -38444,6 +38878,7 @@ SQLITE_PRIVATE void sqlite3PcacheStats(
PgHdr1 *p;
int nRecyclable = 0;
for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){
+ assert( p->isPinned==0 );
nRecyclable++;
}
*pnCurrent = pcache1.grp.nCurrentPage;
@@ -40130,15 +40565,12 @@ static char *print_pager_state(Pager *p){
static int subjRequiresPage(PgHdr *pPg){
Pager *pPager = pPg->pPager;
PagerSavepoint *p;
- Pgno pgno;
+ Pgno pgno = pPg->pgno;
int i;
- if( pPager->nSavepoint ){
- pgno = pPg->pgno;
- for(i=0; i<pPager->nSavepoint; i++){
- p = &pPager->aSavepoint[i];
- if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
- return 1;
- }
+ for(i=0; i<pPager->nSavepoint; i++){
+ p = &pPager->aSavepoint[i];
+ if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
+ return 1;
}
}
return 0;
@@ -40147,8 +40579,8 @@ static int subjRequiresPage(PgHdr *pPg){
/*
** Return true if the page is already in the journal file.
*/
-static int pageInJournal(PgHdr *pPg){
- return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno);
+static int pageInJournal(Pager *pPager, PgHdr *pPg){
+ return sqlite3BitvecTest(pPager->pInJournal, pPg->pgno);
}
/*
@@ -40355,6 +40787,7 @@ static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
|| szJ<16
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
|| len>=nMaster
+ || len==0
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
|| memcmp(aMagic, aJournalMagic, 8)
@@ -40791,7 +41224,7 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
** already in memory.
*/
static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
- PgHdr *p; /* Return value */
+ PgHdr *p = 0; /* Return value */
/* It is not possible for a call to PcacheFetch() with createFlag==0 to
** fail, since no attempt to allocate dynamic memory will be made.
@@ -41095,7 +41528,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
PgHdr *p = pager_lookup(pPager, 1);
if( p ){
p->pageHash = 0;
- sqlite3PagerUnref(p);
+ sqlite3PagerUnrefNotNull(p);
}
}
#endif
@@ -41124,6 +41557,11 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
rc = pager_truncate(pPager, pPager->dbSize);
}
+ if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){
+ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0);
+ if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
+ }
+
if( !pPager->exclusiveMode
&& (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
){
@@ -41937,7 +42375,7 @@ end_playback:
if( rc==SQLITE_OK
&& (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
){
- rc = sqlite3PagerSync(pPager);
+ rc = sqlite3PagerSync(pPager, 0);
}
if( rc==SQLITE_OK ){
rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
@@ -42083,7 +42521,7 @@ static int pagerUndoCallback(void *pCtx, Pgno iPg){
if( rc==SQLITE_OK ){
pPager->xReiniter(pPg);
}
- sqlite3PagerUnref(pPg);
+ sqlite3PagerUnrefNotNull(pPg);
}
}
@@ -43438,7 +43876,7 @@ static int subjournalPage(PgHdr *pPg){
assert( isOpen(pPager->jfd) || pagerUseWal(pPager) );
assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 );
assert( pagerUseWal(pPager)
- || pageInJournal(pPg)
+ || pageInJournal(pPager, pPg)
|| pPg->pgno>pPager->dbOrigSize
);
rc = openSubJournal(pPager);
@@ -43903,6 +44341,30 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
}
+/* Verify that the database file has not be deleted or renamed out from
+** under the pager. Return SQLITE_OK if the database is still were it ought
+** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error
+** code from sqlite3OsAccess()) if the database has gone missing.
+*/
+static int databaseIsUnmoved(Pager *pPager){
+ int bHasMoved = 0;
+ int rc;
+
+ if( pPager->tempFile ) return SQLITE_OK;
+ if( pPager->dbSize==0 ) return SQLITE_OK;
+ assert( pPager->zFilename && pPager->zFilename[0] );
+ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved);
+ if( rc==SQLITE_NOTFOUND ){
+ /* If the HAS_MOVED file-control is unimplemented, assume that the file
+ ** has not been moved. That is the historical behavior of SQLite: prior to
+ ** version 3.8.3, it never checked */
+ rc = SQLITE_OK;
+ }else if( rc==SQLITE_OK && bHasMoved ){
+ rc = SQLITE_READONLY_DBMOVED;
+ }
+ return rc;
+}
+
/*
** This function is called after transitioning from PAGER_UNLOCK to
@@ -43968,15 +44430,17 @@ static int hasHotJournal(Pager *pPager, int *pExists){
if( rc==SQLITE_OK && !locked ){
Pgno nPage; /* Number of pages in database file */
- /* Check the size of the database file. If it consists of 0 pages,
- ** then delete the journal file. See the header comment above for
- ** the reasoning here. Delete the obsolete journal file under
- ** a RESERVED lock to avoid race conditions and to avoid violating
- ** [H33020].
- */
rc = pagerPagecount(pPager, &nPage);
if( rc==SQLITE_OK ){
- if( nPage==0 ){
+ /* If the database is zero pages in size, that means that either (1) the
+ ** journal is a remnant from a prior database with the same name where
+ ** the database file but not the journal was deleted, or (2) the initial
+ ** transaction that populates a new database is being rolled back.
+ ** In either case, the journal file can be deleted. However, take care
+ ** not to delete the journal file if it is already open due to
+ ** journal_mode=PERSIST.
+ */
+ if( nPage==0 && !jrnlOpen ){
sqlite3BeginBenignMalloc();
if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){
sqlite3OsDelete(pVfs, pPager->zJournal, 0);
@@ -44374,7 +44838,7 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
if( rc!=SQLITE_OK ) goto pager_acquire_err;
}
- if( iFrame==0 && bMmapOk ){
+ if( bMmapOk && iFrame==0 ){
void *pData = 0;
rc = sqlite3OsFetch(pPager->fd,
@@ -44515,16 +44979,19 @@ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
** are released, a rollback occurs and the lock on the database is
** removed.
*/
-SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){
- if( pPg ){
- Pager *pPager = pPg->pPager;
- if( pPg->flags & PGHDR_MMAP ){
- pagerReleaseMapPage(pPg);
- }else{
- sqlite3PcacheRelease(pPg);
- }
- pagerUnlockIfUnused(pPager);
+SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage *pPg){
+ Pager *pPager;
+ assert( pPg!=0 );
+ pPager = pPg->pPager;
+ if( pPg->flags & PGHDR_MMAP ){
+ pagerReleaseMapPage(pPg);
+ }else{
+ sqlite3PcacheRelease(pPg);
}
+ pagerUnlockIfUnused(pPager);
+}
+SQLITE_PRIVATE void sqlite3PagerUnref(DbPage *pPg){
+ if( pPg ) sqlite3PagerUnrefNotNull(pPg);
}
/*
@@ -44579,13 +45046,19 @@ static int pager_open_journal(Pager *pPager){
(SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
(SQLITE_OPEN_MAIN_JOURNAL)
);
- #ifdef SQLITE_ENABLE_ATOMIC_WRITE
- rc = sqlite3JournalOpen(
- pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
- );
- #else
- rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
- #endif
+
+ /* Verify that the database still has the same name as it did when
+ ** it was originally opened. */
+ rc = databaseIsUnmoved(pPager);
+ if( rc==SQLITE_OK ){
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+ rc = sqlite3JournalOpen(
+ pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
+ );
+#else
+ rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
+#endif
+ }
}
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
}
@@ -44706,9 +45179,9 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory
** of any open savepoints as appropriate.
*/
static int pager_write(PgHdr *pPg){
- void *pData = pPg->pData;
Pager *pPager = pPg->pPager;
int rc = SQLITE_OK;
+ int inJournal;
/* This routine is not called unless a write-transaction has already
** been started. The journal file may or may not be open at this point.
@@ -44719,14 +45192,8 @@ static int pager_write(PgHdr *pPg){
|| pPager->eState==PAGER_WRITER_DBMOD
);
assert( assert_pager_state(pPager) );
-
- /* If an error has been previously detected, report the same error
- ** again. This should not happen, but the check provides robustness. */
- if( NEVER(pPager->errCode) ) return pPager->errCode;
-
- /* Higher-level routines never call this function if database is not
- ** writable. But check anyway, just for robustness. */
- if( NEVER(pPager->readOnly) ) return SQLITE_PERM;
+ assert( pPager->errCode==0 );
+ assert( pPager->readOnly==0 );
CHECK_PAGE(pPg);
@@ -44750,7 +45217,8 @@ static int pager_write(PgHdr *pPg){
** to the journal then we can return right away.
*/
sqlite3PcacheMakeDirty(pPg);
- if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){
+ inJournal = pageInJournal(pPager, pPg);
+ if( inJournal && (pPager->nSavepoint==0 || !subjRequiresPage(pPg)) ){
assert( !pagerUseWal(pPager) );
}else{
@@ -44758,7 +45226,7 @@ static int pager_write(PgHdr *pPg){
** EXCLUSIVE lock on the main database file. Write the current page to
** the transaction journal if it is not there already.
*/
- if( !pageInJournal(pPg) && !pagerUseWal(pPager) ){
+ if( !inJournal && !pagerUseWal(pPager) ){
assert( pagerUseWal(pPager)==0 );
if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){
u32 cksum;
@@ -44771,7 +45239,7 @@ static int pager_write(PgHdr *pPg){
assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
assert( pPager->journalHdr<=pPager->journalOff );
- CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
+ CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
cksum = pager_cksum(pPager, (u8*)pData2);
/* Even if an IO or diskfull error occurs while journalling the
@@ -44823,7 +45291,7 @@ static int pager_write(PgHdr *pPg){
** the statement journal format differs from the standard journal format
** in that it omits the checksums and the header.
*/
- if( subjRequiresPage(pPg) ){
+ if( pPager->nSavepoint>0 && subjRequiresPage(pPg) ){
rc = subjournalPage(pPg);
}
}
@@ -44855,19 +45323,19 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
PgHdr *pPg = pDbPage;
Pager *pPager = pPg->pPager;
- Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
assert( (pPg->flags & PGHDR_MMAP)==0 );
assert( pPager->eState>=PAGER_WRITER_LOCKED );
assert( pPager->eState!=PAGER_ERROR );
assert( assert_pager_state(pPager) );
- if( nPagePerSector>1 ){
+ if( pPager->sectorSize > (u32)pPager->pageSize ){
Pgno nPageCount; /* Total number of pages in database file */
Pgno pg1; /* First page of the sector pPg is located on. */
int nPage = 0; /* Number of pages starting at pg1 to journal */
int ii; /* Loop counter */
int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */
+ Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
/* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
** a journal header to be written between the pages journaled by
@@ -44906,14 +45374,14 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
if( pPage->flags&PGHDR_NEED_SYNC ){
needSync = 1;
}
- sqlite3PagerUnref(pPage);
+ sqlite3PagerUnrefNotNull(pPage);
}
}
}else if( (pPage = pager_lookup(pPager, pg))!=0 ){
if( pPage->flags&PGHDR_NEED_SYNC ){
needSync = 1;
}
- sqlite3PagerUnref(pPage);
+ sqlite3PagerUnrefNotNull(pPage);
}
}
@@ -44929,7 +45397,7 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
PgHdr *pPage = pager_lookup(pPager, pg1+ii);
if( pPage ){
pPage->flags |= PGHDR_NEED_SYNC;
- sqlite3PagerUnref(pPage);
+ sqlite3PagerUnrefNotNull(pPage);
}
}
}
@@ -45082,17 +45550,17 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
** If successful, or if called on a pager for which it is a no-op, this
** function returns SQLITE_OK. Otherwise, an IO error code is returned.
*/
-SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){
+SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){
int rc = SQLITE_OK;
- if( !pPager->noSync ){
+
+ if( isOpen(pPager->fd) ){
+ void *pArg = (void*)zMaster;
+ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg);
+ if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
+ }
+ if( rc==SQLITE_OK && !pPager->noSync ){
assert( !MEMDB );
rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
- }else if( isOpen(pPager->fd) ){
- assert( !MEMDB );
- rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, 0);
- if( rc==SQLITE_NOTFOUND ){
- rc = SQLITE_OK;
- }
}
return rc;
}
@@ -45291,7 +45759,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
/* Finally, sync the database file. */
if( !noSync ){
- rc = sqlite3PagerSync(pPager);
+ rc = sqlite3PagerSync(pPager, zMaster);
}
IOTRACE(("DBSYNC %p\n", pPager))
}
@@ -45420,7 +45888,9 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT
- || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR );
+ || rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR
+ || rc==SQLITE_CANTOPEN
+ );
/* If an error occurs during a ROLLBACK, we can no longer trust the pager
** cache. So call pager_error() on the way out to make any error persistent.
@@ -45823,7 +46293,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
needSyncPgno = pPg->pgno;
assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
- pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
+ pageInJournal(pPager, pPg) || pPg->pgno>pPager->dbOrigSize );
assert( pPg->flags&PGHDR_DIRTY );
}
@@ -45857,7 +46327,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
if( MEMDB ){
assert( pPgOld );
sqlite3PcacheMove(pPgOld, origPgno);
- sqlite3PagerUnref(pPgOld);
+ sqlite3PagerUnrefNotNull(pPgOld);
}
if( needSyncPgno ){
@@ -45886,7 +46356,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
}
pPgHdr->flags |= PGHDR_NEED_SYNC;
sqlite3PcacheMakeDirty(pPgHdr);
- sqlite3PagerUnref(pPgHdr);
+ sqlite3PagerUnrefNotNull(pPgHdr);
}
return SQLITE_OK;
@@ -47602,7 +48072,7 @@ SQLITE_PRIVATE int sqlite3WalOpen(
sqlite3OsClose(pRet->pWalFd);
sqlite3_free(pRet);
}else{
- int iDC = sqlite3OsDeviceCharacteristics(pRet->pWalFd);
+ int iDC = sqlite3OsDeviceCharacteristics(pDbFd);
if( iDC & SQLITE_IOCAP_SEQUENTIAL ){ pRet->syncHeader = 0; }
if( iDC & SQLITE_IOCAP_POWERSAFE_OVERWRITE ){
pRet->padToSectorBoundary = 0;
@@ -48973,7 +49443,7 @@ static int walWriteToLog(
iAmt -= iFirstAmt;
pContent = (void*)(iFirstAmt + (char*)pContent);
assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) );
- rc = sqlite3OsSync(p->pFd, p->syncFlags);
+ rc = sqlite3OsSync(p->pFd, p->syncFlags & SQLITE_SYNC_MASK);
if( iAmt==0 || rc ) return rc;
}
rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset);
@@ -49911,7 +50381,6 @@ struct BtCursor {
Pgno *aOverflow; /* Cache of overflow page locations */
#endif
Pgno pgnoRoot; /* The root page of this tree */
- sqlite3_int64 cachedRowid; /* Next rowid cache. 0 means not valid */
CellInfo info; /* A parse of the cell we are pointing at */
i64 nKey; /* Size of pKey, or last integer key */
void *pKey; /* Saved key that was cursor's last known position */
@@ -51895,13 +52364,12 @@ static void zeroPage(MemPage *pPage, int flags){
memset(&data[hdr], 0, pBt->usableSize - hdr);
}
data[hdr] = (char)flags;
- first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0);
+ first = hdr + ((flags&PTF_LEAF)==0 ? 12 : 8);
memset(&data[hdr+1], 0, 4);
data[hdr+7] = 0;
put2byte(&data[hdr+5], pBt->usableSize);
pPage->nFree = (u16)(pBt->usableSize - first);
decodeFlags(pPage, flags);
- pPage->hdrOffset = hdr;
pPage->cellOffset = first;
pPage->aDataEnd = &data[pBt->usableSize];
pPage->aCellIdx = &data[first];
@@ -52005,7 +52473,7 @@ static int getAndInitPage(
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = btreeGetPage(pBt, pgno, ppPage, bReadonly);
- if( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){
rc = btreeInitPage(*ppPage);
if( rc!=SQLITE_OK ){
releasePage(*ppPage);
@@ -52026,10 +52494,11 @@ static void releasePage(MemPage *pPage){
if( pPage ){
assert( pPage->aData );
assert( pPage->pBt );
+ assert( pPage->pDbPage!=0 );
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- sqlite3PagerUnref(pPage->pDbPage);
+ sqlite3PagerUnrefNotNull(pPage->pDbPage);
}
}
@@ -53984,7 +54453,6 @@ static int btreeCursor(
}
pBt->pCursor = pCur;
pCur->eState = CURSOR_INVALID;
- pCur->cachedRowid = 0;
return SQLITE_OK;
}
SQLITE_PRIVATE int sqlite3BtreeCursor(
@@ -54026,36 +54494,6 @@ SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){
}
/*
-** Set the cached rowid value of every cursor in the same database file
-** as pCur and having the same root page number as pCur. The value is
-** set to iRowid.
-**
-** Only positive rowid values are considered valid for this cache.
-** The cache is initialized to zero, indicating an invalid cache.
-** A btree will work fine with zero or negative rowids. We just cannot
-** cache zero or negative rowids, which means tables that use zero or
-** negative rowids might run a little slower. But in practice, zero
-** or negative rowids are very uncommon so this should not be a problem.
-*/
-SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor *pCur, sqlite3_int64 iRowid){
- BtCursor *p;
- for(p=pCur->pBt->pCursor; p; p=p->pNext){
- if( p->pgnoRoot==pCur->pgnoRoot ) p->cachedRowid = iRowid;
- }
- assert( pCur->cachedRowid==iRowid );
-}
-
-/*
-** Return the cached rowid for the given cursor. A negative or zero
-** return value indicates that the rowid cache is invalid and should be
-** ignored. If the rowid cache has never before been set, then a
-** zero is returned.
-*/
-SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor *pCur){
- return pCur->cachedRowid;
-}
-
-/*
** Close a cursor. The read lock on the database file is released
** when the last cursor is closed.
*/
@@ -54106,7 +54544,7 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
int iPage = pCur->iPage;
memset(&info, 0, sizeof(info));
btreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info);
- assert( memcmp(&info, &pCur->info, sizeof(info))==0 );
+ assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 );
}
#else
#define assertCellInfo(x)
@@ -54545,10 +54983,10 @@ SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *p
/*
** Return a pointer to payload information from the entry that the
** pCur cursor is pointing to. The pointer is to the beginning of
-** the key if skipKey==0 and it points to the beginning of data if
-** skipKey==1. The number of bytes of available key/data is written
-** into *pAmt. If *pAmt==0, then the value returned will not be
-** a valid pointer.
+** the key if index btrees (pPage->intKey==0) and is the data for
+** table btrees (pPage->intKey==1). The number of bytes of available
+** key/data is written into *pAmt. If *pAmt==0, then the value
+** returned will not be a valid pointer.
**
** This routine is an optimization. It is common for the entire key
** and data to fit on the local page and for there to be no overflow
@@ -54561,41 +54999,21 @@ SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *p
** page of the database. The data might change or move the next time
** any btree routine is called.
*/
-static const unsigned char *fetchPayload(
+static const void *fetchPayload(
BtCursor *pCur, /* Cursor pointing to entry to read from */
- u32 *pAmt, /* Write the number of available bytes here */
- int skipKey /* read beginning at data if this is true */
+ u32 *pAmt /* Write the number of available bytes here */
){
- unsigned char *aPayload;
- MemPage *pPage;
- u32 nKey;
- u32 nLocal;
-
assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
assert( pCur->eState==CURSOR_VALID );
+ assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorHoldsMutex(pCur) );
- pPage = pCur->apPage[pCur->iPage];
- assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
+ assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
if( pCur->info.nSize==0 ){
btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage],
&pCur->info);
}
- aPayload = pCur->info.pCell;
- aPayload += pCur->info.nHeader;
- if( pPage->intKey ){
- nKey = 0;
- }else{
- nKey = (int)pCur->info.nKey;
- }
- if( skipKey ){
- aPayload += nKey;
- nLocal = pCur->info.nLocal - nKey;
- }else{
- nLocal = pCur->info.nLocal;
- assert( nLocal<=nKey );
- }
- *pAmt = nLocal;
- return aPayload;
+ *pAmt = pCur->info.nLocal;
+ return (void*)(pCur->info.pCell + pCur->info.nHeader);
}
@@ -54614,22 +55032,10 @@ static const unsigned char *fetchPayload(
** in the common case where no overflow pages are used.
*/
SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor *pCur, u32 *pAmt){
- const void *p = 0;
- assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
- assert( cursorHoldsMutex(pCur) );
- if( ALWAYS(pCur->eState==CURSOR_VALID) ){
- p = (const void*)fetchPayload(pCur, pAmt, 0);
- }
- return p;
+ return fetchPayload(pCur, pAmt);
}
SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor *pCur, u32 *pAmt){
- const void *p = 0;
- assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
- assert( cursorHoldsMutex(pCur) );
- if( ALWAYS(pCur->eState==CURSOR_VALID) ){
- p = (const void*)fetchPayload(pCur, pAmt, 1);
- }
- return p;
+ return fetchPayload(pCur, pAmt);
}
@@ -54748,8 +55154,6 @@ static void moveToParent(BtCursor *pCur){
static int moveToRoot(BtCursor *pCur){
MemPage *pRoot;
int rc = SQLITE_OK;
- Btree *p = pCur->pBtree;
- BtShared *pBt = p->pBt;
assert( cursorHoldsMutex(pCur) );
assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
@@ -54764,56 +55168,52 @@ static int moveToRoot(BtCursor *pCur){
}
if( pCur->iPage>=0 ){
- int i;
- for(i=1; i<=pCur->iPage; i++){
- releasePage(pCur->apPage[i]);
- }
- pCur->iPage = 0;
+ while( pCur->iPage ) releasePage(pCur->apPage[pCur->iPage--]);
}else if( pCur->pgnoRoot==0 ){
pCur->eState = CURSOR_INVALID;
return SQLITE_OK;
}else{
- rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0],
+ rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
if( rc!=SQLITE_OK ){
pCur->eState = CURSOR_INVALID;
return rc;
}
pCur->iPage = 0;
-
- /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
- ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
- ** NULL, the caller expects a table b-tree. If this is not the case,
- ** return an SQLITE_CORRUPT error. */
- assert( pCur->apPage[0]->intKey==1 || pCur->apPage[0]->intKey==0 );
- if( (pCur->pKeyInfo==0)!=pCur->apPage[0]->intKey ){
- return SQLITE_CORRUPT_BKPT;
- }
}
-
- /* Assert that the root page is of the correct type. This must be the
- ** case as the call to this function that loaded the root-page (either
- ** this call or a previous invocation) would have detected corruption
- ** if the assumption were not true, and it is not possible for the flags
- ** byte to have been modified while this cursor is holding a reference
- ** to the page. */
pRoot = pCur->apPage[0];
assert( pRoot->pgno==pCur->pgnoRoot );
- assert( pRoot->isInit && (pCur->pKeyInfo==0)==pRoot->intKey );
+
+ /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
+ ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
+ ** NULL, the caller expects a table b-tree. If this is not the case,
+ ** return an SQLITE_CORRUPT error.
+ **
+ ** Earlier versions of SQLite assumed that this test could not fail
+ ** if the root page was already loaded when this function was called (i.e.
+ ** if pCur->iPage>=0). But this is not so if the database is corrupted
+ ** in such a way that page pRoot is linked into a second b-tree table
+ ** (or the freelist). */
+ assert( pRoot->intKey==1 || pRoot->intKey==0 );
+ if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
+ return SQLITE_CORRUPT_BKPT;
+ }
pCur->aiIdx[0] = 0;
pCur->info.nSize = 0;
pCur->atLast = 0;
pCur->validNKey = 0;
- if( pRoot->nCell==0 && !pRoot->leaf ){
+ if( pRoot->nCell>0 ){
+ pCur->eState = CURSOR_VALID;
+ }else if( !pRoot->leaf ){
Pgno subpage;
if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT;
subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
pCur->eState = CURSOR_VALID;
rc = moveToChild(pCur, subpage);
}else{
- pCur->eState = ((pRoot->nCell>0)?CURSOR_VALID:CURSOR_INVALID);
+ pCur->eState = CURSOR_INVALID;
}
return rc;
}
@@ -54969,6 +55369,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
int *pRes /* Write search results here */
){
int rc;
+ RecordCompare xRecordCompare;
assert( cursorHoldsMutex(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
@@ -54990,6 +55391,16 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
}
}
+ if( pIdxKey ){
+ xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
+ assert( pIdxKey->default_rc==1
+ || pIdxKey->default_rc==0
+ || pIdxKey->default_rc==-1
+ );
+ }else{
+ xRecordCompare = 0; /* All keys are integers */
+ }
+
rc = moveToRoot(pCur);
if( rc ){
return rc;
@@ -55022,7 +55433,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
assert( biasRight==0 || biasRight==1 );
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
pCur->aiIdx[pCur->iPage] = (u16)idx;
- if( pPage->intKey ){
+ if( xRecordCompare==0 ){
for(;;){
i64 nCellKey;
pCell = findCell(pPage, idx) + pPage->childPtrSize;
@@ -55069,22 +55480,19 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
** 2 bytes of the cell.
*/
nCell = pCell[0];
- if( nCell<=pPage->max1bytePayload
- /* && (pCell+nCell)<pPage->aDataEnd */
- ){
+ if( nCell<=pPage->max1bytePayload ){
/* This branch runs if the record-size field of the cell is a
** single byte varint and the record fits entirely on the main
** b-tree page. */
testcase( pCell+nCell+1==pPage->aDataEnd );
- c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
+ c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey, 0);
}else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
- /* && (pCell+nCell+2)<=pPage->aDataEnd */
){
/* The record-size field is a 2 byte varint and the record
** fits entirely on the main b-tree page. */
testcase( pCell+nCell+2==pPage->aDataEnd );
- c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
+ c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey, 0);
}else{
/* The record flows over onto one or more overflow pages. In
** this case the whole cell needs to be parsed, a buffer allocated
@@ -55105,7 +55513,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
sqlite3_free(pCellKey);
goto moveto_finish;
}
- c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
+ c = xRecordCompare(nCell, pCellKey, pIdxKey, 0);
sqlite3_free(pCellKey);
}
if( c<0 ){
@@ -55170,6 +55578,15 @@ SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor *pCur){
** successful then set *pRes=0. If the cursor
** was already pointing to the last entry in the database before
** this routine was called, then set *pRes=1.
+**
+** The calling function will set *pRes to 0 or 1. The initial *pRes value
+** will be 1 if the cursor being stepped corresponds to an SQL index and
+** if this routine could have been skipped if that SQL index had been
+** a unique index. Otherwise the caller will have set *pRes to zero.
+** Zero is the common case. The btree implementation is free to use the
+** initial *pRes value as a hint to improve performance, but the current
+** SQLite btree implementation does not. (Note that the comdb2 btree
+** implementation does use this hint, however.)
*/
SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
int rc;
@@ -55178,6 +55595,7 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
assert( cursorHoldsMutex(pCur) );
assert( pRes!=0 );
+ assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
if( pCur->eState!=CURSOR_VALID ){
rc = restoreCursorPosition(pCur);
@@ -55256,6 +55674,15 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
** successful then set *pRes=0. If the cursor
** was already pointing to the first entry in the database before
** this routine was called, then set *pRes=1.
+**
+** The calling function will set *pRes to 0 or 1. The initial *pRes value
+** will be 1 if the cursor being stepped corresponds to an SQL index and
+** if this routine could have been skipped if that SQL index had been
+** a unique index. Otherwise the caller will have set *pRes to zero.
+** Zero is the common case. The btree implementation is free to use the
+** initial *pRes value as a hint to improve performance, but the current
+** SQLite btree implementation does not. (Note that the comdb2 btree
+** implementation does use this hint, however.)
*/
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
int rc;
@@ -55263,6 +55690,7 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
assert( cursorHoldsMutex(pCur) );
assert( pRes!=0 );
+ assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->atLast = 0;
if( pCur->eState!=CURSOR_VALID ){
@@ -55642,6 +56070,7 @@ end_allocate_page:
if( rc==SQLITE_OK ){
if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){
releasePage(*ppPage);
+ *ppPage = 0;
return SQLITE_CORRUPT_BKPT;
}
(*ppPage)->isInit = 0;
@@ -55903,7 +56332,7 @@ static int fillInCell(
nHeader += 4;
}
if( pPage->hasData ){
- nHeader += putVarint(&pCell[nHeader], nData+nZero);
+ nHeader += putVarint32(&pCell[nHeader], nData+nZero);
}else{
nData = nZero = 0;
}
@@ -56031,7 +56460,6 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
u32 pc; /* Offset to cell content of cell being deleted */
u8 *data; /* pPage->aData */
u8 *ptr; /* Used to move bytes around within data[] */
- u8 *endPtr; /* End of loop */
int rc; /* The return code */
int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */
@@ -56056,13 +56484,8 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
*pRC = rc;
return;
}
- endPtr = &pPage->aCellIdx[2*pPage->nCell - 2];
- assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */
- while( ptr<endPtr ){
- *(u16*)ptr = *(u16*)&ptr[2];
- ptr += 2;
- }
pPage->nCell--;
+ memmove(ptr, ptr+2, 2*(pPage->nCell - idx));
put2byte(&data[hdr+3], pPage->nCell);
pPage->nFree += 2;
}
@@ -56099,9 +56522,6 @@ static void insertCell(
int ins; /* Index in data[] where new cell pointer is inserted */
int cellOffset; /* Address of first cell pointer in data[] */
u8 *data; /* The content of the whole page */
- u8 *ptr; /* Used for moving information around in data[] */
- u8 *endPtr; /* End of the loop */
-
int nSkip = (iChild ? 4 : 0);
if( *pRC ) return;
@@ -56152,13 +56572,7 @@ static void insertCell(
if( iChild ){
put4byte(&data[idx], iChild);
}
- ptr = &data[end];
- endPtr = &data[ins];
- assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */
- while( ptr>endPtr ){
- *(u16*)ptr = *(u16*)&ptr[-2];
- ptr -= 2;
- }
+ memmove(&data[ins+2], &data[ins], end-ins);
put2byte(&data[ins], idx);
put2byte(&data[pPage->hdrOffset+3], pPage->nCell);
#ifndef SQLITE_OMIT_AUTOVACUUM
@@ -57373,11 +57787,17 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
- /* If this is an insert into a table b-tree, invalidate any incrblob
- ** cursors open on the row being replaced (assuming this is a replace
- ** operation - if it is not, the following is a no-op). */
if( pCur->pKeyInfo==0 ){
+ /* If this is an insert into a table b-tree, invalidate any incrblob
+ ** cursors open on the row being replaced */
invalidateIncrblobCursors(p, nKey, 0);
+
+ /* If the cursor is currently on the last row and we are appending a
+ ** new row onto the end, set the "loc" to avoid an unnecessary btreeMoveto()
+ ** call */
+ if( pCur->validNKey && nKey>0 && pCur->info.nKey==nKey-1 ){
+ loc = -1;
+ }
}
if( !loc ){
@@ -57447,8 +57867,8 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
** row without seeking the cursor. This can be a big performance boost.
*/
pCur->info.nSize = 0;
- pCur->validNKey = 0;
if( rc==SQLITE_OK && pPage->nOverflow ){
+ pCur->validNKey = 0;
rc = balance(pCur);
/* Must make sure nOverflow is reset to zero even if the balance()
@@ -57503,7 +57923,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
** sub-tree headed by the child page of the cell being deleted. This makes
** balancing the tree following the delete operation easier. */
if( !pPage->leaf ){
- int notUsed;
+ int notUsed = 0;
rc = sqlite3BtreePrevious(pCur, &notUsed);
if( rc ) return rc;
}
@@ -57756,6 +58176,7 @@ static int clearDatabasePage(
int rc;
unsigned char *pCell;
int i;
+ int hdr;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pgno>btreePagecount(pBt) ){
@@ -57764,6 +58185,7 @@ static int clearDatabasePage(
rc = getAndInitPage(pBt, pgno, &pPage, 0);
if( rc ) return rc;
+ hdr = pPage->hdrOffset;
for(i=0; i<pPage->nCell; i++){
pCell = findCell(pPage, i);
if( !pPage->leaf ){
@@ -57774,7 +58196,7 @@ static int clearDatabasePage(
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
- rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), 1, pnChange);
+ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}else if( pnChange ){
assert( pPage->intKey );
@@ -57783,7 +58205,7 @@ static int clearDatabasePage(
if( freePageFlag ){
freePage(pPage, &rc);
}else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
- zeroPage(pPage, pPage->aData[0] | PTF_LEAF);
+ zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF);
}
cleardatabasepage_out:
@@ -58120,7 +58542,7 @@ static void checkAppendMsg(
sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1);
}
if( zMsg1 ){
- sqlite3StrAccumAppend(&pCheck->errMsg, zMsg1, -1);
+ sqlite3StrAccumAppendAll(&pCheck->errMsg, zMsg1);
}
sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap);
va_end(ap);
@@ -59414,7 +59836,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
/* Sync the database file to disk. */
if( rc==SQLITE_OK ){
- rc = sqlite3PagerSync(pDestPager);
+ rc = sqlite3PagerSync(pDestPager, 0);
}
}else{
sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
@@ -59489,10 +59911,10 @@ SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){
/* Set the error code of the destination database handle. */
rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
- sqlite3Error(p->pDestDb, rc, 0);
-
- /* Exit the mutexes and free the backup context structure. */
if( p->pDestDb ){
+ sqlite3Error(p->pDestDb, rc, 0);
+
+ /* Exit the mutexes and free the backup context structure. */
sqlite3LeaveMutexAndCloseZombie(p->pDestDb);
}
sqlite3BtreeLeave(p->pSrc);
@@ -59655,6 +60077,42 @@ copy_finished:
** name sqlite_value
*/
+#ifdef SQLITE_DEBUG
+/*
+** Check invariants on a Mem object.
+**
+** This routine is intended for use inside of assert() statements, like
+** this: assert( sqlite3VdbeCheckMemInvariants(pMem) );
+*/
+SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){
+ /* The MEM_Dyn bit is set if and only if Mem.xDel is a non-NULL destructor
+ ** function for Mem.z
+ */
+ assert( (p->flags & MEM_Dyn)==0 || p->xDel!=0 );
+ assert( (p->flags & MEM_Dyn)!=0 || p->xDel==0 );
+
+ /* If p holds a string or blob, the Mem.z must point to exactly
+ ** one of the following:
+ **
+ ** (1) Memory in Mem.zMalloc and managed by the Mem object
+ ** (2) Memory to be freed using Mem.xDel
+ ** (3) An ephermal string or blob
+ ** (4) A static string or blob
+ */
+ if( (p->flags & (MEM_Str|MEM_Blob)) && p->z!=0 ){
+ assert(
+ ((p->z==p->zMalloc)? 1 : 0) +
+ ((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
+ ((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
+ ((p->flags&MEM_Static)!=0 ? 1 : 0) == 1
+ );
+ }
+
+ return 1;
+}
+#endif
+
+
/*
** If pMem is an object with a valid string representation, this routine
** ensures the internal encoding for the string representation is
@@ -59696,57 +60154,51 @@ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
/*
** Make sure pMem->z points to a writable allocation of at least
-** n bytes.
-**
-** If the third argument passed to this function is true, then memory
-** cell pMem must contain a string or blob. In this case the content is
-** preserved. Otherwise, if the third parameter to this function is false,
-** any current string or blob value may be discarded.
-**
-** This function sets the MEM_Dyn flag and clears any xDel callback.
-** It also clears MEM_Ephem and MEM_Static. If the preserve flag is
-** not set, Mem.n is zeroed.
-*/
-SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
- assert( 1 >=
- ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) +
- (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
- ((pMem->flags&MEM_Ephem) ? 1 : 0) +
- ((pMem->flags&MEM_Static) ? 1 : 0)
- );
+** min(n,32) bytes.
+**
+** If the bPreserve argument is true, then copy of the content of
+** pMem->z into the new allocation. pMem must be either a string or
+** blob if bPreserve is true. If bPreserve is false, any prior content
+** in pMem->z is discarded.
+*/
+SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
+ assert( sqlite3VdbeCheckMemInvariants(pMem) );
assert( (pMem->flags&MEM_RowSet)==0 );
- /* If the preserve flag is set to true, then the memory cell must already
+ /* If the bPreserve flag is set to true, then the memory cell must already
** contain a valid string or blob value. */
- assert( preserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
+ assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
+ testcase( bPreserve && pMem->z==0 );
- if( n<32 ) n = 32;
- if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
- if( preserve && pMem->z==pMem->zMalloc ){
+ if( pMem->zMalloc==0 || sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
+ if( n<32 ) n = 32;
+ if( bPreserve && pMem->z==pMem->zMalloc ){
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
- preserve = 0;
+ bPreserve = 0;
}else{
sqlite3DbFree(pMem->db, pMem->zMalloc);
pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
}
+ if( pMem->zMalloc==0 ){
+ VdbeMemRelease(pMem);
+ pMem->z = 0;
+ pMem->flags = MEM_Null;
+ return SQLITE_NOMEM;
+ }
}
- if( pMem->z && preserve && pMem->zMalloc && pMem->z!=pMem->zMalloc ){
+ if( pMem->z && bPreserve && pMem->z!=pMem->zMalloc ){
memcpy(pMem->zMalloc, pMem->z, pMem->n);
}
- if( pMem->flags&MEM_Dyn && pMem->xDel ){
- assert( pMem->xDel!=SQLITE_DYNAMIC );
+ if( (pMem->flags&MEM_Dyn)!=0 ){
+ assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC );
pMem->xDel((void *)(pMem->z));
}
pMem->z = pMem->zMalloc;
- if( pMem->z==0 ){
- pMem->flags = MEM_Null;
- }else{
- pMem->flags &= ~(MEM_Ephem|MEM_Static);
- }
+ pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static);
pMem->xDel = 0;
- return (pMem->z ? SQLITE_OK : SQLITE_NOMEM);
+ return SQLITE_OK;
}
/*
@@ -59913,9 +60365,9 @@ SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){
sqlite3VdbeMemFinalize(p, p->u.pDef);
assert( (p->flags & MEM_Agg)==0 );
sqlite3VdbeMemRelease(p);
- }else if( p->flags&MEM_Dyn && p->xDel ){
+ }else if( p->flags&MEM_Dyn ){
assert( (p->flags&MEM_RowSet)==0 );
- assert( p->xDel!=SQLITE_DYNAMIC );
+ assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 );
p->xDel((void *)p->z);
p->xDel = 0;
}else if( p->flags&MEM_RowSet ){
@@ -59928,14 +60380,17 @@ SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){
/*
** Release any memory held by the Mem. This may leave the Mem in an
** inconsistent state, for example with (Mem.z==0) and
-** (Mem.type==SQLITE_TEXT).
+** (Mem.flags==MEM_Str).
*/
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
+ assert( sqlite3VdbeCheckMemInvariants(p) );
VdbeMemRelease(p);
- sqlite3DbFree(p->db, p->zMalloc);
+ if( p->zMalloc ){
+ sqlite3DbFree(p->db, p->zMalloc);
+ p->zMalloc = 0;
+ }
p->z = 0;
- p->zMalloc = 0;
- p->xDel = 0;
+ assert( p->xDel==0 ); /* Zeroed by VdbeMemRelease() above */
}
/*
@@ -60117,7 +60572,9 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){
sqlite3RowSetClear(pMem->u.pRowSet);
}
MemSetTypeFlag(pMem, MEM_Null);
- pMem->type = SQLITE_NULL;
+}
+SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value *p){
+ sqlite3VdbeMemSetNull((Mem*)p);
}
/*
@@ -60127,7 +60584,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){
SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Blob|MEM_Zero;
- pMem->type = SQLITE_BLOB;
pMem->n = 0;
if( n<0 ) n = 0;
pMem->u.nZero = n;
@@ -60150,7 +60606,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
sqlite3VdbeMemRelease(pMem);
pMem->u.i = val;
pMem->flags = MEM_Int;
- pMem->type = SQLITE_INTEGER;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -60165,7 +60620,6 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
sqlite3VdbeMemRelease(pMem);
pMem->r = val;
pMem->flags = MEM_Real;
- pMem->type = SQLITE_FLOAT;
}
}
#endif
@@ -60221,7 +60675,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
Mem *pX;
for(i=1, pX=&pVdbe->aMem[1]; i<=pVdbe->nMem; i++, pX++){
if( pX->pScopyFrom==pMem ){
- pX->flags |= MEM_Invalid;
+ pX->flags |= MEM_Undefined;
pX->pScopyFrom = 0;
}
}
@@ -60232,7 +60686,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
/*
** Size of struct Mem not including the Mem.zMalloc member.
*/
-#define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc))
+#define MEMCELLSIZE offsetof(Mem,zMalloc)
/*
** Make an shallow copy of pFrom into pTo. Prior contents of
@@ -60263,6 +60717,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
VdbeMemRelease(pTo);
memcpy(pTo, pFrom, MEMCELLSIZE);
pTo->flags &= ~MEM_Dyn;
+ pTo->xDel = 0;
if( pTo->flags&(MEM_Str|MEM_Blob) ){
if( 0==(pFrom->flags&MEM_Static) ){
@@ -60373,7 +60828,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
pMem->n = nByte;
pMem->flags = flags;
pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
- pMem->type = (enc==0 ? SQLITE_BLOB : SQLITE_TEXT);
#ifndef SQLITE_OMIT_UTF16
if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
@@ -60389,119 +60843,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
}
/*
-** Compare the values contained by the two memory cells, returning
-** negative, zero or positive if pMem1 is less than, equal to, or greater
-** than pMem2. Sorting order is NULL's first, followed by numbers (integers
-** and reals) sorted numerically, followed by text ordered by the collating
-** sequence pColl and finally blob's ordered by memcmp().
-**
-** Two NULL values are considered equal by this function.
-*/
-SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
- int rc;
- int f1, f2;
- int combined_flags;
-
- f1 = pMem1->flags;
- f2 = pMem2->flags;
- combined_flags = f1|f2;
- assert( (combined_flags & MEM_RowSet)==0 );
-
- /* If one value is NULL, it is less than the other. If both values
- ** are NULL, return 0.
- */
- if( combined_flags&MEM_Null ){
- return (f2&MEM_Null) - (f1&MEM_Null);
- }
-
- /* If one value is a number and the other is not, the number is less.
- ** If both are numbers, compare as reals if one is a real, or as integers
- ** if both values are integers.
- */
- if( combined_flags&(MEM_Int|MEM_Real) ){
- double r1, r2;
- if( (f1 & f2 & MEM_Int)!=0 ){
- if( pMem1->u.i < pMem2->u.i ) return -1;
- if( pMem1->u.i > pMem2->u.i ) return 1;
- return 0;
- }
- if( (f1&MEM_Real)!=0 ){
- r1 = pMem1->r;
- }else if( (f1&MEM_Int)!=0 ){
- r1 = (double)pMem1->u.i;
- }else{
- return 1;
- }
- if( (f2&MEM_Real)!=0 ){
- r2 = pMem2->r;
- }else if( (f2&MEM_Int)!=0 ){
- r2 = (double)pMem2->u.i;
- }else{
- return -1;
- }
- if( r1<r2 ) return -1;
- if( r1>r2 ) return 1;
- return 0;
- }
-
- /* If one value is a string and the other is a blob, the string is less.
- ** If both are strings, compare using the collating functions.
- */
- if( combined_flags&MEM_Str ){
- if( (f1 & MEM_Str)==0 ){
- return 1;
- }
- if( (f2 & MEM_Str)==0 ){
- return -1;
- }
-
- assert( pMem1->enc==pMem2->enc );
- assert( pMem1->enc==SQLITE_UTF8 ||
- pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
-
- /* The collation sequence must be defined at this point, even if
- ** the user deletes the collation sequence after the vdbe program is
- ** compiled (this was not always the case).
- */
- assert( !pColl || pColl->xCmp );
-
- if( pColl ){
- if( pMem1->enc==pColl->enc ){
- /* The strings are already in the correct encoding. Call the
- ** comparison function directly */
- return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
- }else{
- const void *v1, *v2;
- int n1, n2;
- Mem c1;
- Mem c2;
- memset(&c1, 0, sizeof(c1));
- memset(&c2, 0, sizeof(c2));
- sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
- sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
- v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
- n1 = v1==0 ? 0 : c1.n;
- v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
- n2 = v2==0 ? 0 : c2.n;
- rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
- sqlite3VdbeMemRelease(&c1);
- sqlite3VdbeMemRelease(&c2);
- return rc;
- }
- }
- /* If a NULL pointer was passed as the collate function, fall through
- ** to the blob case and use memcmp(). */
- }
-
- /* Both values must be blobs. Compare using memcmp(). */
- rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
- if( rc==0 ){
- rc = pMem1->n - pMem2->n;
- }
- return rc;
-}
-
-/*
** Move data out of a btree key or data field and into a Mem structure.
** The data or key is taken from the entry that pCur is currently pointing
** to. offset and amt determine what portion of the data or key to retrieve.
@@ -60541,22 +60882,22 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
sqlite3VdbeMemRelease(pMem);
pMem->z = &zData[offset];
pMem->flags = MEM_Blob|MEM_Ephem;
+ pMem->n = (int)amt;
}else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){
- pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term;
- pMem->enc = 0;
- pMem->type = SQLITE_BLOB;
if( key ){
rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
}else{
rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
}
- pMem->z[amt] = 0;
- pMem->z[amt+1] = 0;
- if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_OK ){
+ pMem->z[amt] = 0;
+ pMem->z[amt+1] = 0;
+ pMem->flags = MEM_Blob|MEM_Term;
+ pMem->n = (int)amt;
+ }else{
sqlite3VdbeMemRelease(pMem);
}
}
- pMem->n = (int)amt;
return rc;
}
@@ -60614,7 +60955,6 @@ SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *db){
Mem *p = sqlite3DbMallocZero(db, sizeof(*p));
if( p ){
p->flags = MEM_Null;
- p->type = SQLITE_NULL;
p->db = db;
}
return p;
@@ -60660,11 +61000,9 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
if( pRec->pKeyInfo ){
assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol );
assert( pRec->pKeyInfo->enc==ENC(db) );
- pRec->flags = UNPACKED_PREFIX_MATCH;
pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord)));
for(i=0; i<nCol; i++){
pRec->aMem[i].flags = MEM_Null;
- pRec->aMem[i].type = SQLITE_NULL;
pRec->aMem[i].db = db;
}
}else{
@@ -60737,7 +61075,6 @@ static int valueFromExpr(
zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
if( zVal==0 ) goto no_mem;
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
- if( op==TK_FLOAT ) pVal->type = SQLITE_FLOAT;
}
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
@@ -60755,9 +61092,9 @@ static int valueFromExpr(
){
sqlite3VdbeMemNumerify(pVal);
if( pVal->u.i==SMALLEST_INT64 ){
- pVal->flags &= MEM_Int;
+ pVal->flags &= ~MEM_Int;
pVal->flags |= MEM_Real;
- pVal->r = (double)LARGEST_INT64;
+ pVal->r = (double)SMALLEST_INT64;
}else{
pVal->u.i = -pVal->u.i;
}
@@ -60783,9 +61120,6 @@ static int valueFromExpr(
}
#endif
- if( pVal ){
- sqlite3VdbeMemStoreType(pVal);
- }
*ppVal = pVal;
return rc;
@@ -60856,7 +61190,7 @@ static void recordFunc(
}else{
aRet[0] = nSerial+1;
sqlite3PutVarint(&aRet[1], iSerial);
- sqlite3VdbeSerialPut(&aRet[1+nSerial], nVal, argv[0], file_format);
+ sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial);
sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
sqlite3DbFree(db, aRet);
}
@@ -60949,7 +61283,6 @@ SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(
sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
}
pVal->db = pParse->db;
- sqlite3VdbeMemStoreType((Mem*)pVal);
}
}
}else{
@@ -61041,7 +61374,8 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
/*
** Create a new virtual database engine.
*/
-SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){
+SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){
+ sqlite3 *db = pParse->db;
Vdbe *p;
p = sqlite3DbMallocZero(db, sizeof(Vdbe) );
if( p==0 ) return 0;
@@ -61053,6 +61387,10 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){
p->pPrev = 0;
db->pVdbe = p;
p->magic = VDBE_MAGIC_INIT;
+ p->pParse = pParse;
+ assert( pParse->aLabel==0 );
+ assert( pParse->nLabel==0 );
+ assert( pParse->nOpAlloc==0 );
return p;
}
@@ -61108,13 +61446,14 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
** unchanged (this is so that any opcodes already allocated can be
** correctly deallocated along with the rest of the Vdbe).
*/
-static int growOpArray(Vdbe *p){
+static int growOpArray(Vdbe *v){
VdbeOp *pNew;
+ Parse *p = v->pParse;
int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
- pNew = sqlite3DbRealloc(p->db, p->aOp, nNew*sizeof(Op));
+ pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
if( pNew ){
p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op);
- p->aOp = pNew;
+ v->aOp = pNew;
}
return (pNew ? SQLITE_OK : SQLITE_NOMEM);
}
@@ -61153,7 +61492,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
i = p->nOp;
assert( p->magic==VDBE_MAGIC_INIT );
assert( op>0 && op<0xff );
- if( p->nOpAlloc<=i ){
+ if( p->pParse->nOpAlloc<=i ){
if( growOpArray(p) ){
return 1;
}
@@ -61172,6 +61511,15 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
#endif
#ifdef SQLITE_DEBUG
if( p->db->flags & SQLITE_VdbeAddopTrace ){
+ int jj, kk;
+ Parse *pParse = p->pParse;
+ for(jj=kk=0; jj<SQLITE_N_COLCACHE; jj++){
+ struct yColCache *x = pParse->aColCache + jj;
+ if( x->iLevel>pParse->iCacheLevel || x->iReg==0 ) continue;
+ printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn);
+ kk++;
+ }
+ if( kk ) printf("\n");
sqlite3VdbePrintOp(0, i, &p->aOp[i]);
test_addop_breakpoint();
}
@@ -61180,6 +61528,9 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
pOp->cycles = 0;
pOp->cnt = 0;
#endif
+#ifdef SQLITE_VDBE_COVERAGE
+ pOp->iSrcLine = 0;
+#endif
return i;
}
SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe *p, int op){
@@ -61255,9 +61606,10 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(
**
** Zero is returned if a malloc() fails.
*/
-SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *p){
+SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *v){
+ Parse *p = v->pParse;
int i = p->nLabel++;
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( v->magic==VDBE_MAGIC_INIT );
if( (i & (i-1))==0 ){
p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
(i*2+1)*sizeof(p->aLabel[0]));
@@ -61273,13 +61625,15 @@ SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *p){
** be inserted. The parameter "x" must have been obtained from
** a prior call to sqlite3VdbeMakeLabel().
*/
-SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *p, int x){
+SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){
+ Parse *p = v->pParse;
int j = -1-x;
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( v->magic==VDBE_MAGIC_INIT );
assert( j<p->nLabel );
if( j>=0 && p->aLabel ){
- p->aLabel[j] = p->nOp;
+ p->aLabel[j] = v->nOp;
}
+ p->iFixedOp = v->nOp - 1;
}
/*
@@ -61427,7 +61781,8 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
int i;
int nMaxArgs = *pMaxFuncArgs;
Op *pOp;
- int *aLabel = p->aLabel;
+ Parse *pParse = p->pParse;
+ int *aLabel = pParse->aLabel;
p->readOnly = 1;
p->bIsReader = 0;
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
@@ -61490,12 +61845,13 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
pOp->opflags = sqlite3OpcodeProperty[opcode];
if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
- assert( -1-pOp->p2<p->nLabel );
+ assert( -1-pOp->p2<pParse->nLabel );
pOp->p2 = aLabel[-1-pOp->p2];
}
}
- sqlite3DbFree(p->db, p->aLabel);
- p->aLabel = 0;
+ sqlite3DbFree(p->db, pParse->aLabel);
+ pParse->aLabel = 0;
+ pParse->nLabel = 0;
*pMaxFuncArgs = nMaxArgs;
assert( p->bIsReader!=0 || p->btreeMask==0 );
}
@@ -61536,10 +61892,10 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg)
** Add a whole list of operations to the operation stack. Return the
** address of the first operation added.
*/
-SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
+SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
int addr;
assert( p->magic==VDBE_MAGIC_INIT );
- if( p->nOp + nOp > p->nOpAlloc && growOpArray(p) ){
+ if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p) ){
return 0;
}
addr = p->nOp;
@@ -61564,6 +61920,11 @@ SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp)
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
pOut->zComment = 0;
#endif
+#ifdef SQLITE_VDBE_COVERAGE
+ pOut->iSrcLine = iLineno+i;
+#else
+ (void)iLineno;
+#endif
#ifdef SQLITE_DEBUG
if( p->db->flags & SQLITE_VdbeAddopTrace ){
sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
@@ -61626,7 +61987,8 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 val){
** the address of the next instruction to be coded.
*/
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){
- if( ALWAYS(addr>=0) ) sqlite3VdbeChangeP2(p, addr, p->nOp);
+ sqlite3VdbeChangeP2(p, addr, p->nOp);
+ p->pParse->iFixedOp = p->nOp - 1;
}
@@ -61729,6 +62091,18 @@ SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
}
/*
+** Remove the last opcode inserted
+*/
+SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
+ if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){
+ sqlite3VdbeChangeToNoop(p, p->nOp-1);
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
+/*
** Change the value of the P4 operand for a specific instruction.
** This routine is useful when a large program is loaded from a
** static array using sqlite3VdbeAddOpList but we want to make a
@@ -61839,6 +62213,15 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
}
#endif /* NDEBUG */
+#ifdef SQLITE_VDBE_COVERAGE
+/*
+** Set the value if the iSrcLine field for the previously coded instruction.
+*/
+SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){
+ sqlite3VdbeGetOp(v,-1)->iSrcLine = iLine;
+}
+#endif /* SQLITE_VDBE_COVERAGE */
+
/*
** Return the opcode for a given address. If the address is -1, then
** return the most recently inserted opcode.
@@ -61851,14 +62234,6 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
** this routine is a valid pointer. But because the dummy.opcode is 0,
** dummy will never be written to. This is verified by code inspection and
** by running with Valgrind.
-**
-** About the #ifdef SQLITE_OMIT_TRACE: Normally, this routine is never called
-** unless p->nOp>0. This is because in the absense of SQLITE_OMIT_TRACE,
-** an OP_Trace instruction is always inserted by sqlite3VdbeGet() as soon as
-** a new VDBE is created. So we are free to set addr to p->nOp-1 without
-** having to double-check to make sure that the result is non-negative. But
-** if SQLITE_OMIT_TRACE is defined, the OP_Trace is omitted and we do need to
-** check the value of p->nOp-1 before continuing.
*/
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
/* C89 specifies that the constant "dummy" will be initialized to all
@@ -61866,9 +62241,6 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
assert( p->magic==VDBE_MAGIC_INIT );
if( addr<0 ){
-#ifdef SQLITE_OMIT_TRACE
- if( p->nOp==0 ) return (VdbeOp*)&dummy;
-#endif
addr = p->nOp - 1;
}
assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed );
@@ -61893,7 +62265,17 @@ static int translateP(char c, const Op *pOp){
}
/*
-** Compute a string for the "comment" field of a VDBE opcode listing
+** Compute a string for the "comment" field of a VDBE opcode listing.
+**
+** The Synopsis: field in comments in the vdbe.c source file gets converted
+** to an extra string that is appended to the sqlite3OpcodeName(). In the
+** absence of other comments, this synopsis becomes the comment on the opcode.
+** Some translation occurs:
+**
+** "PX" -> "r[X]"
+** "PX@PY" -> "r[X..X+Y-1]" or "r[x]" if y is 0 or 1
+** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0
+** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x
*/
static int displayComment(
const Op *pOp, /* The opcode to be commented */
@@ -61927,7 +62309,13 @@ static int displayComment(
ii += 3;
jj += sqlite3Strlen30(zTemp+jj);
v2 = translateP(zSynopsis[ii], pOp);
- if( v2>1 ) sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1);
+ if( strncmp(zSynopsis+ii+1,"+1",2)==0 ){
+ ii += 2;
+ v2++;
+ }
+ if( v2>1 ){
+ sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1);
+ }
}else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
ii += 4;
}
@@ -62157,8 +62545,11 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
displayComment(pOp, zP4, zCom, sizeof(zCom));
#else
- zCom[0] = 0
+ zCom[0] = 0;
#endif
+ /* NB: The sqlite3OpcodeName() function is implemented by code created
+ ** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the
+ ** information from the vdbe.c source text */
fprintf(pOut, zFormat1, pc,
sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
zCom
@@ -62183,6 +62574,7 @@ static void releaseMemArray(Mem *p, int N){
}
for(pEnd=&p[N]; p<pEnd; p++){
assert( (&p[1])==pEnd || p[0].db==p[1].db );
+ assert( sqlite3VdbeCheckMemInvariants(p) );
/* This block is really an inlined version of sqlite3VdbeMemRelease()
** that takes advantage of the fact that the memory cell value is
@@ -62196,6 +62588,10 @@ static void releaseMemArray(Mem *p, int N){
** with no indexes using a single prepared INSERT statement, bind()
** and reset(). Inserts are grouped into a transaction.
*/
+ testcase( p->flags & MEM_Agg );
+ testcase( p->flags & MEM_Dyn );
+ testcase( p->flags & MEM_Frame );
+ testcase( p->flags & MEM_RowSet );
if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
sqlite3VdbeMemRelease(p);
}else if( p->zMalloc ){
@@ -62203,7 +62599,7 @@ static void releaseMemArray(Mem *p, int N){
p->zMalloc = 0;
}
- p->flags = MEM_Invalid;
+ p->flags = MEM_Undefined;
}
db->mallocFailed = malloc_failed;
}
@@ -62325,7 +62721,6 @@ SQLITE_PRIVATE int sqlite3VdbeList(
}
if( p->explain==1 ){
pMem->flags = MEM_Int;
- pMem->type = SQLITE_INTEGER;
pMem->u.i = i; /* Program counter */
pMem++;
@@ -62333,7 +62728,6 @@ SQLITE_PRIVATE int sqlite3VdbeList(
pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
assert( pMem->z!=0 );
pMem->n = sqlite3Strlen30(pMem->z);
- pMem->type = SQLITE_TEXT;
pMem->enc = SQLITE_UTF8;
pMem++;
@@ -62359,24 +62753,21 @@ SQLITE_PRIVATE int sqlite3VdbeList(
pMem->flags = MEM_Int;
pMem->u.i = pOp->p1; /* P1 */
- pMem->type = SQLITE_INTEGER;
pMem++;
pMem->flags = MEM_Int;
pMem->u.i = pOp->p2; /* P2 */
- pMem->type = SQLITE_INTEGER;
pMem++;
pMem->flags = MEM_Int;
pMem->u.i = pOp->p3; /* P3 */
- pMem->type = SQLITE_INTEGER;
pMem++;
if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */
assert( p->db->mallocFailed );
return SQLITE_ERROR;
}
- pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
+ pMem->flags = MEM_Str|MEM_Term;
zP4 = displayP4(pOp, pMem->z, 32);
if( zP4!=pMem->z ){
sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
@@ -62385,7 +62776,6 @@ SQLITE_PRIVATE int sqlite3VdbeList(
pMem->n = sqlite3Strlen30(pMem->z);
pMem->enc = SQLITE_UTF8;
}
- pMem->type = SQLITE_TEXT;
pMem++;
if( p->explain==1 ){
@@ -62393,10 +62783,9 @@ SQLITE_PRIVATE int sqlite3VdbeList(
assert( p->db->mallocFailed );
return SQLITE_ERROR;
}
- pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
+ pMem->flags = MEM_Str|MEM_Term;
pMem->n = 2;
sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
- pMem->type = SQLITE_TEXT;
pMem->enc = SQLITE_UTF8;
pMem++;
@@ -62405,13 +62794,11 @@ SQLITE_PRIVATE int sqlite3VdbeList(
assert( p->db->mallocFailed );
return SQLITE_ERROR;
}
- pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
+ pMem->flags = MEM_Str|MEM_Term;
pMem->n = displayComment(pOp, zP4, pMem->z, 500);
- pMem->type = SQLITE_TEXT;
pMem->enc = SQLITE_UTF8;
#else
pMem->flags = MEM_Null; /* Comment */
- pMem->type = SQLITE_NULL;
#endif
}
@@ -62434,7 +62821,7 @@ SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe *p){
z = p->zSql;
}else if( p->nOp>=1 ){
const VdbeOp *pOp = &p->aOp[0];
- if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
+ if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){
z = pOp->p4.z;
while( sqlite3Isspace(*z) ) z++;
}
@@ -62453,7 +62840,7 @@ SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe *p){
if( sqlite3IoTrace==0 ) return;
if( nOp<1 ) return;
pOp = &p->aOp[0];
- if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
+ if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){
int i, j;
char z[1000];
sqlite3_snprintf(sizeof(z), z, "%s", pOp->p4.z);
@@ -62590,6 +62977,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
assert( p->nOp>0 );
assert( pParse!=0 );
assert( p->magic==VDBE_MAGIC_INIT );
+ assert( pParse==p->pParse );
db = p->db;
assert( db->mallocFailed==0 );
nVar = pParse->nVar;
@@ -62613,8 +63001,8 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
/* Allocate space for memory registers, SQL variables, VDBE cursors and
** an array to marshal SQL function arguments in.
*/
- zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */
- zEnd = (u8*)&p->aOp[p->nOpAlloc]; /* First byte past end of zCsr[] */
+ zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */
+ zEnd = (u8*)&p->aOp[pParse->nOpAlloc]; /* First byte past end of zCsr[] */
resolveP2Values(p, &nArg);
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
@@ -62670,7 +63058,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
p->aMem--; /* aMem[] goes from 1..nMem */
p->nMem = nMem; /* not from 0..nMem-1 */
for(n=1; n<=nMem; n++){
- p->aMem[n].flags = MEM_Invalid;
+ p->aMem[n].flags = MEM_Undefined;
p->aMem[n].db = db;
}
}
@@ -62782,7 +63170,7 @@ static void Cleanup(Vdbe *p){
int i;
if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
if( p->aMem ){
- for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Invalid );
+ for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
}
#endif
@@ -63441,6 +63829,7 @@ SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){
if( p->zErrMsg ){
u8 mallocFailed = db->mallocFailed;
sqlite3BeginBenignMalloc();
+ if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db);
sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
sqlite3EndBenignMalloc();
db->mallocFailed = mallocFailed;
@@ -63509,8 +63898,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
** to sqlite3_step(). For consistency (since sqlite3_step() was
** called), set the database error in this case as well.
*/
- sqlite3Error(db, p->rc, 0);
- sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
+ sqlite3Error(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
}
@@ -63531,12 +63919,24 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
fprintf(out, "%02x", p->aOp[i].opcode);
}
fprintf(out, "\n");
+ if( p->zSql ){
+ char c, pc = 0;
+ fprintf(out, "-- ");
+ for(i=0; (c = p->zSql[i])!=0; i++){
+ if( pc=='\n' ) fprintf(out, "-- ");
+ putc(c, out);
+ pc = c;
+ }
+ if( pc!='\n' ) fprintf(out, "\n");
+ }
for(i=0; i<p->nOp; i++){
- fprintf(out, "%6d %10lld %8lld ",
+ char zHdr[100];
+ sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ",
p->aOp[i].cnt,
p->aOp[i].cycles,
p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0
);
+ fprintf(out, "%s", zHdr);
sqlite3VdbePrintOp(out, i, &p->aOp[i]);
}
fclose(out);
@@ -63583,8 +63983,9 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
while( *pp ){
AuxData *pAux = *pp;
if( (iOp<0)
- || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & ((u32)1<<pAux->iArg))))
+ || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & MASKBIT32(pAux->iArg))))
){
+ testcase( pAux->iArg==31 );
if( pAux->xDelete ){
pAux->xDelete(pAux->pAux);
}
@@ -63617,7 +64018,6 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
}
for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
vdbeFreeOpArray(db, p->aOp, p->nOp);
- sqlite3DbFree(db, p->aLabel);
sqlite3DbFree(db, p->aColName);
sqlite3DbFree(db, p->zSql);
sqlite3DbFree(db, p->pFree);
@@ -63848,21 +64248,15 @@ static u64 floatSwap(u64 in){
** buf. It is assumed that the caller has allocated sufficient space.
** Return the number of bytes written.
**
-** nBuf is the amount of space left in buf[]. nBuf must always be
-** large enough to hold the entire field. Except, if the field is
-** a blob with a zero-filled tail, then buf[] might be just the right
-** size to hold everything except for the zero-filled tail. If buf[]
-** is only big enough to hold the non-zero prefix, then only write that
-** prefix into buf[]. But if buf[] is large enough to hold both the
-** prefix and the tail then write the prefix and set the tail to all
-** zeros.
+** nBuf is the amount of space left in buf[]. The caller is responsible
+** for allocating enough space to buf[] to hold the entire field, exclusive
+** of the pMem->u.nZero bytes for a MEM_Zero value.
**
** Return the number of bytes actually written into buf[]. The number
** of bytes in the zero-filled tail is included in the return value only
** if those bytes were zeroed in buf[].
*/
-SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){
- u32 serial_type = sqlite3VdbeSerialType(pMem, file_format);
+SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
u32 len;
/* Integer and Real */
@@ -63877,7 +64271,6 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_f
v = pMem->u.i;
}
len = i = sqlite3VdbeSerialTypeLen(serial_type);
- assert( len<=(u32)nBuf );
while( i-- ){
buf[i] = (u8)(v&0xFF);
v >>= 8;
@@ -63889,17 +64282,8 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_f
if( serial_type>=12 ){
assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0)
== (int)sqlite3VdbeSerialTypeLen(serial_type) );
- assert( pMem->n<=nBuf );
len = pMem->n;
memcpy(buf, pMem->z, len);
- if( pMem->flags & MEM_Zero ){
- len += pMem->u.nZero;
- assert( nBuf>=0 );
- if( len > (u32)nBuf ){
- len = (u32)nBuf;
- }
- memset(&buf[pMem->n], 0, len-pMem->n);
- }
return len;
}
@@ -63907,6 +64291,14 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_f
return 0;
}
+/* Input "x" is a sequence of unsigned characters that represent a
+** big-endian integer. Return the equivalent native integer
+*/
+#define ONE_BYTE_INT(x) ((i8)(x)[0])
+#define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1])
+#define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2])
+#define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
+
/*
** Deserialize the data blob pointed to by buf as serial type serial_type
** and store the result in pMem. Return the number of bytes read.
@@ -63916,6 +64308,8 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
u32 serial_type, /* Serial type to deserialize */
Mem *pMem /* Memory cell to write value into */
){
+ u64 x;
+ u32 y;
switch( serial_type ){
case 10: /* Reserved for future use */
case 11: /* Reserved for future use */
@@ -63924,37 +64318,38 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
break;
}
case 1: { /* 1-byte signed integer */
- pMem->u.i = (signed char)buf[0];
+ pMem->u.i = ONE_BYTE_INT(buf);
pMem->flags = MEM_Int;
+ testcase( pMem->u.i<0 );
return 1;
}
case 2: { /* 2-byte signed integer */
- pMem->u.i = (((signed char)buf[0])<<8) | buf[1];
+ pMem->u.i = TWO_BYTE_INT(buf);
pMem->flags = MEM_Int;
+ testcase( pMem->u.i<0 );
return 2;
}
case 3: { /* 3-byte signed integer */
- pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2];
+ pMem->u.i = THREE_BYTE_INT(buf);
pMem->flags = MEM_Int;
+ testcase( pMem->u.i<0 );
return 3;
}
case 4: { /* 4-byte signed integer */
- pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
+ y = FOUR_BYTE_UINT(buf);
+ pMem->u.i = (i64)*(int*)&y;
pMem->flags = MEM_Int;
+ testcase( pMem->u.i<0 );
return 4;
}
case 5: { /* 6-byte signed integer */
- u64 x = (((signed char)buf[0])<<8) | buf[1];
- u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
- x = (x<<32) | y;
- pMem->u.i = *(i64*)&x;
+ pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf);
pMem->flags = MEM_Int;
+ testcase( pMem->u.i<0 );
return 6;
}
case 6: /* 8-byte signed integer */
case 7: { /* IEEE floating point */
- u64 x;
- u32 y;
#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
/* Verify that integers and floating point values use the same
** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
@@ -63967,13 +64362,13 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
swapMixedEndianFloat(t2);
assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
#endif
-
- x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
- y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
+ x = FOUR_BYTE_UINT(buf);
+ y = FOUR_BYTE_UINT(buf+4);
x = (x<<32) | y;
if( serial_type==6 ){
pMem->u.i = *(i64*)&x;
pMem->flags = MEM_Int;
+ testcase( pMem->u.i<0 );
}else{
assert( sizeof(x)==8 && sizeof(pMem->r)==8 );
swapMixedEndianFloat(x);
@@ -64065,7 +64460,7 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
u32 szHdr;
Mem *pMem = p->aMem;
- p->flags = 0;
+ p->default_rc = 0;
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
idx = getVarint32(aKey, szHdr);
d = szHdr;
@@ -64086,26 +64481,18 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
p->nField = u;
}
+#if SQLITE_DEBUG
/*
-** This function compares the two table rows or index records
-** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
-** or positive integer if key1 is less than, equal to or
-** greater than key2. The {nKey1, pKey1} key must be a blob
-** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
-** key must be a parsed key such as obtained from
-** sqlite3VdbeParseRecord.
-**
-** Key1 and Key2 do not have to contain the same number of fields.
-** The key with fewer fields is usually compares less than the
-** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set
-** and the common prefixes are equal, then key1 is less than key2.
-** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are
-** equal, then the keys are considered to be equal and
-** the parts beyond the common prefix are ignored.
+** This function compares two index or table record keys in the same way
+** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(),
+** this function deserializes and compares values using the
+** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used
+** in assert() statements to ensure that the optimized code in
+** sqlite3VdbeRecordCompare() returns results with these two primitives.
*/
-SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
+static int vdbeRecordCompareDebug(
int nKey1, const void *pKey1, /* Left key */
- UnpackedRecord *pPKey2 /* Right key */
+ const UnpackedRecord *pPKey2 /* Right key */
){
u32 d1; /* Offset into aKey[] of next data element */
u32 idx1; /* Offset into aKey[] of next header element */
@@ -64179,24 +64566,576 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
assert( mem1.zMalloc==0 );
/* rc==0 here means that one of the keys ran out of fields and
- ** all the fields up to that point were equal. If the UNPACKED_INCRKEY
- ** flag is set, then break the tie by treating key2 as larger.
- ** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes
- ** are considered to be equal. Otherwise, the longer key is the
- ** larger. As it happens, the pPKey2 will always be the longer
- ** if there is a difference.
- */
- assert( rc==0 );
- if( pPKey2->flags & UNPACKED_INCRKEY ){
- rc = -1;
- }else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){
- /* Leave rc==0 */
- }else if( idx1<szHdr1 ){
- rc = 1;
+ ** all the fields up to that point were equal. Return the the default_rc
+ ** value. */
+ return pPKey2->default_rc;
+}
+#endif
+
+/*
+** Both *pMem1 and *pMem2 contain string values. Compare the two values
+** using the collation sequence pColl. As usual, return a negative , zero
+** or positive value if *pMem1 is less than, equal to or greater than
+** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);".
+*/
+static int vdbeCompareMemString(
+ const Mem *pMem1,
+ const Mem *pMem2,
+ const CollSeq *pColl
+){
+ if( pMem1->enc==pColl->enc ){
+ /* The strings are already in the correct encoding. Call the
+ ** comparison function directly */
+ return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
+ }else{
+ int rc;
+ const void *v1, *v2;
+ int n1, n2;
+ Mem c1;
+ Mem c2;
+ memset(&c1, 0, sizeof(c1));
+ memset(&c2, 0, sizeof(c2));
+ sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
+ sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
+ v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
+ n1 = v1==0 ? 0 : c1.n;
+ v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
+ n2 = v2==0 ? 0 : c2.n;
+ rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
+ sqlite3VdbeMemRelease(&c1);
+ sqlite3VdbeMemRelease(&c2);
+ return rc;
}
- return rc;
}
+
+/*
+** Compare the values contained by the two memory cells, returning
+** negative, zero or positive if pMem1 is less than, equal to, or greater
+** than pMem2. Sorting order is NULL's first, followed by numbers (integers
+** and reals) sorted numerically, followed by text ordered by the collating
+** sequence pColl and finally blob's ordered by memcmp().
+**
+** Two NULL values are considered equal by this function.
+*/
+SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
+ int rc;
+ int f1, f2;
+ int combined_flags;
+
+ f1 = pMem1->flags;
+ f2 = pMem2->flags;
+ combined_flags = f1|f2;
+ assert( (combined_flags & MEM_RowSet)==0 );
+ /* If one value is NULL, it is less than the other. If both values
+ ** are NULL, return 0.
+ */
+ if( combined_flags&MEM_Null ){
+ return (f2&MEM_Null) - (f1&MEM_Null);
+ }
+
+ /* If one value is a number and the other is not, the number is less.
+ ** If both are numbers, compare as reals if one is a real, or as integers
+ ** if both values are integers.
+ */
+ if( combined_flags&(MEM_Int|MEM_Real) ){
+ double r1, r2;
+ if( (f1 & f2 & MEM_Int)!=0 ){
+ if( pMem1->u.i < pMem2->u.i ) return -1;
+ if( pMem1->u.i > pMem2->u.i ) return 1;
+ return 0;
+ }
+ if( (f1&MEM_Real)!=0 ){
+ r1 = pMem1->r;
+ }else if( (f1&MEM_Int)!=0 ){
+ r1 = (double)pMem1->u.i;
+ }else{
+ return 1;
+ }
+ if( (f2&MEM_Real)!=0 ){
+ r2 = pMem2->r;
+ }else if( (f2&MEM_Int)!=0 ){
+ r2 = (double)pMem2->u.i;
+ }else{
+ return -1;
+ }
+ if( r1<r2 ) return -1;
+ if( r1>r2 ) return 1;
+ return 0;
+ }
+
+ /* If one value is a string and the other is a blob, the string is less.
+ ** If both are strings, compare using the collating functions.
+ */
+ if( combined_flags&MEM_Str ){
+ if( (f1 & MEM_Str)==0 ){
+ return 1;
+ }
+ if( (f2 & MEM_Str)==0 ){
+ return -1;
+ }
+
+ assert( pMem1->enc==pMem2->enc );
+ assert( pMem1->enc==SQLITE_UTF8 ||
+ pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
+
+ /* The collation sequence must be defined at this point, even if
+ ** the user deletes the collation sequence after the vdbe program is
+ ** compiled (this was not always the case).
+ */
+ assert( !pColl || pColl->xCmp );
+
+ if( pColl ){
+ return vdbeCompareMemString(pMem1, pMem2, pColl);
+ }
+ /* If a NULL pointer was passed as the collate function, fall through
+ ** to the blob case and use memcmp(). */
+ }
+
+ /* Both values must be blobs. Compare using memcmp(). */
+ rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
+ if( rc==0 ){
+ rc = pMem1->n - pMem2->n;
+ }
+ return rc;
+}
+
+
+/*
+** The first argument passed to this function is a serial-type that
+** corresponds to an integer - all values between 1 and 9 inclusive
+** except 7. The second points to a buffer containing an integer value
+** serialized according to serial_type. This function deserializes
+** and returns the value.
+*/
+static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
+ u32 y;
+ assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) );
+ switch( serial_type ){
+ case 0:
+ case 1:
+ testcase( aKey[0]&0x80 );
+ return ONE_BYTE_INT(aKey);
+ case 2:
+ testcase( aKey[0]&0x80 );
+ return TWO_BYTE_INT(aKey);
+ case 3:
+ testcase( aKey[0]&0x80 );
+ return THREE_BYTE_INT(aKey);
+ case 4: {
+ testcase( aKey[0]&0x80 );
+ y = FOUR_BYTE_UINT(aKey);
+ return (i64)*(int*)&y;
+ }
+ case 5: {
+ testcase( aKey[0]&0x80 );
+ return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
+ }
+ case 6: {
+ u64 x = FOUR_BYTE_UINT(aKey);
+ testcase( aKey[0]&0x80 );
+ x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
+ return (i64)*(i64*)&x;
+ }
+ }
+
+ return (serial_type - 8);
+}
+
+/*
+** This function compares the two table rows or index records
+** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
+** or positive integer if key1 is less than, equal to or
+** greater than key2. The {nKey1, pKey1} key must be a blob
+** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
+** key must be a parsed key such as obtained from
+** sqlite3VdbeParseRecord.
+**
+** If argument bSkip is non-zero, it is assumed that the caller has already
+** determined that the first fields of the keys are equal.
+**
+** Key1 and Key2 do not have to contain the same number of fields. If all
+** fields that appear in both keys are equal, then pPKey2->default_rc is
+** returned.
+*/
+SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
+ int nKey1, const void *pKey1, /* Left key */
+ const UnpackedRecord *pPKey2, /* Right key */
+ int bSkip /* If true, skip the first field */
+){
+ u32 d1; /* Offset into aKey[] of next data element */
+ int i; /* Index of next field to compare */
+ u32 szHdr1; /* Size of record header in bytes */
+ u32 idx1; /* Offset of first type in header */
+ int rc = 0; /* Return value */
+ Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */
+ KeyInfo *pKeyInfo = pPKey2->pKeyInfo;
+ const unsigned char *aKey1 = (const unsigned char *)pKey1;
+ Mem mem1;
+
+ /* If bSkip is true, then the caller has already determined that the first
+ ** two elements in the keys are equal. Fix the various stack variables so
+ ** that this routine begins comparing at the second field. */
+ if( bSkip ){
+ u32 s1;
+ idx1 = 1 + getVarint32(&aKey1[1], s1);
+ szHdr1 = aKey1[0];
+ d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1);
+ i = 1;
+ pRhs++;
+ }else{
+ idx1 = getVarint32(aKey1, szHdr1);
+ d1 = szHdr1;
+ i = 0;
+ }
+
+ VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
+ assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField
+ || CORRUPT_DB );
+ assert( pPKey2->pKeyInfo->aSortOrder!=0 );
+ assert( pPKey2->pKeyInfo->nField>0 );
+ assert( idx1<=szHdr1 || CORRUPT_DB );
+ do{
+ u32 serial_type;
+
+ /* RHS is an integer */
+ if( pRhs->flags & MEM_Int ){
+ serial_type = aKey1[idx1];
+ testcase( serial_type==12 );
+ if( serial_type>=12 ){
+ rc = +1;
+ }else if( serial_type==0 ){
+ rc = -1;
+ }else if( serial_type==7 ){
+ double rhs = (double)pRhs->u.i;
+ sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
+ if( mem1.r<rhs ){
+ rc = -1;
+ }else if( mem1.r>rhs ){
+ rc = +1;
+ }
+ }else{
+ i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
+ i64 rhs = pRhs->u.i;
+ if( lhs<rhs ){
+ rc = -1;
+ }else if( lhs>rhs ){
+ rc = +1;
+ }
+ }
+ }
+
+ /* RHS is real */
+ else if( pRhs->flags & MEM_Real ){
+ serial_type = aKey1[idx1];
+ if( serial_type>=12 ){
+ rc = +1;
+ }else if( serial_type==0 ){
+ rc = -1;
+ }else{
+ double rhs = pRhs->r;
+ double lhs;
+ sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
+ if( serial_type==7 ){
+ lhs = mem1.r;
+ }else{
+ lhs = (double)mem1.u.i;
+ }
+ if( lhs<rhs ){
+ rc = -1;
+ }else if( lhs>rhs ){
+ rc = +1;
+ }
+ }
+ }
+
+ /* RHS is a string */
+ else if( pRhs->flags & MEM_Str ){
+ getVarint32(&aKey1[idx1], serial_type);
+ testcase( serial_type==12 );
+ if( serial_type<12 ){
+ rc = -1;
+ }else if( !(serial_type & 0x01) ){
+ rc = +1;
+ }else{
+ mem1.n = (serial_type - 12) / 2;
+ testcase( (d1+mem1.n)==(unsigned)nKey1 );
+ testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
+ if( (d1+mem1.n) > (unsigned)nKey1 ){
+ rc = 1; /* Corruption */
+ }else if( pKeyInfo->aColl[i] ){
+ mem1.enc = pKeyInfo->enc;
+ mem1.db = pKeyInfo->db;
+ mem1.flags = MEM_Str;
+ mem1.z = (char*)&aKey1[d1];
+ rc = vdbeCompareMemString(&mem1, pRhs, pKeyInfo->aColl[i]);
+ }else{
+ int nCmp = MIN(mem1.n, pRhs->n);
+ rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
+ if( rc==0 ) rc = mem1.n - pRhs->n;
+ }
+ }
+ }
+
+ /* RHS is a blob */
+ else if( pRhs->flags & MEM_Blob ){
+ getVarint32(&aKey1[idx1], serial_type);
+ testcase( serial_type==12 );
+ if( serial_type<12 || (serial_type & 0x01) ){
+ rc = -1;
+ }else{
+ int nStr = (serial_type - 12) / 2;
+ testcase( (d1+nStr)==(unsigned)nKey1 );
+ testcase( (d1+nStr+1)==(unsigned)nKey1 );
+ if( (d1+nStr) > (unsigned)nKey1 ){
+ rc = 1; /* Corruption */
+ }else{
+ int nCmp = MIN(nStr, pRhs->n);
+ rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
+ if( rc==0 ) rc = nStr - pRhs->n;
+ }
+ }
+ }
+
+ /* RHS is null */
+ else{
+ serial_type = aKey1[idx1];
+ rc = (serial_type!=0);
+ }
+
+ if( rc!=0 ){
+ if( pKeyInfo->aSortOrder[i] ){
+ rc = -rc;
+ }
+ assert( CORRUPT_DB
+ || (rc<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
+ || (rc>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
+ || pKeyInfo->db->mallocFailed
+ );
+ assert( mem1.zMalloc==0 ); /* See comment below */
+ return rc;
+ }
+
+ i++;
+ pRhs++;
+ d1 += sqlite3VdbeSerialTypeLen(serial_type);
+ idx1 += sqlite3VarintLen(serial_type);
+ }while( idx1<(unsigned)szHdr1 && i<pPKey2->nField && d1<=(unsigned)nKey1 );
+
+ /* No memory allocation is ever used on mem1. Prove this using
+ ** the following assert(). If the assert() fails, it indicates a
+ ** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */
+ assert( mem1.zMalloc==0 );
+
+ /* rc==0 here means that one or both of the keys ran out of fields and
+ ** all the fields up to that point were equal. Return the the default_rc
+ ** value. */
+ assert( CORRUPT_DB
+ || pPKey2->default_rc==vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)
+ );
+ return pPKey2->default_rc;
+}
+
+/*
+** This function is an optimized version of sqlite3VdbeRecordCompare()
+** that (a) the first field of pPKey2 is an integer, and (b) the
+** size-of-header varint at the start of (pKey1/nKey1) fits in a single
+** byte (i.e. is less than 128).
+*/
+static int vdbeRecordCompareInt(
+ int nKey1, const void *pKey1, /* Left key */
+ const UnpackedRecord *pPKey2, /* Right key */
+ int bSkip /* Ignored */
+){
+ const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
+ int serial_type = ((const u8*)pKey1)[1];
+ int res;
+ u32 y;
+ u64 x;
+ i64 v = pPKey2->aMem[0].u.i;
+ i64 lhs;
+ UNUSED_PARAMETER(bSkip);
+
+ assert( bSkip==0 );
+ switch( serial_type ){
+ case 1: { /* 1-byte signed integer */
+ lhs = ONE_BYTE_INT(aKey);
+ testcase( lhs<0 );
+ break;
+ }
+ case 2: { /* 2-byte signed integer */
+ lhs = TWO_BYTE_INT(aKey);
+ testcase( lhs<0 );
+ break;
+ }
+ case 3: { /* 3-byte signed integer */
+ lhs = THREE_BYTE_INT(aKey);
+ testcase( lhs<0 );
+ break;
+ }
+ case 4: { /* 4-byte signed integer */
+ y = FOUR_BYTE_UINT(aKey);
+ lhs = (i64)*(int*)&y;
+ testcase( lhs<0 );
+ break;
+ }
+ case 5: { /* 6-byte signed integer */
+ lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
+ testcase( lhs<0 );
+ break;
+ }
+ case 6: { /* 8-byte signed integer */
+ x = FOUR_BYTE_UINT(aKey);
+ x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
+ lhs = *(i64*)&x;
+ testcase( lhs<0 );
+ break;
+ }
+ case 8:
+ lhs = 0;
+ break;
+ case 9:
+ lhs = 1;
+ break;
+
+ /* This case could be removed without changing the results of running
+ ** this code. Including it causes gcc to generate a faster switch
+ ** statement (since the range of switch targets now starts at zero and
+ ** is contiguous) but does not cause any duplicate code to be generated
+ ** (as gcc is clever enough to combine the two like cases). Other
+ ** compilers might be similar. */
+ case 0: case 7:
+ return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
+
+ default:
+ return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
+ }
+
+ if( v>lhs ){
+ res = pPKey2->r1;
+ }else if( v<lhs ){
+ res = pPKey2->r2;
+ }else if( pPKey2->nField>1 ){
+ /* The first fields of the two keys are equal. Compare the trailing
+ ** fields. */
+ res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
+ }else{
+ /* The first fields of the two keys are equal and there are no trailing
+ ** fields. Return pPKey2->default_rc in this case. */
+ res = pPKey2->default_rc;
+ }
+
+ assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0)
+ || (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
+ || (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
+ || CORRUPT_DB
+ );
+ return res;
+}
+
+/*
+** This function is an optimized version of sqlite3VdbeRecordCompare()
+** that (a) the first field of pPKey2 is a string, that (b) the first field
+** uses the collation sequence BINARY and (c) that the size-of-header varint
+** at the start of (pKey1/nKey1) fits in a single byte.
+*/
+static int vdbeRecordCompareString(
+ int nKey1, const void *pKey1, /* Left key */
+ const UnpackedRecord *pPKey2, /* Right key */
+ int bSkip
+){
+ const u8 *aKey1 = (const u8*)pKey1;
+ int serial_type;
+ int res;
+ UNUSED_PARAMETER(bSkip);
+
+ assert( bSkip==0 );
+ getVarint32(&aKey1[1], serial_type);
+
+ if( serial_type<12 ){
+ res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */
+ }else if( !(serial_type & 0x01) ){
+ res = pPKey2->r2; /* (pKey1/nKey1) is a blob */
+ }else{
+ int nCmp;
+ int nStr;
+ int szHdr = aKey1[0];
+
+ nStr = (serial_type-12) / 2;
+ if( (szHdr + nStr) > nKey1 ) return 0; /* Corruption */
+ nCmp = MIN( pPKey2->aMem[0].n, nStr );
+ res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
+
+ if( res==0 ){
+ res = nStr - pPKey2->aMem[0].n;
+ if( res==0 ){
+ if( pPKey2->nField>1 ){
+ res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
+ }else{
+ res = pPKey2->default_rc;
+ }
+ }else if( res>0 ){
+ res = pPKey2->r2;
+ }else{
+ res = pPKey2->r1;
+ }
+ }else if( res>0 ){
+ res = pPKey2->r2;
+ }else{
+ res = pPKey2->r1;
+ }
+ }
+
+ assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0)
+ || (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
+ || (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
+ || CORRUPT_DB
+ );
+ return res;
+}
+
+/*
+** Return a pointer to an sqlite3VdbeRecordCompare() compatible function
+** suitable for comparing serialized records to the unpacked record passed
+** as the only argument.
+*/
+SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
+ /* varintRecordCompareInt() and varintRecordCompareString() both assume
+ ** that the size-of-header varint that occurs at the start of each record
+ ** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt()
+ ** also assumes that it is safe to overread a buffer by at least the
+ ** maximum possible legal header size plus 8 bytes. Because there is
+ ** guaranteed to be at least 74 (but not 136) bytes of padding following each
+ ** buffer passed to varintRecordCompareInt() this makes it convenient to
+ ** limit the size of the header to 64 bytes in cases where the first field
+ ** is an integer.
+ **
+ ** The easiest way to enforce this limit is to consider only records with
+ ** 13 fields or less. If the first field is an integer, the maximum legal
+ ** header size is (12*5 + 1 + 1) bytes. */
+ if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){
+ int flags = p->aMem[0].flags;
+ if( p->pKeyInfo->aSortOrder[0] ){
+ p->r1 = 1;
+ p->r2 = -1;
+ }else{
+ p->r1 = -1;
+ p->r2 = 1;
+ }
+ if( (flags & MEM_Int) ){
+ return vdbeRecordCompareInt;
+ }
+ testcase( flags & MEM_Real );
+ testcase( flags & MEM_Null );
+ testcase( flags & MEM_Blob );
+ if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){
+ assert( flags & MEM_Str );
+ return vdbeRecordCompareString;
+ }
+ }
+
+ return sqlite3VdbeRecordCompare;
+}
/*
** pCur points at an index entry created using the OP_MakeRecord opcode.
@@ -64287,9 +65226,9 @@ idx_rowid_corruption:
** of the keys prior to the final rowid, not the entire key.
*/
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
- VdbeCursor *pC, /* The cursor to compare against */
- UnpackedRecord *pUnpacked, /* Unpacked version of key to compare against */
- int *res /* Write the comparison result here */
+ VdbeCursor *pC, /* The cursor to compare against */
+ const UnpackedRecord *pUnpacked, /* Unpacked version of key */
+ int *res /* Write the comparison result here */
){
i64 nCellKey = 0;
int rc;
@@ -64299,7 +65238,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
assert( sqlite3BtreeCursorIsValid(pCur) );
VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey);
assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
- /* nCellKey will always be between 0 and 0xffffffff because of the say
+ /* nCellKey will always be between 0 and 0xffffffff because of the way
** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
if( nCellKey<=0 || nCellKey>0x7fffffff ){
*res = 0;
@@ -64310,8 +65249,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
if( rc ){
return rc;
}
- assert( pUnpacked->flags & UNPACKED_PREFIX_MATCH );
- *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
+ *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked, 0);
sqlite3VdbeMemRelease(&m);
return SQLITE_OK;
}
@@ -64375,7 +65313,6 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff
if( pRet ){
sqlite3VdbeMemCopy((Mem *)pRet, pMem);
sqlite3ValueApplyAffinity(pRet, aff, SQLITE_UTF8);
- sqlite3VdbeMemStoreType((Mem *)pRet);
}
return pRet;
}
@@ -64549,7 +65486,6 @@ SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){
Mem *p = (Mem*)pVal;
if( p->flags & (MEM_Blob|MEM_Str) ){
sqlite3VdbeMemExpandBlob(p);
- p->flags &= ~MEM_Str;
p->flags |= MEM_Blob;
return p->n ? p->z : 0;
}else{
@@ -64586,7 +65522,41 @@ SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){
}
#endif /* SQLITE_OMIT_UTF16 */
SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){
- return pVal->type;
+ static const u8 aType[] = {
+ SQLITE_BLOB, /* 0x00 */
+ SQLITE_NULL, /* 0x01 */
+ SQLITE_TEXT, /* 0x02 */
+ SQLITE_NULL, /* 0x03 */
+ SQLITE_INTEGER, /* 0x04 */
+ SQLITE_NULL, /* 0x05 */
+ SQLITE_INTEGER, /* 0x06 */
+ SQLITE_NULL, /* 0x07 */
+ SQLITE_FLOAT, /* 0x08 */
+ SQLITE_NULL, /* 0x09 */
+ SQLITE_FLOAT, /* 0x0a */
+ SQLITE_NULL, /* 0x0b */
+ SQLITE_INTEGER, /* 0x0c */
+ SQLITE_NULL, /* 0x0d */
+ SQLITE_INTEGER, /* 0x0e */
+ SQLITE_NULL, /* 0x0f */
+ SQLITE_BLOB, /* 0x10 */
+ SQLITE_NULL, /* 0x11 */
+ SQLITE_TEXT, /* 0x12 */
+ SQLITE_NULL, /* 0x13 */
+ SQLITE_INTEGER, /* 0x14 */
+ SQLITE_NULL, /* 0x15 */
+ SQLITE_INTEGER, /* 0x16 */
+ SQLITE_NULL, /* 0x17 */
+ SQLITE_FLOAT, /* 0x18 */
+ SQLITE_NULL, /* 0x19 */
+ SQLITE_FLOAT, /* 0x1a */
+ SQLITE_NULL, /* 0x1b */
+ SQLITE_INTEGER, /* 0x1c */
+ SQLITE_NULL, /* 0x1d */
+ SQLITE_INTEGER, /* 0x1e */
+ SQLITE_NULL, /* 0x1f */
+ };
+ return aType[pVal->flags&MEM_AffMask];
}
/**************************** sqlite3_result_ *******************************
@@ -64900,7 +65870,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
v->doingRerun = 1;
assert( v->expired==0 );
}
- if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
+ if( rc2!=SQLITE_OK ){
/* This case occurs after failing to recompile an sql statement.
** The error message from the SQL compiler has already been loaded
** into the database handle. This block copies the error message
@@ -64910,6 +65880,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
** sqlite3_errmsg() and sqlite3_errcode().
*/
const char *zErr = (const char *)sqlite3_value_text(db->pErr);
+ assert( zErr!=0 || db->mallocFailed );
sqlite3DbFree(db, v->zErrMsg);
if( !db->mallocFailed ){
v->zErrMsg = sqlite3DbStrDup(db, zErr);
@@ -65106,6 +66077,30 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt){
return pVm->nResColumn;
}
+/*
+** Return a pointer to static memory containing an SQL NULL value.
+*/
+static const Mem *columnNullValue(void){
+ /* Even though the Mem structure contains an element
+ ** of type i64, on certain architectures (x86) with certain compiler
+ ** switches (-Os), gcc may align this Mem object on a 4-byte boundary
+ ** instead of an 8-byte one. This all works fine, except that when
+ ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
+ ** that a Mem structure is located on an 8-byte boundary. To prevent
+ ** these assert()s from failing, when building with SQLITE_DEBUG defined
+ ** using gcc, we force nullMem to be 8-byte aligned using the magical
+ ** __attribute__((aligned(8))) macro. */
+ static const Mem nullMem
+#if defined(SQLITE_DEBUG) && defined(__GNUC__)
+ __attribute__((aligned(8)))
+#endif
+ = {0, "", (double)0, {0}, 0, MEM_Null, 0,
+#ifdef SQLITE_DEBUG
+ 0, 0, /* pScopyFrom, pFiller */
+#endif
+ 0, 0 };
+ return &nullMem;
+}
/*
** Check to see if column iCol of the given statement is valid. If
@@ -65122,32 +66117,11 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
sqlite3_mutex_enter(pVm->db->mutex);
pOut = &pVm->pResultSet[i];
}else{
- /* If the value passed as the second argument is out of range, return
- ** a pointer to the following static Mem object which contains the
- ** value SQL NULL. Even though the Mem structure contains an element
- ** of type i64, on certain architectures (x86) with certain compiler
- ** switches (-Os), gcc may align this Mem object on a 4-byte boundary
- ** instead of an 8-byte one. This all works fine, except that when
- ** running with SQLITE_DEBUG defined the SQLite code sometimes assert()s
- ** that a Mem structure is located on an 8-byte boundary. To prevent
- ** these assert()s from failing, when building with SQLITE_DEBUG defined
- ** using gcc, we force nullMem to be 8-byte aligned using the magical
- ** __attribute__((aligned(8))) macro. */
- static const Mem nullMem
-#if defined(SQLITE_DEBUG) && defined(__GNUC__)
- __attribute__((aligned(8)))
-#endif
- = {0, "", (double)0, {0}, 0, MEM_Null, SQLITE_NULL, 0,
-#ifdef SQLITE_DEBUG
- 0, 0, /* pScopyFrom, pFiller */
-#endif
- 0, 0 };
-
if( pVm && ALWAYS(pVm->db) ){
sqlite3_mutex_enter(pVm->db->mutex);
sqlite3Error(pVm->db, SQLITE_RANGE, 0);
}
- pOut = (Mem*)&nullMem;
+ pOut = (Mem*)columnNullValue();
}
return pOut;
}
@@ -65544,7 +66518,7 @@ SQLITE_API int sqlite3_bind_text16(
#endif /* SQLITE_OMIT_UTF16 */
SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
int rc;
- switch( pValue->type ){
+ switch( sqlite3_value_type((sqlite3_value*)pValue) ){
case SQLITE_INTEGER: {
rc = sqlite3_bind_int64(pStmt, i, pValue->u.i);
break;
@@ -65825,6 +66799,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
const char *zStart = zRawSql;
while( *(zRawSql++)!='\n' && *zRawSql );
sqlite3StrAccumAppend(&out, "-- ", 3);
+ assert( (zRawSql - zStart) > 0 );
sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart));
}
}else{
@@ -65857,9 +66832,9 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
if( pVar->flags & MEM_Null ){
sqlite3StrAccumAppend(&out, "NULL", 4);
}else if( pVar->flags & MEM_Int ){
- sqlite3XPrintf(&out, "%lld", pVar->u.i);
+ sqlite3XPrintf(&out, 0, "%lld", pVar->u.i);
}else if( pVar->flags & MEM_Real ){
- sqlite3XPrintf(&out, "%!.15g", pVar->r);
+ sqlite3XPrintf(&out, 0, "%!.15g", pVar->r);
}else if( pVar->flags & MEM_Str ){
int nOut; /* Number of bytes of the string text to include in output */
#ifndef SQLITE_OMIT_UTF16
@@ -65880,15 +66855,17 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; }
}
#endif
- sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z);
+ sqlite3XPrintf(&out, 0, "'%.*q'", nOut, pVar->z);
#ifdef SQLITE_TRACE_SIZE_LIMIT
- if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
+ if( nOut<pVar->n ){
+ sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut);
+ }
#endif
#ifndef SQLITE_OMIT_UTF16
if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8);
#endif
}else if( pVar->flags & MEM_Zero ){
- sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero);
+ sqlite3XPrintf(&out, 0, "zeroblob(%d)", pVar->u.nZero);
}else{
int nOut; /* Number of bytes of the blob to include in output */
assert( pVar->flags & MEM_Blob );
@@ -65898,11 +66875,13 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT;
#endif
for(i=0; i<nOut; i++){
- sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff);
+ sqlite3XPrintf(&out, 0, "%02x", pVar->z[i]&0xff);
}
sqlite3StrAccumAppend(&out, "'", 1);
#ifdef SQLITE_TRACE_SIZE_LIMIT
- if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
+ if( nOut<pVar->n ){
+ sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut);
+ }
#endif
}
}
@@ -65961,7 +66940,7 @@ SQLITE_PRIVATE void sqlite3ExplainPrintf(Vdbe *pVdbe, const char *zFormat, ...){
sqlite3AppendSpace(&p->str, p->aIndent[n-1]);
}
va_start(ap, zFormat);
- sqlite3VXPrintf(&p->str, 1, zFormat, ap);
+ sqlite3VXPrintf(&p->str, SQLITE_PRINTF_INTERNAL, zFormat, ap);
va_end(ap);
}
}
@@ -66040,33 +67019,8 @@ SQLITE_PRIVATE const char *sqlite3VdbeExplanation(Vdbe *pVdbe){
** May you share freely, never taking more than you give.
**
*************************************************************************
-** The code in this file implements execution method of the
-** Virtual Database Engine (VDBE). A separate file ("vdbeaux.c")
-** handles housekeeping details such as creating and deleting
-** VDBE instances. This file is solely interested in executing
-** the VDBE program.
-**
-** In the external interface, an "sqlite3_stmt*" is an opaque pointer
-** to a VDBE.
-**
-** The SQL parser generates a program which is then executed by
-** the VDBE to do the work of the SQL statement. VDBE programs are
-** similar in form to assembly language. The program consists of
-** a linear sequence of operations. Each operation has an opcode
-** and 5 operands. Operands P1, P2, and P3 are integers. Operand P4
-** is a null-terminated string. Operand P5 is an unsigned character.
-** Few opcodes use all 5 operands.
-**
-** Computation results are stored on a set of registers numbered beginning
-** with 1 and going up to Vdbe.nMem. Each register can store
-** either an integer, a null-terminated string, a floating point
-** number, or the SQL "NULL" value. An implicit conversion from one
-** type to the other occurs as necessary.
-**
-** Most of the code in this file is taken up by the sqlite3VdbeExec()
-** function which does the work of interpreting a VDBE program.
-** But other routines are also provided to help in building up
-** a program instruction by instruction.
+** The code in this file implements the function that runs the
+** bytecode of a prepared statement.
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files. The formatting
@@ -66078,7 +67032,11 @@ SQLITE_PRIVATE const char *sqlite3VdbeExplanation(Vdbe *pVdbe){
/*
** Invoke this macro on memory cells just prior to changing the
** value of the cell. This macro verifies that shallow copies are
-** not misused.
+** not misused. A shallow copy of a string or blob just copies a
+** pointer to the string or blob, not the content. If the original
+** is changed while the copy is still in use, the string or blob might
+** be changed out from under the copy. This macro verifies that nothing
+** like that ever happens.
*/
#ifdef SQLITE_DEBUG
# define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M)
@@ -66137,7 +67095,7 @@ static void updateMaxBlobsize(Mem *p){
#endif
/*
-** The next global variable is incremented each type the OP_Found opcode
+** The next global variable is incremented each time the OP_Found opcode
** is executed. This is used to test whether or not the foreign key
** operation implemented using OP_FkIsZero is working. This variable
** has no function other than to help verify the correct operation of the
@@ -66158,6 +67116,34 @@ SQLITE_API int sqlite3_found_count = 0;
#endif
/*
+** Invoke the VDBE coverage callback, if that callback is defined. This
+** feature is used for test suite validation only and does not appear an
+** production builds.
+**
+** M is an integer, 2 or 3, that indices how many different ways the
+** branch can go. It is usually 2. "I" is the direction the branch
+** goes. 0 means falls through. 1 means branch is taken. 2 means the
+** second alternative branch is taken.
+*/
+#if !defined(SQLITE_VDBE_COVERAGE)
+# define VdbeBranchTaken(I,M)
+#else
+# define VdbeBranchTaken(I,M) vdbeTakeBranch(pOp->iSrcLine,I,M)
+ static void vdbeTakeBranch(int iSrcLine, u8 I, u8 M){
+ if( iSrcLine<=2 && ALWAYS(iSrcLine>0) ){
+ M = iSrcLine;
+ /* Assert the truth of VdbeCoverageAlwaysTaken() and
+ ** VdbeCoverageNeverTaken() */
+ assert( (M & I)==I );
+ }else{
+ if( sqlite3GlobalConfig.xVdbeBranch==0 ) return; /*NO_TEST*/
+ sqlite3GlobalConfig.xVdbeBranch(sqlite3GlobalConfig.pVdbeBranchArg,
+ iSrcLine,I,M);
+ }
+ }
+#endif
+
+/*
** Convert the given register into a string if it isn't one
** already. Return non-zero if a malloc() fails.
*/
@@ -66174,38 +67160,14 @@ SQLITE_API int sqlite3_found_count = 0;
**
** This routine converts an ephemeral string into a dynamically allocated
** string that the register itself controls. In other words, it
-** converts an MEM_Ephem string into an MEM_Dyn string.
+** converts an MEM_Ephem string into a string with P.z==P.zMalloc.
*/
#define Deephemeralize(P) \
if( ((P)->flags&MEM_Ephem)!=0 \
&& sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
-# define isSorter(x) ((x)->pSorter!=0)
-
-/*
-** Argument pMem points at a register that will be passed to a
-** user-defined function or returned to the user as the result of a query.
-** This routine sets the pMem->type variable used by the sqlite3_value_*()
-** routines.
-*/
-SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem){
- int flags = pMem->flags;
- if( flags & MEM_Null ){
- pMem->type = SQLITE_NULL;
- }
- else if( flags & MEM_Int ){
- pMem->type = SQLITE_INTEGER;
- }
- else if( flags & MEM_Real ){
- pMem->type = SQLITE_FLOAT;
- }
- else if( flags & MEM_Str ){
- pMem->type = SQLITE_TEXT;
- }else{
- pMem->type = SQLITE_BLOB;
- }
-}
+#define isSorter(x) ((x)->pSorter!=0)
/*
** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL
@@ -66335,12 +67297,13 @@ static void applyAffinity(
** loss of information and return the revised type of the argument.
*/
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){
- Mem *pMem = (Mem*)pVal;
- if( pMem->type==SQLITE_TEXT ){
+ int eType = sqlite3_value_type(pVal);
+ if( eType==SQLITE_TEXT ){
+ Mem *pMem = (Mem*)pVal;
applyNumericAffinity(pMem);
- sqlite3VdbeMemStoreType(pMem);
+ eType = sqlite3_value_type(pVal);
}
- return pMem->type;
+ return eType;
}
/*
@@ -66443,7 +67406,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
** Print the value of a register for tracing purposes:
*/
static void memTracePrint(Mem *p){
- if( p->flags & MEM_Invalid ){
+ if( p->flags & MEM_Undefined ){
printf(" undefined");
}else if( p->flags & MEM_Null ){
printf(" NULL");
@@ -66576,20 +67539,6 @@ SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
#endif
-/*
-** The CHECK_FOR_INTERRUPT macro defined here looks to see if the
-** sqlite3_interrupt() routine has been called. If it has been, then
-** processing of the VDBE program is interrupted.
-**
-** This macro added to every instruction that does a jump in order to
-** implement a loop. This test used to be on every single instruction,
-** but that meant we more testing than we needed. By only testing the
-** flag on jump instructions, we get a (small) speed improvement.
-*/
-#define CHECK_FOR_INTERRUPT \
- if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
-
-
#ifndef NDEBUG
/*
** This function is only called from within an assert() expression. It
@@ -66612,35 +67561,8 @@ static int checkSavepointCount(sqlite3 *db){
/*
-** Execute as much of a VDBE program as we can then return.
-**
-** sqlite3VdbeMakeReady() must be called before this routine in order to
-** close the program with a final OP_Halt and to set up the callbacks
-** and the error message pointer.
-**
-** Whenever a row or result data is available, this routine will either
-** invoke the result callback (if there is one) or return with
-** SQLITE_ROW.
-**
-** If an attempt is made to open a locked database, then this routine
-** will either invoke the busy callback (if there is one) or it will
-** return SQLITE_BUSY.
-**
-** If an error occurs, an error message is written to memory obtained
-** from sqlite3_malloc() and p->zErrMsg is made to point to that memory.
-** The error code is stored in p->rc and this routine returns SQLITE_ERROR.
-**
-** If the callback ever returns non-zero, then the program exits
-** immediately. There will be no error message but the p->rc field is
-** set to SQLITE_ABORT and this routine will return SQLITE_ERROR.
-**
-** A memory allocation error causes p->rc to be set to SQLITE_NOMEM and this
-** routine to return SQLITE_ERROR.
-**
-** Other fatal errors return SQLITE_ERROR.
-**
-** After this routine has finished, sqlite3VdbeFinalize() should be
-** used to clean up the mess that was left behind.
+** Execute as much of a VDBE program as we can.
+** This is the core of sqlite3_step().
*/
SQLITE_PRIVATE int sqlite3VdbeExec(
Vdbe *p /* The VDBE */
@@ -66666,431 +67588,8 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */
#ifdef VDBE_PROFILE
u64 start; /* CPU clock count at start of opcode */
- int origPc; /* Program counter at start of opcode */
-#endif
- /********************************************************************
- ** Automatically generated code
- **
- ** The following union is automatically generated by the
- ** vdbe-compress.tcl script. The purpose of this union is to
- ** reduce the amount of stack space required by this function.
- ** See comments in the vdbe-compress.tcl script for details.
- */
- union vdbeExecUnion {
- struct OP_Yield_stack_vars {
- int pcDest;
- } aa;
- struct OP_Halt_stack_vars {
- const char *zType;
- const char *zLogFmt;
- } ab;
- struct OP_Null_stack_vars {
- int cnt;
- u16 nullFlag;
- } ac;
- struct OP_Variable_stack_vars {
- Mem *pVar; /* Value being transferred */
- } ad;
- struct OP_Move_stack_vars {
- char *zMalloc; /* Holding variable for allocated memory */
- int n; /* Number of registers left to copy */
- int p1; /* Register to copy from */
- int p2; /* Register to copy to */
- } ae;
- struct OP_Copy_stack_vars {
- int n;
- } af;
- struct OP_ResultRow_stack_vars {
- Mem *pMem;
- int i;
- } ag;
- struct OP_Concat_stack_vars {
- i64 nByte;
- } ah;
- struct OP_Remainder_stack_vars {
- char bIntint; /* Started out as two integer operands */
- int flags; /* Combined MEM_* flags from both inputs */
- i64 iA; /* Integer value of left operand */
- i64 iB; /* Integer value of right operand */
- double rA; /* Real value of left operand */
- double rB; /* Real value of right operand */
- } ai;
- struct OP_Function_stack_vars {
- int i;
- Mem *pArg;
- sqlite3_context ctx;
- sqlite3_value **apVal;
- int n;
- } aj;
- struct OP_ShiftRight_stack_vars {
- i64 iA;
- u64 uA;
- i64 iB;
- u8 op;
- } ak;
- struct OP_Ge_stack_vars {
- int res; /* Result of the comparison of pIn1 against pIn3 */
- char affinity; /* Affinity to use for comparison */
- u16 flags1; /* Copy of initial value of pIn1->flags */
- u16 flags3; /* Copy of initial value of pIn3->flags */
- } al;
- struct OP_Compare_stack_vars {
- int n;
- int i;
- int p1;
- int p2;
- const KeyInfo *pKeyInfo;
- int idx;
- CollSeq *pColl; /* Collating sequence to use on this term */
- int bRev; /* True for DESCENDING sort order */
- } am;
- struct OP_Or_stack_vars {
- int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
- int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
- } an;
- struct OP_IfNot_stack_vars {
- int c;
- } ao;
- struct OP_Column_stack_vars {
- i64 payloadSize64; /* Number of bytes in the record */
- int p2; /* column number to retrieve */
- VdbeCursor *pC; /* The VDBE cursor */
- BtCursor *pCrsr; /* The BTree cursor */
- u32 *aType; /* aType[i] holds the numeric type of the i-th column */
- u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */
- int len; /* The length of the serialized data for the column */
- int i; /* Loop counter */
- Mem *pDest; /* Where to write the extracted value */
- Mem sMem; /* For storing the record being decoded */
- const u8 *zData; /* Part of the record being decoded */
- const u8 *zHdr; /* Next unparsed byte of the header */
- const u8 *zEndHdr; /* Pointer to first byte after the header */
- u32 offset; /* Offset into the data */
- u32 szField; /* Number of bytes in the content of a field */
- u32 avail; /* Number of bytes of available data */
- u32 t; /* A type code from the record header */
- Mem *pReg; /* PseudoTable input register */
- } ap;
- struct OP_Affinity_stack_vars {
- const char *zAffinity; /* The affinity to be applied */
- char cAff; /* A single character of affinity */
- } aq;
- struct OP_MakeRecord_stack_vars {
- u8 *zNewRecord; /* A buffer to hold the data for the new record */
- Mem *pRec; /* The new record */
- u64 nData; /* Number of bytes of data space */
- int nHdr; /* Number of bytes of header space */
- i64 nByte; /* Data space required for this record */
- int nZero; /* Number of zero bytes at the end of the record */
- int nVarint; /* Number of bytes in a varint */
- u32 serial_type; /* Type field */
- Mem *pData0; /* First field to be combined into the record */
- Mem *pLast; /* Last field of the record */
- int nField; /* Number of fields in the record */
- char *zAffinity; /* The affinity string for the record */
- int file_format; /* File format to use for encoding */
- int i; /* Space used in zNewRecord[] */
- int len; /* Length of a field */
- } ar;
- struct OP_Count_stack_vars {
- i64 nEntry;
- BtCursor *pCrsr;
- } as;
- struct OP_Savepoint_stack_vars {
- int p1; /* Value of P1 operand */
- char *zName; /* Name of savepoint */
- int nName;
- Savepoint *pNew;
- Savepoint *pSavepoint;
- Savepoint *pTmp;
- int iSavepoint;
- int ii;
- } at;
- struct OP_AutoCommit_stack_vars {
- int desiredAutoCommit;
- int iRollback;
- int turnOnAC;
- } au;
- struct OP_Transaction_stack_vars {
- Btree *pBt;
- } av;
- struct OP_ReadCookie_stack_vars {
- int iMeta;
- int iDb;
- int iCookie;
- } aw;
- struct OP_SetCookie_stack_vars {
- Db *pDb;
- } ax;
- struct OP_VerifyCookie_stack_vars {
- int iMeta;
- int iGen;
- Btree *pBt;
- } ay;
- struct OP_OpenWrite_stack_vars {
- int nField;
- KeyInfo *pKeyInfo;
- int p2;
- int iDb;
- int wrFlag;
- Btree *pX;
- VdbeCursor *pCur;
- Db *pDb;
- } az;
- struct OP_OpenEphemeral_stack_vars {
- VdbeCursor *pCx;
- KeyInfo *pKeyInfo;
- } ba;
- struct OP_SorterOpen_stack_vars {
- VdbeCursor *pCx;
- } bb;
- struct OP_OpenPseudo_stack_vars {
- VdbeCursor *pCx;
- } bc;
- struct OP_SeekGt_stack_vars {
- int res;
- int oc;
- VdbeCursor *pC;
- UnpackedRecord r;
- int nField;
- i64 iKey; /* The rowid we are to seek to */
- } bd;
- struct OP_Seek_stack_vars {
- VdbeCursor *pC;
- } be;
- struct OP_Found_stack_vars {
- int alreadyExists;
- int ii;
- VdbeCursor *pC;
- int res;
- char *pFree;
- UnpackedRecord *pIdxKey;
- UnpackedRecord r;
- char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7];
- } bf;
- struct OP_NotExists_stack_vars {
- VdbeCursor *pC;
- BtCursor *pCrsr;
- int res;
- u64 iKey;
- } bg;
- struct OP_NewRowid_stack_vars {
- i64 v; /* The new rowid */
- VdbeCursor *pC; /* Cursor of table to get the new rowid */
- int res; /* Result of an sqlite3BtreeLast() */
- int cnt; /* Counter to limit the number of searches */
- Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
- VdbeFrame *pFrame; /* Root frame of VDBE */
- } bh;
- struct OP_InsertInt_stack_vars {
- Mem *pData; /* MEM cell holding data for the record to be inserted */
- Mem *pKey; /* MEM cell holding key for the record */
- i64 iKey; /* The integer ROWID or key for the record to be inserted */
- VdbeCursor *pC; /* Cursor to table into which insert is written */
- int nZero; /* Number of zero-bytes to append */
- int seekResult; /* Result of prior seek or 0 if no USESEEKRESULT flag */
- const char *zDb; /* database name - used by the update hook */
- const char *zTbl; /* Table name - used by the opdate hook */
- int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
- } bi;
- struct OP_Delete_stack_vars {
- i64 iKey;
- VdbeCursor *pC;
- } bj;
- struct OP_SorterCompare_stack_vars {
- VdbeCursor *pC;
- int res;
- int nIgnore;
- } bk;
- struct OP_SorterData_stack_vars {
- VdbeCursor *pC;
- } bl;
- struct OP_RowData_stack_vars {
- VdbeCursor *pC;
- BtCursor *pCrsr;
- u32 n;
- i64 n64;
- } bm;
- struct OP_Rowid_stack_vars {
- VdbeCursor *pC;
- i64 v;
- sqlite3_vtab *pVtab;
- const sqlite3_module *pModule;
- } bn;
- struct OP_NullRow_stack_vars {
- VdbeCursor *pC;
- } bo;
- struct OP_Last_stack_vars {
- VdbeCursor *pC;
- BtCursor *pCrsr;
- int res;
- } bp;
- struct OP_Rewind_stack_vars {
- VdbeCursor *pC;
- BtCursor *pCrsr;
- int res;
- } bq;
- struct OP_SorterNext_stack_vars {
- VdbeCursor *pC;
- int res;
- } br;
- struct OP_IdxInsert_stack_vars {
- VdbeCursor *pC;
- BtCursor *pCrsr;
- int nKey;
- const char *zKey;
- } bs;
- struct OP_IdxDelete_stack_vars {
- VdbeCursor *pC;
- BtCursor *pCrsr;
- int res;
- UnpackedRecord r;
- } bt;
- struct OP_IdxRowid_stack_vars {
- BtCursor *pCrsr;
- VdbeCursor *pC;
- i64 rowid;
- } bu;
- struct OP_IdxGE_stack_vars {
- VdbeCursor *pC;
- int res;
- UnpackedRecord r;
- } bv;
- struct OP_Destroy_stack_vars {
- int iMoved;
- int iCnt;
- Vdbe *pVdbe;
- int iDb;
- } bw;
- struct OP_Clear_stack_vars {
- int nChange;
- } bx;
- struct OP_CreateTable_stack_vars {
- int pgno;
- int flags;
- Db *pDb;
- } by;
- struct OP_ParseSchema_stack_vars {
- int iDb;
- const char *zMaster;
- char *zSql;
- InitData initData;
- } bz;
- struct OP_IntegrityCk_stack_vars {
- int nRoot; /* Number of tables to check. (Number of root pages.) */
- int *aRoot; /* Array of rootpage numbers for tables to be checked */
- int j; /* Loop counter */
- int nErr; /* Number of errors reported */
- char *z; /* Text of the error report */
- Mem *pnErr; /* Register keeping track of errors remaining */
- } ca;
- struct OP_RowSetRead_stack_vars {
- i64 val;
- } cb;
- struct OP_RowSetTest_stack_vars {
- int iSet;
- int exists;
- } cc;
- struct OP_Program_stack_vars {
- int nMem; /* Number of memory registers for sub-program */
- int nByte; /* Bytes of runtime space required for sub-program */
- Mem *pRt; /* Register to allocate runtime space */
- Mem *pMem; /* Used to iterate through memory cells */
- Mem *pEnd; /* Last memory cell in new array */
- VdbeFrame *pFrame; /* New vdbe frame to execute in */
- SubProgram *pProgram; /* Sub-program to execute */
- void *t; /* Token identifying trigger */
- } cd;
- struct OP_Param_stack_vars {
- VdbeFrame *pFrame;
- Mem *pIn;
- } ce;
- struct OP_MemMax_stack_vars {
- Mem *pIn1;
- VdbeFrame *pFrame;
- } cf;
- struct OP_AggStep_stack_vars {
- int n;
- int i;
- Mem *pMem;
- Mem *pRec;
- sqlite3_context ctx;
- sqlite3_value **apVal;
- } cg;
- struct OP_AggFinal_stack_vars {
- Mem *pMem;
- } ch;
- struct OP_Checkpoint_stack_vars {
- int i; /* Loop counter */
- int aRes[3]; /* Results */
- Mem *pMem; /* Write results here */
- } ci;
- struct OP_JournalMode_stack_vars {
- Btree *pBt; /* Btree to change journal mode of */
- Pager *pPager; /* Pager associated with pBt */
- int eNew; /* New journal mode */
- int eOld; /* The old journal mode */
-#ifndef SQLITE_OMIT_WAL
- const char *zFilename; /* Name of database file for pPager */
#endif
- } cj;
- struct OP_IncrVacuum_stack_vars {
- Btree *pBt;
- } ck;
- struct OP_VBegin_stack_vars {
- VTable *pVTab;
- } cl;
- struct OP_VOpen_stack_vars {
- VdbeCursor *pCur;
- sqlite3_vtab_cursor *pVtabCursor;
- sqlite3_vtab *pVtab;
- sqlite3_module *pModule;
- } cm;
- struct OP_VFilter_stack_vars {
- int nArg;
- int iQuery;
- const sqlite3_module *pModule;
- Mem *pQuery;
- Mem *pArgc;
- sqlite3_vtab_cursor *pVtabCursor;
- sqlite3_vtab *pVtab;
- VdbeCursor *pCur;
- int res;
- int i;
- Mem **apArg;
- } cn;
- struct OP_VColumn_stack_vars {
- sqlite3_vtab *pVtab;
- const sqlite3_module *pModule;
- Mem *pDest;
- sqlite3_context sContext;
- } co;
- struct OP_VNext_stack_vars {
- sqlite3_vtab *pVtab;
- const sqlite3_module *pModule;
- int res;
- VdbeCursor *pCur;
- } cp;
- struct OP_VRename_stack_vars {
- sqlite3_vtab *pVtab;
- Mem *pName;
- } cq;
- struct OP_VUpdate_stack_vars {
- sqlite3_vtab *pVtab;
- sqlite3_module *pModule;
- int nArg;
- int i;
- sqlite_int64 rowid;
- Mem **apArg;
- Mem *pX;
- } cr;
- struct OP_Trace_stack_vars {
- char *zTrace;
- char *z;
- } cs;
- } u;
- /* End automatically generated code
- ********************************************************************/
+ /*** INSERT STACK UNION HERE ***/
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
sqlite3VdbeEnter(p);
@@ -67106,7 +67605,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
assert( p->explain==0 );
p->pResultSet = 0;
db->busyHandler.nBusy = 0;
- CHECK_FOR_INTERRUPT;
+ if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
sqlite3VdbeIOTraceSql(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
if( db->xProgress ){
@@ -67150,7 +67649,6 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
assert( pc>=0 && pc<p->nOp );
if( db->mallocFailed ) goto no_mem;
#ifdef VDBE_PROFILE
- origPc = pc;
start = sqlite3Hwtime();
#endif
nVmStep++;
@@ -67198,18 +67696,21 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
assert( pOp->p1>0 );
assert( pOp->p1<=(p->nMem-p->nCursor) );
assert( memIsValid(&aMem[pOp->p1]) );
+ assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p1]) );
REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
}
if( (pOp->opflags & OPFLG_IN2)!=0 ){
assert( pOp->p2>0 );
assert( pOp->p2<=(p->nMem-p->nCursor) );
assert( memIsValid(&aMem[pOp->p2]) );
+ assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p2]) );
REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
}
if( (pOp->opflags & OPFLG_IN3)!=0 ){
assert( pOp->p3>0 );
assert( pOp->p3<=(p->nMem-p->nCursor) );
assert( memIsValid(&aMem[pOp->p3]) );
+ assert( sqlite3VdbeCheckMemInvariants(&aMem[pOp->p3]) );
REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
}
if( (pOp->opflags & OPFLG_OUT2)!=0 ){
@@ -67267,6 +67768,11 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
** The next instruction executed will be
** the one at index P2 from the beginning of
** the program.
+**
+** The P1 parameter is not actually used by this opcode. However, it
+** is sometimes set to 1 instead of 0 as a hint to the command-line shell
+** that this Goto is the bottom of a loop and that the lines from P2 down
+** to the current line should be indented for EXPLAIN output.
*/
case OP_Goto: { /* jump */
pc = pOp->p2 - 1;
@@ -67282,7 +67788,7 @@ case OP_Goto: { /* jump */
** checks on every opcode. This helps sqlite3_step() to run about 1.5%
** faster according to "valgrind --tool=cachegrind" */
check_for_interrupt:
- CHECK_FOR_INTERRUPT;
+ if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Call the progress callback if it is configured and the required number
** of VDBE ops have been executed (either since this invocation of
@@ -67311,7 +67817,7 @@ check_for_interrupt:
case OP_Gosub: { /* jump */
assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
pIn1 = &aMem[pOp->p1];
- assert( (pIn1->flags & MEM_Dyn)==0 );
+ assert( VdbeMemDynamic(pIn1)==0 );
memAboutToChange(p, pIn1);
pIn1->flags = MEM_Int;
pIn1->u.i = pc;
@@ -67322,35 +67828,79 @@ case OP_Gosub: { /* jump */
/* Opcode: Return P1 * * * *
**
-** Jump to the next instruction after the address in register P1.
+** Jump to the next instruction after the address in register P1. After
+** the jump, register P1 becomes undefined.
*/
case OP_Return: { /* in1 */
pIn1 = &aMem[pOp->p1];
- assert( pIn1->flags & MEM_Int );
+ assert( pIn1->flags==MEM_Int );
pc = (int)pIn1->u.i;
+ pIn1->flags = MEM_Undefined;
+ break;
+}
+
+/* Opcode: InitCoroutine P1 P2 P3 * *
+**
+** Set up register P1 so that it will OP_Yield to the co-routine
+** located at address P3.
+**
+** If P2!=0 then the co-routine implementation immediately follows
+** this opcode. So jump over the co-routine implementation to
+** address P2.
+*/
+case OP_InitCoroutine: { /* jump */
+ assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
+ assert( pOp->p2>=0 && pOp->p2<p->nOp );
+ assert( pOp->p3>=0 && pOp->p3<p->nOp );
+ pOut = &aMem[pOp->p1];
+ assert( !VdbeMemDynamic(pOut) );
+ pOut->u.i = pOp->p3 - 1;
+ pOut->flags = MEM_Int;
+ if( pOp->p2 ) pc = pOp->p2 - 1;
break;
}
-/* Opcode: Yield P1 * * * *
+/* Opcode: EndCoroutine P1 * * * *
+**
+** The instruction at the address in register P1 is an OP_Yield.
+** Jump to the P2 parameter of that OP_Yield.
+** After the jump, register P1 becomes undefined.
+*/
+case OP_EndCoroutine: { /* in1 */
+ VdbeOp *pCaller;
+ pIn1 = &aMem[pOp->p1];
+ assert( pIn1->flags==MEM_Int );
+ assert( pIn1->u.i>=0 && pIn1->u.i<p->nOp );
+ pCaller = &aOp[pIn1->u.i];
+ assert( pCaller->opcode==OP_Yield );
+ assert( pCaller->p2>=0 && pCaller->p2<p->nOp );
+ pc = pCaller->p2 - 1;
+ pIn1->flags = MEM_Undefined;
+ break;
+}
+
+/* Opcode: Yield P1 P2 * * *
**
** Swap the program counter with the value in register P1.
+**
+** If the co-routine ends with OP_Yield or OP_Return then continue
+** to the next instruction. But if the co-routine ends with
+** OP_EndCoroutine, jump immediately to P2.
*/
-case OP_Yield: { /* in1 */
-#if 0 /* local variables moved into u.aa */
+case OP_Yield: { /* in1, jump */
int pcDest;
-#endif /* local variables moved into u.aa */
pIn1 = &aMem[pOp->p1];
- assert( (pIn1->flags & MEM_Dyn)==0 );
+ assert( VdbeMemDynamic(pIn1)==0 );
pIn1->flags = MEM_Int;
- u.aa.pcDest = (int)pIn1->u.i;
+ pcDest = (int)pIn1->u.i;
pIn1->u.i = pc;
REGISTER_TRACE(pOp->p1, pIn1);
- pc = u.aa.pcDest;
+ pc = pcDest;
break;
}
/* Opcode: HaltIfNull P1 P2 P3 P4 P5
-** Synopsis: if r[P3] null then halt
+** Synopsis: if r[P3]=null halt
**
** Check the value in register P3. If it is NULL then Halt using
** parameter P1, P2, and P4 as if this were a Halt instruction. If the
@@ -67394,10 +67944,8 @@ case OP_HaltIfNull: { /* in3 */
** is the same as executing Halt.
*/
case OP_Halt: {
-#if 0 /* local variables moved into u.ab */
const char *zType;
const char *zLogFmt;
-#endif /* local variables moved into u.ab */
if( pOp->p1==SQLITE_OK && p->pFrame ){
/* Halt the sub-program. Return control to the parent frame. */
@@ -67408,7 +67956,7 @@ case OP_Halt: {
pc = sqlite3VdbeFrameRestore(pFrame);
lastRowid = db->lastRowid;
if( pOp->p2==OE_Ignore ){
- /* Instruction pc is the OP_Program that invoked the sub-program
+ /* Instruction pc is the OP_Program that invoked the sub-program
** currently being halted. If the p2 instruction of this OP_Halt
** instruction is set to OE_Ignore, then the sub-program is throwing
** an IGNORE exception. In this case jump to the address specified
@@ -67431,21 +67979,21 @@ case OP_Halt: {
testcase( pOp->p5==2 );
testcase( pOp->p5==3 );
testcase( pOp->p5==4 );
- u.ab.zType = azType[pOp->p5-1];
+ zType = azType[pOp->p5-1];
}else{
- u.ab.zType = 0;
+ zType = 0;
}
- assert( u.ab.zType!=0 || pOp->p4.z!=0 );
- u.ab.zLogFmt = "abort at %d in [%s]: %s";
- if( u.ab.zType && pOp->p4.z ){
- sqlite3SetString(&p->zErrMsg, db, "%s constraint failed: %s",
- u.ab.zType, pOp->p4.z);
+ assert( zType!=0 || pOp->p4.z!=0 );
+ zLogFmt = "abort at %d in [%s]: %s";
+ if( zType && pOp->p4.z ){
+ sqlite3SetString(&p->zErrMsg, db, "%s constraint failed: %s",
+ zType, pOp->p4.z);
}else if( pOp->p4.z ){
sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
}else{
- sqlite3SetString(&p->zErrMsg, db, "%s constraint failed", u.ab.zType);
+ sqlite3SetString(&p->zErrMsg, db, "%s constraint failed", zType);
}
- sqlite3_log(pOp->p1, u.ab.zLogFmt, pc, p->zSql, p->zErrMsg);
+ sqlite3_log(pOp->p1, zLogFmt, pc, p->zSql, p->zErrMsg);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
@@ -67500,7 +68048,9 @@ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
** Synopsis: r[P2]='P4'
**
** P4 points to a nul terminated UTF-8 string. This opcode is transformed
-** into an OP_String before it is executed for the first time.
+** into an OP_String before it is executed for the first time. During
+** this transformation, the length of string P4 is computed and stored
+** as the P1 parameter.
*/
case OP_String8: { /* same as TK_STRING, out2-prerelease */
assert( pOp->p4.z!=0 );
@@ -67513,10 +68063,9 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */
if( rc==SQLITE_TOOBIG ) goto too_big;
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
assert( pOut->zMalloc==pOut->z );
- assert( pOut->flags & MEM_Dyn );
+ assert( VdbeMemDynamic(pOut)==0 );
pOut->zMalloc = 0;
pOut->flags |= MEM_Static;
- pOut->flags &= ~MEM_Dyn;
if( pOp->p4type==P4_DYNAMIC ){
sqlite3DbFree(db, pOp->p4.z);
}
@@ -67559,25 +68108,37 @@ case OP_String: { /* out2-prerelease */
** OP_Ne or OP_Eq.
*/
case OP_Null: { /* out2-prerelease */
-#if 0 /* local variables moved into u.ac */
int cnt;
u16 nullFlag;
-#endif /* local variables moved into u.ac */
- u.ac.cnt = pOp->p3-pOp->p2;
+ cnt = pOp->p3-pOp->p2;
assert( pOp->p3<=(p->nMem-p->nCursor) );
- pOut->flags = u.ac.nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
- while( u.ac.cnt>0 ){
+ pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
+ while( cnt>0 ){
pOut++;
memAboutToChange(p, pOut);
VdbeMemRelease(pOut);
- pOut->flags = u.ac.nullFlag;
- u.ac.cnt--;
+ pOut->flags = nullFlag;
+ cnt--;
}
break;
}
+/* Opcode: SoftNull P1 * * * *
+** Synopsis: r[P1]=NULL
+**
+** Set register P1 to have the value NULL as seen by the OP_MakeRecord
+** instruction, but do not free any string or blob memory associated with
+** the register, so that if the value was a string or blob that was
+** previously copied using OP_SCopy, the copies will continue to be valid.
+*/
+case OP_SoftNull: {
+ assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
+ pOut = &aMem[pOp->p1];
+ pOut->flags = (pOut->flags|MEM_Null)&~MEM_Undefined;
+ break;
+}
-/* Opcode: Blob P1 P2 * P4
+/* Opcode: Blob P1 P2 * P4 *
** Synopsis: r[P2]=P4 (len=P1)
**
** P4 points to a blob of data P1 bytes long. Store this
@@ -67596,21 +68157,19 @@ case OP_Blob: { /* out2-prerelease */
**
** Transfer the values of bound parameter P1 into register P2
**
-** If the parameter is named, then its name appears in P4 and P3==1.
+** If the parameter is named, then its name appears in P4.
** The P4 value is used by sqlite3_bind_parameter_name().
*/
case OP_Variable: { /* out2-prerelease */
-#if 0 /* local variables moved into u.ad */
Mem *pVar; /* Value being transferred */
-#endif /* local variables moved into u.ad */
assert( pOp->p1>0 && pOp->p1<=p->nVar );
assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] );
- u.ad.pVar = &p->aVar[pOp->p1 - 1];
- if( sqlite3VdbeMemTooBig(u.ad.pVar) ){
+ pVar = &p->aVar[pOp->p1 - 1];
+ if( sqlite3VdbeMemTooBig(pVar) ){
goto too_big;
}
- sqlite3VdbeMemShallowCopy(pOut, u.ad.pVar, MEM_Static);
+ sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
@@ -67624,44 +68183,44 @@ case OP_Variable: { /* out2-prerelease */
** P1..P1+P3 and P2..P2+P3 to overlap.
*/
case OP_Move: {
-#if 0 /* local variables moved into u.ae */
char *zMalloc; /* Holding variable for allocated memory */
int n; /* Number of registers left to copy */
int p1; /* Register to copy from */
int p2; /* Register to copy to */
-#endif /* local variables moved into u.ae */
- u.ae.n = pOp->p3;
- u.ae.p1 = pOp->p1;
- u.ae.p2 = pOp->p2;
- assert( u.ae.n>=0 && u.ae.p1>0 && u.ae.p2>0 );
- assert( u.ae.p1+u.ae.n<=u.ae.p2 || u.ae.p2+u.ae.n<=u.ae.p1 );
+ n = pOp->p3;
+ p1 = pOp->p1;
+ p2 = pOp->p2;
+ assert( n>=0 && p1>0 && p2>0 );
+ assert( p1+n<=p2 || p2+n<=p1 );
- pIn1 = &aMem[u.ae.p1];
- pOut = &aMem[u.ae.p2];
+ pIn1 = &aMem[p1];
+ pOut = &aMem[p2];
do{
assert( pOut<=&aMem[(p->nMem-p->nCursor)] );
assert( pIn1<=&aMem[(p->nMem-p->nCursor)] );
assert( memIsValid(pIn1) );
memAboutToChange(p, pOut);
- u.ae.zMalloc = pOut->zMalloc;
- pOut->zMalloc = 0;
- sqlite3VdbeMemMove(pOut, pIn1);
+ VdbeMemRelease(pOut);
+ zMalloc = pOut->zMalloc;
+ memcpy(pOut, pIn1, sizeof(Mem));
#ifdef SQLITE_DEBUG
- if( pOut->pScopyFrom>=&aMem[u.ae.p1] && pOut->pScopyFrom<&aMem[u.ae.p1+pOp->p3] ){
- pOut->pScopyFrom += u.ae.p1 - pOp->p2;
+ if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){
+ pOut->pScopyFrom += p1 - pOp->p2;
}
#endif
- pIn1->zMalloc = u.ae.zMalloc;
- REGISTER_TRACE(u.ae.p2++, pOut);
+ pIn1->flags = MEM_Undefined;
+ pIn1->xDel = 0;
+ pIn1->zMalloc = zMalloc;
+ REGISTER_TRACE(p2++, pOut);
pIn1++;
pOut++;
- }while( u.ae.n-- );
+ }while( n-- );
break;
}
/* Opcode: Copy P1 P2 P3 * *
-** Synopsis: r[P2@P3]=r[P1@P3]
+** Synopsis: r[P2@P3+1]=r[P1@P3+1]
**
** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
**
@@ -67669,11 +68228,9 @@ case OP_Move: {
** is made of any string or blob constant. See also OP_SCopy.
*/
case OP_Copy: {
-#if 0 /* local variables moved into u.af */
int n;
-#endif /* local variables moved into u.af */
- u.af.n = pOp->p3;
+ n = pOp->p3;
pIn1 = &aMem[pOp->p1];
pOut = &aMem[pOp->p2];
assert( pOut!=pIn1 );
@@ -67683,8 +68240,8 @@ case OP_Copy: {
#ifdef SQLITE_DEBUG
pOut->pScopyFrom = 0;
#endif
- REGISTER_TRACE(pOp->p2+pOp->p3-u.af.n, pOut);
- if( (u.af.n--)==0 ) break;
+ REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut);
+ if( (n--)==0 ) break;
pOut++;
pIn1++;
}
@@ -67721,14 +68278,12 @@ case OP_SCopy: { /* out2 */
** The registers P1 through P1+P2-1 contain a single row of
** results. This opcode causes the sqlite3_step() call to terminate
** with an SQLITE_ROW return code and it sets up the sqlite3_stmt
-** structure to provide access to the top P1 values as the result
-** row.
+** structure to provide access to the r(P1)..r(P1+P2-1) values as
+** the result row.
*/
case OP_ResultRow: {
-#if 0 /* local variables moved into u.ag */
Mem *pMem;
int i;
-#endif /* local variables moved into u.ag */
assert( p->nResColumn==pOp->p2 );
assert( pOp->p1>0 );
assert( pOp->p1+pOp->p2<=(p->nMem-p->nCursor)+1 );
@@ -67754,8 +68309,8 @@ case OP_ResultRow: {
break;
}
- /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then
- ** DML statements invoke this opcode to return the number of rows
+ /* If the SQLITE_CountRows flag is set in sqlite3.flags mask, then
+ ** DML statements invoke this opcode to return the number of rows
** modified to the user. This is the only way that a VM that
** opens a statement transaction may invoke this opcode.
**
@@ -67782,15 +68337,14 @@ case OP_ResultRow: {
** and have an assigned type. The results are de-ephemeralized as
** a side effect.
*/
- u.ag.pMem = p->pResultSet = &aMem[pOp->p1];
- for(u.ag.i=0; u.ag.i<pOp->p2; u.ag.i++){
- assert( memIsValid(&u.ag.pMem[u.ag.i]) );
- Deephemeralize(&u.ag.pMem[u.ag.i]);
- assert( (u.ag.pMem[u.ag.i].flags & MEM_Ephem)==0
- || (u.ag.pMem[u.ag.i].flags & (MEM_Str|MEM_Blob))==0 );
- sqlite3VdbeMemNulTerminate(&u.ag.pMem[u.ag.i]);
- sqlite3VdbeMemStoreType(&u.ag.pMem[u.ag.i]);
- REGISTER_TRACE(pOp->p1+u.ag.i, &u.ag.pMem[u.ag.i]);
+ pMem = p->pResultSet = &aMem[pOp->p1];
+ for(i=0; i<pOp->p2; i++){
+ assert( memIsValid(&pMem[i]) );
+ Deephemeralize(&pMem[i]);
+ assert( (pMem[i].flags & MEM_Ephem)==0
+ || (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
+ sqlite3VdbeMemNulTerminate(&pMem[i]);
+ REGISTER_TRACE(pOp->p1+i, &pMem[i]);
}
if( db->mallocFailed ) goto no_mem;
@@ -67815,9 +68369,7 @@ case OP_ResultRow: {
** to avoid a memcpy().
*/
case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
-#if 0 /* local variables moved into u.ah */
i64 nByte;
-#endif /* local variables moved into u.ah */
pIn1 = &aMem[pOp->p1];
pIn2 = &aMem[pOp->p2];
@@ -67830,22 +68382,22 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem;
Stringify(pIn1, encoding);
Stringify(pIn2, encoding);
- u.ah.nByte = pIn1->n + pIn2->n;
- if( u.ah.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ nByte = pIn1->n + pIn2->n;
+ if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
- MemSetTypeFlag(pOut, MEM_Str);
- if( sqlite3VdbeMemGrow(pOut, (int)u.ah.nByte+2, pOut==pIn2) ){
+ if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
goto no_mem;
}
+ MemSetTypeFlag(pOut, MEM_Str);
if( pOut!=pIn2 ){
memcpy(pOut->z, pIn2->z, pIn2->n);
}
memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
- pOut->z[u.ah.nByte]=0;
- pOut->z[u.ah.nByte+1] = 0;
+ pOut->z[nByte]=0;
+ pOut->z[nByte+1] = 0;
pOut->flags |= MEM_Term;
- pOut->n = (int)u.ah.nByte;
+ pOut->n = (int)nByte;
pOut->enc = encoding;
UPDATE_MAX_BLOBSIZE(pOut);
break;
@@ -67894,79 +68446,77 @@ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */
case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */
case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
-#if 0 /* local variables moved into u.ai */
char bIntint; /* Started out as two integer operands */
int flags; /* Combined MEM_* flags from both inputs */
i64 iA; /* Integer value of left operand */
i64 iB; /* Integer value of right operand */
double rA; /* Real value of left operand */
double rB; /* Real value of right operand */
-#endif /* local variables moved into u.ai */
pIn1 = &aMem[pOp->p1];
applyNumericAffinity(pIn1);
pIn2 = &aMem[pOp->p2];
applyNumericAffinity(pIn2);
pOut = &aMem[pOp->p3];
- u.ai.flags = pIn1->flags | pIn2->flags;
- if( (u.ai.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
+ flags = pIn1->flags | pIn2->flags;
+ if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
- u.ai.iA = pIn1->u.i;
- u.ai.iB = pIn2->u.i;
- u.ai.bIntint = 1;
+ iA = pIn1->u.i;
+ iB = pIn2->u.i;
+ bIntint = 1;
switch( pOp->opcode ){
- case OP_Add: if( sqlite3AddInt64(&u.ai.iB,u.ai.iA) ) goto fp_math; break;
- case OP_Subtract: if( sqlite3SubInt64(&u.ai.iB,u.ai.iA) ) goto fp_math; break;
- case OP_Multiply: if( sqlite3MulInt64(&u.ai.iB,u.ai.iA) ) goto fp_math; break;
+ case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break;
+ case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break;
+ case OP_Multiply: if( sqlite3MulInt64(&iB,iA) ) goto fp_math; break;
case OP_Divide: {
- if( u.ai.iA==0 ) goto arithmetic_result_is_null;
- if( u.ai.iA==-1 && u.ai.iB==SMALLEST_INT64 ) goto fp_math;
- u.ai.iB /= u.ai.iA;
+ if( iA==0 ) goto arithmetic_result_is_null;
+ if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math;
+ iB /= iA;
break;
}
default: {
- if( u.ai.iA==0 ) goto arithmetic_result_is_null;
- if( u.ai.iA==-1 ) u.ai.iA = 1;
- u.ai.iB %= u.ai.iA;
+ if( iA==0 ) goto arithmetic_result_is_null;
+ if( iA==-1 ) iA = 1;
+ iB %= iA;
break;
}
}
- pOut->u.i = u.ai.iB;
+ pOut->u.i = iB;
MemSetTypeFlag(pOut, MEM_Int);
}else{
- u.ai.bIntint = 0;
+ bIntint = 0;
fp_math:
- u.ai.rA = sqlite3VdbeRealValue(pIn1);
- u.ai.rB = sqlite3VdbeRealValue(pIn2);
+ rA = sqlite3VdbeRealValue(pIn1);
+ rB = sqlite3VdbeRealValue(pIn2);
switch( pOp->opcode ){
- case OP_Add: u.ai.rB += u.ai.rA; break;
- case OP_Subtract: u.ai.rB -= u.ai.rA; break;
- case OP_Multiply: u.ai.rB *= u.ai.rA; break;
+ case OP_Add: rB += rA; break;
+ case OP_Subtract: rB -= rA; break;
+ case OP_Multiply: rB *= rA; break;
case OP_Divide: {
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
- if( u.ai.rA==(double)0 ) goto arithmetic_result_is_null;
- u.ai.rB /= u.ai.rA;
+ if( rA==(double)0 ) goto arithmetic_result_is_null;
+ rB /= rA;
break;
}
default: {
- u.ai.iA = (i64)u.ai.rA;
- u.ai.iB = (i64)u.ai.rB;
- if( u.ai.iA==0 ) goto arithmetic_result_is_null;
- if( u.ai.iA==-1 ) u.ai.iA = 1;
- u.ai.rB = (double)(u.ai.iB % u.ai.iA);
+ iA = (i64)rA;
+ iB = (i64)rB;
+ if( iA==0 ) goto arithmetic_result_is_null;
+ if( iA==-1 ) iA = 1;
+ rB = (double)(iB % iA);
break;
}
}
#ifdef SQLITE_OMIT_FLOATING_POINT
- pOut->u.i = u.ai.rB;
+ pOut->u.i = rB;
MemSetTypeFlag(pOut, MEM_Int);
#else
- if( sqlite3IsNaN(u.ai.rB) ){
+ if( sqlite3IsNaN(rB) ){
goto arithmetic_result_is_null;
}
- pOut->r = u.ai.rB;
+ pOut->r = rB;
MemSetTypeFlag(pOut, MEM_Real);
- if( (u.ai.flags & MEM_Real)==0 && !u.ai.bIntint ){
+ if( (flags & MEM_Real)==0 && !bIntint ){
sqlite3VdbeIntegerAffinity(pOut);
}
#endif
@@ -68019,56 +68569,53 @@ case OP_CollSeq: {
** See also: AggStep and AggFinal
*/
case OP_Function: {
-#if 0 /* local variables moved into u.aj */
int i;
Mem *pArg;
sqlite3_context ctx;
sqlite3_value **apVal;
int n;
-#endif /* local variables moved into u.aj */
- u.aj.n = pOp->p5;
- u.aj.apVal = p->apArg;
- assert( u.aj.apVal || u.aj.n==0 );
+ n = pOp->p5;
+ apVal = p->apArg;
+ assert( apVal || n==0 );
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
pOut = &aMem[pOp->p3];
memAboutToChange(p, pOut);
- assert( u.aj.n==0 || (pOp->p2>0 && pOp->p2+u.aj.n<=(p->nMem-p->nCursor)+1) );
- assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+u.aj.n );
- u.aj.pArg = &aMem[pOp->p2];
- for(u.aj.i=0; u.aj.i<u.aj.n; u.aj.i++, u.aj.pArg++){
- assert( memIsValid(u.aj.pArg) );
- u.aj.apVal[u.aj.i] = u.aj.pArg;
- Deephemeralize(u.aj.pArg);
- sqlite3VdbeMemStoreType(u.aj.pArg);
- REGISTER_TRACE(pOp->p2+u.aj.i, u.aj.pArg);
+ assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem-p->nCursor)+1) );
+ assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
+ pArg = &aMem[pOp->p2];
+ for(i=0; i<n; i++, pArg++){
+ assert( memIsValid(pArg) );
+ apVal[i] = pArg;
+ Deephemeralize(pArg);
+ REGISTER_TRACE(pOp->p2+i, pArg);
}
assert( pOp->p4type==P4_FUNCDEF );
- u.aj.ctx.pFunc = pOp->p4.pFunc;
- u.aj.ctx.iOp = pc;
- u.aj.ctx.pVdbe = p;
+ ctx.pFunc = pOp->p4.pFunc;
+ ctx.iOp = pc;
+ ctx.pVdbe = p;
/* The output cell may already have a buffer allocated. Move
- ** the pointer to u.aj.ctx.s so in case the user-function can use
+ ** the pointer to ctx.s so in case the user-function can use
** the already allocated buffer instead of allocating a new one.
*/
- memcpy(&u.aj.ctx.s, pOut, sizeof(Mem));
+ memcpy(&ctx.s, pOut, sizeof(Mem));
pOut->flags = MEM_Null;
pOut->xDel = 0;
pOut->zMalloc = 0;
- MemSetTypeFlag(&u.aj.ctx.s, MEM_Null);
+ MemSetTypeFlag(&ctx.s, MEM_Null);
- u.aj.ctx.fErrorOrAux = 0;
- if( u.aj.ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
+ ctx.fErrorOrAux = 0;
+ if( ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
assert( pOp>aOp );
assert( pOp[-1].p4type==P4_COLLSEQ );
assert( pOp[-1].opcode==OP_CollSeq );
- u.aj.ctx.pColl = pOp[-1].p4.pColl;
+ ctx.pColl = pOp[-1].p4.pColl;
}
db->lastRowid = lastRowid;
- (*u.aj.ctx.pFunc->xFunc)(&u.aj.ctx, u.aj.n, u.aj.apVal); /* IMP: R-24505-23230 */
+ (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */
lastRowid = db->lastRowid;
if( db->mallocFailed ){
@@ -68077,23 +68624,23 @@ case OP_Function: {
** to return a value. The following call releases any resources
** associated with such a value.
*/
- sqlite3VdbeMemRelease(&u.aj.ctx.s);
+ sqlite3VdbeMemRelease(&ctx.s);
goto no_mem;
}
/* If the function returned an error, throw an exception */
- if( u.aj.ctx.fErrorOrAux ){
- if( u.aj.ctx.isError ){
- sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.aj.ctx.s));
- rc = u.aj.ctx.isError;
+ if( ctx.fErrorOrAux ){
+ if( ctx.isError ){
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s));
+ rc = ctx.isError;
}
sqlite3VdbeDeleteAuxData(p, pc, pOp->p1);
}
/* Copy the result of the function into register P3 */
- sqlite3VdbeChangeEncoding(&u.aj.ctx.s, encoding);
+ sqlite3VdbeChangeEncoding(&ctx.s, encoding);
assert( pOut->flags==MEM_Null );
- memcpy(pOut, &u.aj.ctx.s, sizeof(Mem));
+ memcpy(pOut, &ctx.s, sizeof(Mem));
if( sqlite3VdbeMemTooBig(pOut) ){
goto too_big;
}
@@ -68145,12 +68692,10 @@ case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */
case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */
case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */
case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
-#if 0 /* local variables moved into u.ak */
i64 iA;
u64 uA;
i64 iB;
u8 op;
-#endif /* local variables moved into u.ak */
pIn1 = &aMem[pOp->p1];
pIn2 = &aMem[pOp->p2];
@@ -68159,38 +68704,38 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
sqlite3VdbeMemSetNull(pOut);
break;
}
- u.ak.iA = sqlite3VdbeIntValue(pIn2);
- u.ak.iB = sqlite3VdbeIntValue(pIn1);
- u.ak.op = pOp->opcode;
- if( u.ak.op==OP_BitAnd ){
- u.ak.iA &= u.ak.iB;
- }else if( u.ak.op==OP_BitOr ){
- u.ak.iA |= u.ak.iB;
- }else if( u.ak.iB!=0 ){
- assert( u.ak.op==OP_ShiftRight || u.ak.op==OP_ShiftLeft );
+ iA = sqlite3VdbeIntValue(pIn2);
+ iB = sqlite3VdbeIntValue(pIn1);
+ op = pOp->opcode;
+ if( op==OP_BitAnd ){
+ iA &= iB;
+ }else if( op==OP_BitOr ){
+ iA |= iB;
+ }else if( iB!=0 ){
+ assert( op==OP_ShiftRight || op==OP_ShiftLeft );
/* If shifting by a negative amount, shift in the other direction */
- if( u.ak.iB<0 ){
+ if( iB<0 ){
assert( OP_ShiftRight==OP_ShiftLeft+1 );
- u.ak.op = 2*OP_ShiftLeft + 1 - u.ak.op;
- u.ak.iB = u.ak.iB>(-64) ? -u.ak.iB : 64;
+ op = 2*OP_ShiftLeft + 1 - op;
+ iB = iB>(-64) ? -iB : 64;
}
- if( u.ak.iB>=64 ){
- u.ak.iA = (u.ak.iA>=0 || u.ak.op==OP_ShiftLeft) ? 0 : -1;
+ if( iB>=64 ){
+ iA = (iA>=0 || op==OP_ShiftLeft) ? 0 : -1;
}else{
- memcpy(&u.ak.uA, &u.ak.iA, sizeof(u.ak.uA));
- if( u.ak.op==OP_ShiftLeft ){
- u.ak.uA <<= u.ak.iB;
+ memcpy(&uA, &iA, sizeof(uA));
+ if( op==OP_ShiftLeft ){
+ uA <<= iB;
}else{
- u.ak.uA >>= u.ak.iB;
+ uA >>= iB;
/* Sign-extend on a right shift of a negative number */
- if( u.ak.iA<0 ) u.ak.uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-u.ak.iB);
+ if( iA<0 ) uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-iB);
}
- memcpy(&u.ak.iA, &u.ak.uA, sizeof(u.ak.iA));
+ memcpy(&iA, &uA, sizeof(iA));
}
}
- pOut->u.i = u.ak.iA;
+ pOut->u.i = iA;
MemSetTypeFlag(pOut, MEM_Int);
break;
}
@@ -68222,6 +68767,7 @@ case OP_MustBeInt: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_Int)==0 ){
applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
+ VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2);
if( (pIn1->flags & MEM_Int)==0 ){
if( pOp->p2==0 ){
rc = SQLITE_MISMATCH;
@@ -68260,7 +68806,7 @@ case OP_RealAffinity: { /* in1 */
**
** Force the value in register P1 to be text.
** If the value is numeric, convert it to a string using the
-** equivalent of printf(). Blob values are unchanged and
+** equivalent of sprintf(). Blob values are unchanged and
** are afterwards simply interpreted as text.
**
** A NULL value is not changed by this routine. It remains NULL.
@@ -68444,18 +68990,16 @@ case OP_Lt: /* same as TK_LT, jump, in1, in3 */
case OP_Le: /* same as TK_LE, jump, in1, in3 */
case OP_Gt: /* same as TK_GT, jump, in1, in3 */
case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
-#if 0 /* local variables moved into u.al */
int res; /* Result of the comparison of pIn1 against pIn3 */
char affinity; /* Affinity to use for comparison */
u16 flags1; /* Copy of initial value of pIn1->flags */
u16 flags3; /* Copy of initial value of pIn3->flags */
-#endif /* local variables moved into u.al */
pIn1 = &aMem[pOp->p1];
pIn3 = &aMem[pOp->p3];
- u.al.flags1 = pIn1->flags;
- u.al.flags3 = pIn3->flags;
- if( (u.al.flags1 | u.al.flags3)&MEM_Null ){
+ flags1 = pIn1->flags;
+ flags3 = pIn3->flags;
+ if( (flags1 | flags3)&MEM_Null ){
/* One or both operands are NULL */
if( pOp->p5 & SQLITE_NULLEQ ){
/* If SQLITE_NULLEQ is set (which will only happen if the operator is
@@ -68463,65 +69007,71 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
** or not both operands are null.
*/
assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
- assert( (u.al.flags1 & MEM_Cleared)==0 );
- if( (u.al.flags1&MEM_Null)!=0
- && (u.al.flags3&MEM_Null)!=0
- && (u.al.flags3&MEM_Cleared)==0
+ assert( (flags1 & MEM_Cleared)==0 );
+ assert( (pOp->p5 & SQLITE_JUMPIFNULL)==0 );
+ if( (flags1&MEM_Null)!=0
+ && (flags3&MEM_Null)!=0
+ && (flags3&MEM_Cleared)==0
){
- u.al.res = 0; /* Results are equal */
+ res = 0; /* Results are equal */
}else{
- u.al.res = 1; /* Results are not equal */
+ res = 1; /* Results are not equal */
}
}else{
/* SQLITE_NULLEQ is clear and at least one operand is NULL,
** then the result is always NULL.
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
*/
- if( pOp->p5 & SQLITE_JUMPIFNULL ){
- pc = pOp->p2-1;
- }else if( pOp->p5 & SQLITE_STOREP2 ){
+ if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &aMem[pOp->p2];
MemSetTypeFlag(pOut, MEM_Null);
REGISTER_TRACE(pOp->p2, pOut);
+ }else{
+ VdbeBranchTaken(2,3);
+ if( pOp->p5 & SQLITE_JUMPIFNULL ){
+ pc = pOp->p2-1;
+ }
}
break;
}
}else{
/* Neither operand is NULL. Do a comparison. */
- u.al.affinity = pOp->p5 & SQLITE_AFF_MASK;
- if( u.al.affinity ){
- applyAffinity(pIn1, u.al.affinity, encoding);
- applyAffinity(pIn3, u.al.affinity, encoding);
+ affinity = pOp->p5 & SQLITE_AFF_MASK;
+ if( affinity ){
+ applyAffinity(pIn1, affinity, encoding);
+ applyAffinity(pIn3, affinity, encoding);
if( db->mallocFailed ) goto no_mem;
}
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
ExpandBlob(pIn1);
ExpandBlob(pIn3);
- u.al.res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
+ res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
}
switch( pOp->opcode ){
- case OP_Eq: u.al.res = u.al.res==0; break;
- case OP_Ne: u.al.res = u.al.res!=0; break;
- case OP_Lt: u.al.res = u.al.res<0; break;
- case OP_Le: u.al.res = u.al.res<=0; break;
- case OP_Gt: u.al.res = u.al.res>0; break;
- default: u.al.res = u.al.res>=0; break;
+ case OP_Eq: res = res==0; break;
+ case OP_Ne: res = res!=0; break;
+ case OP_Lt: res = res<0; break;
+ case OP_Le: res = res<=0; break;
+ case OP_Gt: res = res>0; break;
+ default: res = res>=0; break;
}
if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &aMem[pOp->p2];
memAboutToChange(p, pOut);
MemSetTypeFlag(pOut, MEM_Int);
- pOut->u.i = u.al.res;
+ pOut->u.i = res;
REGISTER_TRACE(pOp->p2, pOut);
- }else if( u.al.res ){
- pc = pOp->p2-1;
+ }else{
+ VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ if( res ){
+ pc = pOp->p2-1;
+ }
}
-
/* Undo any changes made by applyAffinity() to the input registers. */
- pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.al.flags1&MEM_TypeMask);
- pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.al.flags3&MEM_TypeMask);
+ pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (flags1&MEM_TypeMask);
+ pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (flags3&MEM_TypeMask);
break;
}
@@ -68561,7 +69111,6 @@ case OP_Permutation: {
** and strings are less than blobs.
*/
case OP_Compare: {
-#if 0 /* local variables moved into u.am */
int n;
int i;
int p1;
@@ -68570,38 +69119,37 @@ case OP_Compare: {
int idx;
CollSeq *pColl; /* Collating sequence to use on this term */
int bRev; /* True for DESCENDING sort order */
-#endif /* local variables moved into u.am */
if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
- u.am.n = pOp->p3;
- u.am.pKeyInfo = pOp->p4.pKeyInfo;
- assert( u.am.n>0 );
- assert( u.am.pKeyInfo!=0 );
- u.am.p1 = pOp->p1;
- u.am.p2 = pOp->p2;
+ n = pOp->p3;
+ pKeyInfo = pOp->p4.pKeyInfo;
+ assert( n>0 );
+ assert( pKeyInfo!=0 );
+ p1 = pOp->p1;
+ p2 = pOp->p2;
#if SQLITE_DEBUG
if( aPermute ){
int k, mx = 0;
- for(k=0; k<u.am.n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
- assert( u.am.p1>0 && u.am.p1+mx<=(p->nMem-p->nCursor)+1 );
- assert( u.am.p2>0 && u.am.p2+mx<=(p->nMem-p->nCursor)+1 );
+ for(k=0; k<n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
+ assert( p1>0 && p1+mx<=(p->nMem-p->nCursor)+1 );
+ assert( p2>0 && p2+mx<=(p->nMem-p->nCursor)+1 );
}else{
- assert( u.am.p1>0 && u.am.p1+u.am.n<=(p->nMem-p->nCursor)+1 );
- assert( u.am.p2>0 && u.am.p2+u.am.n<=(p->nMem-p->nCursor)+1 );
+ assert( p1>0 && p1+n<=(p->nMem-p->nCursor)+1 );
+ assert( p2>0 && p2+n<=(p->nMem-p->nCursor)+1 );
}
#endif /* SQLITE_DEBUG */
- for(u.am.i=0; u.am.i<u.am.n; u.am.i++){
- u.am.idx = aPermute ? aPermute[u.am.i] : u.am.i;
- assert( memIsValid(&aMem[u.am.p1+u.am.idx]) );
- assert( memIsValid(&aMem[u.am.p2+u.am.idx]) );
- REGISTER_TRACE(u.am.p1+u.am.idx, &aMem[u.am.p1+u.am.idx]);
- REGISTER_TRACE(u.am.p2+u.am.idx, &aMem[u.am.p2+u.am.idx]);
- assert( u.am.i<u.am.pKeyInfo->nField );
- u.am.pColl = u.am.pKeyInfo->aColl[u.am.i];
- u.am.bRev = u.am.pKeyInfo->aSortOrder[u.am.i];
- iCompare = sqlite3MemCompare(&aMem[u.am.p1+u.am.idx], &aMem[u.am.p2+u.am.idx], u.am.pColl);
+ for(i=0; i<n; i++){
+ idx = aPermute ? aPermute[i] : i;
+ assert( memIsValid(&aMem[p1+idx]) );
+ assert( memIsValid(&aMem[p2+idx]) );
+ REGISTER_TRACE(p1+idx, &aMem[p1+idx]);
+ REGISTER_TRACE(p2+idx, &aMem[p2+idx]);
+ assert( i<pKeyInfo->nField );
+ pColl = pKeyInfo->aColl[i];
+ bRev = pKeyInfo->aSortOrder[i];
+ iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl);
if( iCompare ){
- if( u.am.bRev ) iCompare = -iCompare;
+ if( bRev ) iCompare = -iCompare;
break;
}
}
@@ -68617,11 +69165,11 @@ case OP_Compare: {
*/
case OP_Jump: { /* jump */
if( iCompare<0 ){
- pc = pOp->p1 - 1;
+ pc = pOp->p1 - 1; VdbeBranchTaken(0,3);
}else if( iCompare==0 ){
- pc = pOp->p2 - 1;
+ pc = pOp->p2 - 1; VdbeBranchTaken(1,3);
}else{
- pc = pOp->p3 - 1;
+ pc = pOp->p3 - 1; VdbeBranchTaken(2,3);
}
break;
}
@@ -68648,35 +69196,33 @@ case OP_Jump: { /* jump */
*/
case OP_And: /* same as TK_AND, in1, in2, out3 */
case OP_Or: { /* same as TK_OR, in1, in2, out3 */
-#if 0 /* local variables moved into u.an */
int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
-#endif /* local variables moved into u.an */
pIn1 = &aMem[pOp->p1];
if( pIn1->flags & MEM_Null ){
- u.an.v1 = 2;
+ v1 = 2;
}else{
- u.an.v1 = sqlite3VdbeIntValue(pIn1)!=0;
+ v1 = sqlite3VdbeIntValue(pIn1)!=0;
}
pIn2 = &aMem[pOp->p2];
if( pIn2->flags & MEM_Null ){
- u.an.v2 = 2;
+ v2 = 2;
}else{
- u.an.v2 = sqlite3VdbeIntValue(pIn2)!=0;
+ v2 = sqlite3VdbeIntValue(pIn2)!=0;
}
if( pOp->opcode==OP_And ){
static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
- u.an.v1 = and_logic[u.an.v1*3+u.an.v2];
+ v1 = and_logic[v1*3+v2];
}else{
static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
- u.an.v1 = or_logic[u.an.v1*3+u.an.v2];
+ v1 = or_logic[v1*3+v2];
}
pOut = &aMem[pOp->p3];
- if( u.an.v1==2 ){
+ if( v1==2 ){
MemSetTypeFlag(pOut, MEM_Null);
}else{
- pOut->u.i = u.an.v1;
+ pOut->u.i = v1;
MemSetTypeFlag(pOut, MEM_Int);
}
break;
@@ -68721,10 +69267,13 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
/* Opcode: Once P1 P2 * * *
**
** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
-** set the flag and fall through to the next instruction.
+** set the flag and fall through to the next instruction. In other words,
+** this opcode causes all following opcodes up through P2 (but not including
+** P2) to run just once and to be skipped on subsequent times through the loop.
*/
case OP_Once: { /* jump */
assert( pOp->p1<p->nOnceFlag );
+ VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2);
if( p->aOnceFlag[pOp->p1] ){
pc = pOp->p2-1;
}else{
@@ -68747,21 +69296,20 @@ case OP_Once: { /* jump */
*/
case OP_If: /* jump, in1 */
case OP_IfNot: { /* jump, in1 */
-#if 0 /* local variables moved into u.ao */
int c;
-#endif /* local variables moved into u.ao */
pIn1 = &aMem[pOp->p1];
if( pIn1->flags & MEM_Null ){
- u.ao.c = pOp->p3;
+ c = pOp->p3;
}else{
#ifdef SQLITE_OMIT_FLOATING_POINT
- u.ao.c = sqlite3VdbeIntValue(pIn1)!=0;
+ c = sqlite3VdbeIntValue(pIn1)!=0;
#else
- u.ao.c = sqlite3VdbeRealValue(pIn1)!=0.0;
+ c = sqlite3VdbeRealValue(pIn1)!=0.0;
#endif
- if( pOp->opcode==OP_IfNot ) u.ao.c = !u.ao.c;
+ if( pOp->opcode==OP_IfNot ) c = !c;
}
- if( u.ao.c ){
+ VdbeBranchTaken(c!=0, 2);
+ if( c ){
pc = pOp->p2-1;
}
break;
@@ -68774,6 +69322,7 @@ case OP_IfNot: { /* jump, in1 */
*/
case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
pIn1 = &aMem[pOp->p1];
+ VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2);
if( (pIn1->flags & MEM_Null)!=0 ){
pc = pOp->p2 - 1;
}
@@ -68787,6 +69336,7 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
*/
case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
pIn1 = &aMem[pOp->p1];
+ VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2);
if( (pIn1->flags & MEM_Null)==0 ){
pc = pOp->p2 - 1;
}
@@ -68819,7 +69369,6 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
** skipped for length() and all content loading can be skipped for typeof().
*/
case OP_Column: {
-#if 0 /* local variables moved into u.ap */
i64 payloadSize64; /* Number of bytes in the record */
int p2; /* column number to retrieve */
VdbeCursor *pC; /* The VDBE cursor */
@@ -68838,85 +69387,79 @@ case OP_Column: {
u32 avail; /* Number of bytes of available data */
u32 t; /* A type code from the record header */
Mem *pReg; /* PseudoTable input register */
-#endif /* local variables moved into u.ap */
- u.ap.p2 = pOp->p2;
+ p2 = pOp->p2;
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
- u.ap.pDest = &aMem[pOp->p3];
- memAboutToChange(p, u.ap.pDest);
+ pDest = &aMem[pOp->p3];
+ memAboutToChange(p, pDest);
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.ap.pC = p->apCsr[pOp->p1];
- assert( u.ap.pC!=0 );
- assert( u.ap.p2<u.ap.pC->nField );
- u.ap.aType = u.ap.pC->aType;
- u.ap.aOffset = u.ap.aType + u.ap.pC->nField;
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( p2<pC->nField );
+ aType = pC->aType;
+ aOffset = aType + pC->nField;
#ifndef SQLITE_OMIT_VIRTUALTABLE
- assert( u.ap.pC->pVtabCursor==0 ); /* OP_Column never called on virtual table */
+ assert( pC->pVtabCursor==0 ); /* OP_Column never called on virtual table */
#endif
- u.ap.pCrsr = u.ap.pC->pCursor;
- assert( u.ap.pCrsr!=0 || u.ap.pC->pseudoTableReg>0 ); /* u.ap.pCrsr NULL on PseudoTables */
- assert( u.ap.pCrsr!=0 || u.ap.pC->nullRow ); /* u.ap.pC->nullRow on PseudoTables */
+ pCrsr = pC->pCursor;
+ assert( pCrsr!=0 || pC->pseudoTableReg>0 ); /* pCrsr NULL on PseudoTables */
+ assert( pCrsr!=0 || pC->nullRow ); /* pC->nullRow on PseudoTables */
/* If the cursor cache is stale, bring it up-to-date */
- rc = sqlite3VdbeCursorMoveto(u.ap.pC);
+ rc = sqlite3VdbeCursorMoveto(pC);
if( rc ) goto abort_due_to_error;
- if( u.ap.pC->cacheStatus!=p->cacheCtr || (pOp->p5&OPFLAG_CLEARCACHE)!=0 ){
- if( u.ap.pC->nullRow ){
- if( u.ap.pCrsr==0 ){
- assert( u.ap.pC->pseudoTableReg>0 );
- u.ap.pReg = &aMem[u.ap.pC->pseudoTableReg];
- if( u.ap.pC->multiPseudo ){
- sqlite3VdbeMemShallowCopy(u.ap.pDest, u.ap.pReg+u.ap.p2, MEM_Ephem);
- Deephemeralize(u.ap.pDest);
- goto op_column_out;
- }
- assert( u.ap.pReg->flags & MEM_Blob );
- assert( memIsValid(u.ap.pReg) );
- u.ap.pC->payloadSize = u.ap.pC->szRow = u.ap.avail = u.ap.pReg->n;
- u.ap.pC->aRow = (u8*)u.ap.pReg->z;
+ if( pC->cacheStatus!=p->cacheCtr || (pOp->p5&OPFLAG_CLEARCACHE)!=0 ){
+ if( pC->nullRow ){
+ if( pCrsr==0 ){
+ assert( pC->pseudoTableReg>0 );
+ pReg = &aMem[pC->pseudoTableReg];
+ assert( pReg->flags & MEM_Blob );
+ assert( memIsValid(pReg) );
+ pC->payloadSize = pC->szRow = avail = pReg->n;
+ pC->aRow = (u8*)pReg->z;
}else{
- MemSetTypeFlag(u.ap.pDest, MEM_Null);
+ MemSetTypeFlag(pDest, MEM_Null);
goto op_column_out;
}
}else{
- assert( u.ap.pCrsr );
- if( u.ap.pC->isTable==0 ){
- assert( sqlite3BtreeCursorIsValid(u.ap.pCrsr) );
- VVA_ONLY(rc =) sqlite3BtreeKeySize(u.ap.pCrsr, &u.ap.payloadSize64);
+ assert( pCrsr );
+ if( pC->isTable==0 ){
+ assert( sqlite3BtreeCursorIsValid(pCrsr) );
+ VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &payloadSize64);
assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
/* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
- ** payload size, so it is impossible for u.ap.payloadSize64 to be
+ ** payload size, so it is impossible for payloadSize64 to be
** larger than 32 bits. */
- assert( (u.ap.payloadSize64 & SQLITE_MAX_U32)==(u64)u.ap.payloadSize64 );
- u.ap.pC->aRow = sqlite3BtreeKeyFetch(u.ap.pCrsr, &u.ap.avail);
- u.ap.pC->payloadSize = (u32)u.ap.payloadSize64;
+ assert( (payloadSize64 & SQLITE_MAX_U32)==(u64)payloadSize64 );
+ pC->aRow = sqlite3BtreeKeyFetch(pCrsr, &avail);
+ pC->payloadSize = (u32)payloadSize64;
}else{
- assert( sqlite3BtreeCursorIsValid(u.ap.pCrsr) );
- VVA_ONLY(rc =) sqlite3BtreeDataSize(u.ap.pCrsr, &u.ap.pC->payloadSize);
+ assert( sqlite3BtreeCursorIsValid(pCrsr) );
+ VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &pC->payloadSize);
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
- u.ap.pC->aRow = sqlite3BtreeDataFetch(u.ap.pCrsr, &u.ap.avail);
+ pC->aRow = sqlite3BtreeDataFetch(pCrsr, &avail);
}
- assert( u.ap.avail<=65536 ); /* Maximum page size is 64KiB */
- if( u.ap.pC->payloadSize <= (u32)u.ap.avail ){
- u.ap.pC->szRow = u.ap.pC->payloadSize;
+ assert( avail<=65536 ); /* Maximum page size is 64KiB */
+ if( pC->payloadSize <= (u32)avail ){
+ pC->szRow = pC->payloadSize;
}else{
- u.ap.pC->szRow = u.ap.avail;
+ pC->szRow = avail;
}
- if( u.ap.pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
}
- u.ap.pC->cacheStatus = p->cacheCtr;
- u.ap.pC->iHdrOffset = getVarint32(u.ap.pC->aRow, u.ap.offset);
- u.ap.pC->nHdrParsed = 0;
- u.ap.aOffset[0] = u.ap.offset;
- if( u.ap.avail<u.ap.offset ){
- /* u.ap.pC->aRow does not have to hold the entire row, but it does at least
- ** need to cover the header of the record. If u.ap.pC->aRow does not contain
+ pC->cacheStatus = p->cacheCtr;
+ pC->iHdrOffset = getVarint32(pC->aRow, offset);
+ pC->nHdrParsed = 0;
+ aOffset[0] = offset;
+ if( avail<offset ){
+ /* pC->aRow does not have to hold the entire row, but it does at least
+ ** need to cover the header of the record. If pC->aRow does not contain
** the complete header, then set it to zero, forcing the header to be
** dynamically allocated. */
- u.ap.pC->aRow = 0;
- u.ap.pC->szRow = 0;
+ pC->aRow = 0;
+ pC->szRow = 0;
}
/* Make sure a corrupt database has not given us an oversize header.
@@ -68928,72 +69471,72 @@ case OP_Column: {
** 3-byte type for each of the maximum of 32768 columns plus three
** extra bytes for the header length itself. 32768*3 + 3 = 98307.
*/
- if( u.ap.offset > 98307 || u.ap.offset > u.ap.pC->payloadSize ){
+ if( offset > 98307 || offset > pC->payloadSize ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_error;
}
}
- /* Make sure at least the first u.ap.p2+1 entries of the header have been
- ** parsed and valid information is in u.ap.aOffset[] and u.ap.aType[].
+ /* Make sure at least the first p2+1 entries of the header have been
+ ** parsed and valid information is in aOffset[] and aType[].
*/
- if( u.ap.pC->nHdrParsed<=u.ap.p2 ){
+ if( pC->nHdrParsed<=p2 ){
/* If there is more header available for parsing in the record, try
- ** to extract additional fields up through the u.ap.p2+1-th field
+ ** to extract additional fields up through the p2+1-th field
*/
- if( u.ap.pC->iHdrOffset<u.ap.aOffset[0] ){
- /* Make sure u.ap.zData points to enough of the record to cover the header. */
- if( u.ap.pC->aRow==0 ){
- memset(&u.ap.sMem, 0, sizeof(u.ap.sMem));
- rc = sqlite3VdbeMemFromBtree(u.ap.pCrsr, 0, u.ap.aOffset[0],
- !u.ap.pC->isTable, &u.ap.sMem);
+ if( pC->iHdrOffset<aOffset[0] ){
+ /* Make sure zData points to enough of the record to cover the header. */
+ if( pC->aRow==0 ){
+ memset(&sMem, 0, sizeof(sMem));
+ rc = sqlite3VdbeMemFromBtree(pCrsr, 0, aOffset[0],
+ !pC->isTable, &sMem);
if( rc!=SQLITE_OK ){
goto op_column_error;
}
- u.ap.zData = (u8*)u.ap.sMem.z;
+ zData = (u8*)sMem.z;
}else{
- u.ap.zData = u.ap.pC->aRow;
+ zData = pC->aRow;
}
-
- /* Fill in u.ap.aType[u.ap.i] and u.ap.aOffset[u.ap.i] values through the u.ap.p2-th field. */
- u.ap.i = u.ap.pC->nHdrParsed;
- u.ap.offset = u.ap.aOffset[u.ap.i];
- u.ap.zHdr = u.ap.zData + u.ap.pC->iHdrOffset;
- u.ap.zEndHdr = u.ap.zData + u.ap.aOffset[0];
- assert( u.ap.i<=u.ap.p2 && u.ap.zHdr<u.ap.zEndHdr );
+
+ /* Fill in aType[i] and aOffset[i] values through the p2-th field. */
+ i = pC->nHdrParsed;
+ offset = aOffset[i];
+ zHdr = zData + pC->iHdrOffset;
+ zEndHdr = zData + aOffset[0];
+ assert( i<=p2 && zHdr<zEndHdr );
do{
- if( u.ap.zHdr[0]<0x80 ){
- u.ap.t = u.ap.zHdr[0];
- u.ap.zHdr++;
+ if( zHdr[0]<0x80 ){
+ t = zHdr[0];
+ zHdr++;
}else{
- u.ap.zHdr += sqlite3GetVarint32(u.ap.zHdr, &u.ap.t);
+ zHdr += sqlite3GetVarint32(zHdr, &t);
}
- u.ap.aType[u.ap.i] = u.ap.t;
- u.ap.szField = sqlite3VdbeSerialTypeLen(u.ap.t);
- u.ap.offset += u.ap.szField;
- if( u.ap.offset<u.ap.szField ){ /* True if u.ap.offset overflows */
- u.ap.zHdr = &u.ap.zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
+ aType[i] = t;
+ szField = sqlite3VdbeSerialTypeLen(t);
+ offset += szField;
+ if( offset<szField ){ /* True if offset overflows */
+ zHdr = &zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
break;
}
- u.ap.i++;
- u.ap.aOffset[u.ap.i] = u.ap.offset;
- }while( u.ap.i<=u.ap.p2 && u.ap.zHdr<u.ap.zEndHdr );
- u.ap.pC->nHdrParsed = u.ap.i;
- u.ap.pC->iHdrOffset = (u32)(u.ap.zHdr - u.ap.zData);
- if( u.ap.pC->aRow==0 ){
- sqlite3VdbeMemRelease(&u.ap.sMem);
- u.ap.sMem.flags = MEM_Null;
+ i++;
+ aOffset[i] = offset;
+ }while( i<=p2 && zHdr<zEndHdr );
+ pC->nHdrParsed = i;
+ pC->iHdrOffset = (u32)(zHdr - zData);
+ if( pC->aRow==0 ){
+ sqlite3VdbeMemRelease(&sMem);
+ sMem.flags = MEM_Null;
}
-
+
/* If we have read more header data than was contained in the header,
** or if the end of the last field appears to be past the end of the
** record, or if the end of the last field appears to be before the end
- ** of the record (when all fields present), then we must be dealing
+ ** of the record (when all fields present), then we must be dealing
** with a corrupt database.
*/
- if( (u.ap.zHdr > u.ap.zEndHdr)
- || (u.ap.offset > u.ap.pC->payloadSize)
- || (u.ap.zHdr==u.ap.zEndHdr && u.ap.offset!=u.ap.pC->payloadSize)
+ if( (zHdr > zEndHdr)
+ || (offset > pC->payloadSize)
+ || (zHdr==zEndHdr && offset!=pC->payloadSize)
){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_error;
@@ -69001,77 +69544,78 @@ case OP_Column: {
}
/* If after trying to extra new entries from the header, nHdrParsed is
- ** still not up to u.ap.p2, that means that the record has fewer than u.ap.p2
+ ** still not up to p2, that means that the record has fewer than p2
** columns. So the result will be either the default value or a NULL.
*/
- if( u.ap.pC->nHdrParsed<=u.ap.p2 ){
+ if( pC->nHdrParsed<=p2 ){
if( pOp->p4type==P4_MEM ){
- sqlite3VdbeMemShallowCopy(u.ap.pDest, pOp->p4.pMem, MEM_Static);
+ sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
}else{
- MemSetTypeFlag(u.ap.pDest, MEM_Null);
+ MemSetTypeFlag(pDest, MEM_Null);
}
goto op_column_out;
}
}
- /* Extract the content for the u.ap.p2+1-th column. Control can only
- ** reach this point if u.ap.aOffset[u.ap.p2], u.ap.aOffset[u.ap.p2+1], and u.ap.aType[u.ap.p2] are
+ /* Extract the content for the p2+1-th column. Control can only
+ ** reach this point if aOffset[p2], aOffset[p2+1], and aType[p2] are
** all valid.
*/
- assert( u.ap.p2<u.ap.pC->nHdrParsed );
+ assert( p2<pC->nHdrParsed );
assert( rc==SQLITE_OK );
- if( u.ap.pC->szRow>=u.ap.aOffset[u.ap.p2+1] ){
+ assert( sqlite3VdbeCheckMemInvariants(pDest) );
+ if( pC->szRow>=aOffset[p2+1] ){
/* This is the common case where the desired content fits on the original
** page - where the content is not on an overflow page */
- VdbeMemRelease(u.ap.pDest);
- sqlite3VdbeSerialGet(u.ap.pC->aRow+u.ap.aOffset[u.ap.p2], u.ap.aType[u.ap.p2], u.ap.pDest);
+ VdbeMemRelease(pDest);
+ sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest);
}else{
/* This branch happens only when content is on overflow pages */
- u.ap.t = u.ap.aType[u.ap.p2];
+ t = aType[p2];
if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
- && ((u.ap.t>=12 && (u.ap.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
- || (u.ap.len = sqlite3VdbeSerialTypeLen(u.ap.t))==0
+ && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
+ || (len = sqlite3VdbeSerialTypeLen(t))==0
){
/* Content is irrelevant for the typeof() function and for
** the length(X) function if X is a blob. So we might as well use
** bogus content rather than reading content from disk. NULL works
- ** for text and blob and whatever is in the u.ap.payloadSize64 variable
+ ** for text and blob and whatever is in the payloadSize64 variable
** will work for everything else. Content is also irrelevant if
** the content length is 0. */
- u.ap.zData = u.ap.t<=13 ? (u8*)&u.ap.payloadSize64 : 0;
- u.ap.sMem.zMalloc = 0;
+ zData = t<=13 ? (u8*)&payloadSize64 : 0;
+ sMem.zMalloc = 0;
}else{
- memset(&u.ap.sMem, 0, sizeof(u.ap.sMem));
- sqlite3VdbeMemMove(&u.ap.sMem, u.ap.pDest);
- rc = sqlite3VdbeMemFromBtree(u.ap.pCrsr, u.ap.aOffset[u.ap.p2], u.ap.len, !u.ap.pC->isTable,
- &u.ap.sMem);
+ memset(&sMem, 0, sizeof(sMem));
+ sqlite3VdbeMemMove(&sMem, pDest);
+ rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable,
+ &sMem);
if( rc!=SQLITE_OK ){
goto op_column_error;
}
- u.ap.zData = (u8*)u.ap.sMem.z;
+ zData = (u8*)sMem.z;
}
- sqlite3VdbeSerialGet(u.ap.zData, u.ap.t, u.ap.pDest);
+ sqlite3VdbeSerialGet(zData, t, pDest);
/* If we dynamically allocated space to hold the data (in the
** sqlite3VdbeMemFromBtree() call above) then transfer control of that
- ** dynamically allocated space over to the u.ap.pDest structure.
+ ** dynamically allocated space over to the pDest structure.
** This prevents a memory copy. */
- if( u.ap.sMem.zMalloc ){
- assert( u.ap.sMem.z==u.ap.sMem.zMalloc );
- assert( !(u.ap.pDest->flags & MEM_Dyn) );
- assert( !(u.ap.pDest->flags & (MEM_Blob|MEM_Str)) || u.ap.pDest->z==u.ap.sMem.z );
- u.ap.pDest->flags &= ~(MEM_Ephem|MEM_Static);
- u.ap.pDest->flags |= MEM_Term;
- u.ap.pDest->z = u.ap.sMem.z;
- u.ap.pDest->zMalloc = u.ap.sMem.zMalloc;
+ if( sMem.zMalloc ){
+ assert( sMem.z==sMem.zMalloc );
+ assert( VdbeMemDynamic(pDest)==0 );
+ assert( (pDest->flags & (MEM_Blob|MEM_Str))==0 || pDest->z==sMem.z );
+ pDest->flags &= ~(MEM_Ephem|MEM_Static);
+ pDest->flags |= MEM_Term;
+ pDest->z = sMem.z;
+ pDest->zMalloc = sMem.zMalloc;
}
}
- u.ap.pDest->enc = encoding;
+ pDest->enc = encoding;
op_column_out:
- rc = sqlite3VdbeMemMakeWriteable(u.ap.pDest);
+ Deephemeralize(pDest);
op_column_error:
- UPDATE_MAX_BLOBSIZE(u.ap.pDest);
- REGISTER_TRACE(pOp->p3, u.ap.pDest);
+ UPDATE_MAX_BLOBSIZE(pDest);
+ REGISTER_TRACE(pOp->p3, pDest);
break;
}
@@ -69085,20 +69629,17 @@ op_column_error:
** memory cell in the range.
*/
case OP_Affinity: {
-#if 0 /* local variables moved into u.aq */
const char *zAffinity; /* The affinity to be applied */
char cAff; /* A single character of affinity */
-#endif /* local variables moved into u.aq */
- u.aq.zAffinity = pOp->p4.z;
- assert( u.aq.zAffinity!=0 );
- assert( u.aq.zAffinity[pOp->p2]==0 );
+ zAffinity = pOp->p4.z;
+ assert( zAffinity!=0 );
+ assert( zAffinity[pOp->p2]==0 );
pIn1 = &aMem[pOp->p1];
- while( (u.aq.cAff = *(u.aq.zAffinity++))!=0 ){
+ while( (cAff = *(zAffinity++))!=0 ){
assert( pIn1 <= &p->aMem[(p->nMem-p->nCursor)] );
assert( memIsValid(pIn1) );
- ExpandBlob(pIn1);
- applyAffinity(pIn1, u.aq.cAff, encoding);
+ applyAffinity(pIn1, cAff, encoding);
pIn1++;
}
break;
@@ -69121,7 +69662,6 @@ case OP_Affinity: {
** If P4 is NULL then all index fields have the affinity NONE.
*/
case OP_MakeRecord: {
-#if 0 /* local variables moved into u.ar */
u8 *zNewRecord; /* A buffer to hold the data for the new record */
Mem *pRec; /* The new record */
u64 nData; /* Number of bytes of data space */
@@ -69135,102 +69675,120 @@ case OP_MakeRecord: {
int nField; /* Number of fields in the record */
char *zAffinity; /* The affinity string for the record */
int file_format; /* File format to use for encoding */
- int i; /* Space used in zNewRecord[] */
+ int i; /* Space used in zNewRecord[] header */
+ int j; /* Space used in zNewRecord[] content */
int len; /* Length of a field */
-#endif /* local variables moved into u.ar */
/* Assuming the record contains N fields, the record format looks
** like this:
**
** ------------------------------------------------------------------------
- ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 |
+ ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 |
** ------------------------------------------------------------------------
**
** Data(0) is taken from register P1. Data(1) comes from register P1+1
** and so froth.
**
- ** Each type field is a varint representing the serial type of the
+ ** Each type field is a varint representing the serial type of the
** corresponding data element (see sqlite3VdbeSerialType()). The
** hdr-size field is also a varint which is the offset from the beginning
** of the record to data0.
*/
- u.ar.nData = 0; /* Number of bytes of data space */
- u.ar.nHdr = 0; /* Number of bytes of header space */
- u.ar.nZero = 0; /* Number of zero bytes at the end of the record */
- u.ar.nField = pOp->p1;
- u.ar.zAffinity = pOp->p4.z;
- assert( u.ar.nField>0 && pOp->p2>0 && pOp->p2+u.ar.nField<=(p->nMem-p->nCursor)+1 );
- u.ar.pData0 = &aMem[u.ar.nField];
- u.ar.nField = pOp->p2;
- u.ar.pLast = &u.ar.pData0[u.ar.nField-1];
- u.ar.file_format = p->minWriteFileFormat;
+ nData = 0; /* Number of bytes of data space */
+ nHdr = 0; /* Number of bytes of header space */
+ nZero = 0; /* Number of zero bytes at the end of the record */
+ nField = pOp->p1;
+ zAffinity = pOp->p4.z;
+ assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=(p->nMem-p->nCursor)+1 );
+ pData0 = &aMem[nField];
+ nField = pOp->p2;
+ pLast = &pData0[nField-1];
+ file_format = p->minWriteFileFormat;
/* Identify the output register */
assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
pOut = &aMem[pOp->p3];
memAboutToChange(p, pOut);
+ /* Apply the requested affinity to all inputs
+ */
+ assert( pData0<=pLast );
+ if( zAffinity ){
+ pRec = pData0;
+ do{
+ applyAffinity(pRec++, *(zAffinity++), encoding);
+ assert( zAffinity[0]==0 || pRec<=pLast );
+ }while( zAffinity[0] );
+ }
+
/* Loop through the elements that will make up the record to figure
** out how much space is required for the new record.
*/
- for(u.ar.pRec=u.ar.pData0; u.ar.pRec<=u.ar.pLast; u.ar.pRec++){
- assert( memIsValid(u.ar.pRec) );
- if( u.ar.zAffinity ){
- applyAffinity(u.ar.pRec, u.ar.zAffinity[u.ar.pRec-u.ar.pData0], encoding);
- }
- if( u.ar.pRec->flags&MEM_Zero && u.ar.pRec->n>0 ){
- sqlite3VdbeMemExpandBlob(u.ar.pRec);
- }
- u.ar.serial_type = sqlite3VdbeSerialType(u.ar.pRec, u.ar.file_format);
- u.ar.len = sqlite3VdbeSerialTypeLen(u.ar.serial_type);
- u.ar.nData += u.ar.len;
- u.ar.nHdr += sqlite3VarintLen(u.ar.serial_type);
- if( u.ar.pRec->flags & MEM_Zero ){
- /* Only pure zero-filled BLOBs can be input to this Opcode.
- ** We do not allow blobs with a prefix and a zero-filled tail. */
- u.ar.nZero += u.ar.pRec->u.nZero;
- }else if( u.ar.len ){
- u.ar.nZero = 0;
+ pRec = pLast;
+ do{
+ assert( memIsValid(pRec) );
+ serial_type = sqlite3VdbeSerialType(pRec, file_format);
+ len = sqlite3VdbeSerialTypeLen(serial_type);
+ if( pRec->flags & MEM_Zero ){
+ if( nData ){
+ sqlite3VdbeMemExpandBlob(pRec);
+ }else{
+ nZero += pRec->u.nZero;
+ len -= pRec->u.nZero;
+ }
}
- }
+ nData += len;
+ testcase( serial_type==127 );
+ testcase( serial_type==128 );
+ nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
+ }while( (--pRec)>=pData0 );
/* Add the initial header varint and total the size */
- u.ar.nHdr += u.ar.nVarint = sqlite3VarintLen(u.ar.nHdr);
- if( u.ar.nVarint<sqlite3VarintLen(u.ar.nHdr) ){
- u.ar.nHdr++;
- }
- u.ar.nByte = u.ar.nHdr+u.ar.nData-u.ar.nZero;
- if( u.ar.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ testcase( nHdr==126 );
+ testcase( nHdr==127 );
+ if( nHdr<=126 ){
+ /* The common case */
+ nHdr += 1;
+ }else{
+ /* Rare case of a really large header */
+ nVarint = sqlite3VarintLen(nHdr);
+ nHdr += nVarint;
+ if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++;
+ }
+ nByte = nHdr+nData;
+ if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
- /* Make sure the output register has a buffer large enough to store
+ /* Make sure the output register has a buffer large enough to store
** the new record. The output register (pOp->p3) is not allowed to
** be one of the input registers (because the following call to
** sqlite3VdbeMemGrow() could clobber the value before it is used).
*/
- if( sqlite3VdbeMemGrow(pOut, (int)u.ar.nByte, 0) ){
+ if( sqlite3VdbeMemGrow(pOut, (int)nByte, 0) ){
goto no_mem;
}
- u.ar.zNewRecord = (u8 *)pOut->z;
+ zNewRecord = (u8 *)pOut->z;
/* Write the record */
- u.ar.i = putVarint32(u.ar.zNewRecord, u.ar.nHdr);
- for(u.ar.pRec=u.ar.pData0; u.ar.pRec<=u.ar.pLast; u.ar.pRec++){
- u.ar.serial_type = sqlite3VdbeSerialType(u.ar.pRec, u.ar.file_format);
- u.ar.i += putVarint32(&u.ar.zNewRecord[u.ar.i], u.ar.serial_type); /* serial type */
- }
- for(u.ar.pRec=u.ar.pData0; u.ar.pRec<=u.ar.pLast; u.ar.pRec++){ /* serial data */
- u.ar.i += sqlite3VdbeSerialPut(&u.ar.zNewRecord[u.ar.i], (int)(u.ar.nByte-u.ar.i), u.ar.pRec,u.ar.file_format);
- }
- assert( u.ar.i==u.ar.nByte );
+ i = putVarint32(zNewRecord, nHdr);
+ j = nHdr;
+ assert( pData0<=pLast );
+ pRec = pData0;
+ do{
+ serial_type = sqlite3VdbeSerialType(pRec, file_format);
+ i += putVarint32(&zNewRecord[i], serial_type); /* serial type */
+ j += sqlite3VdbeSerialPut(&zNewRecord[j], pRec, serial_type); /* content */
+ }while( (++pRec)<=pLast );
+ assert( i==nHdr );
+ assert( j==nByte );
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
- pOut->n = (int)u.ar.nByte;
- pOut->flags = MEM_Blob | MEM_Dyn;
+ pOut->n = (int)nByte;
+ pOut->flags = MEM_Blob;
pOut->xDel = 0;
- if( u.ar.nZero ){
- pOut->u.nZero = u.ar.nZero;
+ if( nZero ){
+ pOut->u.nZero = nZero;
pOut->flags |= MEM_Zero;
}
pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */
@@ -69247,15 +69805,14 @@ case OP_MakeRecord: {
*/
#ifndef SQLITE_OMIT_BTREECOUNT
case OP_Count: { /* out2-prerelease */
-#if 0 /* local variables moved into u.as */
i64 nEntry;
BtCursor *pCrsr;
-#endif /* local variables moved into u.as */
- u.as.pCrsr = p->apCsr[pOp->p1]->pCursor;
- assert( u.as.pCrsr );
- rc = sqlite3BtreeCount(u.as.pCrsr, &u.as.nEntry);
- pOut->u.i = u.as.nEntry;
+ pCrsr = p->apCsr[pOp->p1]->pCursor;
+ assert( pCrsr );
+ nEntry = 0; /* Not needed. Only used to silence a warning. */
+ rc = sqlite3BtreeCount(pCrsr, &nEntry);
+ pOut->u.i = nEntry;
break;
}
#endif
@@ -69267,7 +69824,6 @@ case OP_Count: { /* out2-prerelease */
** existing savepoint, P1==1, or to rollback an existing savepoint P1==2.
*/
case OP_Savepoint: {
-#if 0 /* local variables moved into u.at */
int p1; /* Value of P1 operand */
char *zName; /* Name of savepoint */
int nName;
@@ -69276,30 +69832,29 @@ case OP_Savepoint: {
Savepoint *pTmp;
int iSavepoint;
int ii;
-#endif /* local variables moved into u.at */
- u.at.p1 = pOp->p1;
- u.at.zName = pOp->p4.z;
+ p1 = pOp->p1;
+ zName = pOp->p4.z;
- /* Assert that the u.at.p1 parameter is valid. Also that if there is no open
- ** transaction, then there cannot be any savepoints.
+ /* Assert that the p1 parameter is valid. Also that if there is no open
+ ** transaction, then there cannot be any savepoints.
*/
assert( db->pSavepoint==0 || db->autoCommit==0 );
- assert( u.at.p1==SAVEPOINT_BEGIN||u.at.p1==SAVEPOINT_RELEASE||u.at.p1==SAVEPOINT_ROLLBACK );
+ assert( p1==SAVEPOINT_BEGIN||p1==SAVEPOINT_RELEASE||p1==SAVEPOINT_ROLLBACK );
assert( db->pSavepoint || db->isTransactionSavepoint==0 );
assert( checkSavepointCount(db) );
assert( p->bIsReader );
- if( u.at.p1==SAVEPOINT_BEGIN ){
+ if( p1==SAVEPOINT_BEGIN ){
if( db->nVdbeWrite>0 ){
- /* A new savepoint cannot be created if there are active write
+ /* A new savepoint cannot be created if there are active write
** statements (i.e. open read/write incremental blob handles).
*/
sqlite3SetString(&p->zErrMsg, db, "cannot open savepoint - "
"SQL statements in progress");
rc = SQLITE_BUSY;
}else{
- u.at.nName = sqlite3Strlen30(u.at.zName);
+ nName = sqlite3Strlen30(zName);
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* This call is Ok even if this savepoint is actually a transaction
@@ -69313,11 +69868,11 @@ case OP_Savepoint: {
#endif
/* Create a new savepoint structure. */
- u.at.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.at.nName+1);
- if( u.at.pNew ){
- u.at.pNew->zName = (char *)&u.at.pNew[1];
- memcpy(u.at.pNew->zName, u.at.zName, u.at.nName+1);
-
+ pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+nName+1);
+ if( pNew ){
+ pNew->zName = (char *)&pNew[1];
+ memcpy(pNew->zName, zName, nName+1);
+
/* If there is no open transaction, then mark this as a special
** "transaction savepoint". */
if( db->autoCommit ){
@@ -69326,45 +69881,45 @@ case OP_Savepoint: {
}else{
db->nSavepoint++;
}
-
+
/* Link the new savepoint into the database handle's list. */
- u.at.pNew->pNext = db->pSavepoint;
- db->pSavepoint = u.at.pNew;
- u.at.pNew->nDeferredCons = db->nDeferredCons;
- u.at.pNew->nDeferredImmCons = db->nDeferredImmCons;
+ pNew->pNext = db->pSavepoint;
+ db->pSavepoint = pNew;
+ pNew->nDeferredCons = db->nDeferredCons;
+ pNew->nDeferredImmCons = db->nDeferredImmCons;
}
}
}else{
- u.at.iSavepoint = 0;
+ iSavepoint = 0;
/* Find the named savepoint. If there is no such savepoint, then an
** an error is returned to the user. */
for(
- u.at.pSavepoint = db->pSavepoint;
- u.at.pSavepoint && sqlite3StrICmp(u.at.pSavepoint->zName, u.at.zName);
- u.at.pSavepoint = u.at.pSavepoint->pNext
+ pSavepoint = db->pSavepoint;
+ pSavepoint && sqlite3StrICmp(pSavepoint->zName, zName);
+ pSavepoint = pSavepoint->pNext
){
- u.at.iSavepoint++;
+ iSavepoint++;
}
- if( !u.at.pSavepoint ){
- sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.at.zName);
+ if( !pSavepoint ){
+ sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", zName);
rc = SQLITE_ERROR;
- }else if( db->nVdbeWrite>0 && u.at.p1==SAVEPOINT_RELEASE ){
- /* It is not possible to release (commit) a savepoint if there are
+ }else if( db->nVdbeWrite>0 && p1==SAVEPOINT_RELEASE ){
+ /* It is not possible to release (commit) a savepoint if there are
** active write statements.
*/
- sqlite3SetString(&p->zErrMsg, db,
+ sqlite3SetString(&p->zErrMsg, db,
"cannot release savepoint - SQL statements in progress"
);
rc = SQLITE_BUSY;
}else{
/* Determine whether or not this is a transaction savepoint. If so,
- ** and this is a RELEASE command, then the current transaction
- ** is committed.
+ ** and this is a RELEASE command, then the current transaction
+ ** is committed.
*/
- int isTransaction = u.at.pSavepoint->pNext==0 && db->isTransactionSavepoint;
- if( isTransaction && u.at.p1==SAVEPOINT_RELEASE ){
+ int isTransaction = pSavepoint->pNext==0 && db->isTransactionSavepoint;
+ if( isTransaction && p1==SAVEPOINT_RELEASE ){
if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
goto vdbe_return;
}
@@ -69378,52 +69933,52 @@ case OP_Savepoint: {
db->isTransactionSavepoint = 0;
rc = p->rc;
}else{
- u.at.iSavepoint = db->nSavepoint - u.at.iSavepoint - 1;
- if( u.at.p1==SAVEPOINT_ROLLBACK ){
- for(u.at.ii=0; u.at.ii<db->nDb; u.at.ii++){
- sqlite3BtreeTripAllCursors(db->aDb[u.at.ii].pBt, SQLITE_ABORT);
+ iSavepoint = db->nSavepoint - iSavepoint - 1;
+ if( p1==SAVEPOINT_ROLLBACK ){
+ for(ii=0; ii<db->nDb; ii++){
+ sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT);
}
}
- for(u.at.ii=0; u.at.ii<db->nDb; u.at.ii++){
- rc = sqlite3BtreeSavepoint(db->aDb[u.at.ii].pBt, u.at.p1, u.at.iSavepoint);
+ for(ii=0; ii<db->nDb; ii++){
+ rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
}
- if( u.at.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
+ if( p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
sqlite3ExpirePreparedStatements(db);
sqlite3ResetAllSchemasOfConnection(db);
db->flags = (db->flags | SQLITE_InternChanges);
}
}
-
- /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
+
+ /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
** savepoints nested inside of the savepoint being operated on. */
- while( db->pSavepoint!=u.at.pSavepoint ){
- u.at.pTmp = db->pSavepoint;
- db->pSavepoint = u.at.pTmp->pNext;
- sqlite3DbFree(db, u.at.pTmp);
+ while( db->pSavepoint!=pSavepoint ){
+ pTmp = db->pSavepoint;
+ db->pSavepoint = pTmp->pNext;
+ sqlite3DbFree(db, pTmp);
db->nSavepoint--;
}
- /* If it is a RELEASE, then destroy the savepoint being operated on
- ** too. If it is a ROLLBACK TO, then set the number of deferred
+ /* If it is a RELEASE, then destroy the savepoint being operated on
+ ** too. If it is a ROLLBACK TO, then set the number of deferred
** constraint violations present in the database to the value stored
** when the savepoint was created. */
- if( u.at.p1==SAVEPOINT_RELEASE ){
- assert( u.at.pSavepoint==db->pSavepoint );
- db->pSavepoint = u.at.pSavepoint->pNext;
- sqlite3DbFree(db, u.at.pSavepoint);
+ if( p1==SAVEPOINT_RELEASE ){
+ assert( pSavepoint==db->pSavepoint );
+ db->pSavepoint = pSavepoint->pNext;
+ sqlite3DbFree(db, pSavepoint);
if( !isTransaction ){
db->nSavepoint--;
}
}else{
- db->nDeferredCons = u.at.pSavepoint->nDeferredCons;
- db->nDeferredImmCons = u.at.pSavepoint->nDeferredImmCons;
+ db->nDeferredCons = pSavepoint->nDeferredCons;
+ db->nDeferredImmCons = pSavepoint->nDeferredImmCons;
}
if( !isTransaction ){
- rc = sqlite3VtabSavepoint(db, u.at.p1, u.at.iSavepoint);
+ rc = sqlite3VtabSavepoint(db, p1, iSavepoint);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}
}
@@ -69442,50 +69997,48 @@ case OP_Savepoint: {
** This instruction causes the VM to halt.
*/
case OP_AutoCommit: {
-#if 0 /* local variables moved into u.au */
int desiredAutoCommit;
int iRollback;
int turnOnAC;
-#endif /* local variables moved into u.au */
- u.au.desiredAutoCommit = pOp->p1;
- u.au.iRollback = pOp->p2;
- u.au.turnOnAC = u.au.desiredAutoCommit && !db->autoCommit;
- assert( u.au.desiredAutoCommit==1 || u.au.desiredAutoCommit==0 );
- assert( u.au.desiredAutoCommit==1 || u.au.iRollback==0 );
+ desiredAutoCommit = pOp->p1;
+ iRollback = pOp->p2;
+ turnOnAC = desiredAutoCommit && !db->autoCommit;
+ assert( desiredAutoCommit==1 || desiredAutoCommit==0 );
+ assert( desiredAutoCommit==1 || iRollback==0 );
assert( db->nVdbeActive>0 ); /* At least this one VM is active */
assert( p->bIsReader );
#if 0
- if( u.au.turnOnAC && u.au.iRollback && db->nVdbeActive>1 ){
+ if( turnOnAC && iRollback && db->nVdbeActive>1 ){
/* If this instruction implements a ROLLBACK and other VMs are
** still running, and a transaction is active, return an error indicating
- ** that the other VMs must complete first.
+ ** that the other VMs must complete first.
*/
sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - "
"SQL statements in progress");
rc = SQLITE_BUSY;
}else
#endif
- if( u.au.turnOnAC && !u.au.iRollback && db->nVdbeWrite>0 ){
+ if( turnOnAC && !iRollback && db->nVdbeWrite>0 ){
/* If this instruction implements a COMMIT and other VMs are writing
- ** return an error indicating that the other VMs must complete first.
+ ** return an error indicating that the other VMs must complete first.
*/
sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - "
"SQL statements in progress");
rc = SQLITE_BUSY;
- }else if( u.au.desiredAutoCommit!=db->autoCommit ){
- if( u.au.iRollback ){
- assert( u.au.desiredAutoCommit==1 );
+ }else if( desiredAutoCommit!=db->autoCommit ){
+ if( iRollback ){
+ assert( desiredAutoCommit==1 );
sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
db->autoCommit = 1;
}else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
goto vdbe_return;
}else{
- db->autoCommit = (u8)u.au.desiredAutoCommit;
+ db->autoCommit = (u8)desiredAutoCommit;
if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
p->pc = pc;
- db->autoCommit = (u8)(1-u.au.desiredAutoCommit);
+ db->autoCommit = (u8)(1-desiredAutoCommit);
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
}
@@ -69500,34 +70053,28 @@ case OP_AutoCommit: {
goto vdbe_return;
}else{
sqlite3SetString(&p->zErrMsg, db,
- (!u.au.desiredAutoCommit)?"cannot start a transaction within a transaction":(
- (u.au.iRollback)?"cannot rollback - no transaction is active":
+ (!desiredAutoCommit)?"cannot start a transaction within a transaction":(
+ (iRollback)?"cannot rollback - no transaction is active":
"cannot commit - no transaction is active"));
-
+
rc = SQLITE_ERROR;
}
break;
}
-/* Opcode: Transaction P1 P2 * * *
+/* Opcode: Transaction P1 P2 P3 P4 P5
**
-** Begin a transaction. The transaction ends when a Commit or Rollback
-** opcode is encountered. Depending on the ON CONFLICT setting, the
-** transaction might also be rolled back if an error is encountered.
+** Begin a transaction on database P1 if a transaction is not already
+** active.
+** If P2 is non-zero, then a write-transaction is started, or if a
+** read-transaction is already active, it is upgraded to a write-transaction.
+** If P2 is zero, then a read-transaction is started.
**
** P1 is the index of the database file on which the transaction is
** started. Index 0 is the main database file and index 1 is the
** file used for temporary tables. Indices of 2 or more are used for
** attached databases.
**
-** If P2 is non-zero, then a write-transaction is started. A RESERVED lock is
-** obtained on the database file when a write-transaction is started. No
-** other process can start another write transaction while this transaction is
-** underway. Starting a write transaction also creates a rollback journal. A
-** write transaction must be started before any changes can be made to the
-** database. If P2 is greater than or equal to 2 then an EXCLUSIVE lock is
-** also obtained on the file.
-**
** If a write-transaction is started and the Vdbe.usesStmtJournal flag is
** true (this flag is set if the Vdbe may modify more than one row and may
** throw an ABORT exception), a statement transaction may also be opened.
@@ -69538,12 +70085,21 @@ case OP_AutoCommit: {
** entire transaction. If no error is encountered, the statement transaction
** will automatically commit when the VDBE halts.
**
-** If P2 is zero, then a read-lock is obtained on the database file.
+** If P5!=0 then this opcode also checks the schema cookie against P3
+** and the schema generation counter against P4.
+** The cookie changes its value whenever the database schema changes.
+** This operation is used to detect when that the cookie has changed
+** and that the current process needs to reread the schema. If the schema
+** cookie in P3 differs from the schema cookie in the database header or
+** if the schema generation counter in P4 differs from the current
+** generation counter, then an SQLITE_SCHEMA error is raised and execution
+** halts. The sqlite3_step() wrapper function might then reprepare the
+** statement and rerun it from the beginning.
*/
case OP_Transaction: {
-#if 0 /* local variables moved into u.av */
Btree *pBt;
-#endif /* local variables moved into u.av */
+ int iMeta;
+ int iGen;
assert( p->bIsReader );
assert( p->readOnly==0 || pOp->p2==0 );
@@ -69553,10 +70109,10 @@ case OP_Transaction: {
rc = SQLITE_READONLY;
goto abort_due_to_error;
}
- u.av.pBt = db->aDb[pOp->p1].pBt;
+ pBt = db->aDb[pOp->p1].pBt;
- if( u.av.pBt ){
- rc = sqlite3BtreeBeginTrans(u.av.pBt, pOp->p2);
+ if( pBt ){
+ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2);
if( rc==SQLITE_BUSY ){
p->pc = pc;
p->rc = rc = SQLITE_BUSY;
@@ -69566,19 +70122,19 @@ case OP_Transaction: {
goto abort_due_to_error;
}
- if( pOp->p2 && p->usesStmtJournal
- && (db->autoCommit==0 || db->nVdbeRead>1)
+ if( pOp->p2 && p->usesStmtJournal
+ && (db->autoCommit==0 || db->nVdbeRead>1)
){
- assert( sqlite3BtreeIsInTrans(u.av.pBt) );
+ assert( sqlite3BtreeIsInTrans(pBt) );
if( p->iStatement==0 ){
assert( db->nStatement>=0 && db->nSavepoint>=0 );
- db->nStatement++;
+ db->nStatement++;
p->iStatement = db->nSavepoint + db->nStatement;
}
rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1);
if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginStmt(u.av.pBt, p->iStatement);
+ rc = sqlite3BtreeBeginStmt(pBt, p->iStatement);
}
/* Store the current value of the database handles deferred constraint
@@ -69587,6 +70143,35 @@ case OP_Transaction: {
p->nStmtDefCons = db->nDeferredCons;
p->nStmtDefImmCons = db->nDeferredImmCons;
}
+
+ /* Gather the schema version number for checking */
+ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
+ iGen = db->aDb[pOp->p1].pSchema->iGeneration;
+ }else{
+ iGen = iMeta = 0;
+ }
+ assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
+ if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
+ /* If the schema-cookie from the database file matches the cookie
+ ** stored with the in-memory representation of the schema, do
+ ** not reload the schema from the database file.
+ **
+ ** If virtual-tables are in use, this is not just an optimization.
+ ** Often, v-tables store their data in other SQLite tables, which
+ ** are queried from within xNext() and other v-table methods using
+ ** prepared queries. If such a query is out-of-date, we do not want to
+ ** discard the database schema, as the user code implementing the
+ ** v-table would have to be ready for the sqlite3_vtab structure itself
+ ** to be invalidated whenever sqlite3_step() is called from within
+ ** a v-table method.
+ */
+ if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
+ sqlite3ResetOneSchema(db, pOp->p1);
+ }
+ p->expired = 1;
+ rc = SQLITE_SCHEMA;
}
break;
}
@@ -69604,22 +70189,20 @@ case OP_Transaction: {
** executing this instruction.
*/
case OP_ReadCookie: { /* out2-prerelease */
-#if 0 /* local variables moved into u.aw */
int iMeta;
int iDb;
int iCookie;
-#endif /* local variables moved into u.aw */
assert( p->bIsReader );
- u.aw.iDb = pOp->p1;
- u.aw.iCookie = pOp->p3;
+ iDb = pOp->p1;
+ iCookie = pOp->p3;
assert( pOp->p3<SQLITE_N_BTREE_META );
- assert( u.aw.iDb>=0 && u.aw.iDb<db->nDb );
- assert( db->aDb[u.aw.iDb].pBt!=0 );
- assert( (p->btreeMask & (((yDbMask)1)<<u.aw.iDb))!=0 );
+ assert( iDb>=0 && iDb<db->nDb );
+ assert( db->aDb[iDb].pBt!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
- sqlite3BtreeGetMeta(db->aDb[u.aw.iDb].pBt, u.aw.iCookie, (u32 *)&u.aw.iMeta);
- pOut->u.i = u.aw.iMeta;
+ sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta);
+ pOut->u.i = iMeta;
break;
}
@@ -69634,27 +70217,25 @@ case OP_ReadCookie: { /* out2-prerelease */
** A transaction must be started before executing this opcode.
*/
case OP_SetCookie: { /* in3 */
-#if 0 /* local variables moved into u.ax */
Db *pDb;
-#endif /* local variables moved into u.ax */
assert( pOp->p2<SQLITE_N_BTREE_META );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
assert( p->readOnly==0 );
- u.ax.pDb = &db->aDb[pOp->p1];
- assert( u.ax.pDb->pBt!=0 );
+ pDb = &db->aDb[pOp->p1];
+ assert( pDb->pBt!=0 );
assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
pIn3 = &aMem[pOp->p3];
sqlite3VdbeMemIntegerify(pIn3);
/* See note about index shifting on OP_ReadCookie */
- rc = sqlite3BtreeUpdateMeta(u.ax.pDb->pBt, pOp->p2, (int)pIn3->u.i);
+ rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, (int)pIn3->u.i);
if( pOp->p2==BTREE_SCHEMA_VERSION ){
/* When the schema cookie changes, record the new cookie internally */
- u.ax.pDb->pSchema->schema_cookie = (int)pIn3->u.i;
+ pDb->pSchema->schema_cookie = (int)pIn3->u.i;
db->flags |= SQLITE_InternChanges;
}else if( pOp->p2==BTREE_FILE_FORMAT ){
/* Record changes in the file format */
- u.ax.pDb->pSchema->file_format = (u8)pIn3->u.i;
+ pDb->pSchema->file_format = (u8)pIn3->u.i;
}
if( pOp->p1==1 ){
/* Invalidate all prepared statements whenever the TEMP database
@@ -69665,68 +70246,6 @@ case OP_SetCookie: { /* in3 */
break;
}
-/* Opcode: VerifyCookie P1 P2 P3 * *
-**
-** Check the value of global database parameter number 0 (the
-** schema version) and make sure it is equal to P2 and that the
-** generation counter on the local schema parse equals P3.
-**
-** P1 is the database number which is 0 for the main database file
-** and 1 for the file holding temporary tables and some higher number
-** for auxiliary databases.
-**
-** The cookie changes its value whenever the database schema changes.
-** This operation is used to detect when that the cookie has changed
-** and that the current process needs to reread the schema.
-**
-** Either a transaction needs to have been started or an OP_Open needs
-** to be executed (to establish a read lock) before this opcode is
-** invoked.
-*/
-case OP_VerifyCookie: {
-#if 0 /* local variables moved into u.ay */
- int iMeta;
- int iGen;
- Btree *pBt;
-#endif /* local variables moved into u.ay */
-
- assert( pOp->p1>=0 && pOp->p1<db->nDb );
- assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
- assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
- assert( p->bIsReader );
- u.ay.pBt = db->aDb[pOp->p1].pBt;
- if( u.ay.pBt ){
- sqlite3BtreeGetMeta(u.ay.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.ay.iMeta);
- u.ay.iGen = db->aDb[pOp->p1].pSchema->iGeneration;
- }else{
- u.ay.iGen = u.ay.iMeta = 0;
- }
- if( u.ay.iMeta!=pOp->p2 || u.ay.iGen!=pOp->p3 ){
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
- /* If the schema-cookie from the database file matches the cookie
- ** stored with the in-memory representation of the schema, do
- ** not reload the schema from the database file.
- **
- ** If virtual-tables are in use, this is not just an optimization.
- ** Often, v-tables store their data in other SQLite tables, which
- ** are queried from within xNext() and other v-table methods using
- ** prepared queries. If such a query is out-of-date, we do not want to
- ** discard the database schema, as the user code implementing the
- ** v-table would have to be ready for the sqlite3_vtab structure itself
- ** to be invalidated whenever sqlite3_step() is called from within
- ** a v-table method.
- */
- if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.ay.iMeta ){
- sqlite3ResetOneSchema(db, pOp->p1);
- }
-
- p->expired = 1;
- rc = SQLITE_SCHEMA;
- }
- break;
-}
-
/* Opcode: OpenRead P1 P2 P3 P4 P5
** Synopsis: root=P2 iDb=P3
**
@@ -69780,7 +70299,6 @@ case OP_VerifyCookie: {
*/
case OP_OpenRead:
case OP_OpenWrite: {
-#if 0 /* local variables moved into u.az */
int nField;
KeyInfo *pKeyInfo;
int p2;
@@ -69789,7 +70307,6 @@ case OP_OpenWrite: {
Btree *pX;
VdbeCursor *pCur;
Db *pDb;
-#endif /* local variables moved into u.az */
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
@@ -69801,60 +70318,60 @@ case OP_OpenWrite: {
break;
}
- u.az.nField = 0;
- u.az.pKeyInfo = 0;
- u.az.p2 = pOp->p2;
- u.az.iDb = pOp->p3;
- assert( u.az.iDb>=0 && u.az.iDb<db->nDb );
- assert( (p->btreeMask & (((yDbMask)1)<<u.az.iDb))!=0 );
- u.az.pDb = &db->aDb[u.az.iDb];
- u.az.pX = u.az.pDb->pBt;
- assert( u.az.pX!=0 );
+ nField = 0;
+ pKeyInfo = 0;
+ p2 = pOp->p2;
+ iDb = pOp->p3;
+ assert( iDb>=0 && iDb<db->nDb );
+ assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
+ pDb = &db->aDb[iDb];
+ pX = pDb->pBt;
+ assert( pX!=0 );
if( pOp->opcode==OP_OpenWrite ){
- u.az.wrFlag = 1;
- assert( sqlite3SchemaMutexHeld(db, u.az.iDb, 0) );
- if( u.az.pDb->pSchema->file_format < p->minWriteFileFormat ){
- p->minWriteFileFormat = u.az.pDb->pSchema->file_format;
+ wrFlag = 1;
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ if( pDb->pSchema->file_format < p->minWriteFileFormat ){
+ p->minWriteFileFormat = pDb->pSchema->file_format;
}
}else{
- u.az.wrFlag = 0;
+ wrFlag = 0;
}
if( pOp->p5 & OPFLAG_P2ISREG ){
- assert( u.az.p2>0 );
- assert( u.az.p2<=(p->nMem-p->nCursor) );
- pIn2 = &aMem[u.az.p2];
+ assert( p2>0 );
+ assert( p2<=(p->nMem-p->nCursor) );
+ pIn2 = &aMem[p2];
assert( memIsValid(pIn2) );
assert( (pIn2->flags & MEM_Int)!=0 );
sqlite3VdbeMemIntegerify(pIn2);
- u.az.p2 = (int)pIn2->u.i;
- /* The u.az.p2 value always comes from a prior OP_CreateTable opcode and
- ** that opcode will always set the u.az.p2 value to 2 or more or else fail.
+ p2 = (int)pIn2->u.i;
+ /* The p2 value always comes from a prior OP_CreateTable opcode and
+ ** that opcode will always set the p2 value to 2 or more or else fail.
** If there were a failure, the prepared statement would have halted
** before reaching this instruction. */
- if( NEVER(u.az.p2<2) ) {
+ if( NEVER(p2<2) ) {
rc = SQLITE_CORRUPT_BKPT;
goto abort_due_to_error;
}
}
if( pOp->p4type==P4_KEYINFO ){
- u.az.pKeyInfo = pOp->p4.pKeyInfo;
- assert( u.az.pKeyInfo->enc==ENC(db) );
- assert( u.az.pKeyInfo->db==db );
- u.az.nField = u.az.pKeyInfo->nField+u.az.pKeyInfo->nXField;
+ pKeyInfo = pOp->p4.pKeyInfo;
+ assert( pKeyInfo->enc==ENC(db) );
+ assert( pKeyInfo->db==db );
+ nField = pKeyInfo->nField+pKeyInfo->nXField;
}else if( pOp->p4type==P4_INT32 ){
- u.az.nField = pOp->p4.i;
+ nField = pOp->p4.i;
}
assert( pOp->p1>=0 );
- assert( u.az.nField>=0 );
- testcase( u.az.nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */
- u.az.pCur = allocateCursor(p, pOp->p1, u.az.nField, u.az.iDb, 1);
- if( u.az.pCur==0 ) goto no_mem;
- u.az.pCur->nullRow = 1;
- u.az.pCur->isOrdered = 1;
- rc = sqlite3BtreeCursor(u.az.pX, u.az.p2, u.az.wrFlag, u.az.pKeyInfo, u.az.pCur->pCursor);
- u.az.pCur->pKeyInfo = u.az.pKeyInfo;
+ assert( nField>=0 );
+ testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */
+ pCur = allocateCursor(p, pOp->p1, nField, iDb, 1);
+ if( pCur==0 ) goto no_mem;
+ pCur->nullRow = 1;
+ pCur->isOrdered = 1;
+ rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
+ pCur->pKeyInfo = pKeyInfo;
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
- sqlite3BtreeCursorHints(u.az.pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
+ sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
/* Since it performs no memory allocation or IO, the only value that
** sqlite3BtreeCursor() may return is SQLITE_OK. */
@@ -69863,8 +70380,8 @@ case OP_OpenWrite: {
/* Set the VdbeCursor.isTable variable. Previous versions of
** SQLite used to check if the root-page flags were sane at this point
** and report database corruption if they were not, but this check has
- ** since moved into the btree layer. */
- u.az.pCur->isTable = pOp->p4type!=P4_KEYINFO;
+ ** since moved into the btree layer. */
+ pCur->isTable = pOp->p4type!=P4_KEYINFO;
break;
}
@@ -69896,12 +70413,10 @@ case OP_OpenWrite: {
*/
case OP_OpenAutoindex:
case OP_OpenEphemeral: {
-#if 0 /* local variables moved into u.ba */
VdbeCursor *pCx;
KeyInfo *pKeyInfo;
-#endif /* local variables moved into u.ba */
- static const int vfsFlags =
+ static const int vfsFlags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
SQLITE_OPEN_EXCLUSIVE |
@@ -69909,13 +70424,13 @@ case OP_OpenEphemeral: {
SQLITE_OPEN_TRANSIENT_DB;
assert( pOp->p1>=0 );
assert( pOp->p2>=0 );
- u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
- if( u.ba.pCx==0 ) goto no_mem;
- u.ba.pCx->nullRow = 1;
- rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ba.pCx->pBt,
+ pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+ if( pCx==0 ) goto no_mem;
+ pCx->nullRow = 1;
+ rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt,
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginTrans(u.ba.pCx->pBt, 1);
+ rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
}
if( rc==SQLITE_OK ){
/* If a transient index is required, create it by calling
@@ -69923,57 +70438,54 @@ case OP_OpenEphemeral: {
** opening it. If a transient table is required, just use the
** automatically created table with root-page 1 (an BLOB_INTKEY table).
*/
- if( (u.ba.pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
+ if( (pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
int pgno;
assert( pOp->p4type==P4_KEYINFO );
- rc = sqlite3BtreeCreateTable(u.ba.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
+ rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
if( rc==SQLITE_OK ){
assert( pgno==MASTER_ROOT+1 );
- assert( u.ba.pKeyInfo->db==db );
- assert( u.ba.pKeyInfo->enc==ENC(db) );
- u.ba.pCx->pKeyInfo = u.ba.pKeyInfo;
- rc = sqlite3BtreeCursor(u.ba.pCx->pBt, pgno, 1, u.ba.pKeyInfo, u.ba.pCx->pCursor);
+ assert( pKeyInfo->db==db );
+ assert( pKeyInfo->enc==ENC(db) );
+ pCx->pKeyInfo = pKeyInfo;
+ rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, pKeyInfo, pCx->pCursor);
}
- u.ba.pCx->isTable = 0;
+ pCx->isTable = 0;
}else{
- rc = sqlite3BtreeCursor(u.ba.pCx->pBt, MASTER_ROOT, 1, 0, u.ba.pCx->pCursor);
- u.ba.pCx->isTable = 1;
+ rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor);
+ pCx->isTable = 1;
}
}
- u.ba.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
+ pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
break;
}
-/* Opcode: SorterOpen P1 * * P4 *
+/* Opcode: SorterOpen P1 P2 * P4 *
**
** This opcode works like OP_OpenEphemeral except that it opens
** a transient index that is specifically designed to sort large
** tables using an external merge-sort algorithm.
*/
case OP_SorterOpen: {
-#if 0 /* local variables moved into u.bb */
VdbeCursor *pCx;
-#endif /* local variables moved into u.bb */
assert( pOp->p1>=0 );
assert( pOp->p2>=0 );
- u.bb.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
- if( u.bb.pCx==0 ) goto no_mem;
- u.bb.pCx->pKeyInfo = pOp->p4.pKeyInfo;
- assert( u.bb.pCx->pKeyInfo->db==db );
- assert( u.bb.pCx->pKeyInfo->enc==ENC(db) );
- rc = sqlite3VdbeSorterInit(db, u.bb.pCx);
+ pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+ if( pCx==0 ) goto no_mem;
+ pCx->pKeyInfo = pOp->p4.pKeyInfo;
+ assert( pCx->pKeyInfo->db==db );
+ assert( pCx->pKeyInfo->enc==ENC(db) );
+ rc = sqlite3VdbeSorterInit(db, pCx);
break;
}
-/* Opcode: OpenPseudo P1 P2 P3 * P5
-** Synopsis: content in r[P2@P3]
+/* Opcode: OpenPseudo P1 P2 P3 * *
+** Synopsis: P3 columns in r[P2]
**
** Open a new cursor that points to a fake table that contains a single
-** row of data. The content of that one row in the content of memory
-** register P2 when P5==0. In other words, cursor P1 becomes an alias for the
-** MEM_Blob content contained in register P2. When P5==1, then the
-** row is represented by P3 consecutive registers beginning with P2.
+** row of data. The content of that one row is the content of memory
+** register P2. In other words, cursor P1 becomes an alias for the
+** MEM_Blob content contained in register P2.
**
** A pseudo-table created by this opcode is used to hold a single
** row output from the sorter so that the row can be decomposed into
@@ -69984,18 +70496,16 @@ case OP_SorterOpen: {
** the pseudo-table.
*/
case OP_OpenPseudo: {
-#if 0 /* local variables moved into u.bc */
VdbeCursor *pCx;
-#endif /* local variables moved into u.bc */
assert( pOp->p1>=0 );
assert( pOp->p3>=0 );
- u.bc.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
- if( u.bc.pCx==0 ) goto no_mem;
- u.bc.pCx->nullRow = 1;
- u.bc.pCx->pseudoTableReg = pOp->p2;
- u.bc.pCx->isTable = 1;
- u.bc.pCx->multiPseudo = pOp->p5;
+ pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
+ if( pCx==0 ) goto no_mem;
+ pCx->nullRow = 1;
+ pCx->pseudoTableReg = pOp->p2;
+ pCx->isTable = 1;
+ assert( pOp->p5==0 );
break;
}
@@ -70067,39 +70577,37 @@ case OP_Close: {
**
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt
*/
-case OP_SeekLt: /* jump, in3 */
-case OP_SeekLe: /* jump, in3 */
-case OP_SeekGe: /* jump, in3 */
-case OP_SeekGt: { /* jump, in3 */
-#if 0 /* local variables moved into u.bd */
+case OP_SeekLT: /* jump, in3 */
+case OP_SeekLE: /* jump, in3 */
+case OP_SeekGE: /* jump, in3 */
+case OP_SeekGT: { /* jump, in3 */
int res;
int oc;
VdbeCursor *pC;
UnpackedRecord r;
int nField;
i64 iKey; /* The rowid we are to seek to */
-#endif /* local variables moved into u.bd */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p2!=0 );
- u.bd.pC = p->apCsr[pOp->p1];
- assert( u.bd.pC!=0 );
- assert( u.bd.pC->pseudoTableReg==0 );
- assert( OP_SeekLe == OP_SeekLt+1 );
- assert( OP_SeekGe == OP_SeekLt+2 );
- assert( OP_SeekGt == OP_SeekLt+3 );
- assert( u.bd.pC->isOrdered );
- assert( u.bd.pC->pCursor!=0 );
- u.bd.oc = pOp->opcode;
- u.bd.pC->nullRow = 0;
- if( u.bd.pC->isTable ){
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( pC->pseudoTableReg==0 );
+ assert( OP_SeekLE == OP_SeekLT+1 );
+ assert( OP_SeekGE == OP_SeekLT+2 );
+ assert( OP_SeekGT == OP_SeekLT+3 );
+ assert( pC->isOrdered );
+ assert( pC->pCursor!=0 );
+ oc = pOp->opcode;
+ pC->nullRow = 0;
+ if( pC->isTable ){
/* The input value in P3 might be of any type: integer, real, string,
** blob, or NULL. But it needs to be an integer before we can do
** the seek, so covert it. */
pIn3 = &aMem[pOp->p3];
applyNumericAffinity(pIn3);
- u.bd.iKey = sqlite3VdbeIntValue(pIn3);
- u.bd.pC->rowidIsValid = 0;
+ iKey = sqlite3VdbeIntValue(pIn3);
+ pC->rowidIsValid = 0;
/* If the P3 value could not be converted into an integer without
** loss of information, then special processing is required... */
@@ -70107,100 +70615,103 @@ case OP_SeekGt: { /* jump, in3 */
if( (pIn3->flags & MEM_Real)==0 ){
/* If the P3 value cannot be converted into any kind of a number,
** then the seek is not possible, so jump to P2 */
- pc = pOp->p2 - 1;
+ pc = pOp->p2 - 1; VdbeBranchTaken(1,2);
break;
}
- /* If the approximation u.bd.iKey is larger than the actual real search
+ /* If the approximation iKey is larger than the actual real search
** term, substitute >= for > and < for <=. e.g. if the search term
** is 4.9 and the integer approximation 5:
**
** (x > 4.9) -> (x >= 5)
** (x <= 4.9) -> (x < 5)
*/
- if( pIn3->r<(double)u.bd.iKey ){
- assert( OP_SeekGe==(OP_SeekGt-1) );
- assert( OP_SeekLt==(OP_SeekLe-1) );
- assert( (OP_SeekLe & 0x0001)==(OP_SeekGt & 0x0001) );
- if( (u.bd.oc & 0x0001)==(OP_SeekGt & 0x0001) ) u.bd.oc--;
+ if( pIn3->r<(double)iKey ){
+ assert( OP_SeekGE==(OP_SeekGT-1) );
+ assert( OP_SeekLT==(OP_SeekLE-1) );
+ assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) );
+ if( (oc & 0x0001)==(OP_SeekGT & 0x0001) ) oc--;
}
- /* If the approximation u.bd.iKey is smaller than the actual real search
+ /* If the approximation iKey is smaller than the actual real search
** term, substitute <= for < and > for >=. */
- else if( pIn3->r>(double)u.bd.iKey ){
- assert( OP_SeekLe==(OP_SeekLt+1) );
- assert( OP_SeekGt==(OP_SeekGe+1) );
- assert( (OP_SeekLt & 0x0001)==(OP_SeekGe & 0x0001) );
- if( (u.bd.oc & 0x0001)==(OP_SeekLt & 0x0001) ) u.bd.oc++;
+ else if( pIn3->r>(double)iKey ){
+ assert( OP_SeekLE==(OP_SeekLT+1) );
+ assert( OP_SeekGT==(OP_SeekGE+1) );
+ assert( (OP_SeekLT & 0x0001)==(OP_SeekGE & 0x0001) );
+ if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++;
}
- }
- rc = sqlite3BtreeMovetoUnpacked(u.bd.pC->pCursor, 0, (u64)u.bd.iKey, 0, &u.bd.res);
+ }
+ rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- if( u.bd.res==0 ){
- u.bd.pC->rowidIsValid = 1;
- u.bd.pC->lastRowid = u.bd.iKey;
+ if( res==0 ){
+ pC->rowidIsValid = 1;
+ pC->lastRowid = iKey;
}
}else{
- u.bd.nField = pOp->p4.i;
+ nField = pOp->p4.i;
assert( pOp->p4type==P4_INT32 );
- assert( u.bd.nField>0 );
- u.bd.r.pKeyInfo = u.bd.pC->pKeyInfo;
- u.bd.r.nField = (u16)u.bd.nField;
+ assert( nField>0 );
+ r.pKeyInfo = pC->pKeyInfo;
+ r.nField = (u16)nField;
/* The next line of code computes as follows, only faster:
- ** if( u.bd.oc==OP_SeekGt || u.bd.oc==OP_SeekLe ){
- ** u.bd.r.flags = UNPACKED_INCRKEY;
+ ** if( oc==OP_SeekGT || oc==OP_SeekLE ){
+ ** r.default_rc = -1;
** }else{
- ** u.bd.r.flags = 0;
+ ** r.default_rc = +1;
** }
*/
- u.bd.r.flags = (u8)(UNPACKED_INCRKEY * (1 & (u.bd.oc - OP_SeekLt)));
- assert( u.bd.oc!=OP_SeekGt || u.bd.r.flags==UNPACKED_INCRKEY );
- assert( u.bd.oc!=OP_SeekLe || u.bd.r.flags==UNPACKED_INCRKEY );
- assert( u.bd.oc!=OP_SeekGe || u.bd.r.flags==0 );
- assert( u.bd.oc!=OP_SeekLt || u.bd.r.flags==0 );
+ r.default_rc = ((1 & (oc - OP_SeekLT)) ? -1 : +1);
+ assert( oc!=OP_SeekGT || r.default_rc==-1 );
+ assert( oc!=OP_SeekLE || r.default_rc==-1 );
+ assert( oc!=OP_SeekGE || r.default_rc==+1 );
+ assert( oc!=OP_SeekLT || r.default_rc==+1 );
- u.bd.r.aMem = &aMem[pOp->p3];
+ r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
- { int i; for(i=0; i<u.bd.r.nField; i++) assert( memIsValid(&u.bd.r.aMem[i]) ); }
+ { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
#endif
- ExpandBlob(u.bd.r.aMem);
- rc = sqlite3BtreeMovetoUnpacked(u.bd.pC->pCursor, &u.bd.r, 0, 0, &u.bd.res);
+ ExpandBlob(r.aMem);
+ rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- u.bd.pC->rowidIsValid = 0;
+ pC->rowidIsValid = 0;
}
- u.bd.pC->deferredMoveto = 0;
- u.bd.pC->cacheStatus = CACHE_STALE;
+ pC->deferredMoveto = 0;
+ pC->cacheStatus = CACHE_STALE;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
- if( u.bd.oc>=OP_SeekGe ){ assert( u.bd.oc==OP_SeekGe || u.bd.oc==OP_SeekGt );
- if( u.bd.res<0 || (u.bd.res==0 && u.bd.oc==OP_SeekGt) ){
- rc = sqlite3BtreeNext(u.bd.pC->pCursor, &u.bd.res);
+ if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT );
+ if( res<0 || (res==0 && oc==OP_SeekGT) ){
+ res = 0;
+ rc = sqlite3BtreeNext(pC->pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
- u.bd.pC->rowidIsValid = 0;
+ pC->rowidIsValid = 0;
}else{
- u.bd.res = 0;
+ res = 0;
}
}else{
- assert( u.bd.oc==OP_SeekLt || u.bd.oc==OP_SeekLe );
- if( u.bd.res>0 || (u.bd.res==0 && u.bd.oc==OP_SeekLt) ){
- rc = sqlite3BtreePrevious(u.bd.pC->pCursor, &u.bd.res);
+ assert( oc==OP_SeekLT || oc==OP_SeekLE );
+ if( res>0 || (res==0 && oc==OP_SeekLT) ){
+ res = 0;
+ rc = sqlite3BtreePrevious(pC->pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
- u.bd.pC->rowidIsValid = 0;
+ pC->rowidIsValid = 0;
}else{
- /* u.bd.res might be negative because the table is empty. Check to
+ /* res might be negative because the table is empty. Check to
** see if this is the case.
*/
- u.bd.res = sqlite3BtreeEof(u.bd.pC->pCursor);
+ res = sqlite3BtreeEof(pC->pCursor);
}
}
assert( pOp->p2>0 );
- if( u.bd.res ){
+ VdbeBranchTaken(res!=0,2);
+ if( res ){
pc = pOp->p2 - 1;
}
break;
@@ -70217,20 +70728,18 @@ case OP_SeekGt: { /* jump, in3 */
** occur, no unnecessary I/O happens.
*/
case OP_Seek: { /* in2 */
-#if 0 /* local variables moved into u.be */
VdbeCursor *pC;
-#endif /* local variables moved into u.be */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.be.pC = p->apCsr[pOp->p1];
- assert( u.be.pC!=0 );
- assert( u.be.pC->pCursor!=0 );
- assert( u.be.pC->isTable );
- u.be.pC->nullRow = 0;
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( pC->pCursor!=0 );
+ assert( pC->isTable );
+ pC->nullRow = 0;
pIn2 = &aMem[pOp->p2];
- u.be.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
- u.be.pC->rowidIsValid = 0;
- u.be.pC->deferredMoveto = 1;
+ pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
+ pC->rowidIsValid = 0;
+ pC->deferredMoveto = 1;
break;
}
@@ -70285,7 +70794,6 @@ case OP_Seek: { /* in2 */
case OP_NoConflict: /* jump, in3 */
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
-#if 0 /* local variables moved into u.bf */
int alreadyExists;
int ii;
VdbeCursor *pC;
@@ -70294,72 +70802,70 @@ case OP_Found: { /* jump, in3 */
UnpackedRecord *pIdxKey;
UnpackedRecord r;
char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7];
-#endif /* local variables moved into u.bf */
#ifdef SQLITE_TEST
if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++;
#endif
- u.bf.alreadyExists = 0;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p4type==P4_INT32 );
- u.bf.pC = p->apCsr[pOp->p1];
- assert( u.bf.pC!=0 );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
pIn3 = &aMem[pOp->p3];
- assert( u.bf.pC->pCursor!=0 );
- assert( u.bf.pC->isTable==0 );
+ assert( pC->pCursor!=0 );
+ assert( pC->isTable==0 );
+ pFree = 0; /* Not needed. Only used to suppress a compiler warning. */
if( pOp->p4.i>0 ){
- u.bf.r.pKeyInfo = u.bf.pC->pKeyInfo;
- u.bf.r.nField = (u16)pOp->p4.i;
- u.bf.r.aMem = pIn3;
+ r.pKeyInfo = pC->pKeyInfo;
+ r.nField = (u16)pOp->p4.i;
+ r.aMem = pIn3;
+ for(ii=0; ii<r.nField; ii++){
+ assert( memIsValid(&r.aMem[ii]) );
+ ExpandBlob(&r.aMem[ii]);
#ifdef SQLITE_DEBUG
- {
- int i;
- for(i=0; i<u.bf.r.nField; i++){
- assert( memIsValid(&u.bf.r.aMem[i]) );
- if( i ) REGISTER_TRACE(pOp->p3+i, &u.bf.r.aMem[i]);
- }
- }
+ if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
#endif
- u.bf.r.flags = UNPACKED_PREFIX_MATCH;
- u.bf.pIdxKey = &u.bf.r;
+ }
+ pIdxKey = &r;
}else{
- u.bf.pIdxKey = sqlite3VdbeAllocUnpackedRecord(
- u.bf.pC->pKeyInfo, u.bf.aTempRec, sizeof(u.bf.aTempRec), &u.bf.pFree
- );
- if( u.bf.pIdxKey==0 ) goto no_mem;
+ pIdxKey = sqlite3VdbeAllocUnpackedRecord(
+ pC->pKeyInfo, aTempRec, sizeof(aTempRec), &pFree
+ );
+ if( pIdxKey==0 ) goto no_mem;
assert( pIn3->flags & MEM_Blob );
assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
- sqlite3VdbeRecordUnpack(u.bf.pC->pKeyInfo, pIn3->n, pIn3->z, u.bf.pIdxKey);
- u.bf.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
+ sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
}
+ pIdxKey->default_rc = 0;
if( pOp->opcode==OP_NoConflict ){
/* For the OP_NoConflict opcode, take the jump if any of the
** input fields are NULL, since any key with a NULL will not
** conflict */
- for(u.bf.ii=0; u.bf.ii<u.bf.r.nField; u.bf.ii++){
- if( u.bf.r.aMem[u.bf.ii].flags & MEM_Null ){
- pc = pOp->p2 - 1;
+ for(ii=0; ii<r.nField; ii++){
+ if( r.aMem[ii].flags & MEM_Null ){
+ pc = pOp->p2 - 1; VdbeBranchTaken(1,2);
break;
}
}
}
- rc = sqlite3BtreeMovetoUnpacked(u.bf.pC->pCursor, u.bf.pIdxKey, 0, 0, &u.bf.res);
+ rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res);
if( pOp->p4.i==0 ){
- sqlite3DbFree(db, u.bf.pFree);
+ sqlite3DbFree(db, pFree);
}
if( rc!=SQLITE_OK ){
break;
}
- u.bf.pC->seekResult = u.bf.res;
- u.bf.alreadyExists = (u.bf.res==0);
- u.bf.pC->nullRow = 1-u.bf.alreadyExists;
- u.bf.pC->deferredMoveto = 0;
- u.bf.pC->cacheStatus = CACHE_STALE;
+ pC->seekResult = res;
+ alreadyExists = (res==0);
+ pC->nullRow = 1-alreadyExists;
+ pC->deferredMoveto = 0;
+ pC->cacheStatus = CACHE_STALE;
if( pOp->opcode==OP_Found ){
- if( u.bf.alreadyExists ) pc = pOp->p2 - 1;
+ VdbeBranchTaken(alreadyExists!=0,2);
+ if( alreadyExists ) pc = pOp->p2 - 1;
}else{
- if( !u.bf.alreadyExists ) pc = pOp->p2 - 1;
+ VdbeBranchTaken(alreadyExists==0,2);
+ if( !alreadyExists ) pc = pOp->p2 - 1;
}
break;
}
@@ -70379,35 +70885,34 @@ case OP_Found: { /* jump, in3 */
** See also: Found, NotFound, NoConflict
*/
case OP_NotExists: { /* jump, in3 */
-#if 0 /* local variables moved into u.bg */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
u64 iKey;
-#endif /* local variables moved into u.bg */
pIn3 = &aMem[pOp->p3];
assert( pIn3->flags & MEM_Int );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.bg.pC = p->apCsr[pOp->p1];
- assert( u.bg.pC!=0 );
- assert( u.bg.pC->isTable );
- assert( u.bg.pC->pseudoTableReg==0 );
- u.bg.pCrsr = u.bg.pC->pCursor;
- assert( u.bg.pCrsr!=0 );
- u.bg.res = 0;
- u.bg.iKey = pIn3->u.i;
- rc = sqlite3BtreeMovetoUnpacked(u.bg.pCrsr, 0, u.bg.iKey, 0, &u.bg.res);
- u.bg.pC->lastRowid = pIn3->u.i;
- u.bg.pC->rowidIsValid = u.bg.res==0 ?1:0;
- u.bg.pC->nullRow = 0;
- u.bg.pC->cacheStatus = CACHE_STALE;
- u.bg.pC->deferredMoveto = 0;
- if( u.bg.res!=0 ){
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( pC->isTable );
+ assert( pC->pseudoTableReg==0 );
+ pCrsr = pC->pCursor;
+ assert( pCrsr!=0 );
+ res = 0;
+ iKey = pIn3->u.i;
+ rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
+ pC->lastRowid = pIn3->u.i;
+ pC->rowidIsValid = res==0 ?1:0;
+ pC->nullRow = 0;
+ pC->cacheStatus = CACHE_STALE;
+ pC->deferredMoveto = 0;
+ VdbeBranchTaken(res!=0,2);
+ if( res!=0 ){
pc = pOp->p2 - 1;
- assert( u.bg.pC->rowidIsValid==0 );
+ assert( pC->rowidIsValid==0 );
}
- u.bg.pC->seekResult = u.bg.res;
+ pC->seekResult = res;
break;
}
@@ -70443,21 +70948,19 @@ case OP_Sequence: { /* out2-prerelease */
** AUTOINCREMENT feature.
*/
case OP_NewRowid: { /* out2-prerelease */
-#if 0 /* local variables moved into u.bh */
i64 v; /* The new rowid */
VdbeCursor *pC; /* Cursor of table to get the new rowid */
int res; /* Result of an sqlite3BtreeLast() */
int cnt; /* Counter to limit the number of searches */
Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
VdbeFrame *pFrame; /* Root frame of VDBE */
-#endif /* local variables moved into u.bh */
- u.bh.v = 0;
- u.bh.res = 0;
+ v = 0;
+ res = 0;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.bh.pC = p->apCsr[pOp->p1];
- assert( u.bh.pC!=0 );
- if( NEVER(u.bh.pC->pCursor==0) ){
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ if( NEVER(pC->pCursor==0) ){
/* The zero initialization above is all that is needed */
}else{
/* The next rowid or record number (different terms for the same
@@ -70473,7 +70976,7 @@ case OP_NewRowid: { /* out2-prerelease */
** succeeded. If the random rowid does exist, we select a new one
** and try again, up to 100 times.
*/
- assert( u.bh.pC->isTable );
+ assert( pC->isTable );
#ifdef SQLITE_32BIT_ROWID
# define MAX_ROWID 0x7fffffff
@@ -70485,61 +70988,56 @@ case OP_NewRowid: { /* out2-prerelease */
# define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
#endif
- if( !u.bh.pC->useRandomRowid ){
- u.bh.v = sqlite3BtreeGetCachedRowid(u.bh.pC->pCursor);
- if( u.bh.v==0 ){
- rc = sqlite3BtreeLast(u.bh.pC->pCursor, &u.bh.res);
- if( rc!=SQLITE_OK ){
- goto abort_due_to_error;
- }
- if( u.bh.res ){
- u.bh.v = 1; /* IMP: R-61914-48074 */
+ if( !pC->useRandomRowid ){
+ rc = sqlite3BtreeLast(pC->pCursor, &res);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
+ if( res ){
+ v = 1; /* IMP: R-61914-48074 */
+ }else{
+ assert( sqlite3BtreeCursorIsValid(pC->pCursor) );
+ rc = sqlite3BtreeKeySize(pC->pCursor, &v);
+ assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */
+ if( v>=MAX_ROWID ){
+ pC->useRandomRowid = 1;
}else{
- assert( sqlite3BtreeCursorIsValid(u.bh.pC->pCursor) );
- rc = sqlite3BtreeKeySize(u.bh.pC->pCursor, &u.bh.v);
- assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */
- if( u.bh.v>=MAX_ROWID ){
- u.bh.pC->useRandomRowid = 1;
- }else{
- u.bh.v++; /* IMP: R-29538-34987 */
- }
+ v++; /* IMP: R-29538-34987 */
}
}
+ }
#ifndef SQLITE_OMIT_AUTOINCREMENT
- if( pOp->p3 ){
+ if( pOp->p3 ){
+ /* Assert that P3 is a valid memory cell. */
+ assert( pOp->p3>0 );
+ if( p->pFrame ){
+ for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
/* Assert that P3 is a valid memory cell. */
- assert( pOp->p3>0 );
- if( p->pFrame ){
- for(u.bh.pFrame=p->pFrame; u.bh.pFrame->pParent; u.bh.pFrame=u.bh.pFrame->pParent);
- /* Assert that P3 is a valid memory cell. */
- assert( pOp->p3<=u.bh.pFrame->nMem );
- u.bh.pMem = &u.bh.pFrame->aMem[pOp->p3];
- }else{
- /* Assert that P3 is a valid memory cell. */
- assert( pOp->p3<=(p->nMem-p->nCursor) );
- u.bh.pMem = &aMem[pOp->p3];
- memAboutToChange(p, u.bh.pMem);
- }
- assert( memIsValid(u.bh.pMem) );
-
- REGISTER_TRACE(pOp->p3, u.bh.pMem);
- sqlite3VdbeMemIntegerify(u.bh.pMem);
- assert( (u.bh.pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
- if( u.bh.pMem->u.i==MAX_ROWID || u.bh.pC->useRandomRowid ){
- rc = SQLITE_FULL; /* IMP: R-12275-61338 */
- goto abort_due_to_error;
- }
- if( u.bh.v<u.bh.pMem->u.i+1 ){
- u.bh.v = u.bh.pMem->u.i + 1;
- }
- u.bh.pMem->u.i = u.bh.v;
+ assert( pOp->p3<=pFrame->nMem );
+ pMem = &pFrame->aMem[pOp->p3];
+ }else{
+ /* Assert that P3 is a valid memory cell. */
+ assert( pOp->p3<=(p->nMem-p->nCursor) );
+ pMem = &aMem[pOp->p3];
+ memAboutToChange(p, pMem);
}
-#endif
+ assert( memIsValid(pMem) );
- sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, u.bh.v<MAX_ROWID ? u.bh.v+1 : 0);
+ REGISTER_TRACE(pOp->p3, pMem);
+ sqlite3VdbeMemIntegerify(pMem);
+ assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
+ if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
+ rc = SQLITE_FULL; /* IMP: R-12275-61338 */
+ goto abort_due_to_error;
+ }
+ if( v<pMem->u.i+1 ){
+ v = pMem->u.i + 1;
+ }
+ pMem->u.i = v;
}
- if( u.bh.pC->useRandomRowid ){
+#endif
+ if( pC->useRandomRowid ){
/* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
** largest possible integer (9223372036854775807) then the database
** engine starts picking positive candidate ROWIDs at random until
@@ -70547,35 +71045,35 @@ case OP_NewRowid: { /* out2-prerelease */
assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
** an AUTOINCREMENT table. */
/* on the first attempt, simply do one more than previous */
- u.bh.v = lastRowid;
- u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
- u.bh.v++; /* ensure non-zero */
- u.bh.cnt = 0;
- while( ((rc = sqlite3BtreeMovetoUnpacked(u.bh.pC->pCursor, 0, (u64)u.bh.v,
- 0, &u.bh.res))==SQLITE_OK)
- && (u.bh.res==0)
- && (++u.bh.cnt<100)){
+ v = lastRowid;
+ v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+ v++; /* ensure non-zero */
+ cnt = 0;
+ while( ((rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)v,
+ 0, &res))==SQLITE_OK)
+ && (res==0)
+ && (++cnt<100)){
/* collision - try another random rowid */
- sqlite3_randomness(sizeof(u.bh.v), &u.bh.v);
- if( u.bh.cnt<5 ){
+ sqlite3_randomness(sizeof(v), &v);
+ if( cnt<5 ){
/* try "small" random rowids for the initial attempts */
- u.bh.v &= 0xffffff;
+ v &= 0xffffff;
}else{
- u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+ v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
}
- u.bh.v++; /* ensure non-zero */
+ v++; /* ensure non-zero */
}
- if( rc==SQLITE_OK && u.bh.res==0 ){
+ if( rc==SQLITE_OK && res==0 ){
rc = SQLITE_FULL; /* IMP: R-38219-53002 */
goto abort_due_to_error;
}
- assert( u.bh.v>0 ); /* EV: R-40812-03570 */
+ assert( v>0 ); /* EV: R-40812-03570 */
}
- u.bh.pC->rowidIsValid = 0;
- u.bh.pC->deferredMoveto = 0;
- u.bh.pC->cacheStatus = CACHE_STALE;
+ pC->rowidIsValid = 0;
+ pC->deferredMoveto = 0;
+ pC->cacheStatus = CACHE_STALE;
}
- pOut->u.i = u.bh.v;
+ pOut->u.i = v;
break;
}
@@ -70627,7 +71125,6 @@ case OP_NewRowid: { /* out2-prerelease */
*/
case OP_Insert:
case OP_InsertInt: {
-#if 0 /* local variables moved into u.bi */
Mem *pData; /* MEM cell holding data for the record to be inserted */
Mem *pKey; /* MEM cell holding key for the record */
i64 iKey; /* The integer ROWID or key for the record to be inserted */
@@ -70637,60 +71134,58 @@ case OP_InsertInt: {
const char *zDb; /* database name - used by the update hook */
const char *zTbl; /* Table name - used by the opdate hook */
int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
-#endif /* local variables moved into u.bi */
- u.bi.pData = &aMem[pOp->p2];
+ pData = &aMem[pOp->p2];
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- assert( memIsValid(u.bi.pData) );
- u.bi.pC = p->apCsr[pOp->p1];
- assert( u.bi.pC!=0 );
- assert( u.bi.pC->pCursor!=0 );
- assert( u.bi.pC->pseudoTableReg==0 );
- assert( u.bi.pC->isTable );
- REGISTER_TRACE(pOp->p2, u.bi.pData);
+ assert( memIsValid(pData) );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( pC->pCursor!=0 );
+ assert( pC->pseudoTableReg==0 );
+ assert( pC->isTable );
+ REGISTER_TRACE(pOp->p2, pData);
if( pOp->opcode==OP_Insert ){
- u.bi.pKey = &aMem[pOp->p3];
- assert( u.bi.pKey->flags & MEM_Int );
- assert( memIsValid(u.bi.pKey) );
- REGISTER_TRACE(pOp->p3, u.bi.pKey);
- u.bi.iKey = u.bi.pKey->u.i;
+ pKey = &aMem[pOp->p3];
+ assert( pKey->flags & MEM_Int );
+ assert( memIsValid(pKey) );
+ REGISTER_TRACE(pOp->p3, pKey);
+ iKey = pKey->u.i;
}else{
assert( pOp->opcode==OP_InsertInt );
- u.bi.iKey = pOp->p3;
+ iKey = pOp->p3;
}
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
- if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bi.iKey;
- if( u.bi.pData->flags & MEM_Null ){
- u.bi.pData->z = 0;
- u.bi.pData->n = 0;
+ if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = iKey;
+ if( pData->flags & MEM_Null ){
+ pData->z = 0;
+ pData->n = 0;
}else{
- assert( u.bi.pData->flags & (MEM_Blob|MEM_Str) );
+ assert( pData->flags & (MEM_Blob|MEM_Str) );
}
- u.bi.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bi.pC->seekResult : 0);
- if( u.bi.pData->flags & MEM_Zero ){
- u.bi.nZero = u.bi.pData->u.nZero;
+ seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
+ if( pData->flags & MEM_Zero ){
+ nZero = pData->u.nZero;
}else{
- u.bi.nZero = 0;
+ nZero = 0;
}
- sqlite3BtreeSetCachedRowid(u.bi.pC->pCursor, 0);
- rc = sqlite3BtreeInsert(u.bi.pC->pCursor, 0, u.bi.iKey,
- u.bi.pData->z, u.bi.pData->n, u.bi.nZero,
- (pOp->p5 & OPFLAG_APPEND)!=0, u.bi.seekResult
+ rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey,
+ pData->z, pData->n, nZero,
+ (pOp->p5 & OPFLAG_APPEND)!=0, seekResult
);
- u.bi.pC->rowidIsValid = 0;
- u.bi.pC->deferredMoveto = 0;
- u.bi.pC->cacheStatus = CACHE_STALE;
+ pC->rowidIsValid = 0;
+ pC->deferredMoveto = 0;
+ pC->cacheStatus = CACHE_STALE;
/* Invoke the update-hook if required. */
if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
- u.bi.zDb = db->aDb[u.bi.pC->iDb].zName;
- u.bi.zTbl = pOp->p4.z;
- u.bi.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
- assert( u.bi.pC->isTable );
- db->xUpdateCallback(db->pUpdateArg, u.bi.op, u.bi.zDb, u.bi.zTbl, u.bi.iKey);
- assert( u.bi.pC->iDb>=0 );
+ zDb = db->aDb[pC->iDb].zName;
+ zTbl = pOp->p4.z;
+ op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
+ assert( pC->isTable );
+ db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey);
+ assert( pC->iDb>=0 );
}
break;
}
@@ -70716,37 +71211,34 @@ case OP_InsertInt: {
** using OP_NotFound prior to invoking this opcode.
*/
case OP_Delete: {
-#if 0 /* local variables moved into u.bj */
i64 iKey;
VdbeCursor *pC;
-#endif /* local variables moved into u.bj */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.bj.pC = p->apCsr[pOp->p1];
- assert( u.bj.pC!=0 );
- assert( u.bj.pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
- u.bj.iKey = u.bj.pC->lastRowid; /* Only used for the update hook */
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
+ iKey = pC->lastRowid; /* Only used for the update hook */
/* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
** OP_Column on the same table without any intervening operations that
- ** might move or invalidate the cursor. Hence cursor u.bj.pC is always pointing
+ ** might move or invalidate the cursor. Hence cursor pC is always pointing
** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
** below is always a no-op and cannot fail. We will run it anyhow, though,
** to guard against future changes to the code generator.
**/
- assert( u.bj.pC->deferredMoveto==0 );
- rc = sqlite3VdbeCursorMoveto(u.bj.pC);
+ assert( pC->deferredMoveto==0 );
+ rc = sqlite3VdbeCursorMoveto(pC);
if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
- sqlite3BtreeSetCachedRowid(u.bj.pC->pCursor, 0);
- rc = sqlite3BtreeDelete(u.bj.pC->pCursor);
- u.bj.pC->cacheStatus = CACHE_STALE;
+ rc = sqlite3BtreeDelete(pC->pCursor);
+ pC->cacheStatus = CACHE_STALE;
/* Invoke the update-hook if required. */
- if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z && u.bj.pC->isTable ){
+ if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z && pC->isTable ){
db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE,
- db->aDb[u.bj.pC->iDb].zName, pOp->p4.z, u.bj.iKey);
- assert( u.bj.pC->iDb>=0 );
+ db->aDb[pC->iDb].zName, pOp->p4.z, iKey);
+ assert( pC->iDb>=0 );
}
if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
break;
@@ -70780,19 +71272,18 @@ case OP_ResetCount: {
** each other. Jump to P2 if they are different.
*/
case OP_SorterCompare: {
-#if 0 /* local variables moved into u.bk */
VdbeCursor *pC;
int res;
int nIgnore;
-#endif /* local variables moved into u.bk */
- u.bk.pC = p->apCsr[pOp->p1];
- assert( isSorter(u.bk.pC) );
+ pC = p->apCsr[pOp->p1];
+ assert( isSorter(pC) );
assert( pOp->p4type==P4_INT32 );
pIn3 = &aMem[pOp->p3];
- u.bk.nIgnore = pOp->p4.i;
- rc = sqlite3VdbeSorterCompare(u.bk.pC, pIn3, u.bk.nIgnore, &u.bk.res);
- if( u.bk.res ){
+ nIgnore = pOp->p4.i;
+ rc = sqlite3VdbeSorterCompare(pC, pIn3, nIgnore, &res);
+ VdbeBranchTaken(res!=0,2);
+ if( res ){
pc = pOp->p2-1;
}
break;
@@ -70804,14 +71295,12 @@ case OP_SorterCompare: {
** Write into register P2 the current sorter data for sorter cursor P1.
*/
case OP_SorterData: {
-#if 0 /* local variables moved into u.bl */
VdbeCursor *pC;
-#endif /* local variables moved into u.bl */
pOut = &aMem[pOp->p2];
- u.bl.pC = p->apCsr[pOp->p1];
- assert( isSorter(u.bl.pC) );
- rc = sqlite3VdbeSorterRowkey(u.bl.pC, pOut);
+ pC = p->apCsr[pOp->p1];
+ assert( isSorter(pC) );
+ rc = sqlite3VdbeSorterRowkey(pC, pOut);
break;
}
@@ -70831,7 +71320,7 @@ case OP_SorterData: {
**
** Write into register P2 the complete row key for cursor P1.
** There is no interpretation of the data.
-** The key is copied onto the P3 register exactly as
+** The key is copied onto the P2 register exactly as
** it is found in the database file.
**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
@@ -70839,62 +71328,60 @@ case OP_SorterData: {
*/
case OP_RowKey:
case OP_RowData: {
-#if 0 /* local variables moved into u.bm */
VdbeCursor *pC;
BtCursor *pCrsr;
u32 n;
i64 n64;
-#endif /* local variables moved into u.bm */
pOut = &aMem[pOp->p2];
memAboutToChange(p, pOut);
/* Note that RowKey and RowData are really exactly the same instruction */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.bm.pC = p->apCsr[pOp->p1];
- assert( isSorter(u.bm.pC)==0 );
- assert( u.bm.pC->isTable || pOp->opcode!=OP_RowData );
- assert( u.bm.pC->isTable==0 || pOp->opcode==OP_RowData );
- assert( u.bm.pC!=0 );
- assert( u.bm.pC->nullRow==0 );
- assert( u.bm.pC->pseudoTableReg==0 );
- assert( u.bm.pC->pCursor!=0 );
- u.bm.pCrsr = u.bm.pC->pCursor;
- assert( sqlite3BtreeCursorIsValid(u.bm.pCrsr) );
+ pC = p->apCsr[pOp->p1];
+ assert( isSorter(pC)==0 );
+ assert( pC->isTable || pOp->opcode!=OP_RowData );
+ assert( pC->isTable==0 || pOp->opcode==OP_RowData );
+ assert( pC!=0 );
+ assert( pC->nullRow==0 );
+ assert( pC->pseudoTableReg==0 );
+ assert( pC->pCursor!=0 );
+ pCrsr = pC->pCursor;
+ assert( sqlite3BtreeCursorIsValid(pCrsr) );
/* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
** OP_Rewind/Op_Next with no intervening instructions that might invalidate
** the cursor. Hence the following sqlite3VdbeCursorMoveto() call is always
** a no-op and can never fail. But we leave it in place as a safety.
*/
- assert( u.bm.pC->deferredMoveto==0 );
- rc = sqlite3VdbeCursorMoveto(u.bm.pC);
+ assert( pC->deferredMoveto==0 );
+ rc = sqlite3VdbeCursorMoveto(pC);
if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
- if( u.bm.pC->isTable==0 ){
- assert( !u.bm.pC->isTable );
- VVA_ONLY(rc =) sqlite3BtreeKeySize(u.bm.pCrsr, &u.bm.n64);
+ if( pC->isTable==0 ){
+ assert( !pC->isTable );
+ VVA_ONLY(rc =) sqlite3BtreeKeySize(pCrsr, &n64);
assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
- if( u.bm.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
- u.bm.n = (u32)u.bm.n64;
+ n = (u32)n64;
}else{
- VVA_ONLY(rc =) sqlite3BtreeDataSize(u.bm.pCrsr, &u.bm.n);
+ VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &n);
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
- if( u.bm.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ if( n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
}
- if( sqlite3VdbeMemGrow(pOut, u.bm.n, 0) ){
+ if( sqlite3VdbeMemGrow(pOut, n, 0) ){
goto no_mem;
}
- pOut->n = u.bm.n;
+ pOut->n = n;
MemSetTypeFlag(pOut, MEM_Blob);
- if( u.bm.pC->isTable==0 ){
- rc = sqlite3BtreeKey(u.bm.pCrsr, 0, u.bm.n, pOut->z);
+ if( pC->isTable==0 ){
+ rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z);
}else{
- rc = sqlite3BtreeData(u.bm.pCrsr, 0, u.bm.n, pOut->z);
+ rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z);
}
pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
UPDATE_MAX_BLOBSIZE(pOut);
@@ -70913,42 +71400,40 @@ case OP_RowData: {
** one opcode now works for both table types.
*/
case OP_Rowid: { /* out2-prerelease */
-#if 0 /* local variables moved into u.bn */
VdbeCursor *pC;
i64 v;
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
-#endif /* local variables moved into u.bn */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.bn.pC = p->apCsr[pOp->p1];
- assert( u.bn.pC!=0 );
- assert( u.bn.pC->pseudoTableReg==0 || u.bn.pC->nullRow );
- if( u.bn.pC->nullRow ){
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( pC->pseudoTableReg==0 || pC->nullRow );
+ if( pC->nullRow ){
pOut->flags = MEM_Null;
break;
- }else if( u.bn.pC->deferredMoveto ){
- u.bn.v = u.bn.pC->movetoTarget;
+ }else if( pC->deferredMoveto ){
+ v = pC->movetoTarget;
#ifndef SQLITE_OMIT_VIRTUALTABLE
- }else if( u.bn.pC->pVtabCursor ){
- u.bn.pVtab = u.bn.pC->pVtabCursor->pVtab;
- u.bn.pModule = u.bn.pVtab->pModule;
- assert( u.bn.pModule->xRowid );
- rc = u.bn.pModule->xRowid(u.bn.pC->pVtabCursor, &u.bn.v);
- sqlite3VtabImportErrmsg(p, u.bn.pVtab);
+ }else if( pC->pVtabCursor ){
+ pVtab = pC->pVtabCursor->pVtab;
+ pModule = pVtab->pModule;
+ assert( pModule->xRowid );
+ rc = pModule->xRowid(pC->pVtabCursor, &v);
+ sqlite3VtabImportErrmsg(p, pVtab);
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
- assert( u.bn.pC->pCursor!=0 );
- rc = sqlite3VdbeCursorMoveto(u.bn.pC);
+ assert( pC->pCursor!=0 );
+ rc = sqlite3VdbeCursorMoveto(pC);
if( rc ) goto abort_due_to_error;
- if( u.bn.pC->rowidIsValid ){
- u.bn.v = u.bn.pC->lastRowid;
+ if( pC->rowidIsValid ){
+ v = pC->lastRowid;
}else{
- rc = sqlite3BtreeKeySize(u.bn.pC->pCursor, &u.bn.v);
+ rc = sqlite3BtreeKeySize(pC->pCursor, &v);
assert( rc==SQLITE_OK ); /* Always so because of CursorMoveto() above */
}
}
- pOut->u.i = u.bn.v;
+ pOut->u.i = v;
break;
}
@@ -70959,19 +71444,16 @@ case OP_Rowid: { /* out2-prerelease */
** write a NULL.
*/
case OP_NullRow: {
-#if 0 /* local variables moved into u.bo */
VdbeCursor *pC;
-#endif /* local variables moved into u.bo */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.bo.pC = p->apCsr[pOp->p1];
- assert( u.bo.pC!=0 );
- u.bo.pC->nullRow = 1;
- u.bo.pC->rowidIsValid = 0;
- u.bo.pC->cacheStatus = CACHE_STALE;
- assert( u.bo.pC->pCursor || u.bo.pC->pVtabCursor );
- if( u.bo.pC->pCursor ){
- sqlite3BtreeClearCursor(u.bo.pC->pCursor);
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ pC->nullRow = 1;
+ pC->rowidIsValid = 0;
+ pC->cacheStatus = CACHE_STALE;
+ if( pC->pCursor ){
+ sqlite3BtreeClearCursor(pC->pCursor);
}
break;
}
@@ -70985,25 +71467,24 @@ case OP_NullRow: {
** to the following instruction.
*/
case OP_Last: { /* jump */
-#if 0 /* local variables moved into u.bp */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
-#endif /* local variables moved into u.bp */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.bp.pC = p->apCsr[pOp->p1];
- assert( u.bp.pC!=0 );
- u.bp.pCrsr = u.bp.pC->pCursor;
- u.bp.res = 0;
- assert( u.bp.pCrsr!=0 );
- rc = sqlite3BtreeLast(u.bp.pCrsr, &u.bp.res);
- u.bp.pC->nullRow = (u8)u.bp.res;
- u.bp.pC->deferredMoveto = 0;
- u.bp.pC->rowidIsValid = 0;
- u.bp.pC->cacheStatus = CACHE_STALE;
- if( pOp->p2>0 && u.bp.res ){
- pc = pOp->p2 - 1;
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ pCrsr = pC->pCursor;
+ res = 0;
+ assert( pCrsr!=0 );
+ rc = sqlite3BtreeLast(pCrsr, &res);
+ pC->nullRow = (u8)res;
+ pC->deferredMoveto = 0;
+ pC->rowidIsValid = 0;
+ pC->cacheStatus = CACHE_STALE;
+ if( pOp->p2>0 ){
+ VdbeBranchTaken(res!=0,2);
+ if( res ) pc = pOp->p2 - 1;
}
break;
}
@@ -71039,36 +71520,35 @@ case OP_Sort: { /* jump */
** to the following instruction.
*/
case OP_Rewind: { /* jump */
-#if 0 /* local variables moved into u.bq */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
-#endif /* local variables moved into u.bq */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.bq.pC = p->apCsr[pOp->p1];
- assert( u.bq.pC!=0 );
- assert( isSorter(u.bq.pC)==(pOp->opcode==OP_SorterSort) );
- u.bq.res = 1;
- if( isSorter(u.bq.pC) ){
- rc = sqlite3VdbeSorterRewind(db, u.bq.pC, &u.bq.res);
- }else{
- u.bq.pCrsr = u.bq.pC->pCursor;
- assert( u.bq.pCrsr );
- rc = sqlite3BtreeFirst(u.bq.pCrsr, &u.bq.res);
- u.bq.pC->deferredMoveto = 0;
- u.bq.pC->cacheStatus = CACHE_STALE;
- u.bq.pC->rowidIsValid = 0;
- }
- u.bq.pC->nullRow = (u8)u.bq.res;
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( isSorter(pC)==(pOp->opcode==OP_SorterSort) );
+ res = 1;
+ if( isSorter(pC) ){
+ rc = sqlite3VdbeSorterRewind(db, pC, &res);
+ }else{
+ pCrsr = pC->pCursor;
+ assert( pCrsr );
+ rc = sqlite3BtreeFirst(pCrsr, &res);
+ pC->deferredMoveto = 0;
+ pC->cacheStatus = CACHE_STALE;
+ pC->rowidIsValid = 0;
+ }
+ pC->nullRow = (u8)res;
assert( pOp->p2>0 && pOp->p2<p->nOp );
- if( u.bq.res ){
+ VdbeBranchTaken(res!=0,2);
+ if( res ){
pc = pOp->p2 - 1;
}
break;
}
-/* Opcode: Next P1 P2 * * P5
+/* Opcode: Next P1 P2 P3 P4 P5
**
** Advance cursor P1 so that it points to the next key/data pair in its
** table or index. If there are no more key/value pairs then fall through
@@ -71078,6 +71558,11 @@ case OP_Rewind: { /* jump */
** The P1 cursor must be for a real table, not a pseudo-table. P1 must have
** been opened prior to this opcode or the program will segfault.
**
+** The P3 value is a hint to the btree implementation. If P3==1, that
+** means P1 is an SQL index and that this instruction could have been
+** omitted if that index had been unique. P3 is usually 0. P3 is
+** always either 0 or 1.
+**
** P4 is always of type P4_ADVANCE. The function pointer points to
** sqlite3BtreeNext().
**
@@ -71086,12 +71571,12 @@ case OP_Rewind: { /* jump */
**
** See also: Prev, NextIfOpen
*/
-/* Opcode: NextIfOpen P1 P2 * * P5
+/* Opcode: NextIfOpen P1 P2 P3 P4 P5
**
** This opcode works just like OP_Next except that if cursor P1 is not
** open it behaves a no-op.
*/
-/* Opcode: Prev P1 P2 * * P5
+/* Opcode: Prev P1 P2 P3 P4 P5
**
** Back up cursor P1 so that it points to the previous key/data pair in its
** table or index. If there is no previous key/value pairs then fall through
@@ -71101,26 +71586,29 @@ case OP_Rewind: { /* jump */
** The P1 cursor must be for a real table, not a pseudo-table. If P1 is
** not open then the behavior is undefined.
**
+** The P3 value is a hint to the btree implementation. If P3==1, that
+** means P1 is an SQL index and that this instruction could have been
+** omitted if that index had been unique. P3 is usually 0. P3 is
+** always either 0 or 1.
+**
** P4 is always of type P4_ADVANCE. The function pointer points to
** sqlite3BtreePrevious().
**
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
*/
-/* Opcode: PrevIfOpen P1 P2 * * P5
+/* Opcode: PrevIfOpen P1 P2 P3 P4 P5
**
** This opcode works just like OP_Prev except that if cursor P1 is not
** open it behaves a no-op.
*/
case OP_SorterNext: { /* jump */
-#if 0 /* local variables moved into u.br */
VdbeCursor *pC;
int res;
-#endif /* local variables moved into u.br */
- u.br.pC = p->apCsr[pOp->p1];
- assert( isSorter(u.br.pC) );
- rc = sqlite3VdbeSorterNext(db, u.br.pC, &u.br.res);
+ pC = p->apCsr[pOp->p1];
+ assert( isSorter(pC) );
+ rc = sqlite3VdbeSorterNext(db, pC, &res);
goto next_tail;
case OP_PrevIfOpen: /* jump */
case OP_NextIfOpen: /* jump */
@@ -71130,28 +71618,32 @@ case OP_Prev: /* jump */
case OP_Next: /* jump */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p5<ArraySize(p->aCounter) );
- u.br.pC = p->apCsr[pOp->p1];
- assert( u.br.pC!=0 );
- assert( u.br.pC->deferredMoveto==0 );
- assert( u.br.pC->pCursor );
+ pC = p->apCsr[pOp->p1];
+ res = pOp->p3;
+ assert( pC!=0 );
+ assert( pC->deferredMoveto==0 );
+ assert( pC->pCursor );
+ assert( res==0 || (res==1 && pC->isTable==0) );
+ testcase( res==1 );
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious);
- rc = pOp->p4.xAdvance(u.br.pC->pCursor, &u.br.res);
+ rc = pOp->p4.xAdvance(pC->pCursor, &res);
next_tail:
- u.br.pC->cacheStatus = CACHE_STALE;
- if( u.br.res==0 ){
- u.br.pC->nullRow = 0;
+ pC->cacheStatus = CACHE_STALE;
+ VdbeBranchTaken(res==0,2);
+ if( res==0 ){
+ pC->nullRow = 0;
pc = pOp->p2 - 1;
p->aCounter[pOp->p5]++;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
}else{
- u.br.pC->nullRow = 1;
+ pC->nullRow = 1;
}
- u.br.pC->rowidIsValid = 0;
+ pC->rowidIsValid = 0;
goto check_for_interrupt;
}
@@ -71165,40 +71657,46 @@ next_tail:
** P3 is a flag that provides a hint to the b-tree layer that this
** insert is likely to be an append.
**
+** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is
+** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear,
+** then the change counter is unchanged.
+**
+** If P5 has the OPFLAG_USESEEKRESULT bit set, then the cursor must have
+** just done a seek to the spot where the new entry is to be inserted.
+** This flag avoids doing an extra seek.
+**
** This instruction only works for indices. The equivalent instruction
** for tables is OP_Insert.
*/
case OP_SorterInsert: /* in2 */
case OP_IdxInsert: { /* in2 */
-#if 0 /* local variables moved into u.bs */
VdbeCursor *pC;
BtCursor *pCrsr;
int nKey;
const char *zKey;
-#endif /* local variables moved into u.bs */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.bs.pC = p->apCsr[pOp->p1];
- assert( u.bs.pC!=0 );
- assert( isSorter(u.bs.pC)==(pOp->opcode==OP_SorterInsert) );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) );
pIn2 = &aMem[pOp->p2];
assert( pIn2->flags & MEM_Blob );
- u.bs.pCrsr = u.bs.pC->pCursor;
+ pCrsr = pC->pCursor;
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
- assert( u.bs.pCrsr!=0 );
- assert( u.bs.pC->isTable==0 );
+ assert( pCrsr!=0 );
+ assert( pC->isTable==0 );
rc = ExpandBlob(pIn2);
if( rc==SQLITE_OK ){
- if( isSorter(u.bs.pC) ){
- rc = sqlite3VdbeSorterWrite(db, u.bs.pC, pIn2);
+ if( isSorter(pC) ){
+ rc = sqlite3VdbeSorterWrite(db, pC, pIn2);
}else{
- u.bs.nKey = pIn2->n;
- u.bs.zKey = pIn2->z;
- rc = sqlite3BtreeInsert(u.bs.pCrsr, u.bs.zKey, u.bs.nKey, "", 0, 0, pOp->p3,
- ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bs.pC->seekResult : 0)
+ nKey = pIn2->n;
+ zKey = pIn2->z;
+ rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3,
+ ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
);
- assert( u.bs.pC->deferredMoveto==0 );
- u.bs.pC->cacheStatus = CACHE_STALE;
+ assert( pC->deferredMoveto==0 );
+ pC->cacheStatus = CACHE_STALE;
}
}
break;
@@ -71212,34 +71710,32 @@ case OP_IdxInsert: { /* in2 */
** index opened by cursor P1.
*/
case OP_IdxDelete: {
-#if 0 /* local variables moved into u.bt */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
UnpackedRecord r;
-#endif /* local variables moved into u.bt */
assert( pOp->p3>0 );
assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem-p->nCursor)+1 );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.bt.pC = p->apCsr[pOp->p1];
- assert( u.bt.pC!=0 );
- u.bt.pCrsr = u.bt.pC->pCursor;
- assert( u.bt.pCrsr!=0 );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ pCrsr = pC->pCursor;
+ assert( pCrsr!=0 );
assert( pOp->p5==0 );
- u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo;
- u.bt.r.nField = (u16)pOp->p3;
- u.bt.r.flags = UNPACKED_PREFIX_MATCH;
- u.bt.r.aMem = &aMem[pOp->p2];
+ r.pKeyInfo = pC->pKeyInfo;
+ r.nField = (u16)pOp->p3;
+ r.default_rc = 0;
+ r.aMem = &aMem[pOp->p2];
#ifdef SQLITE_DEBUG
- { int i; for(i=0; i<u.bt.r.nField; i++) assert( memIsValid(&u.bt.r.aMem[i]) ); }
+ { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
#endif
- rc = sqlite3BtreeMovetoUnpacked(u.bt.pCrsr, &u.bt.r, 0, 0, &u.bt.res);
- if( rc==SQLITE_OK && u.bt.res==0 ){
- rc = sqlite3BtreeDelete(u.bt.pCrsr);
+ rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
+ if( rc==SQLITE_OK && res==0 ){
+ rc = sqlite3BtreeDelete(pCrsr);
}
- assert( u.bt.pC->deferredMoveto==0 );
- u.bt.pC->cacheStatus = CACHE_STALE;
+ assert( pC->deferredMoveto==0 );
+ pC->cacheStatus = CACHE_STALE;
break;
}
@@ -71253,28 +71749,27 @@ case OP_IdxDelete: {
** See also: Rowid, MakeRecord.
*/
case OP_IdxRowid: { /* out2-prerelease */
-#if 0 /* local variables moved into u.bu */
BtCursor *pCrsr;
VdbeCursor *pC;
i64 rowid;
-#endif /* local variables moved into u.bu */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.bu.pC = p->apCsr[pOp->p1];
- assert( u.bu.pC!=0 );
- u.bu.pCrsr = u.bu.pC->pCursor;
- assert( u.bu.pCrsr!=0 );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ pCrsr = pC->pCursor;
+ assert( pCrsr!=0 );
pOut->flags = MEM_Null;
- rc = sqlite3VdbeCursorMoveto(u.bu.pC);
+ rc = sqlite3VdbeCursorMoveto(pC);
if( NEVER(rc) ) goto abort_due_to_error;
- assert( u.bu.pC->deferredMoveto==0 );
- assert( u.bu.pC->isTable==0 );
- if( !u.bu.pC->nullRow ){
- rc = sqlite3VdbeIdxRowid(db, u.bu.pCrsr, &u.bu.rowid);
+ assert( pC->deferredMoveto==0 );
+ assert( pC->isTable==0 );
+ if( !pC->nullRow ){
+ rowid = 0; /* Not needed. Only used to silence a warning. */
+ rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- pOut->u.i = u.bu.rowid;
+ pOut->u.i = rowid;
pOut->flags = MEM_Int;
}
break;
@@ -71284,65 +71779,87 @@ case OP_IdxRowid: { /* out2-prerelease */
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
-** key that omits the ROWID. Compare this key value against the index
-** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
+** key that omits the PRIMARY KEY. Compare this key value against the index
+** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID
+** fields at the end.
**
** If the P1 index entry is greater than or equal to the key value
** then jump to P2. Otherwise fall through to the next instruction.
+*/
+/* Opcode: IdxGT P1 P2 P3 P4 P5
+** Synopsis: key=r[P3@P4]
**
-** If P5 is non-zero then the key value is increased by an epsilon
-** prior to the comparison. This make the opcode work like IdxGT except
-** that if the key from register P3 is a prefix of the key in the cursor,
-** the result is false whereas it would be true with IdxGT.
+** The P4 register values beginning with P3 form an unpacked index
+** key that omits the PRIMARY KEY. Compare this key value against the index
+** that P1 is currently pointing to, ignoring the PRIMARY KEY or ROWID
+** fields at the end.
+**
+** If the P1 index entry is greater than the key value
+** then jump to P2. Otherwise fall through to the next instruction.
*/
/* Opcode: IdxLT P1 P2 P3 P4 P5
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
-** key that omits the ROWID. Compare this key value against the index
-** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
+** key that omits the PRIMARY KEY or ROWID. Compare this key value against
+** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or
+** ROWID on the P1 index.
**
** If the P1 index entry is less than the key value then jump to P2.
** Otherwise fall through to the next instruction.
+*/
+/* Opcode: IdxLE P1 P2 P3 P4 P5
+** Synopsis: key=r[P3@P4]
+**
+** The P4 register values beginning with P3 form an unpacked index
+** key that omits the PRIMARY KEY or ROWID. Compare this key value against
+** the index that P1 is currently pointing to, ignoring the PRIMARY KEY or
+** ROWID on the P1 index.
**
-** If P5 is non-zero then the key value is increased by an epsilon prior
-** to the comparison. This makes the opcode work like IdxLE.
+** If the P1 index entry is less than or equal to the key value then jump
+** to P2. Otherwise fall through to the next instruction.
*/
+case OP_IdxLE: /* jump */
+case OP_IdxGT: /* jump */
case OP_IdxLT: /* jump */
-case OP_IdxGE: { /* jump */
-#if 0 /* local variables moved into u.bv */
+case OP_IdxGE: { /* jump */
VdbeCursor *pC;
int res;
UnpackedRecord r;
-#endif /* local variables moved into u.bv */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.bv.pC = p->apCsr[pOp->p1];
- assert( u.bv.pC!=0 );
- assert( u.bv.pC->isOrdered );
- assert( u.bv.pC->pCursor!=0);
- assert( u.bv.pC->deferredMoveto==0 );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( pC->isOrdered );
+ assert( pC->pCursor!=0);
+ assert( pC->deferredMoveto==0 );
assert( pOp->p5==0 || pOp->p5==1 );
assert( pOp->p4type==P4_INT32 );
- u.bv.r.pKeyInfo = u.bv.pC->pKeyInfo;
- u.bv.r.nField = (u16)pOp->p4.i;
- if( pOp->p5 ){
- u.bv.r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
+ r.pKeyInfo = pC->pKeyInfo;
+ r.nField = (u16)pOp->p4.i;
+ if( pOp->opcode<OP_IdxLT ){
+ assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxGT );
+ r.default_rc = -1;
}else{
- u.bv.r.flags = UNPACKED_PREFIX_MATCH;
+ assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxLT );
+ r.default_rc = 0;
}
- u.bv.r.aMem = &aMem[pOp->p3];
+ r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
- { int i; for(i=0; i<u.bv.r.nField; i++) assert( memIsValid(&u.bv.r.aMem[i]) ); }
+ { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
#endif
- rc = sqlite3VdbeIdxKeyCompare(u.bv.pC, &u.bv.r, &u.bv.res);
- if( pOp->opcode==OP_IdxLT ){
- u.bv.res = -u.bv.res;
+ res = 0; /* Not needed. Only used to silence a warning. */
+ rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res);
+ assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) );
+ if( (pOp->opcode&1)==(OP_IdxLT&1) ){
+ assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT );
+ res = -res;
}else{
- assert( pOp->opcode==OP_IdxGE );
- u.bv.res++;
+ assert( pOp->opcode==OP_IdxGE || pOp->opcode==OP_IdxGT );
+ res++;
}
- if( u.bv.res>0 ){
+ VdbeBranchTaken(res>0,2);
+ if( res>0 ){
pc = pOp->p2 - 1 ;
}
break;
@@ -71369,43 +71886,42 @@ case OP_IdxGE: { /* jump */
** See also: Clear
*/
case OP_Destroy: { /* out2-prerelease */
-#if 0 /* local variables moved into u.bw */
int iMoved;
int iCnt;
Vdbe *pVdbe;
int iDb;
-#endif /* local variables moved into u.bw */
assert( p->readOnly==0 );
#ifndef SQLITE_OMIT_VIRTUALTABLE
- u.bw.iCnt = 0;
- for(u.bw.pVdbe=db->pVdbe; u.bw.pVdbe; u.bw.pVdbe = u.bw.pVdbe->pNext){
- if( u.bw.pVdbe->magic==VDBE_MAGIC_RUN && u.bw.pVdbe->bIsReader
- && u.bw.pVdbe->inVtabMethod<2 && u.bw.pVdbe->pc>=0
+ iCnt = 0;
+ for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){
+ if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->bIsReader
+ && pVdbe->inVtabMethod<2 && pVdbe->pc>=0
){
- u.bw.iCnt++;
+ iCnt++;
}
}
#else
- u.bw.iCnt = db->nVdbeRead;
+ iCnt = db->nVdbeRead;
#endif
pOut->flags = MEM_Null;
- if( u.bw.iCnt>1 ){
+ if( iCnt>1 ){
rc = SQLITE_LOCKED;
p->errorAction = OE_Abort;
}else{
- u.bw.iDb = pOp->p3;
- assert( u.bw.iCnt==1 );
- assert( (p->btreeMask & (((yDbMask)1)<<u.bw.iDb))!=0 );
- rc = sqlite3BtreeDropTable(db->aDb[u.bw.iDb].pBt, pOp->p1, &u.bw.iMoved);
+ iDb = pOp->p3;
+ assert( iCnt==1 );
+ assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
+ iMoved = 0; /* Not needed. Only to silence a warning. */
+ rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
pOut->flags = MEM_Int;
- pOut->u.i = u.bw.iMoved;
+ pOut->u.i = iMoved;
#ifndef SQLITE_OMIT_AUTOVACUUM
- if( rc==SQLITE_OK && u.bw.iMoved!=0 ){
- sqlite3RootPageMoved(db, u.bw.iDb, u.bw.iMoved, pOp->p1);
+ if( rc==SQLITE_OK && iMoved!=0 ){
+ sqlite3RootPageMoved(db, iDb, iMoved, pOp->p1);
/* All OP_Destroy operations occur on the same btree */
- assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bw.iDb+1 );
- resetSchemaOnFault = u.bw.iDb+1;
+ assert( resetSchemaOnFault==0 || resetSchemaOnFault==iDb+1 );
+ resetSchemaOnFault = iDb+1;
}
#endif
}
@@ -71431,23 +71947,20 @@ case OP_Destroy: { /* out2-prerelease */
** See also: Destroy
*/
case OP_Clear: {
-#if 0 /* local variables moved into u.bx */
int nChange;
-#endif /* local variables moved into u.bx */
-
- u.bx.nChange = 0;
+
+ nChange = 0;
assert( p->readOnly==0 );
- assert( pOp->p1!=1 );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
rc = sqlite3BtreeClearTable(
- db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bx.nChange : 0)
+ db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0)
);
if( pOp->p3 ){
- p->nChange += u.bx.nChange;
+ p->nChange += nChange;
if( pOp->p3>0 ){
assert( memIsValid(&aMem[pOp->p3]) );
memAboutToChange(p, &aMem[pOp->p3]);
- aMem[pOp->p3].u.i += u.bx.nChange;
+ aMem[pOp->p3].u.i += nChange;
}
}
break;
@@ -71479,26 +71992,24 @@ case OP_Clear: {
*/
case OP_CreateIndex: /* out2-prerelease */
case OP_CreateTable: { /* out2-prerelease */
-#if 0 /* local variables moved into u.by */
int pgno;
int flags;
Db *pDb;
-#endif /* local variables moved into u.by */
- u.by.pgno = 0;
+ pgno = 0;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
assert( p->readOnly==0 );
- u.by.pDb = &db->aDb[pOp->p1];
- assert( u.by.pDb->pBt!=0 );
+ pDb = &db->aDb[pOp->p1];
+ assert( pDb->pBt!=0 );
if( pOp->opcode==OP_CreateTable ){
- /* u.by.flags = BTREE_INTKEY; */
- u.by.flags = BTREE_INTKEY;
+ /* flags = BTREE_INTKEY; */
+ flags = BTREE_INTKEY;
}else{
- u.by.flags = BTREE_BLOBKEY;
+ flags = BTREE_BLOBKEY;
}
- rc = sqlite3BtreeCreateTable(u.by.pDb->pBt, &u.by.pgno, u.by.flags);
- pOut->u.i = u.by.pgno;
+ rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
+ pOut->u.i = pgno;
break;
}
@@ -71511,44 +72022,42 @@ case OP_CreateTable: { /* out2-prerelease */
** then runs the new virtual machine. It is thus a re-entrant opcode.
*/
case OP_ParseSchema: {
-#if 0 /* local variables moved into u.bz */
int iDb;
const char *zMaster;
char *zSql;
InitData initData;
-#endif /* local variables moved into u.bz */
/* Any prepared statement that invokes this opcode will hold mutexes
- ** on every btree. This is a prerequisite for invoking
+ ** on every btree. This is a prerequisite for invoking
** sqlite3InitCallback().
*/
#ifdef SQLITE_DEBUG
- for(u.bz.iDb=0; u.bz.iDb<db->nDb; u.bz.iDb++){
- assert( u.bz.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bz.iDb].pBt) );
+ for(iDb=0; iDb<db->nDb; iDb++){
+ assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
}
#endif
- u.bz.iDb = pOp->p1;
- assert( u.bz.iDb>=0 && u.bz.iDb<db->nDb );
- assert( DbHasProperty(db, u.bz.iDb, DB_SchemaLoaded) );
+ iDb = pOp->p1;
+ assert( iDb>=0 && iDb<db->nDb );
+ assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
/* Used to be a conditional */ {
- u.bz.zMaster = SCHEMA_TABLE(u.bz.iDb);
- u.bz.initData.db = db;
- u.bz.initData.iDb = pOp->p1;
- u.bz.initData.pzErrMsg = &p->zErrMsg;
- u.bz.zSql = sqlite3MPrintf(db,
+ zMaster = SCHEMA_TABLE(iDb);
+ initData.db = db;
+ initData.iDb = pOp->p1;
+ initData.pzErrMsg = &p->zErrMsg;
+ zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
- db->aDb[u.bz.iDb].zName, u.bz.zMaster, pOp->p4.z);
- if( u.bz.zSql==0 ){
+ db->aDb[iDb].zName, zMaster, pOp->p4.z);
+ if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
assert( db->init.busy==0 );
db->init.busy = 1;
- u.bz.initData.rc = SQLITE_OK;
+ initData.rc = SQLITE_OK;
assert( !db->mallocFailed );
- rc = sqlite3_exec(db, u.bz.zSql, sqlite3InitCallback, &u.bz.initData, 0);
- if( rc==SQLITE_OK ) rc = u.bz.initData.rc;
- sqlite3DbFree(db, u.bz.zSql);
+ rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
+ if( rc==SQLITE_OK ) rc = initData.rc;
+ sqlite3DbFree(db, zSql);
db->init.busy = 0;
}
}
@@ -71556,7 +72065,7 @@ case OP_ParseSchema: {
if( rc==SQLITE_NOMEM ){
goto no_mem;
}
- break;
+ break;
}
#if !defined(SQLITE_OMIT_ANALYZE)
@@ -71632,42 +72141,40 @@ case OP_DropTrigger: {
** This opcode is used to implement the integrity_check pragma.
*/
case OP_IntegrityCk: {
-#if 0 /* local variables moved into u.ca */
int nRoot; /* Number of tables to check. (Number of root pages.) */
int *aRoot; /* Array of rootpage numbers for tables to be checked */
int j; /* Loop counter */
int nErr; /* Number of errors reported */
char *z; /* Text of the error report */
Mem *pnErr; /* Register keeping track of errors remaining */
-#endif /* local variables moved into u.ca */
assert( p->bIsReader );
- u.ca.nRoot = pOp->p2;
- assert( u.ca.nRoot>0 );
- u.ca.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.ca.nRoot+1) );
- if( u.ca.aRoot==0 ) goto no_mem;
+ nRoot = pOp->p2;
+ assert( nRoot>0 );
+ aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) );
+ if( aRoot==0 ) goto no_mem;
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
- u.ca.pnErr = &aMem[pOp->p3];
- assert( (u.ca.pnErr->flags & MEM_Int)!=0 );
- assert( (u.ca.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
+ pnErr = &aMem[pOp->p3];
+ assert( (pnErr->flags & MEM_Int)!=0 );
+ assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 );
pIn1 = &aMem[pOp->p1];
- for(u.ca.j=0; u.ca.j<u.ca.nRoot; u.ca.j++){
- u.ca.aRoot[u.ca.j] = (int)sqlite3VdbeIntValue(&pIn1[u.ca.j]);
+ for(j=0; j<nRoot; j++){
+ aRoot[j] = (int)sqlite3VdbeIntValue(&pIn1[j]);
}
- u.ca.aRoot[u.ca.j] = 0;
+ aRoot[j] = 0;
assert( pOp->p5<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p5))!=0 );
- u.ca.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.ca.aRoot, u.ca.nRoot,
- (int)u.ca.pnErr->u.i, &u.ca.nErr);
- sqlite3DbFree(db, u.ca.aRoot);
- u.ca.pnErr->u.i -= u.ca.nErr;
+ z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
+ (int)pnErr->u.i, &nErr);
+ sqlite3DbFree(db, aRoot);
+ pnErr->u.i -= nErr;
sqlite3VdbeMemSetNull(pIn1);
- if( u.ca.nErr==0 ){
- assert( u.ca.z==0 );
- }else if( u.ca.z==0 ){
+ if( nErr==0 ){
+ assert( z==0 );
+ }else if( z==0 ){
goto no_mem;
}else{
- sqlite3VdbeMemSetStr(pIn1, u.ca.z, -1, SQLITE_UTF8, sqlite3_free);
+ sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free);
}
UPDATE_MAX_BLOBSIZE(pIn1);
sqlite3VdbeChangeEncoding(pIn1, encoding);
@@ -71703,20 +72210,20 @@ case OP_RowSetAdd: { /* in1, in2 */
** unchanged and jump to instruction P2.
*/
case OP_RowSetRead: { /* jump, in1, out3 */
-#if 0 /* local variables moved into u.cb */
i64 val;
-#endif /* local variables moved into u.cb */
pIn1 = &aMem[pOp->p1];
- if( (pIn1->flags & MEM_RowSet)==0
- || sqlite3RowSetNext(pIn1->u.pRowSet, &u.cb.val)==0
+ if( (pIn1->flags & MEM_RowSet)==0
+ || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0
){
/* The boolean index is empty */
sqlite3VdbeMemSetNull(pIn1);
pc = pOp->p2 - 1;
+ VdbeBranchTaken(1,2);
}else{
/* A value was pulled from the index */
- sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.cb.val);
+ sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val);
+ VdbeBranchTaken(0,2);
}
goto check_for_interrupt;
}
@@ -71746,14 +72253,12 @@ case OP_RowSetRead: { /* jump, in1, out3 */
** inserted as part of some other set).
*/
case OP_RowSetTest: { /* jump, in1, in3 */
-#if 0 /* local variables moved into u.cc */
int iSet;
int exists;
-#endif /* local variables moved into u.cc */
pIn1 = &aMem[pOp->p1];
pIn3 = &aMem[pOp->p3];
- u.cc.iSet = pOp->p4.i;
+ iSet = pOp->p4.i;
assert( pIn3->flags&MEM_Int );
/* If there is anything other than a rowset object in memory cell P1,
@@ -71765,17 +72270,18 @@ case OP_RowSetTest: { /* jump, in1, in3 */
}
assert( pOp->p4type==P4_INT32 );
- assert( u.cc.iSet==-1 || u.cc.iSet>=0 );
- if( u.cc.iSet ){
- u.cc.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
- (u8)(u.cc.iSet>=0 ? u.cc.iSet & 0xf : 0xff),
+ assert( iSet==-1 || iSet>=0 );
+ if( iSet ){
+ exists = sqlite3RowSetTest(pIn1->u.pRowSet,
+ (u8)(iSet>=0 ? iSet & 0xf : 0xff),
pIn3->u.i);
- if( u.cc.exists ){
+ VdbeBranchTaken(exists!=0,2);
+ if( exists ){
pc = pOp->p2 - 1;
break;
}
}
- if( u.cc.iSet>=0 ){
+ if( iSet>=0 ){
sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
}
break;
@@ -71784,7 +72290,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */
#ifndef SQLITE_OMIT_TRIGGER
-/* Opcode: Program P1 P2 P3 P4 *
+/* Opcode: Program P1 P2 P3 P4 P5
**
** Execute the trigger program passed as P4 (type P4_SUBPROGRAM).
**
@@ -71796,9 +72302,10 @@ case OP_RowSetTest: { /* jump, in1, in3 */
** memory required by the sub-vdbe at runtime.
**
** P4 is a pointer to the VM containing the trigger program.
+**
+** If P5 is non-zero, then recursive program invocation is enabled.
*/
case OP_Program: { /* jump */
-#if 0 /* local variables moved into u.cd */
int nMem; /* Number of memory registers for sub-program */
int nByte; /* Bytes of runtime space required for sub-program */
Mem *pRt; /* Register to allocate runtime space */
@@ -71807,27 +72314,26 @@ case OP_Program: { /* jump */
VdbeFrame *pFrame; /* New vdbe frame to execute in */
SubProgram *pProgram; /* Sub-program to execute */
void *t; /* Token identifying trigger */
-#endif /* local variables moved into u.cd */
-
- u.cd.pProgram = pOp->p4.pProgram;
- u.cd.pRt = &aMem[pOp->p3];
- assert( u.cd.pProgram->nOp>0 );
- /* If the p5 flag is clear, then recursive invocation of triggers is
+ pProgram = pOp->p4.pProgram;
+ pRt = &aMem[pOp->p3];
+ assert( pProgram->nOp>0 );
+
+ /* If the p5 flag is clear, then recursive invocation of triggers is
** disabled for backwards compatibility (p5 is set if this sub-program
** is really a trigger, not a foreign key action, and the flag set
** and cleared by the "PRAGMA recursive_triggers" command is clear).
- **
- ** It is recursive invocation of triggers, at the SQL level, that is
- ** disabled. In some cases a single trigger may generate more than one
- ** SubProgram (if the trigger may be executed with more than one different
+ **
+ ** It is recursive invocation of triggers, at the SQL level, that is
+ ** disabled. In some cases a single trigger may generate more than one
+ ** SubProgram (if the trigger may be executed with more than one different
** ON CONFLICT algorithm). SubProgram structures associated with a
- ** single trigger all have the same value for the SubProgram.token
+ ** single trigger all have the same value for the SubProgram.token
** variable. */
if( pOp->p5 ){
- u.cd.t = u.cd.pProgram->token;
- for(u.cd.pFrame=p->pFrame; u.cd.pFrame && u.cd.pFrame->token!=u.cd.t; u.cd.pFrame=u.cd.pFrame->pParent);
- if( u.cd.pFrame ) break;
+ t = pProgram->token;
+ for(pFrame=p->pFrame; pFrame && pFrame->token!=t; pFrame=pFrame->pParent);
+ if( pFrame ) break;
}
if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
@@ -71836,69 +72342,69 @@ case OP_Program: { /* jump */
break;
}
- /* Register u.cd.pRt is used to store the memory required to save the state
+ /* Register pRt is used to store the memory required to save the state
** of the current program, and the memory required at runtime to execute
- ** the trigger program. If this trigger has been fired before, then u.cd.pRt
+ ** the trigger program. If this trigger has been fired before, then pRt
** is already allocated. Otherwise, it must be initialized. */
- if( (u.cd.pRt->flags&MEM_Frame)==0 ){
- /* SubProgram.nMem is set to the number of memory cells used by the
+ if( (pRt->flags&MEM_Frame)==0 ){
+ /* SubProgram.nMem is set to the number of memory cells used by the
** program stored in SubProgram.aOp. As well as these, one memory
** cell is required for each cursor used by the program. Set local
- ** variable u.cd.nMem (and later, VdbeFrame.nChildMem) to this value.
+ ** variable nMem (and later, VdbeFrame.nChildMem) to this value.
*/
- u.cd.nMem = u.cd.pProgram->nMem + u.cd.pProgram->nCsr;
- u.cd.nByte = ROUND8(sizeof(VdbeFrame))
- + u.cd.nMem * sizeof(Mem)
- + u.cd.pProgram->nCsr * sizeof(VdbeCursor *)
- + u.cd.pProgram->nOnce * sizeof(u8);
- u.cd.pFrame = sqlite3DbMallocZero(db, u.cd.nByte);
- if( !u.cd.pFrame ){
+ nMem = pProgram->nMem + pProgram->nCsr;
+ nByte = ROUND8(sizeof(VdbeFrame))
+ + nMem * sizeof(Mem)
+ + pProgram->nCsr * sizeof(VdbeCursor *)
+ + pProgram->nOnce * sizeof(u8);
+ pFrame = sqlite3DbMallocZero(db, nByte);
+ if( !pFrame ){
goto no_mem;
}
- sqlite3VdbeMemRelease(u.cd.pRt);
- u.cd.pRt->flags = MEM_Frame;
- u.cd.pRt->u.pFrame = u.cd.pFrame;
+ sqlite3VdbeMemRelease(pRt);
+ pRt->flags = MEM_Frame;
+ pRt->u.pFrame = pFrame;
- u.cd.pFrame->v = p;
- u.cd.pFrame->nChildMem = u.cd.nMem;
- u.cd.pFrame->nChildCsr = u.cd.pProgram->nCsr;
- u.cd.pFrame->pc = pc;
- u.cd.pFrame->aMem = p->aMem;
- u.cd.pFrame->nMem = p->nMem;
- u.cd.pFrame->apCsr = p->apCsr;
- u.cd.pFrame->nCursor = p->nCursor;
- u.cd.pFrame->aOp = p->aOp;
- u.cd.pFrame->nOp = p->nOp;
- u.cd.pFrame->token = u.cd.pProgram->token;
- u.cd.pFrame->aOnceFlag = p->aOnceFlag;
- u.cd.pFrame->nOnceFlag = p->nOnceFlag;
+ pFrame->v = p;
+ pFrame->nChildMem = nMem;
+ pFrame->nChildCsr = pProgram->nCsr;
+ pFrame->pc = pc;
+ pFrame->aMem = p->aMem;
+ pFrame->nMem = p->nMem;
+ pFrame->apCsr = p->apCsr;
+ pFrame->nCursor = p->nCursor;
+ pFrame->aOp = p->aOp;
+ pFrame->nOp = p->nOp;
+ pFrame->token = pProgram->token;
+ pFrame->aOnceFlag = p->aOnceFlag;
+ pFrame->nOnceFlag = p->nOnceFlag;
- u.cd.pEnd = &VdbeFrameMem(u.cd.pFrame)[u.cd.pFrame->nChildMem];
- for(u.cd.pMem=VdbeFrameMem(u.cd.pFrame); u.cd.pMem!=u.cd.pEnd; u.cd.pMem++){
- u.cd.pMem->flags = MEM_Invalid;
- u.cd.pMem->db = db;
+ pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
+ for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
+ pMem->flags = MEM_Undefined;
+ pMem->db = db;
}
}else{
- u.cd.pFrame = u.cd.pRt->u.pFrame;
- assert( u.cd.pProgram->nMem+u.cd.pProgram->nCsr==u.cd.pFrame->nChildMem );
- assert( u.cd.pProgram->nCsr==u.cd.pFrame->nChildCsr );
- assert( pc==u.cd.pFrame->pc );
+ pFrame = pRt->u.pFrame;
+ assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem );
+ assert( pProgram->nCsr==pFrame->nChildCsr );
+ assert( pc==pFrame->pc );
}
p->nFrame++;
- u.cd.pFrame->pParent = p->pFrame;
- u.cd.pFrame->lastRowid = lastRowid;
- u.cd.pFrame->nChange = p->nChange;
+ pFrame->pParent = p->pFrame;
+ pFrame->lastRowid = lastRowid;
+ pFrame->nChange = p->nChange;
p->nChange = 0;
- p->pFrame = u.cd.pFrame;
- p->aMem = aMem = &VdbeFrameMem(u.cd.pFrame)[-1];
- p->nMem = u.cd.pFrame->nChildMem;
- p->nCursor = (u16)u.cd.pFrame->nChildCsr;
+ p->pFrame = pFrame;
+ p->aMem = aMem = &VdbeFrameMem(pFrame)[-1];
+ p->nMem = pFrame->nChildMem;
+ p->nCursor = (u16)pFrame->nChildCsr;
p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
- p->aOp = aOp = u.cd.pProgram->aOp;
- p->nOp = u.cd.pProgram->nOp;
+ p->aOp = aOp = pProgram->aOp;
+ p->nOp = pProgram->nOp;
p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
- p->nOnceFlag = u.cd.pProgram->nOnce;
+ p->nOnceFlag = pProgram->nOnce;
pc = -1;
memset(p->aOnceFlag, 0, p->nOnceFlag);
@@ -71918,13 +72424,11 @@ case OP_Program: { /* jump */
** calling OP_Program instruction.
*/
case OP_Param: { /*