rhodes 2.3.2 → 2.4.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +18 -0
- data/CREDITS +38 -0
- data/README.md +2 -2
- data/Rakefile +60 -2
- data/bin/set-rhodes-sdk.bat +1 -0
- data/doc/application.txt +11 -0
- data/doc/build.txt +156 -39
- data/doc/configuration.txt +1 -10
- data/doc/connect-to-web-services.txt +6 -6
- data/doc/device-caps.txt +48 -5
- data/doc/extensions.txt +8 -1
- data/doc/rhom.txt +16 -0
- data/doc/synchronization.txt +56 -14
- data/doc/ui.txt +23 -2
- data/installer/instant-rhodes.nsi +6 -6
- data/lib/extensions/barcode/ext/barcode/platform/iphone/Barcode.xcodeproj/project.pbxproj +4 -2
- data/lib/extensions/barcode/ext/barcode/platform/wm/Rakefile +1 -1
- data/lib/extensions/digest-md5/ext/Rakefile +3 -3
- data/lib/extensions/digest-md5/ext/build +0 -1
- data/lib/extensions/digest-sha1/ext/Rakefile +1 -1
- data/lib/extensions/digest-sha1/ext/build +0 -1
- data/lib/extensions/digest/ext/Rakefile +3 -3
- data/lib/extensions/digest/ext/build +0 -1
- data/lib/extensions/fcntl/ext/Rakefile +1 -1
- data/lib/extensions/mspec/mspec/guards/guard.rb +4 -0
- data/lib/extensions/mspec/mspec/helpers/environment.rb +4 -0
- data/lib/extensions/nfc/ext.yml +2 -0
- data/lib/extensions/nfc/ext/build +12 -0
- data/lib/extensions/nfc/ext/build.bat +8 -0
- data/lib/extensions/nfc/ext/nfc/platform/android/AndroidManifest.xml +25 -0
- data/lib/extensions/nfc/ext/nfc/platform/android/Rakefile +94 -0
- data/lib/extensions/nfc/ext/nfc/platform/android/ext_build.files +4 -0
- data/lib/extensions/nfc/ext/nfc/platform/android/jni/src/nfc.cpp +404 -0
- data/lib/extensions/nfc/ext/nfc/platform/android/src/com/nfc/Nfc.java +138 -0
- data/lib/extensions/nfc/ext/nfc/platform/android/src/com/nfc/NfcMessage.java +34 -0
- data/lib/extensions/nfc/ext/nfc/platform/android/src/com/nfc/NfcMessagePack.java +33 -0
- data/lib/extensions/nfc/ext/nfc/platform/android/src/com/nfc/NfcRecord.java +149 -0
- data/lib/extensions/nfc/ext/nfc/shared/ruby/nfc.i +22 -0
- data/lib/extensions/nfc/ext/nfc/shared/ruby/nfc_wrap.c +2034 -0
- data/lib/extensions/nfc/nfc.rb +120 -0
- data/lib/extensions/rholang/{lang_ca.rb → rholang/lang_ca.rb} +0 -0
- data/lib/extensions/rholang/{lang_cf.rb → rholang/lang_cf.rb} +0 -0
- data/lib/extensions/rholang/{lang_chef.rb → rholang/lang_chef.rb} +0 -0
- data/lib/extensions/rholang/{lang_cs.rb → rholang/lang_cs.rb} +0 -0
- data/lib/extensions/rholang/{lang_da.rb → rholang/lang_da.rb} +0 -0
- data/lib/extensions/rholang/{lang_de.rb → rholang/lang_de.rb} +0 -0
- data/lib/extensions/rholang/{lang_es.rb → rholang/lang_es.rb} +0 -0
- data/lib/extensions/rholang/{lang_es_ar.rb → rholang/lang_es_ar.rb} +0 -0
- data/lib/extensions/rholang/{lang_fi.rb → rholang/lang_fi.rb} +0 -0
- data/lib/extensions/rholang/{lang_fr.rb → rholang/lang_fr.rb} +0 -0
- data/lib/extensions/rholang/{lang_it.rb → rholang/lang_it.rb} +0 -0
- data/lib/extensions/rholang/{lang_ko.rb → rholang/lang_ko.rb} +0 -0
- data/lib/extensions/rholang/{lang_nl.rb → rholang/lang_nl.rb} +0 -0
- data/lib/extensions/rholang/{lang_no.rb → rholang/lang_no.rb} +0 -0
- data/lib/extensions/rholang/{lang_pt.rb → rholang/lang_pt.rb} +0 -0
- data/lib/extensions/rholang/{lang_pt_br.rb → rholang/lang_pt_br.rb} +0 -0
- data/lib/extensions/rholang/{lang_ru.rb → rholang/lang_ru.rb} +0 -0
- data/lib/extensions/rholang/{lang_se.rb → rholang/lang_se.rb} +0 -0
- data/lib/extensions/rholang/{lang_sr.rb → rholang/lang_sr.rb} +0 -0
- data/lib/extensions/rholang/{rhoerror_ru.rb → rholang/rhoerror_ru.rb} +0 -0
- data/lib/extensions/rholang/{rhomsg_ru.rb → rholang/rhomsg_ru.rb} +0 -0
- data/lib/framework/date/format.rb +2 -0
- data/lib/framework/dateOrig.rb +17 -8
- data/lib/framework/rational18.rb +532 -0
- data/lib/framework/res/back_btn.wp7.png +0 -0
- data/lib/framework/res/blue_pushpin.wp7.png +0 -0
- data/lib/framework/res/blue_pushpin_small.wp7.png +0 -0
- data/lib/framework/res/callout.wp7.png +0 -0
- data/lib/framework/res/callout_link.wp7.png +0 -0
- data/lib/framework/res/esri.wp7.png +0 -0
- data/lib/framework/res/forward_btn.wp7.png +0 -0
- data/lib/framework/res/home_btn.wp7.png +0 -0
- data/lib/framework/res/options_btn.wp7.png +0 -0
- data/lib/framework/res/refresh_btn.wp7.png +0 -0
- data/lib/framework/rho/render.rb +8 -1
- data/lib/framework/rho/rho.rb +30 -7
- data/lib/framework/rho/rhoapplication.rb +9 -4
- data/lib/framework/rho/rhofsconnector.rb +5 -1
- data/lib/framework/rho/rhotabbar.rb +8 -0
- data/lib/framework/rho/rhotoolbar.rb +1 -1
- data/lib/framework/rho/rhoviewhelpers.rb +18 -1
- data/lib/framework/rhodes.rb +1 -1
- data/lib/framework/rhoframework.rb +46 -1
- data/lib/framework/rholang/localization_simplified.rb +17 -16
- data/lib/framework/rhom/rhom_db_adapter.rb +2 -2
- data/lib/framework/rhom/rhom_object_factory.rb +115 -12
- data/lib/framework/rhosystem.rb +135 -0
- data/lib/framework/version.rb +1 -1
- data/lib/rhodes.rb +1 -1
- data/lib/test/apps/rhoconfig.txt +23 -23
- data/platform/android/Rhodes/AndroidManifest.full.xml +101 -0
- data/platform/android/Rhodes/AndroidManifest.xml +10 -15
- data/platform/android/Rhodes/default.properties +11 -0
- data/platform/android/Rhodes/gen/com/rhomobile/rhodes/R.java +59 -53
- data/platform/android/Rhodes/jni/include/rhodes.h +1 -0
- data/platform/android/Rhodes/jni/include/rhodes/jni/com_rhomobile_rhodes_RhodesApplication.h +21 -0
- data/platform/android/Rhodes/jni/include/rhodes/jni/com_rhomobile_rhodes_alert_PopupActivity.h +21 -0
- data/platform/android/Rhodes/jni/include/rhodes/jni/com_rhomobile_rhodes_file_RhoFileApi.h +10 -2
- data/platform/android/Rhodes/jni/src/alert.cpp +2 -1
- data/platform/android/Rhodes/jni/src/datetimepicker.cpp +2 -0
- data/platform/android/Rhodes/jni/src/fileapi.cpp +671 -84
- data/platform/android/Rhodes/jni/src/nativebar.cpp +18 -0
- data/platform/android/Rhodes/jni/src/rhodes.cpp +92 -1
- data/platform/android/Rhodes/res/values/styles.xml +7 -0
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/BaseActivity.java +35 -2
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/Capabilities.java +12 -13
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/LocalFileProvider.java +130 -0
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/NativeBar.java +6 -0
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/PushReceiver.java +5 -1
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/PushService.java +6 -2
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhoMenu.java +7 -36
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhodesActivity.java +43 -20
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhodesApplication.java +2 -0
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhodesService.java +63 -28
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/Utils.java +2 -2
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/WebView.java +6 -2
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/alert/Alert.java +19 -282
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/alert/PopupActivity.java +354 -0
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/datetime/DateTimePickerScreen.java +4 -0
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/event/EventStore.java +1 -2
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/file/RhoFileApi.java +71 -5
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/geolocation/GeoLocationImpl.java +107 -37
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/SimpleMainView.java +10 -7
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/TabbedMainView.java +156 -56
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/mapview/MapView.java +0 -1
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/ContactAccessorNew.java +40 -32
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/signature/SignatureView.java +1 -0
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/uri/ExternalHttpHandler.java +14 -6
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/uri/LocalFileHandler.java +46 -0
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/uri/MailUriHandler.java +4 -24
- data/platform/android/Rhodes/src/com/rhomobile/rhodes/uri/UriHandler.java +3 -1
- data/platform/android/build/RhodesSRC_build.files +28 -25
- data/platform/android/build/android.rake +230 -54
- data/platform/android/build/androidcommon.rb +1 -1
- data/platform/android/build/librhocommon_build.files +1 -0
- data/platform/bb/Hsqldb/BlackBerry_App_Descriptor.xml +20 -0
- data/platform/bb/Hsqldb/src/com/rho/db/HsqlDBResult.java +1 -5
- data/platform/bb/Hsqldb/src/com/rho/db/HsqlDBStorage.java +6 -1
- data/platform/bb/Hsqldb/src/org/hsqldb/rowio/RowOutputBase.java +1 -1
- data/platform/bb/Hsqldb/src/org/hsqldb/rowio/RowOutputBinary.java +1 -1
- data/platform/bb/RubyVM/BlackBerry_App_Descriptor.xml +20 -0
- data/platform/bb/RubyVM/src/com/rho/IRhoRubyHelper.java +2 -0
- data/platform/bb/RubyVM/src/com/rho/RhoLogOutputSink.java +0 -1
- data/platform/bb/RubyVM/src/com/rho/RhoLogger.java +12 -10
- data/platform/bb/RubyVM/src/com/rho/RhoThread.java +16 -0
- data/platform/bb/RubyVM/src/com/rho/RhoTimer.java +89 -0
- data/platform/bb/RubyVM/src/com/rho/RhodesApp.java +20 -13
- data/platform/bb/RubyVM/src/com/rho/SplashScreen.java +1 -2
- data/platform/bb/RubyVM/src/com/rho/ThreadQueue.java +2 -2
- data/platform/bb/RubyVM/src/com/rho/TimeInterval.java +5 -0
- data/platform/bb/RubyVM/src/com/rho/db/DBAdapter.java +54 -48
- data/platform/bb/RubyVM/src/com/rho/db/IDBResult.java +0 -1
- data/platform/bb/RubyVM/src/com/rho/db/IDBStorage.java +1 -0
- data/platform/bb/RubyVM/src/com/rho/net/AsyncHttp.java +1 -1
- data/platform/bb/RubyVM/src/com/rho/sync/ClientRegister.java +1 -1
- data/platform/bb/RubyVM/src/com/rho/sync/JSONStructIterator.java +1 -1
- data/platform/bb/RubyVM/src/com/rho/sync/SyncEngine.java +16 -8
- data/platform/bb/RubyVM/src/com/rho/sync/SyncNotify.java +2 -2
- data/platform/bb/RubyVM/src/com/rho/sync/SyncSource.java +52 -29
- data/platform/bb/RubyVM/src/com/rho/sync/SyncThread.java +1 -3
- data/platform/bb/build/RubyVM_build.files +1 -0
- data/platform/bb/build/bb.rake +29 -9
- data/platform/bb/rhodes/BlackBerry_App_Descriptor.xml +23 -0
- data/platform/bb/rhodes/platform/5.0/com/rho/RhodesApplicationPlatform.java +1 -1
- data/platform/bb/rhodes/platform/5.0/com/rho/db/SqliteCopyResult.java +0 -4
- data/platform/bb/rhodes/platform/5.0/com/rho/db/SqliteResult.java +13 -20
- data/platform/bb/rhodes/platform/5.0/com/rho/db/SqliteStorage.java +183 -157
- data/platform/bb/rhodes/src/com/rho/RhoRubyHelper.java +22 -0
- data/platform/bb/rhodes/src/com/rho/RhodesApplicationPlatform.java +1 -1
- data/platform/bb/rhodes/src/com/rho/db/SqliteCopyResult.java +0 -4
- data/platform/bb/rhodes/src/com/rho/db/SqliteResult.java +13 -20
- data/platform/bb/rhodes/src/com/rho/db/SqliteStorage.java +183 -157
- data/platform/bb/rhodes/src/com/rho/rubyext/System.java +46 -1
- data/platform/bb/rhodes/src/rhomobile/RhodesApplication.java +8 -1
- data/platform/bb/rhodes/src/rhomobile/camera/CameraFilesListener.java +13 -3
- data/platform/iphone/Classes/AppManager/AppManager.h +5 -1
- data/platform/iphone/Classes/AppManager/AppManager.m +170 -7
- data/platform/iphone/Classes/DateTimePicker.m +14 -1
- data/platform/iphone/Classes/DateTimePickerDelegate.h +2 -0
- data/platform/iphone/Classes/DateTimePickerDelegate.m +36 -2
- data/platform/iphone/Classes/NativeBar.h +1 -0
- data/platform/iphone/Classes/NativeBar.m +15 -3
- data/platform/iphone/Classes/Phonebook/phonebook.m +8 -9
- data/platform/iphone/Classes/Rhodes.m +50 -6
- data/platform/iphone/Classes/SimpleMainView.m +7 -6
- data/platform/iphone/Classes/SplitView/RightViewController.h +3 -1
- data/platform/iphone/Classes/SplitView/RightViewController.m +14 -1
- data/platform/iphone/Classes/TabbedMainView.h +4 -0
- data/platform/iphone/Classes/TabbedMainView.m +43 -26
- data/platform/iphone/Info.plist +1 -1
- data/platform/iphone/RhoLib/RhoLib.xcodeproj/project.pbxproj +4 -0
- data/platform/iphone/curl/curl.xcodeproj/project.pbxproj +3 -3
- data/platform/iphone/rbuild/iphone.rake +168 -119
- data/platform/iphone/rhoextlib/rhoextlib.xcodeproj/project.pbxproj +4 -2
- data/platform/iphone/rhorubylib/rhorubylib.xcodeproj/project.pbxproj +3 -3
- data/platform/iphone/rhorunner.xcodeproj/project.pbxproj +2 -2
- data/platform/iphone/rhosynclib/rhosynclib.xcodeproj/project.pbxproj +3 -3
- data/platform/shared/SyncClient/SyncClient.cpp +20 -8
- data/platform/shared/SyncClient/SyncClient.h +2 -1
- data/platform/shared/common/RhoDefs.h +4 -0
- data/platform/shared/common/RhoPort.h +22 -0
- data/platform/shared/common/RhoStd.h +5 -0
- data/platform/shared/common/RhoTime.cpp +73 -0
- data/platform/shared/common/RhoTime.h +26 -53
- data/platform/shared/common/RhodesApp.cpp +29 -28
- data/platform/shared/common/RhodesApp.h +4 -1
- data/platform/shared/common/StringConverter.h +37 -10
- data/platform/shared/common/app_build_capabilities.h +2 -0
- data/platform/shared/common/rhoparams.cpp +25 -12
- data/platform/shared/common/rhoparams.h +10 -8
- data/platform/shared/db/DBAdapter.cpp +0 -22
- data/platform/shared/json/RJSONTokener.c +15 -23
- data/platform/shared/net/AsyncHttp.cpp +9 -8
- data/platform/shared/net/HttpServer.cpp +61 -19
- data/platform/shared/net/HttpServer.h +2 -0
- data/platform/shared/ruby/ext/datetimepicker/datetimepicker.i +3 -0
- data/platform/shared/ruby/ext/datetimepicker/datetimepicker_wrap.c +151 -402
- data/platform/shared/ruby/ext/nativebar/nativebar.i +3 -0
- data/platform/shared/ruby/ext/nativebar/nativebar_wrap.c +154 -403
- data/platform/shared/ruby/ext/rho/rhoruby.c +4 -0
- data/platform/shared/ruby/ext/rho/rhoruby.h +2 -0
- data/platform/shared/ruby/ext/system/system.i +8 -0
- data/platform/shared/ruby/ext/system/system_wrap.c +80 -5
- data/platform/shared/ruby/file.c +6 -4
- data/platform/shared/ruby/gc.c +1 -1
- data/platform/shared/ruby/linux/ruby/config.h +7 -2
- data/platform/shared/ruby/missing/acosh.c +3 -3
- data/platform/shared/ruby/wince/_time.h +1 -1
- data/platform/shared/ruby/wince/stdlib.c +1 -1
- data/platform/shared/ruby/wince/string_wce.c +2 -2
- data/platform/shared/ruby/wince/sys/timeb.c +1 -0
- data/platform/shared/ruby/wince/time_wce.c +8 -0
- data/platform/shared/ruby/wince/wince.c +7 -7
- data/platform/shared/ruby/wince/wince.h +22 -0
- data/platform/shared/rubyext/System.cpp +19 -1
- data/platform/shared/sqlite/sqlite3.c +18993 -8129
- data/platform/shared/sqlite/sqlite3.h +953 -358
- data/platform/shared/sqlite/sqlite3ext.h +42 -0
- data/platform/shared/sync/SyncEngine.cpp +10 -0
- data/platform/shared/sync/SyncSource.cpp +41 -19
- data/platform/shared/sync/SyncSource.h +1 -1
- data/platform/shared/tcmalloc/rhomem.h +7 -2
- data/platform/shared/tcmalloc/windows/port.h +2 -0
- data/platform/shared/unzip/unzip.cpp +1 -0
- data/platform/shared/xruby/src/com/xruby/compiler/parser/RubyParser.java +11 -1
- data/platform/wm/RhoLib/RhoLib.vcproj +182 -24
- data/platform/wm/build/wm.rake +16 -3
- data/platform/wm/rhodes.sln +106 -113
- data/platform/wm/rhodes/Alert.cpp +6 -7
- data/platform/wm/rhodes/AppManager.cpp +8 -17
- data/platform/wm/rhodes/DateTimePicker.cpp +3 -0
- data/platform/wm/rhodes/DateTimePicker.h +2 -0
- data/platform/wm/rhodes/MainWindow.cpp +36 -16
- data/platform/wm/rhodes/MainWindow.h +6 -3
- data/platform/wm/rhodes/OutlookApp.cpp +3 -3
- data/platform/wm/rhodes/Rhodes.cpp +46 -27
- data/platform/wm/rhodes/Rhodes.rc +16 -3
- data/platform/wm/rhodes/RingtoneManager.cpp +7 -7
- data/platform/wm/rhodes/RingtoneManager.h +1 -1
- data/platform/wm/rhodes/Utils.cpp +2 -1
- data/platform/wm/rhodes/bluetooth/Bluetooth.cpp +1 -13
- data/platform/wm/rhodes/bluetooth/Bluetooth.h +1 -2
- data/platform/wm/rhodes/camera/Camera.cpp +6 -12
- data/platform/wm/rhodes/phonebook/phonebook.cpp +11 -11
- data/platform/wm/rhodes/phonebook/phonebook.h +1 -1
- data/platform/wm/rhodes/resource.h +3 -1
- data/platform/wm/rhodes/rho/net/NetRequestImpl.cpp +7 -5
- data/platform/wm/rhodes/rho/rubyext/GeoLocationImpl.cpp +6 -6
- data/platform/wm/rhodes/rho/rubyext/GeoLocationImpl.h +1 -1
- data/platform/wm/rhodes/rho/rubyext/NativeToolbar.cpp +6 -1
- data/platform/wm/rhodes/rho/rubyext/SystemImpl.cpp +84 -19
- data/platform/wm/rhodes/rho/rubyext/calendar.cpp +2 -2
- data/platform/wm/rhodes/rhodes.vcproj +316 -73
- data/platform/wm/rhodes/signature/Signature.cpp +336 -6
- data/platform/wm/rhodes/signature/Signature.h +55 -0
- data/platform/wm/rhodes/stdafx.h +7 -4
- data/platform/wm/rubylib/rubylib.vcproj +261 -91
- data/platform/wm/sqlite3/sqlite3.vcproj +223 -69
- data/platform/wm/syncengine/syncengine.vcproj +220 -66
- data/platform/wm/tcmalloc/tcmalloc.vcproj +197 -43
- data/platform/wp7/IronRuby/Languages/Ruby/Ruby/Builtins/ConsoleStream.cs +107 -0
- data/platform/wp7/IronRuby/Languages/Ruby/Ruby/Runtime/Loader.cs +1037 -0
- data/platform/wp7/IronRuby/Languages/Ruby/Ruby/Runtime/RubyUtils.cs +1476 -0
- data/platform/wp7/RhoAppRunner/Program.cs +55 -0
- data/platform/wp7/RhoAppRunner/Properties/AssemblyInfo.cs +36 -0
- data/platform/wp7/RhoAppRunner/RhoAppRunner.csproj +69 -0
- data/platform/wp7/RhoRubyExtGen/GenerateInitializers.cmd +7 -0
- data/platform/wp7/RhoRubyExtGen/Properties/AssemblyInfo.cs +36 -0
- data/platform/wp7/RhoRubyExtGen/RhoAsyncHttp.cs +38 -0
- data/platform/wp7/RhoRubyExtGen/RhoDatabase.cs +93 -0
- data/platform/wp7/RhoRubyExtGen/RhoJSON.cs +37 -0
- data/platform/wp7/RhoRubyExtGen/RhoNativeBar.cs +106 -0
- data/platform/wp7/RhoRubyExtGen/RhoRubyExtGen.csproj +75 -0
- data/platform/wp7/RhoRubyExtGen/RhoSyncEngine.cs +123 -0
- data/platform/wp7/RhoRubyExtGen/RhoWebView.cs +42 -0
- data/platform/wp7/RhoRubyLib/Initializers.Generated.cs +309 -0
- data/platform/wp7/RhoRubyLib/Properties/AssemblyInfo.cs +36 -0
- data/platform/wp7/RhoRubyLib/RhoAppAdapter.cs +96 -0
- data/platform/wp7/RhoRubyLib/RhoRuby.cs +296 -0
- data/platform/wp7/RhoRubyLib/RhoRubyLib.csproj +155 -0
- data/platform/wp7/RhoRubyLib/WP_PlatformAdaptationLayer.cs +107 -0
- data/platform/wp7/RhoRubyLib/common/IInputStream.cs +21 -0
- data/platform/wp7/RhoRubyLib/common/Mutex.cs +30 -0
- data/platform/wp7/RhoRubyLib/common/RhoConf.cs +389 -0
- data/platform/wp7/RhoRubyLib/common/RhoEmptyProfiler.cs +27 -0
- data/platform/wp7/RhoRubyLib/common/RhoFile.cs +332 -0
- data/platform/wp7/RhoRubyLib/common/RhoFilePath.cs +89 -0
- data/platform/wp7/RhoRubyLib/common/RhoParamArray.cs +33 -0
- data/platform/wp7/RhoRubyLib/common/RhoParams.cs +66 -0
- data/platform/wp7/RhoRubyLib/common/RhoProfiler.cs +145 -0
- data/platform/wp7/RhoRubyLib/common/RhoResourceMap.cs +68 -0
- data/platform/wp7/RhoRubyLib/common/RhoStd.cs +205 -0
- data/platform/wp7/RhoRubyLib/common/RhoThread.cs +114 -0
- data/platform/wp7/RhoRubyLib/common/RhodesApp.cs +504 -0
- data/platform/wp7/RhoRubyLib/common/ThreadQueue.cs +199 -0
- data/platform/wp7/RhoRubyLib/common/TimeInterval.cs +56 -0
- data/platform/wp7/RhoRubyLib/common/Tokenizer.cs +52 -0
- data/platform/wp7/RhoRubyLib/db/DBAdapter.cs +1129 -0
- data/platform/wp7/RhoRubyLib/db/DBAttrManager.cs +92 -0
- data/platform/wp7/RhoRubyLib/db/DBException.cs +35 -0
- data/platform/wp7/RhoRubyLib/db/IDBCallback.cs +10 -0
- data/platform/wp7/RhoRubyLib/db/IDBResult.cs +33 -0
- data/platform/wp7/RhoRubyLib/db/IDBStorage.cs +32 -0
- data/platform/wp7/RhoRubyLib/db/SqliteCopyResult.cs +79 -0
- data/platform/wp7/RhoRubyLib/db/SqliteResult.cs +267 -0
- data/platform/wp7/RhoRubyLib/db/SqliteStorage.cs +319 -0
- data/platform/wp7/RhoRubyLib/json/JSONArrayIterator.cs +63 -0
- data/platform/wp7/RhoRubyLib/json/JSONEntry.cs +96 -0
- data/platform/wp7/RhoRubyLib/json/JSONStructIterator.cs +77 -0
- data/platform/wp7/RhoRubyLib/json/JsonParser.cs +483 -0
- data/platform/wp7/RhoRubyLib/json/RJSONTokener.cs +406 -0
- data/platform/wp7/RhoRubyLib/logging/IRhoLogSink.cs +12 -0
- data/platform/wp7/RhoRubyLib/logging/RhoLogConf.cs +161 -0
- data/platform/wp7/RhoRubyLib/logging/RhoLogFileSink.cs +174 -0
- data/platform/wp7/RhoRubyLib/logging/RhoLogger.cs +320 -0
- data/platform/wp7/RhoRubyLib/net/AsyncHttp.cs +362 -0
- data/platform/wp7/RhoRubyLib/net/HttpServer.cs +466 -0
- data/platform/wp7/RhoRubyLib/net/NetRequest.cs +717 -0
- data/platform/wp7/RhoRubyLib/net/NetResponse.cs +64 -0
- data/platform/wp7/RhoRubyLib/net/URI.cs +187 -0
- data/platform/wp7/RhoRubyLib/rubyext/RhoAsyncHttp.cs +43 -0
- data/platform/wp7/RhoRubyLib/rubyext/RhoDatabase.cs +177 -0
- data/platform/wp7/RhoRubyLib/rubyext/RhoJSON.cs +39 -0
- data/platform/wp7/RhoRubyLib/rubyext/RhoKernelOps.cs +19 -0
- data/platform/wp7/RhoRubyLib/rubyext/RhoNativeBar.cs +117 -0
- data/platform/wp7/RhoRubyLib/rubyext/RhoSyncEngine.cs +199 -0
- data/platform/wp7/RhoRubyLib/rubyext/RhoWebView.cs +49 -0
- data/platform/wp7/RhoRubyLib/sync/ClientRegister.cs +142 -0
- data/platform/wp7/RhoRubyLib/sync/ISyncProtocol.cs +23 -0
- data/platform/wp7/RhoRubyLib/sync/ISyncStatusListener.cs +10 -0
- data/platform/wp7/RhoRubyLib/sync/SyncEngine.cs +1051 -0
- data/platform/wp7/RhoRubyLib/sync/SyncNotify.cs +651 -0
- data/platform/wp7/RhoRubyLib/sync/SyncProtocol_3.cs +79 -0
- data/platform/wp7/RhoRubyLib/sync/SyncSource.cs +1105 -0
- data/platform/wp7/RhoRubyLib/sync/SyncThread.cs +301 -0
- data/platform/wp7/WPApplication.sln +50 -0
- data/platform/wp7/WPApplication/App.xaml +19 -0
- data/platform/wp7/WPApplication/App.xaml.cs +211 -0
- data/platform/wp7/WPApplication/ApplicationIcon.png +0 -0
- data/platform/wp7/WPApplication/Background.png +0 -0
- data/platform/wp7/WPApplication/MainPage.xaml +44 -0
- data/platform/wp7/WPApplication/MainPage.xaml.cs +132 -0
- data/platform/wp7/WPApplication/Properties/AppManifest.xml +6 -0
- data/platform/wp7/WPApplication/Properties/AssemblyInfo.cs +35 -0
- data/platform/wp7/WPApplication/Properties/WMAppManifest.xml +32 -0
- data/platform/wp7/WPApplication/SplashScreenImage.jpg +0 -0
- data/platform/wp7/WPApplication/WPApplication.csproj +201 -0
- data/platform/wp7/WPApplication/WP_PlatformAdaptationLayer.cs +88 -0
- data/platform/wp7/WPApplication/app_manifest.txt +1 -0
- data/platform/wp7/WPApplication/readme.htm +40 -0
- data/platform/wp7/WPApplication/readme2.htm +37 -0
- data/platform/wp7/WPApplication/rho/apps/app/Model1/edit.bb.erb +29 -0
- data/platform/wp7/WPApplication/rho/apps/app/Model1/edit.erb +32 -0
- data/platform/wp7/WPApplication/rho/apps/app/Model1/index.bb.erb +21 -0
- data/platform/wp7/WPApplication/rho/apps/app/Model1/index.erb +26 -0
- data/platform/wp7/WPApplication/rho/apps/app/Model1/model1.rb +10 -0
- data/platform/wp7/WPApplication/rho/apps/app/Model1/model1_controller.rb +58 -0
- data/platform/wp7/WPApplication/rho/apps/app/Model1/new.bb.erb +29 -0
- data/platform/wp7/WPApplication/rho/apps/app/Model1/new.erb +31 -0
- data/platform/wp7/WPApplication/rho/apps/app/Model1/show.bb.erb +26 -0
- data/platform/wp7/WPApplication/rho/apps/app/Model1/show.erb +28 -0
- data/platform/wp7/WPApplication/rho/apps/app/Settings/controller.rb +75 -0
- data/platform/wp7/WPApplication/rho/apps/app/Settings/home.bb.erb +17 -0
- data/platform/wp7/WPApplication/rho/apps/app/Settings/home.erb +20 -0
- data/platform/wp7/WPApplication/rho/apps/app/Settings/index.bb.erb +32 -0
- data/platform/wp7/WPApplication/rho/apps/app/Settings/index.erb +30 -0
- data/platform/wp7/WPApplication/rho/apps/app/Settings/login.bb.erb +35 -0
- data/platform/wp7/WPApplication/rho/apps/app/Settings/login.erb +27 -0
- data/platform/wp7/WPApplication/rho/apps/app/Settings/reset.bb.erb +15 -0
- data/platform/wp7/WPApplication/rho/apps/app/Settings/reset.erb +17 -0
- data/platform/wp7/WPApplication/rho/apps/app/Settings/wait.bb.erb +3 -0
- data/platform/wp7/WPApplication/rho/apps/app/Settings/wait.erb +5 -0
- data/platform/wp7/WPApplication/rho/apps/app/application.rb +16 -0
- data/platform/wp7/WPApplication/rho/apps/app/helpers/application_helper.rb +126 -0
- data/platform/wp7/WPApplication/rho/apps/app/helpers/browser_helper.rb +18 -0
- data/platform/wp7/WPApplication/rho/apps/app/index.bb.erb +26 -0
- data/platform/wp7/WPApplication/rho/apps/app/index.erb +26 -0
- data/platform/wp7/WPApplication/rho/apps/app/layout.erb +45 -0
- data/platform/wp7/WPApplication/rho/apps/app/loading.html +11 -0
- data/platform/wp7/WPApplication/rho/apps/app_manifest.txt +1 -0
- data/platform/wp7/WPApplication/rho/apps/public/css/android.css +330 -0
- data/platform/wp7/WPApplication/rho/apps/public/css/blackberry.css +115 -0
- data/platform/wp7/WPApplication/rho/apps/public/css/iphone.css +410 -0
- data/platform/wp7/WPApplication/rho/apps/public/css/windows_mobile.css +222 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/IUI_LICENSE.txt +21 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/android/btn_check_off.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/android/btn_check_on.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/android/btn_radio_off.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/android/btn_radio_on.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/android/disclosure.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/android/ic_menu_more.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/backButton.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/blueButton.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/cancel.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/grayButton.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/disclosure.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/disclosure_detail.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/backButton.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/blueButton.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/cancel.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/chevron.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/grayButton.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/listArrowSel.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/listGroup.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/loading.gif +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/on_off.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/pinstripes.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/selection.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/thumb.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/toggle.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/toggleOn.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/toolButton.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/toolbar.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/whiteButton.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/radiobutton.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/select.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iphone/switch.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/iui-logo-touch-icon.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/listArrow.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/listArrowDown.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/listArrowSel.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/listGroup.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/loading.gif +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/pinstripes.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/right_button.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/selection.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/thumb.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/toggle.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/toggleOn.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/toolButton.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/toolButton_new.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/toolbar.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/images/whiteButton.png +0 -0
- data/platform/wp7/WPApplication/rho/apps/public/jqtouch/jqtouch-iphone.css +9 -0
- data/platform/wp7/WPApplication/rho/apps/public/jqtouch/jqtouch.css +374 -0
- data/platform/wp7/WPApplication/rho/apps/public/jqtouch/jqtouch.js +742 -0
- data/platform/wp7/WPApplication/rho/apps/public/jqtouch/jqtouch.transitions.js +60 -0
- data/platform/wp7/WPApplication/rho/apps/public/jqtouch/jquery.1.3.2.min.js +19 -0
- data/platform/wp7/WPApplication/rho/apps/public/js/application.js +1 -0
- data/platform/wp7/WPApplication/rho/apps/public/js/rho.js +4 -0
- data/platform/wp7/WPApplication/rho/apps/public/js/rhogeolocation-wm.js +59 -0
- data/platform/wp7/WPApplication/rho/apps/public/js/rhogeolocation.js +11 -0
- data/platform/wp7/WPApplication/rho/apps/rhoconfig.txt +32 -0
- data/platform/wp7/WPApplication/rhoconfig.txt +32 -0
- data/platform/wp7/WPApplication/windows_mobile.css +222 -0
- data/platform/wp7/build/wp.rake +261 -0
- data/platform/wp7/rhodes.sln +79 -0
- data/platform/wp7/rhodes/App.xaml +19 -0
- data/platform/wp7/rhodes/App.xaml.cs +144 -0
- data/platform/wp7/rhodes/Background.png +0 -0
- data/platform/wp7/rhodes/MainPage.xaml +44 -0
- data/platform/wp7/rhodes/MainPage.xaml.cs +98 -0
- data/platform/wp7/rhodes/Properties/AppManifest.xml +6 -0
- data/platform/wp7/rhodes/Properties/AssemblyInfo.cs +35 -0
- data/platform/wp7/rhodes/Properties/WMAppManifest.xml +31 -0
- data/platform/wp7/rhodes/Rhodes.csproj +127 -0
- data/platform/wp7/rhodes/SplashScreenImage.jpg +0 -0
- data/platform/wp7/rhodes/icon.png +0 -0
- data/platform/wp7/sqlite3/Properties/AssemblyInfo.cs +35 -0
- data/platform/wp7/sqlite3/SQLiteClient.cs +550 -0
- data/platform/wp7/sqlite3/SqliteWrapper/BtreeInt_h.cs +774 -0
- data/platform/wp7/sqlite3/SqliteWrapper/Btree_h.cs +280 -0
- data/platform/wp7/sqlite3/SqliteWrapper/ClassDiagram1.cd +1306 -0
- data/platform/wp7/sqlite3/SqliteWrapper/Delagates.cs +365 -0
- data/platform/wp7/sqlite3/SqliteWrapper/Hash_h.cs +133 -0
- data/platform/wp7/sqlite3/SqliteWrapper/VdbeInt_h.cs +620 -0
- data/platform/wp7/sqlite3/SqliteWrapper/Vdbe_h.cs +302 -0
- data/platform/wp7/sqlite3/SqliteWrapper/_Custom.cs +449 -0
- data/platform/wp7/sqlite3/SqliteWrapper/alter_c.cs +872 -0
- data/platform/wp7/sqlite3/SqliteWrapper/analyze_c.cs +757 -0
- data/platform/wp7/sqlite3/SqliteWrapper/attach_c.cs +628 -0
- data/platform/wp7/sqlite3/SqliteWrapper/auth_c.cs +268 -0
- data/platform/wp7/sqlite3/SqliteWrapper/backup_c.cs +737 -0
- data/platform/wp7/sqlite3/SqliteWrapper/bitvec_c.cs +509 -0
- data/platform/wp7/sqlite3/SqliteWrapper/btmutex_c.cs +379 -0
- data/platform/wp7/sqlite3/SqliteWrapper/btree_c.cs +9138 -0
- data/platform/wp7/sqlite3/SqliteWrapper/build_c.cs +4189 -0
- data/platform/wp7/sqlite3/SqliteWrapper/callback_c.cs +548 -0
- data/platform/wp7/sqlite3/SqliteWrapper/complete_c.cs +342 -0
- data/platform/wp7/sqlite3/SqliteWrapper/ctime_cs.cs +408 -0
- data/platform/wp7/sqlite3/SqliteWrapper/date_c.cs +1317 -0
- data/platform/wp7/sqlite3/SqliteWrapper/delete_c.cs +726 -0
- data/platform/wp7/sqlite3/SqliteWrapper/expr_c.cs +4406 -0
- data/platform/wp7/sqlite3/SqliteWrapper/fault_c.cs +115 -0
- data/platform/wp7/sqlite3/SqliteWrapper/fkey_c.cs +1330 -0
- data/platform/wp7/sqlite3/SqliteWrapper/func_c.cs +2025 -0
- data/platform/wp7/sqlite3/SqliteWrapper/global_c.cs +228 -0
- data/platform/wp7/sqlite3/SqliteWrapper/hash_c.cs +351 -0
- data/platform/wp7/sqlite3/SqliteWrapper/hwtime_c.cs +101 -0
- data/platform/wp7/sqlite3/SqliteWrapper/insert_c.cs +2122 -0
- data/platform/wp7/sqlite3/SqliteWrapper/journal_c.cs +247 -0
- data/platform/wp7/sqlite3/SqliteWrapper/keywordhash_h.cs +302 -0
- data/platform/wp7/sqlite3/SqliteWrapper/legacy_c.cs +223 -0
- data/platform/wp7/sqlite3/SqliteWrapper/loadext_c.cs +683 -0
- data/platform/wp7/sqlite3/SqliteWrapper/main_c.cs +2716 -0
- data/platform/wp7/sqlite3/SqliteWrapper/malloc_c.cs +977 -0
- data/platform/wp7/sqlite3/SqliteWrapper/mem_Pool.cs +394 -0
- data/platform/wp7/sqlite3/SqliteWrapper/memjournal_c.cs +315 -0
- data/platform/wp7/sqlite3/SqliteWrapper/mutex_c.cs +182 -0
- data/platform/wp7/sqlite3/SqliteWrapper/mutex_h.cs +91 -0
- data/platform/wp7/sqlite3/SqliteWrapper/mutex_noop_c.cs +202 -0
- data/platform/wp7/sqlite3/SqliteWrapper/mutex_w32.cs +344 -0
- data/platform/wp7/sqlite3/SqliteWrapper/notify_c.cs +347 -0
- data/platform/wp7/sqlite3/SqliteWrapper/opcodes_c.cs +171 -0
- data/platform/wp7/sqlite3/SqliteWrapper/opcodes_h.cs +346 -0
- data/platform/wp7/sqlite3/SqliteWrapper/os_c.cs +367 -0
- data/platform/wp7/sqlite3/SqliteWrapper/os_common_h.cs +174 -0
- data/platform/wp7/sqlite3/SqliteWrapper/os_h.cs +295 -0
- data/platform/wp7/sqlite3/SqliteWrapper/os_win_c.cs +1255 -0
- data/platform/wp7/sqlite3/SqliteWrapper/pager_c.cs +6078 -0
- data/platform/wp7/sqlite3/SqliteWrapper/pager_h.cs +188 -0
- data/platform/wp7/sqlite3/SqliteWrapper/parse_c.cs +4045 -0
- data/platform/wp7/sqlite3/SqliteWrapper/parse_h.cs +331 -0
- data/platform/wp7/sqlite3/SqliteWrapper/pcache1_c.cs +969 -0
- data/platform/wp7/sqlite3/SqliteWrapper/pcache_c.cs +712 -0
- data/platform/wp7/sqlite3/SqliteWrapper/pcache_h.cs +213 -0
- data/platform/wp7/sqlite3/SqliteWrapper/pragma_c.cs +1767 -0
- data/platform/wp7/sqlite3/SqliteWrapper/prepare_c.cs +1015 -0
- data/platform/wp7/sqlite3/SqliteWrapper/printf_c.cs +1300 -0
- data/platform/wp7/sqlite3/SqliteWrapper/random_c.cs +201 -0
- data/platform/wp7/sqlite3/SqliteWrapper/resolve_c.cs +1396 -0
- data/platform/wp7/sqlite3/SqliteWrapper/rowset_c.cs +519 -0
- data/platform/wp7/sqlite3/SqliteWrapper/select_c.cs +4878 -0
- data/platform/wp7/sqlite3/SqliteWrapper/sqlite3_h.cs +6253 -0
- data/platform/wp7/sqlite3/SqliteWrapper/sqlite3ext_h.cs +397 -0
- data/platform/wp7/sqlite3/SqliteWrapper/sqliteInt_h.cs +4075 -0
- data/platform/wp7/sqlite3/SqliteWrapper/sqliteLimit_h.cs +214 -0
- data/platform/wp7/sqlite3/SqliteWrapper/sqliteicu_h.cs +39 -0
- data/platform/wp7/sqlite3/SqliteWrapper/status_c.cs +155 -0
- data/platform/wp7/sqlite3/SqliteWrapper/table_c.cs +222 -0
- data/platform/wp7/sqlite3/SqliteWrapper/tokenize_c.cs +673 -0
- data/platform/wp7/sqlite3/SqliteWrapper/trigger_c.cs +1219 -0
- data/platform/wp7/sqlite3/SqliteWrapper/update_c.cs +766 -0
- data/platform/wp7/sqlite3/SqliteWrapper/utf_c.cs +612 -0
- data/platform/wp7/sqlite3/SqliteWrapper/util_c.cs +1476 -0
- data/platform/wp7/sqlite3/SqliteWrapper/vacuum_c.cs +382 -0
- data/platform/wp7/sqlite3/SqliteWrapper/vdbe_c.cs +6566 -0
- data/platform/wp7/sqlite3/SqliteWrapper/vdbeapi_c.cs +1557 -0
- data/platform/wp7/sqlite3/SqliteWrapper/vdbeaux_c.cs +4019 -0
- data/platform/wp7/sqlite3/SqliteWrapper/vdbeblob_c.cs +396 -0
- data/platform/wp7/sqlite3/SqliteWrapper/vdbemem_c.cs +1480 -0
- data/platform/wp7/sqlite3/SqliteWrapper/vdbetrace_c.cs +181 -0
- data/platform/wp7/sqlite3/SqliteWrapper/vtab_c.cs +957 -0
- data/platform/wp7/sqlite3/SqliteWrapper/walker_c.cs +174 -0
- data/platform/wp7/sqlite3/SqliteWrapper/where_c.cs +4651 -0
- data/platform/wp7/sqlite3/sqlite3.csproj +155 -0
- data/rakefile.rb +60 -2
- data/res/build-tools/7za.exe +0 -0
- data/res/build-tools/RhoAppRunner.exe +0 -0
- data/res/build-tools/xruby-0.3.3.jar +0 -0
- data/res/generators/rhogen.rb +9 -1
- data/res/generators/templates/application/app/Settings/reset.erb +1 -1
- data/res/generators/templates/application/app/layout.erb +17 -10
- data/res/generators/templates/application/build.yml +5 -3
- data/res/generators/templates/application/public/jqtouch/changes.txt +20 -0
- data/res/generators/templates/application/public/jqtouch/jqtouch.js +12 -4
- data/res/generators/templates/application/public/jqtouch/jquery.1.3.2.min.js +1 -1
- data/res/generators/templates/application/public/js/wp7.js +7 -0
- data/res/generators/templates/model/controller.rb +5 -6
- data/rhobuild.yml.example +1 -0
- data/rhodes.gemspec +2 -1
- data/spec/framework_spec/app/spec/core/dir/close_spec.rb +1 -1
- data/spec/framework_spec/app/spec/core/dir/shared/pwd.rb +13 -11
- data/spec/framework_spec/app/spec/core/env/shared/store.rb +12 -10
- data/spec/framework_spec/app/spec/core/env/update_spec.rb +1 -0
- data/spec/framework_spec/app/spec/core/file/expand_path_spec.rb +3 -2
- data/spec/framework_spec/app/spec/core/file/fixtures/file_types.rb +7 -1
- data/spec/framework_spec/app/spec/core/file/flock_spec.rb +8 -1
- data/spec/framework_spec/app/spec/core/file/ftype_spec.rb +5 -3
- data/spec/framework_spec/app/spec/core/file/lchmod_spec.rb +1 -1
- data/spec/framework_spec/app/spec/core/file/setgid_spec.rb +1 -1
- data/spec/framework_spec/app/spec/core/file/setuid_spec.rb +1 -1
- data/spec/framework_spec/app/spec/core/file/stat/ftype_spec.rb +6 -4
- data/spec/framework_spec/app/spec/core/file/truncate_spec.rb +5 -1
- data/spec/framework_spec/app/spec/core/float/to_s_spec.rb +1 -1
- data/spec/framework_spec/app/spec/core/process/gid_spec.rb +5 -3
- data/spec/framework_spec/app/spec/core/process/groups_spec.rb +11 -9
- data/spec/framework_spec/app/spec/core/process/uid_spec.rb +5 -3
- data/spec/framework_spec/app/spec/language/execution_spec.rb +10 -6
- data/spec/framework_spec/app/spec/shared/file/directory.rb +6 -1
- data/spec/framework_spec/app/spec/shared/file/executable.rb +7 -1
- data/spec/framework_spec/app/spec/shared/file/file.rb +6 -1
- data/spec/framework_spec/app/spec/shared/file/readable.rb +13 -4
- data/spec/framework_spec/app/spec/shared/file/writable.rb +6 -1
- data/spec/phone_spec/app/spec/rho_controller_spec.rb +11 -0
- data/spec/phone_spec/app/spec/rho_spec.rb +11 -0
- data/spec/phone_spec/app/spec/rhom_object_spec.rb +102 -6
- data/spec/phone_spec/app/spec/string/end_with_spec.rb +4 -1
- data/spec/phone_spec/app/spec/string/slice_spec.rb +5 -1
- data/spec/phone_spec/app/spec/string/start_with_spec.rb +4 -0
- data/spec/phone_spec/app/spec/syncengine_spec.rb +73 -6
- data/spec/phone_spec/app/spec_runner.rb +7 -3
- metadata +380 -41
- data/Manifest.txt +0 -5819
- data/platform/bb/Hsqldb/Hsqldb.cso +0 -5
- data/platform/bb/Hsqldb/Hsqldb.jdp +0 -197
- data/platform/bb/RhoBundle/RhoBundle.cso +0 -5
- data/platform/bb/RhoBundle/RhoBundle.jdp +0 -42
- data/platform/bb/RubyVM/RubyVM.cso +0 -5
- data/platform/bb/RubyVM/RubyVM.jdp +0 -467
- data/platform/bb/rhodes/rhodes.csl +0 -3
- data/platform/bb/rhodes/rhodes.cso +0 -5
- data/platform/bb/rhodes/rhodes.jdp +0 -104
@@ -0,0 +1,4019 @@
|
|
1
|
+
using System;
|
2
|
+
using System.Diagnostics;
|
3
|
+
using System.Text;
|
4
|
+
|
5
|
+
using FILE = System.IO.TextWriter;
|
6
|
+
using i32 = System.Int32;
|
7
|
+
using i64 = System.Int64;
|
8
|
+
using u8 = System.Byte;
|
9
|
+
using u16 = System.UInt16;
|
10
|
+
using u32 = System.UInt32;
|
11
|
+
using u64 = System.UInt64;
|
12
|
+
|
13
|
+
using Pgno = System.UInt32;
|
14
|
+
|
15
|
+
#if !SQLITE_MAX_VARIABLE_NUMBER
|
16
|
+
using ynVar = System.Int16;
|
17
|
+
#else
|
18
|
+
using ynVar = System.Int32;
|
19
|
+
#endif
|
20
|
+
|
21
|
+
namespace Community.CsharpSqlite
|
22
|
+
{
|
23
|
+
using Op = Sqlite3.VdbeOp;
|
24
|
+
using sqlite3_stmt = Sqlite3.Vdbe;
|
25
|
+
using sqlite3_value = Sqlite3.Mem;
|
26
|
+
|
27
|
+
public partial class Sqlite3
|
28
|
+
{
|
29
|
+
/*
|
30
|
+
** 2003 September 6
|
31
|
+
**
|
32
|
+
** The author disclaims copyright to this source code. In place of
|
33
|
+
** a legal notice, here is a blessing:
|
34
|
+
**
|
35
|
+
** May you do good and not evil.
|
36
|
+
** May you find forgiveness for yourself and forgive others.
|
37
|
+
** May you share freely, never taking more than you give.
|
38
|
+
**
|
39
|
+
*************************************************************************
|
40
|
+
** This file contains code used for creating, destroying, and populating
|
41
|
+
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior
|
42
|
+
** to version 2.8.7, all this code was combined into the vdbe.c source file.
|
43
|
+
** But that file was getting too big so this subroutines were split out.
|
44
|
+
*************************************************************************
|
45
|
+
** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
|
46
|
+
** C#-SQLite is an independent reimplementation of the SQLite software library
|
47
|
+
**
|
48
|
+
** SQLITE_SOURCE_ID: 2010-03-09 19:31:43 4ae453ea7be69018d8c16eb8dabe05617397dc4d
|
49
|
+
**
|
50
|
+
** $Header$
|
51
|
+
*************************************************************************
|
52
|
+
*/
|
53
|
+
//#include "sqliteInt.h"
|
54
|
+
//#include "vdbeInt.h"
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
/*
|
59
|
+
** When debugging the code generator in a symbolic debugger, one can
|
60
|
+
** set the sqlite3VdbeAddopTrace to 1 and all opcodes will be printed
|
61
|
+
** as they are added to the instruction stream.
|
62
|
+
*/
|
63
|
+
#if SQLITE_DEBUG
|
64
|
+
static bool sqlite3VdbeAddopTrace = false;
|
65
|
+
#endif
|
66
|
+
|
67
|
+
|
68
|
+
/*
|
69
|
+
** Create a new virtual database engine.
|
70
|
+
*/
|
71
|
+
static Vdbe sqlite3VdbeCreate( sqlite3 db )
|
72
|
+
{
|
73
|
+
Vdbe p;
|
74
|
+
p = new Vdbe();// sqlite3DbMallocZero(db, Vdbe).Length;
|
75
|
+
if ( p == null ) return null;
|
76
|
+
p.db = db;
|
77
|
+
if ( db.pVdbe != null )
|
78
|
+
{
|
79
|
+
db.pVdbe.pPrev = p;
|
80
|
+
}
|
81
|
+
p.pNext = db.pVdbe;
|
82
|
+
p.pPrev = null;
|
83
|
+
db.pVdbe = p;
|
84
|
+
p.magic = VDBE_MAGIC_INIT;
|
85
|
+
return p;
|
86
|
+
}
|
87
|
+
|
88
|
+
/*
|
89
|
+
** Remember the SQL string for a prepared statement.
|
90
|
+
*/
|
91
|
+
static void sqlite3VdbeSetSql( Vdbe p, string z, int n, int isPrepareV2 )
|
92
|
+
{
|
93
|
+
Debug.Assert( isPrepareV2 == 1 || isPrepareV2 == 0 );
|
94
|
+
if ( p == null ) return;
|
95
|
+
#if SQLITE_OMIT_TRACE
|
96
|
+
if( 0==isPrepareV2 ) return;
|
97
|
+
#endif
|
98
|
+
Debug.Assert( p.zSql == "" );
|
99
|
+
p.zSql = z.Substring( 0, n );// sqlite3DbStrNDup(p.db, z, n);
|
100
|
+
p.isPrepareV2 = isPrepareV2 != 0;
|
101
|
+
}
|
102
|
+
|
103
|
+
/*
|
104
|
+
** Return the SQL associated with a prepared statement
|
105
|
+
*/
|
106
|
+
static string sqlite3_sql( sqlite3_stmt pStmt )
|
107
|
+
{
|
108
|
+
Vdbe p = (Vdbe)pStmt;
|
109
|
+
return ( p!=null && p.isPrepareV2 ? p.zSql : "" );
|
110
|
+
}
|
111
|
+
|
112
|
+
/*
|
113
|
+
** Swap all content between two VDBE structures.
|
114
|
+
*/
|
115
|
+
static void sqlite3VdbeSwap( Vdbe pA, Vdbe pB )
|
116
|
+
{
|
117
|
+
Vdbe tmp = new Vdbe(); Vdbe pTmp = new Vdbe();
|
118
|
+
string zTmp;
|
119
|
+
pA.CopyTo( tmp );
|
120
|
+
pB.CopyTo( pA );
|
121
|
+
tmp.CopyTo( pB );
|
122
|
+
pTmp = pA.pNext;
|
123
|
+
pA.pNext = pB.pNext;
|
124
|
+
pB.pNext = pTmp;
|
125
|
+
pTmp = pA.pPrev;
|
126
|
+
pA.pPrev = pB.pPrev;
|
127
|
+
pB.pPrev = pTmp;
|
128
|
+
zTmp = pA.zSql;
|
129
|
+
pA.zSql = pB.zSql;
|
130
|
+
pB.zSql = zTmp;
|
131
|
+
pB.isPrepareV2 = pA.isPrepareV2;
|
132
|
+
}
|
133
|
+
|
134
|
+
#if SQLITE_DEBUG
|
135
|
+
/*
|
136
|
+
** Turn tracing on or off
|
137
|
+
*/
|
138
|
+
static void sqlite3VdbeTrace( Vdbe p, FILE trace )
|
139
|
+
{
|
140
|
+
p.trace = trace;
|
141
|
+
}
|
142
|
+
#endif
|
143
|
+
|
144
|
+
/*
|
145
|
+
** Resize the Vdbe.aOp array so that it is at least one op larger than
|
146
|
+
** it was.
|
147
|
+
**
|
148
|
+
** If an out-of-memory error occurs while resizing the array, return
|
149
|
+
** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain
|
150
|
+
** unchanged (this is so that any opcodes already allocated can be
|
151
|
+
** correctly deallocated along with the rest of the Vdbe).
|
152
|
+
*/
|
153
|
+
static int growOpArray( Vdbe p )
|
154
|
+
{
|
155
|
+
//VdbeOp pNew;
|
156
|
+
int nNew = ( p.nOpAlloc != 0 ? p.nOpAlloc * 2 : 1024 / 4 );//(int)(1024/sizeof(Op)));
|
157
|
+
// pNew = sqlite3DbRealloc( p.db, p.aOp, nNew * sizeof( Op ) );
|
158
|
+
//if (pNew != null)
|
159
|
+
//{
|
160
|
+
// p.nOpAlloc = sqlite3DbMallocSize(p.db, pNew)/sizeof(Op);
|
161
|
+
// p.aOp = pNew;
|
162
|
+
//}
|
163
|
+
p.nOpAlloc = nNew;
|
164
|
+
if ( p.aOp == null ) p.aOp = new VdbeOp[nNew]; else Array.Resize( ref p.aOp, nNew );
|
165
|
+
return ( p.aOp != null ? SQLITE_OK : SQLITE_NOMEM ); // return (pNew ? SQLITE_OK : SQLITE_NOMEM);
|
166
|
+
}
|
167
|
+
|
168
|
+
/*
|
169
|
+
** Add a new instruction to the list of instructions current in the
|
170
|
+
** VDBE. Return the address of the new instruction.
|
171
|
+
**
|
172
|
+
** Parameters:
|
173
|
+
**
|
174
|
+
** p Pointer to the VDBE
|
175
|
+
**
|
176
|
+
** op The opcode for this instruction
|
177
|
+
**
|
178
|
+
** p1, p2, p3 Operands
|
179
|
+
**
|
180
|
+
** Use the sqlite3VdbeResolveLabel() function to fix an address and
|
181
|
+
** the sqlite3VdbeChangeP4() function to change the value of the P4
|
182
|
+
** operand.
|
183
|
+
*/
|
184
|
+
static int sqlite3VdbeAddOp3( Vdbe p, int op, int p1, int p2, int p3 )
|
185
|
+
{
|
186
|
+
int i;
|
187
|
+
VdbeOp pOp;
|
188
|
+
|
189
|
+
i = p.nOp;
|
190
|
+
Debug.Assert( p.magic == VDBE_MAGIC_INIT );
|
191
|
+
Debug.Assert( op > 0 && op < 0xff );
|
192
|
+
if ( p.nOpAlloc <= i )
|
193
|
+
{
|
194
|
+
if ( growOpArray( p ) != 0 )
|
195
|
+
{
|
196
|
+
return 1;
|
197
|
+
}
|
198
|
+
}
|
199
|
+
p.nOp++;
|
200
|
+
if ( p.aOp[i] == null ) p.aOp[i] = new VdbeOp();
|
201
|
+
pOp = p.aOp[i];
|
202
|
+
pOp.opcode = (u8)op;
|
203
|
+
pOp.p5 = 0;
|
204
|
+
pOp.p1 = p1;
|
205
|
+
pOp.p2 = p2;
|
206
|
+
pOp.p3 = p3;
|
207
|
+
pOp.p4.p = null;
|
208
|
+
pOp.p4type = P4_NOTUSED;
|
209
|
+
p.expired = false;
|
210
|
+
//sqlite3VdbePrintOp(null, i, p.aOp[i]);
|
211
|
+
#if SQLITE_DEBUG
|
212
|
+
pOp.zComment = null;
|
213
|
+
if ( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp( null, i, p.aOp[i] );
|
214
|
+
#endif
|
215
|
+
#if VDBE_PROFILE
|
216
|
+
pOp.cycles = 0;
|
217
|
+
pOp.cnt = 0;
|
218
|
+
#endif
|
219
|
+
return i;
|
220
|
+
}
|
221
|
+
static int sqlite3VdbeAddOp0( Vdbe p, int op )
|
222
|
+
{
|
223
|
+
return sqlite3VdbeAddOp3( p, op, 0, 0, 0 );
|
224
|
+
}
|
225
|
+
static int sqlite3VdbeAddOp1( Vdbe p, int op, int p1 )
|
226
|
+
{
|
227
|
+
return sqlite3VdbeAddOp3( p, op, p1, 0, 0 );
|
228
|
+
}
|
229
|
+
static int sqlite3VdbeAddOp2( Vdbe p, int op, int p1, bool b2 )
|
230
|
+
{
|
231
|
+
return sqlite3VdbeAddOp2( p, op, p1, (int)( b2 ? 1 : 0 ) );
|
232
|
+
}
|
233
|
+
|
234
|
+
static int sqlite3VdbeAddOp2( Vdbe p, int op, int p1, int p2 )
|
235
|
+
{
|
236
|
+
return sqlite3VdbeAddOp3( p, op, p1, p2, 0 );
|
237
|
+
}
|
238
|
+
|
239
|
+
|
240
|
+
/*
|
241
|
+
** Add an opcode that includes the p4 value as a pointer.
|
242
|
+
*/
|
243
|
+
//P4_INT32
|
244
|
+
static int sqlite3VdbeAddOp4( Vdbe p, int op, int p1, int p2, int p3, i32 pP4, int p4type )
|
245
|
+
{
|
246
|
+
union_p4 _p4 = new union_p4(); _p4.i = pP4;
|
247
|
+
int addr = sqlite3VdbeAddOp3( p, op, p1, p2, p3 );
|
248
|
+
sqlite3VdbeChangeP4( p, addr, _p4, p4type );
|
249
|
+
return addr;
|
250
|
+
}
|
251
|
+
|
252
|
+
//char
|
253
|
+
static int sqlite3VdbeAddOp4( Vdbe p, int op, int p1, int p2, int p3, char pP4, int p4type )
|
254
|
+
{
|
255
|
+
union_p4 _p4 = new union_p4(); _p4.z = pP4.ToString();
|
256
|
+
int addr = sqlite3VdbeAddOp3( p, op, p1, p2, p3 );
|
257
|
+
sqlite3VdbeChangeP4( p, addr, _p4, p4type );
|
258
|
+
return addr;
|
259
|
+
}
|
260
|
+
|
261
|
+
//String
|
262
|
+
static int sqlite3VdbeAddOp4( Vdbe p, int op, int p1, int p2, int p3, string pP4, int p4type )
|
263
|
+
{
|
264
|
+
// Debug.Assert( pP4 != null );
|
265
|
+
union_p4 _p4 = new union_p4(); _p4.z = pP4;
|
266
|
+
int addr = sqlite3VdbeAddOp3( p, op, p1, p2, p3 );
|
267
|
+
sqlite3VdbeChangeP4( p, addr, _p4, p4type );
|
268
|
+
return addr;
|
269
|
+
}
|
270
|
+
|
271
|
+
static int sqlite3VdbeAddOp4( Vdbe p, int op, int p1, int p2, int p3, byte[] pP4, int p4type )
|
272
|
+
{
|
273
|
+
Debug.Assert( op == OP_Null || pP4 != null );
|
274
|
+
union_p4 _p4 = new union_p4(); _p4.z = Encoding.UTF8.GetString( pP4, 0, pP4.Length );
|
275
|
+
int addr = sqlite3VdbeAddOp3( p, op, p1, p2, p3 );
|
276
|
+
sqlite3VdbeChangeP4( p, addr, _p4, p4type );
|
277
|
+
return addr;
|
278
|
+
}
|
279
|
+
|
280
|
+
//P4_INTARRAY
|
281
|
+
static int sqlite3VdbeAddOp4( Vdbe p, int op, int p1, int p2, int p3, int[] pP4, int p4type )
|
282
|
+
{
|
283
|
+
Debug.Assert( pP4 != null );
|
284
|
+
union_p4 _p4 = new union_p4(); _p4.ai = pP4;
|
285
|
+
int addr = sqlite3VdbeAddOp3( p, op, p1, p2, p3 );
|
286
|
+
sqlite3VdbeChangeP4( p, addr, _p4, p4type );
|
287
|
+
return addr;
|
288
|
+
}
|
289
|
+
//P4_INT64
|
290
|
+
static int sqlite3VdbeAddOp4( Vdbe p, int op, int p1, int p2, int p3, i64 pP4, int p4type )
|
291
|
+
{
|
292
|
+
union_p4 _p4 = new union_p4(); _p4.pI64 = pP4;
|
293
|
+
int addr = sqlite3VdbeAddOp3( p, op, p1, p2, p3 );
|
294
|
+
sqlite3VdbeChangeP4( p, addr, _p4, p4type );
|
295
|
+
return addr;
|
296
|
+
}
|
297
|
+
|
298
|
+
//DOUBLE (REAL)
|
299
|
+
static int sqlite3VdbeAddOp4( Vdbe p, int op, int p1, int p2, int p3, double pP4, int p4type )
|
300
|
+
{
|
301
|
+
union_p4 _p4 = new union_p4(); _p4.pReal = pP4;
|
302
|
+
int addr = sqlite3VdbeAddOp3( p, op, p1, p2, p3 );
|
303
|
+
sqlite3VdbeChangeP4( p, addr, _p4, p4type );
|
304
|
+
return addr;
|
305
|
+
}
|
306
|
+
|
307
|
+
//FUNCDEF
|
308
|
+
static int sqlite3VdbeAddOp4( Vdbe p, int op, int p1, int p2, int p3, FuncDef pP4, int p4type )
|
309
|
+
{
|
310
|
+
union_p4 _p4 = new union_p4(); _p4.pFunc = pP4;
|
311
|
+
int addr = sqlite3VdbeAddOp3( p, op, p1, p2, p3 );
|
312
|
+
sqlite3VdbeChangeP4( p, addr, _p4, p4type );
|
313
|
+
return addr;
|
314
|
+
}
|
315
|
+
|
316
|
+
//CollSeq
|
317
|
+
static int sqlite3VdbeAddOp4( Vdbe p, int op, int p1, int p2, int p3, CollSeq pP4, int p4type )
|
318
|
+
{
|
319
|
+
union_p4 _p4 = new union_p4(); _p4.pColl = pP4;
|
320
|
+
int addr = sqlite3VdbeAddOp3( p, op, p1, p2, p3 );
|
321
|
+
sqlite3VdbeChangeP4( p, addr, _p4, p4type );
|
322
|
+
return addr;
|
323
|
+
}
|
324
|
+
|
325
|
+
//KeyInfo
|
326
|
+
static int sqlite3VdbeAddOp4( Vdbe p, int op, int p1, int p2, int p3, KeyInfo pP4, int p4type )
|
327
|
+
{
|
328
|
+
union_p4 _p4 = new union_p4(); _p4.pKeyInfo = pP4;
|
329
|
+
int addr = sqlite3VdbeAddOp3( p, op, p1, p2, p3 );
|
330
|
+
sqlite3VdbeChangeP4( p, addr, _p4, p4type );
|
331
|
+
return addr;
|
332
|
+
}
|
333
|
+
|
334
|
+
// static int sqlite3VdbeAddOp4(
|
335
|
+
// Vdbe p, /* Add the opcode to this VM */
|
336
|
+
// int op, /* The new opcode */
|
337
|
+
// int p1, /* The P1 operand */
|
338
|
+
// int p2, /* The P2 operand */
|
339
|
+
// int p3, /* The P3 operand */
|
340
|
+
// union_p4 _p4, /* The P4 operand */
|
341
|
+
// int p4type /* P4 operand type */
|
342
|
+
//)
|
343
|
+
// {
|
344
|
+
// int addr = sqlite3VdbeAddOp3(p, op, p1, p2, p3);
|
345
|
+
// sqlite3VdbeChangeP4(p, addr, _p4, p4type);
|
346
|
+
// return addr;
|
347
|
+
// }
|
348
|
+
|
349
|
+
/*
|
350
|
+
** Add an opcode that includes the p4 value as an integer.
|
351
|
+
*/
|
352
|
+
static int sqlite3VdbeAddOp4Int(
|
353
|
+
Vdbe p, /* Add the opcode to this VM */
|
354
|
+
int op, /* The new opcode */
|
355
|
+
int p1, /* The P1 operand */
|
356
|
+
int p2, /* The P2 operand */
|
357
|
+
int p3, /* The P3 operand */
|
358
|
+
int p4 /* The P4 operand as an integer */
|
359
|
+
)
|
360
|
+
{
|
361
|
+
union_p4 _p4 = new union_p4(); _p4.i = p4;
|
362
|
+
int addr = sqlite3VdbeAddOp3( p, op, p1, p2, p3 );
|
363
|
+
sqlite3VdbeChangeP4( p, addr, _p4, P4_INT32 );
|
364
|
+
return addr;
|
365
|
+
}
|
366
|
+
/*
|
367
|
+
** Create a new symbolic label for an instruction that has yet to be
|
368
|
+
** coded. The symbolic label is really just a negative number. The
|
369
|
+
** label can be used as the P2 value of an operation. Later, when
|
370
|
+
** the label is resolved to a specific address, the VDBE will scan
|
371
|
+
** through its operation list and change all values of P2 which match
|
372
|
+
** the label into the resolved address.
|
373
|
+
**
|
374
|
+
** The VDBE knows that a P2 value is a label because labels are
|
375
|
+
** always negative and P2 values are suppose to be non-negative.
|
376
|
+
** Hence, a negative P2 value is a label that has yet to be resolved.
|
377
|
+
**
|
378
|
+
** Zero is returned if a malloc() fails.
|
379
|
+
*/
|
380
|
+
static int sqlite3VdbeMakeLabel( Vdbe p )
|
381
|
+
{
|
382
|
+
int i;
|
383
|
+
i = p.nLabel++;
|
384
|
+
Debug.Assert( p.magic == VDBE_MAGIC_INIT );
|
385
|
+
if ( i >= p.nLabelAlloc )
|
386
|
+
{
|
387
|
+
int n = p.nLabelAlloc == 0 ? 15 : p.nLabelAlloc * 2 + 5;
|
388
|
+
if (p.aLabel == null) p.aLabel = sqlite3Malloc(p.aLabel, n);
|
389
|
+
else Array.Resize(ref p.aLabel, n);
|
390
|
+
//p.aLabel = sqlite3DbReallocOrFree(p.db, p.aLabel,
|
391
|
+
// n*sizeof(p.aLabel[0]));
|
392
|
+
p.nLabelAlloc = p.aLabel.Length;//sqlite3DbMallocSize(p.db, p.aLabel)/sizeof(p.aLabel[0]);
|
393
|
+
}
|
394
|
+
if ( p.aLabel != null )
|
395
|
+
{
|
396
|
+
p.aLabel[i] = -1;
|
397
|
+
}
|
398
|
+
return -1 - i;
|
399
|
+
}
|
400
|
+
|
401
|
+
/*
|
402
|
+
** Resolve label "x" to be the address of the next instruction to
|
403
|
+
** be inserted. The parameter "x" must have been obtained from
|
404
|
+
** a prior call to sqlite3VdbeMakeLabel().
|
405
|
+
*/
|
406
|
+
static void sqlite3VdbeResolveLabel( Vdbe p, int x )
|
407
|
+
{
|
408
|
+
int j = -1 - x;
|
409
|
+
Debug.Assert( p.magic == VDBE_MAGIC_INIT );
|
410
|
+
Debug.Assert( j >= 0 && j < p.nLabel );
|
411
|
+
if ( p.aLabel != null )
|
412
|
+
{
|
413
|
+
p.aLabel[j] = p.nOp;
|
414
|
+
}
|
415
|
+
}
|
416
|
+
|
417
|
+
/*
|
418
|
+
** Mark the VDBE as one that can only be run one time.
|
419
|
+
*/
|
420
|
+
static void sqlite3VdbeRunOnlyOnce(Vdbe p)
|
421
|
+
{
|
422
|
+
p.runOnlyOnce = 1;
|
423
|
+
}
|
424
|
+
|
425
|
+
#if SQLITE_DEBUG //* sqlite3AssertMayAbort() logic */
|
426
|
+
|
427
|
+
/*
|
428
|
+
** The following type and function are used to iterate through all opcodes
|
429
|
+
** in a Vdbe main program and each of the sub-programs (triggers) it may
|
430
|
+
** invoke directly or indirectly. It should be used as follows:
|
431
|
+
**
|
432
|
+
** Op *pOp;
|
433
|
+
** VdbeOpIter sIter;
|
434
|
+
**
|
435
|
+
** memset(&sIter, 0, sizeof(sIter));
|
436
|
+
** sIter.v = v; // v is of type Vdbe*
|
437
|
+
** while( (pOp = opIterNext(&sIter)) ){
|
438
|
+
** // Do something with pOp
|
439
|
+
** }
|
440
|
+
** sqlite3DbFree(v->db, sIter.apSub);
|
441
|
+
**
|
442
|
+
*/
|
443
|
+
//typedef struct VdbeOpIter VdbeOpIter;
|
444
|
+
public class VdbeOpIter
|
445
|
+
{
|
446
|
+
public Vdbe v; /* Vdbe to iterate through the opcodes of */
|
447
|
+
public SubProgram[] apSub; /* Array of subprograms */
|
448
|
+
public int nSub; /* Number of entries in apSub */
|
449
|
+
public int iAddr; /* Address of next instruction to return */
|
450
|
+
public int iSub; /* 0 = main program, 1 = first sub-program etc. */
|
451
|
+
};
|
452
|
+
|
453
|
+
static Op opIterNext( VdbeOpIter p )
|
454
|
+
{
|
455
|
+
Vdbe v = p.v;
|
456
|
+
Op pRet = null;
|
457
|
+
Op[] aOp;
|
458
|
+
int nOp;
|
459
|
+
|
460
|
+
if ( p.iSub <= p.nSub )
|
461
|
+
{
|
462
|
+
|
463
|
+
if ( p.iSub == 0 )
|
464
|
+
{
|
465
|
+
aOp = v.aOp;
|
466
|
+
nOp = v.nOp;
|
467
|
+
}
|
468
|
+
else
|
469
|
+
{
|
470
|
+
aOp = p.apSub[p.iSub - 1].aOp;
|
471
|
+
nOp = p.apSub[p.iSub - 1].nOp;
|
472
|
+
}
|
473
|
+
Debug.Assert( p.iAddr < nOp );
|
474
|
+
|
475
|
+
pRet = aOp[p.iAddr];
|
476
|
+
p.iAddr++;
|
477
|
+
if ( p.iAddr == nOp )
|
478
|
+
{
|
479
|
+
p.iSub++;
|
480
|
+
p.iAddr = 0;
|
481
|
+
}
|
482
|
+
|
483
|
+
if ( pRet.p4type == P4_SUBPROGRAM )
|
484
|
+
{
|
485
|
+
//int nByte = p.nSub + 1 ) * sizeof( SubProgram* );
|
486
|
+
int j;
|
487
|
+
for ( j = 0; j < p.nSub; j++ )
|
488
|
+
{
|
489
|
+
if ( p.apSub[j] == pRet.p4.pProgram ) break;
|
490
|
+
}
|
491
|
+
if ( j == p.nSub )
|
492
|
+
{
|
493
|
+
Array.Resize( ref p.apSub, p.nSub + 1 );/// sqlite3DbReallocOrFree( v.db, p.apSub, nByte );
|
494
|
+
//if( null==p.apSub ){
|
495
|
+
// pRet = null;
|
496
|
+
//}else{
|
497
|
+
p.apSub[p.nSub++] = pRet.p4.pProgram;
|
498
|
+
//}
|
499
|
+
}
|
500
|
+
}
|
501
|
+
}
|
502
|
+
|
503
|
+
return pRet;
|
504
|
+
}
|
505
|
+
|
506
|
+
/*
|
507
|
+
** Check if the program stored in the VM associated with pParse may
|
508
|
+
** throw an ABORT exception (causing the statement, but not entire transaction
|
509
|
+
** to be rolled back). This condition is true if the main program or any
|
510
|
+
** sub-programs contains any of the following:
|
511
|
+
**
|
512
|
+
** * OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
|
513
|
+
** * OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
|
514
|
+
** * OP_Destroy
|
515
|
+
** * OP_VUpdate
|
516
|
+
** * OP_VRename
|
517
|
+
** * OP_FkCounter with P2==0 (immediate foreign key constraint)
|
518
|
+
**
|
519
|
+
** Then check that the value of Parse.mayAbort is true if an
|
520
|
+
** ABORT may be thrown, or false otherwise. Return true if it does
|
521
|
+
** match, or false otherwise. This function is intended to be used as
|
522
|
+
** part of an assert statement in the compiler. Similar to:
|
523
|
+
**
|
524
|
+
** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) );
|
525
|
+
*/
|
526
|
+
static int sqlite3VdbeAssertMayAbort( Vdbe v, int mayAbort )
|
527
|
+
{
|
528
|
+
int hasAbort = 0;
|
529
|
+
Op pOp;
|
530
|
+
VdbeOpIter sIter;
|
531
|
+
sIter = new VdbeOpIter();// memset( &sIter, 0, sizeof( sIter ) );
|
532
|
+
sIter.v = v;
|
533
|
+
|
534
|
+
while ( ( pOp = opIterNext( sIter ) ) != null )
|
535
|
+
{
|
536
|
+
int opcode = pOp.opcode;
|
537
|
+
if ( opcode == OP_Destroy || opcode == OP_VUpdate || opcode == OP_VRename
|
538
|
+
#if !SQLITE_OMIT_FOREIGN_KEY
|
539
|
+
|| ( opcode == OP_FkCounter && pOp.p1 == 0 && pOp.p2 == 1 )
|
540
|
+
#endif
|
541
|
+
|| ( ( opcode == OP_Halt || opcode == OP_HaltIfNull )
|
542
|
+
&& ( pOp.p1 == SQLITE_CONSTRAINT && pOp.p2 == OE_Abort ) )
|
543
|
+
)
|
544
|
+
{
|
545
|
+
hasAbort = 1;
|
546
|
+
break;
|
547
|
+
}
|
548
|
+
}
|
549
|
+
sIter.apSub = null;// sqlite3DbFree( v.db, sIter.apSub );
|
550
|
+
|
551
|
+
/* Return true if hasAbort==mayAbort. Or if a malloc failure occured.
|
552
|
+
** If malloc failed, then the while() loop above may not have iterated
|
553
|
+
** through all opcodes and hasAbort may be set incorrectly. Return
|
554
|
+
** true for this case to prevent the assert() in the callers frame
|
555
|
+
** from failing. */
|
556
|
+
return ( hasAbort == mayAbort ) ? 1 : 0;//v.db.mallocFailed !=0|| hasAbort==mayAbort );
|
557
|
+
}
|
558
|
+
#endif //* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
|
559
|
+
|
560
|
+
/*
|
561
|
+
** Loop through the program looking for P2 values that are negative
|
562
|
+
** on jump instructions. Each such value is a label. Resolve the
|
563
|
+
** label by setting the P2 value to its correct non-zero value.
|
564
|
+
**
|
565
|
+
** This routine is called once after all opcodes have been inserted.
|
566
|
+
**
|
567
|
+
** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument
|
568
|
+
** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by
|
569
|
+
** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array.
|
570
|
+
**
|
571
|
+
** The Op.opflags field is set on all opcodes.
|
572
|
+
*/
|
573
|
+
static void resolveP2Values( Vdbe p, ref int pMaxFuncArgs )
|
574
|
+
{
|
575
|
+
int i;
|
576
|
+
int nMaxArgs = pMaxFuncArgs;
|
577
|
+
Op pOp;
|
578
|
+
int[] aLabel = p.aLabel;
|
579
|
+
p.readOnly = true;
|
580
|
+
for ( i = 0; i < p.nOp; i++ )// for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++)
|
581
|
+
{
|
582
|
+
pOp = p.aOp[i];
|
583
|
+
u8 opcode = pOp.opcode;
|
584
|
+
|
585
|
+
pOp.opflags = (u8)sqlite3OpcodeProperty[opcode];
|
586
|
+
if ( opcode == OP_Function || opcode == OP_AggStep )
|
587
|
+
{
|
588
|
+
if ( pOp.p5 > nMaxArgs ) nMaxArgs = pOp.p5;
|
589
|
+
}
|
590
|
+
else if ( opcode == OP_Transaction && pOp.p2 != 0 )
|
591
|
+
{
|
592
|
+
p.readOnly = false;
|
593
|
+
#if ! SQLITE_OMIT_VIRTUALTABLE
|
594
|
+
}else if( opcode==OP_VUpdate ){
|
595
|
+
if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
|
596
|
+
}else if( opcode==OP_VFilter ){
|
597
|
+
int n;
|
598
|
+
Debug.Assert( i < p.nOp - 3 );
|
599
|
+
Debug.Assert( pOp[-1].opcode==OP_Integer );
|
600
|
+
n = pOp[-1].p1;
|
601
|
+
if( n>nMaxArgs ) nMaxArgs = n;
|
602
|
+
#endif
|
603
|
+
}
|
604
|
+
|
605
|
+
if ( ( pOp.opflags & OPFLG_JUMP ) != 0 && pOp.p2 < 0 )
|
606
|
+
{
|
607
|
+
Debug.Assert( -1 - pOp.p2 < p.nLabel );
|
608
|
+
pOp.p2 = aLabel[-1 - pOp.p2];
|
609
|
+
}
|
610
|
+
}
|
611
|
+
sqlite3DbFree( p.db, ref p.aLabel );
|
612
|
+
|
613
|
+
pMaxFuncArgs = nMaxArgs;
|
614
|
+
}
|
615
|
+
|
616
|
+
/*
|
617
|
+
** Return the address of the next instruction to be inserted.
|
618
|
+
*/
|
619
|
+
static int sqlite3VdbeCurrentAddr( Vdbe p )
|
620
|
+
{
|
621
|
+
Debug.Assert( p.magic == VDBE_MAGIC_INIT );
|
622
|
+
return p.nOp;
|
623
|
+
}
|
624
|
+
|
625
|
+
/*
|
626
|
+
** This function returns a pointer to the array of opcodes associated with
|
627
|
+
** the Vdbe passed as the first argument. It is the callers responsibility
|
628
|
+
** to arrange for the returned array to be eventually freed using the
|
629
|
+
** vdbeFreeOpArray() function.
|
630
|
+
**
|
631
|
+
** Before returning, *pnOp is set to the number of entries in the returned
|
632
|
+
** array. Also, *pnMaxArg is set to the larger of its current value and
|
633
|
+
** the number of entries in the Vdbe.apArg[] array required to execute the
|
634
|
+
** returned program.
|
635
|
+
*/
|
636
|
+
static VdbeOp[] sqlite3VdbeTakeOpArray( Vdbe p, ref int pnOp, ref int pnMaxArg )
|
637
|
+
{
|
638
|
+
VdbeOp[] aOp = p.aOp;
|
639
|
+
Debug.Assert( aOp != null );// && 0==p.db.mallocFailed );
|
640
|
+
|
641
|
+
/* Check that sqlite3VdbeUsesBtree() was not called on this VM */
|
642
|
+
Debug.Assert( p.aMutex == null || p.aMutex.nMutex == 0 );
|
643
|
+
|
644
|
+
resolveP2Values( p, ref pnMaxArg );
|
645
|
+
pnOp = p.nOp;
|
646
|
+
p.aOp = null;
|
647
|
+
return aOp;
|
648
|
+
}
|
649
|
+
|
650
|
+
/*
|
651
|
+
** Add a whole list of operations to the operation stack. Return the
|
652
|
+
** address of the first operation added.
|
653
|
+
*/
|
654
|
+
static int sqlite3VdbeAddOpList( Vdbe p, int nOp, VdbeOpList[] aOp )
|
655
|
+
{
|
656
|
+
int addr;
|
657
|
+
Debug.Assert( p.magic == VDBE_MAGIC_INIT );
|
658
|
+
if ( p.nOp + nOp > p.nOpAlloc && growOpArray( p ) != 0 )
|
659
|
+
{
|
660
|
+
return 0;
|
661
|
+
}
|
662
|
+
addr = p.nOp;
|
663
|
+
if ( ALWAYS( nOp > 0 ) )
|
664
|
+
{
|
665
|
+
int i;
|
666
|
+
VdbeOpList pIn;
|
667
|
+
for ( i = 0; i < nOp; i++ )
|
668
|
+
{
|
669
|
+
pIn = aOp[i];
|
670
|
+
int p2 = pIn.p2;
|
671
|
+
if ( p.aOp[i + addr] == null ) p.aOp[i + addr] = new VdbeOp();
|
672
|
+
VdbeOp pOut = p.aOp[i + addr];
|
673
|
+
pOut.opcode = pIn.opcode;
|
674
|
+
pOut.p1 = pIn.p1;
|
675
|
+
if ( p2 < 0 && ( sqlite3OpcodeProperty[pOut.opcode] & OPFLG_JUMP ) != 0 )
|
676
|
+
{
|
677
|
+
pOut.p2 = addr + ( -1 - p2 );// ADDR(p2);
|
678
|
+
}
|
679
|
+
else
|
680
|
+
{
|
681
|
+
pOut.p2 = p2;
|
682
|
+
}
|
683
|
+
pOut.p3 = pIn.p3;
|
684
|
+
pOut.p4type = P4_NOTUSED;
|
685
|
+
pOut.p4.p = null;
|
686
|
+
pOut.p5 = 0;
|
687
|
+
#if SQLITE_DEBUG
|
688
|
+
pOut.zComment = null;
|
689
|
+
if ( sqlite3VdbeAddopTrace )
|
690
|
+
{
|
691
|
+
sqlite3VdbePrintOp( null, i + addr, p.aOp[i + addr] );
|
692
|
+
}
|
693
|
+
#endif
|
694
|
+
}
|
695
|
+
p.nOp += nOp;
|
696
|
+
}
|
697
|
+
return addr;
|
698
|
+
}
|
699
|
+
|
700
|
+
/*
|
701
|
+
** Change the value of the P1 operand for a specific instruction.
|
702
|
+
** This routine is useful when a large program is loaded from a
|
703
|
+
** static array using sqlite3VdbeAddOpList but we want to make a
|
704
|
+
** few minor changes to the program.
|
705
|
+
*/
|
706
|
+
static void sqlite3VdbeChangeP1( Vdbe p, int addr, int val )
|
707
|
+
{
|
708
|
+
Debug.Assert( p != null );
|
709
|
+
Debug.Assert( addr >= 0 );
|
710
|
+
if ( p.nOp > addr )
|
711
|
+
{
|
712
|
+
p.aOp[addr].p1 = val;
|
713
|
+
}
|
714
|
+
}
|
715
|
+
|
716
|
+
/*
|
717
|
+
** Change the value of the P2 operand for a specific instruction.
|
718
|
+
** This routine is useful for setting a jump destination.
|
719
|
+
*/
|
720
|
+
static void sqlite3VdbeChangeP2( Vdbe p, int addr, int val )
|
721
|
+
{
|
722
|
+
Debug.Assert( p != null );
|
723
|
+
Debug.Assert( addr >= 0 );
|
724
|
+
if ( p.nOp > addr )
|
725
|
+
{
|
726
|
+
p.aOp[addr].p2 = val;
|
727
|
+
}
|
728
|
+
}
|
729
|
+
|
730
|
+
/*
|
731
|
+
** Change the value of the P3 operand for a specific instruction.
|
732
|
+
*/
|
733
|
+
static void sqlite3VdbeChangeP3( Vdbe p, int addr, int val )
|
734
|
+
{
|
735
|
+
Debug.Assert( p != null );
|
736
|
+
Debug.Assert( addr >= 0 );
|
737
|
+
if ( p.nOp > addr )
|
738
|
+
{
|
739
|
+
p.aOp[addr].p3 = val;
|
740
|
+
}
|
741
|
+
}
|
742
|
+
|
743
|
+
/*
|
744
|
+
** Change the value of the P5 operand for the most recently
|
745
|
+
** added operation.
|
746
|
+
*/
|
747
|
+
static void sqlite3VdbeChangeP5( Vdbe p, u8 val )
|
748
|
+
{
|
749
|
+
Debug.Assert( p != null );
|
750
|
+
if ( p.aOp != null )
|
751
|
+
{
|
752
|
+
Debug.Assert( p.nOp > 0 );
|
753
|
+
p.aOp[p.nOp - 1].p5 = val;
|
754
|
+
}
|
755
|
+
}
|
756
|
+
|
757
|
+
/*
|
758
|
+
** Change the P2 operand of instruction addr so that it points to
|
759
|
+
** the address of the next instruction to be coded.
|
760
|
+
*/
|
761
|
+
static void sqlite3VdbeJumpHere( Vdbe p, int addr )
|
762
|
+
{
|
763
|
+
sqlite3VdbeChangeP2( p, addr, p.nOp );
|
764
|
+
}
|
765
|
+
|
766
|
+
|
767
|
+
/*
|
768
|
+
** If the input FuncDef structure is ephemeral, then free it. If
|
769
|
+
** the FuncDef is not ephermal, then do nothing.
|
770
|
+
*/
|
771
|
+
static void freeEphemeralFunction( sqlite3 db, FuncDef pDef )
|
772
|
+
{
|
773
|
+
if ( ALWAYS( pDef ) && ( pDef.flags & SQLITE_FUNC_EPHEM ) != 0 )
|
774
|
+
{
|
775
|
+
pDef = null;
|
776
|
+
sqlite3DbFree( db, ref pDef );
|
777
|
+
}
|
778
|
+
}
|
779
|
+
|
780
|
+
/*
|
781
|
+
** Delete a P4 value if necessary.
|
782
|
+
*/
|
783
|
+
static void freeP4( sqlite3 db, int p4type, object p4 )
|
784
|
+
{
|
785
|
+
if ( p4 != null )
|
786
|
+
{
|
787
|
+
switch ( p4type )
|
788
|
+
{
|
789
|
+
case P4_REAL:
|
790
|
+
case P4_INT64:
|
791
|
+
case P4_MPRINTF:
|
792
|
+
case P4_DYNAMIC:
|
793
|
+
case P4_KEYINFO:
|
794
|
+
case P4_INTARRAY:
|
795
|
+
case P4_KEYINFO_HANDOFF:
|
796
|
+
{
|
797
|
+
sqlite3DbFree( db, ref p4 );
|
798
|
+
break;
|
799
|
+
}
|
800
|
+
case P4_VDBEFUNC:
|
801
|
+
{
|
802
|
+
VdbeFunc pVdbeFunc = (VdbeFunc)p4;
|
803
|
+
freeEphemeralFunction( db, pVdbeFunc.pFunc );
|
804
|
+
sqlite3VdbeDeleteAuxData( pVdbeFunc, 0 );
|
805
|
+
sqlite3DbFree( db, ref pVdbeFunc );
|
806
|
+
break;
|
807
|
+
}
|
808
|
+
case P4_FUNCDEF:
|
809
|
+
{
|
810
|
+
freeEphemeralFunction( db, (FuncDef)p4 );
|
811
|
+
break;
|
812
|
+
}
|
813
|
+
case P4_MEM:
|
814
|
+
{
|
815
|
+
p4 = null;// sqlite3ValueFree(ref (sqlite3_value)p4);
|
816
|
+
break;
|
817
|
+
}
|
818
|
+
case P4_VTAB:
|
819
|
+
{
|
820
|
+
sqlite3VtabUnlock( (VTable)p4 );
|
821
|
+
break;
|
822
|
+
}
|
823
|
+
case P4_SUBPROGRAM:
|
824
|
+
{
|
825
|
+
sqlite3VdbeProgramDelete( db, (SubProgram)p4, 1 );
|
826
|
+
break;
|
827
|
+
}
|
828
|
+
}
|
829
|
+
}
|
830
|
+
}
|
831
|
+
|
832
|
+
/*
|
833
|
+
** Free the space allocated for aOp and any p4 values allocated for the
|
834
|
+
** opcodes contained within. If aOp is not NULL it is assumed to contain
|
835
|
+
** nOp entries.
|
836
|
+
*/
|
837
|
+
static void vdbeFreeOpArray( sqlite3 db, ref Op[] aOp, int nOp )
|
838
|
+
{
|
839
|
+
if ( aOp != null )
|
840
|
+
{
|
841
|
+
//Op pOp;
|
842
|
+
// for(pOp=aOp; pOp<&aOp[nOp]; pOp++){
|
843
|
+
// freeP4(db, pOp.p4type, pOp.p4.p);
|
844
|
+
//#if SQLITE_DEBUG
|
845
|
+
// sqlite3DbFree(db, ref pOp.zComment);
|
846
|
+
//#endif
|
847
|
+
// }
|
848
|
+
// }
|
849
|
+
// sqlite3DbFree(db, aOp);
|
850
|
+
aOp = null;
|
851
|
+
}
|
852
|
+
}
|
853
|
+
|
854
|
+
/*
|
855
|
+
** Decrement the ref-count on the SubProgram structure passed as the
|
856
|
+
** second argument. If the ref-count reaches zero, free the structure.
|
857
|
+
**
|
858
|
+
** The array of VDBE opcodes stored as SubProgram.aOp is freed if
|
859
|
+
** either the ref-count reaches zero or parameter freeop is non-zero.
|
860
|
+
**
|
861
|
+
** Since the array of opcodes pointed to by SubProgram.aOp may directly
|
862
|
+
** or indirectly contain a reference to the SubProgram structure itself.
|
863
|
+
** By passing a non-zero freeop parameter, the caller may ensure that all
|
864
|
+
** SubProgram structures and their aOp arrays are freed, even when there
|
865
|
+
** are such circular references.
|
866
|
+
*/
|
867
|
+
static void sqlite3VdbeProgramDelete( sqlite3 db, SubProgram p, int freeop )
|
868
|
+
{
|
869
|
+
if ( p != null )
|
870
|
+
{
|
871
|
+
Debug.Assert( p.nRef > 0 );
|
872
|
+
if ( freeop != 0 || p.nRef == 1 )
|
873
|
+
{
|
874
|
+
Op[] aOp = p.aOp;
|
875
|
+
p.aOp = null;
|
876
|
+
vdbeFreeOpArray( db, ref aOp, p.nOp );
|
877
|
+
p.nOp = 0;
|
878
|
+
}
|
879
|
+
p.nRef--;
|
880
|
+
if ( p.nRef == 0 )
|
881
|
+
{
|
882
|
+
p = null; sqlite3DbFree( db, ref p );
|
883
|
+
}
|
884
|
+
}
|
885
|
+
}
|
886
|
+
/*
|
887
|
+
** Change N opcodes starting at addr to No-ops.
|
888
|
+
*/
|
889
|
+
static void sqlite3VdbeChangeToNoop( Vdbe p, int addr, int N )
|
890
|
+
{
|
891
|
+
if ( p.aOp != null )
|
892
|
+
{
|
893
|
+
sqlite3 db = p.db;
|
894
|
+
while ( N-- > 0 )
|
895
|
+
{
|
896
|
+
VdbeOp pOp = p.aOp[addr + N];
|
897
|
+
freeP4( db, pOp.p4type, pOp.p4.p );
|
898
|
+
pOp = p.aOp[addr + N] = new VdbeOp();//memset(pOp, 0, sizeof(pOp[0]));
|
899
|
+
pOp.opcode = OP_Noop;
|
900
|
+
//pOp++;
|
901
|
+
}
|
902
|
+
}
|
903
|
+
}
|
904
|
+
|
905
|
+
/*
|
906
|
+
** Change the value of the P4 operand for a specific instruction.
|
907
|
+
** This routine is useful when a large program is loaded from a
|
908
|
+
** static array using sqlite3VdbeAddOpList but we want to make a
|
909
|
+
** few minor changes to the program.
|
910
|
+
**
|
911
|
+
** If n>=0 then the P4 operand is dynamic, meaning that a copy of
|
912
|
+
** the string is made into memory obtained from sqlite3Malloc().
|
913
|
+
** A value of n==0 means copy bytes of zP4 up to and including the
|
914
|
+
** first null byte. If n>0 then copy n+1 bytes of zP4.
|
915
|
+
**
|
916
|
+
** If n==P4_KEYINFO it means that zP4 is a pointer to a KeyInfo structure.
|
917
|
+
** A copy is made of the KeyInfo structure into memory obtained from
|
918
|
+
** sqlite3Malloc, to be freed when the Vdbe is finalized.
|
919
|
+
** n==P4_KEYINFO_HANDOFF indicates that zP4 points to a KeyInfo structure
|
920
|
+
** stored in memory that the caller has obtained from sqlite3Malloc. The
|
921
|
+
** caller should not free the allocation, it will be freed when the Vdbe is
|
922
|
+
** finalized.
|
923
|
+
**
|
924
|
+
** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points
|
925
|
+
** to a string or structure that is guaranteed to exist for the lifetime of
|
926
|
+
** the Vdbe. In these cases we can just copy the pointer.
|
927
|
+
**
|
928
|
+
** If addr<0 then change P4 on the most recently inserted instruction.
|
929
|
+
*/
|
930
|
+
|
931
|
+
//P4_COLLSEQ
|
932
|
+
static void sqlite3VdbeChangeP4( Vdbe p, int addr, CollSeq pColl, int n )
|
933
|
+
{
|
934
|
+
union_p4 _p4 = new union_p4(); _p4.pColl = pColl;
|
935
|
+
sqlite3VdbeChangeP4( p, addr, _p4, n );
|
936
|
+
}
|
937
|
+
//P4_FUNCDEF
|
938
|
+
static void sqlite3VdbeChangeP4( Vdbe p, int addr, FuncDef pFunc, int n )
|
939
|
+
{
|
940
|
+
union_p4 _p4 = new union_p4(); _p4.pFunc = pFunc;
|
941
|
+
sqlite3VdbeChangeP4( p, addr, _p4, n );
|
942
|
+
}
|
943
|
+
//P4_INT32
|
944
|
+
static void sqlite3VdbeChangeP4( Vdbe p, int addr, int i32n, int n )
|
945
|
+
{
|
946
|
+
union_p4 _p4 = new union_p4(); _p4.i = i32n;
|
947
|
+
sqlite3VdbeChangeP4( p, addr, _p4, n );
|
948
|
+
}
|
949
|
+
|
950
|
+
//P4_KEYINFO
|
951
|
+
static void sqlite3VdbeChangeP4( Vdbe p, int addr, KeyInfo pKeyInfo, int n )
|
952
|
+
{
|
953
|
+
union_p4 _p4 = new union_p4(); _p4.pKeyInfo = pKeyInfo;
|
954
|
+
sqlite3VdbeChangeP4( p, addr, _p4, n );
|
955
|
+
}
|
956
|
+
//CHAR
|
957
|
+
static void sqlite3VdbeChangeP4( Vdbe p, int addr, char c, int n )
|
958
|
+
{
|
959
|
+
union_p4 _p4 = new union_p4(); _p4.z = c.ToString();
|
960
|
+
sqlite3VdbeChangeP4( p, addr, _p4, n );
|
961
|
+
}
|
962
|
+
|
963
|
+
//MEM
|
964
|
+
static void sqlite3VdbeChangeP4( Vdbe p, int addr, Mem m, int n )
|
965
|
+
{
|
966
|
+
union_p4 _p4 = new union_p4(); _p4.pMem = m;
|
967
|
+
sqlite3VdbeChangeP4( p, addr, _p4, n );
|
968
|
+
}
|
969
|
+
|
970
|
+
//STRING
|
971
|
+
|
972
|
+
//STRING + Type
|
973
|
+
static void sqlite3VdbeChangeP4( Vdbe p, int addr, string z, dxDel P4_Type )
|
974
|
+
{
|
975
|
+
union_p4 _p4 = new union_p4();
|
976
|
+
_p4.z = z;
|
977
|
+
sqlite3VdbeChangeP4( p, addr, _p4, P4_DYNAMIC );
|
978
|
+
}
|
979
|
+
|
980
|
+
//SUBPROGRAM
|
981
|
+
static void sqlite3VdbeChangeP4( Vdbe p, int addr, SubProgram pProgram, int n )
|
982
|
+
{
|
983
|
+
union_p4 _p4 = new union_p4();
|
984
|
+
_p4.pProgram = pProgram;
|
985
|
+
sqlite3VdbeChangeP4( p, addr, _p4, n );
|
986
|
+
}
|
987
|
+
|
988
|
+
static void sqlite3VdbeChangeP4( Vdbe p, int addr, string z, int n )
|
989
|
+
{
|
990
|
+
union_p4 _p4 = new union_p4();
|
991
|
+
if ( n > 0 && n <= z.Length ) _p4.z = z.Substring( 0, n );
|
992
|
+
else _p4.z = z;
|
993
|
+
sqlite3VdbeChangeP4( p, addr, _p4, n );
|
994
|
+
}
|
995
|
+
|
996
|
+
static void sqlite3VdbeChangeP4( Vdbe p, int addr, union_p4 _p4, int n )
|
997
|
+
{
|
998
|
+
Op pOp;
|
999
|
+
sqlite3 db;
|
1000
|
+
Debug.Assert( p != null );
|
1001
|
+
db = p.db;
|
1002
|
+
Debug.Assert( p.magic == VDBE_MAGIC_INIT );
|
1003
|
+
if ( p.aOp == null /*|| db.mallocFailed != 0 */)
|
1004
|
+
{
|
1005
|
+
if ( n != P4_KEYINFO && n != P4_VTAB )
|
1006
|
+
{
|
1007
|
+
freeP4( db, n, _p4 );
|
1008
|
+
}
|
1009
|
+
return;
|
1010
|
+
}
|
1011
|
+
Debug.Assert( p.nOp > 0 );
|
1012
|
+
Debug.Assert( addr < p.nOp );
|
1013
|
+
if ( addr < 0 )
|
1014
|
+
{
|
1015
|
+
addr = p.nOp - 1;
|
1016
|
+
}
|
1017
|
+
pOp = p.aOp[addr];
|
1018
|
+
freeP4( db, pOp.p4type, pOp.p4.p );
|
1019
|
+
pOp.p4.p = null;
|
1020
|
+
if ( n == P4_INT32 )
|
1021
|
+
{
|
1022
|
+
/* Note: this cast is safe, because the origin data point was an int
|
1023
|
+
** that was cast to a (const char *). */
|
1024
|
+
pOp.p4.i = _p4.i; // SQLITE_PTR_TO_INT(zP4);
|
1025
|
+
pOp.p4type = P4_INT32;
|
1026
|
+
}
|
1027
|
+
else if ( n == P4_INT64 )
|
1028
|
+
{
|
1029
|
+
pOp.p4.pI64 = _p4.pI64;
|
1030
|
+
pOp.p4type = n;
|
1031
|
+
}
|
1032
|
+
else if ( n == P4_REAL )
|
1033
|
+
{
|
1034
|
+
pOp.p4.pReal = _p4.pReal;
|
1035
|
+
pOp.p4type = n;
|
1036
|
+
}
|
1037
|
+
else if ( _p4 == null )
|
1038
|
+
{
|
1039
|
+
pOp.p4.p = null;
|
1040
|
+
pOp.p4type = P4_NOTUSED;
|
1041
|
+
}
|
1042
|
+
else if ( n == P4_KEYINFO )
|
1043
|
+
{
|
1044
|
+
KeyInfo pKeyInfo;
|
1045
|
+
int nField, nByte;
|
1046
|
+
|
1047
|
+
nField = _p4.pKeyInfo.nField;
|
1048
|
+
//nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo.aColl[0]) + nField;
|
1049
|
+
pKeyInfo = new KeyInfo();//sqlite3Malloc( nByte );
|
1050
|
+
pOp.p4.pKeyInfo = pKeyInfo;
|
1051
|
+
if ( pKeyInfo != null )
|
1052
|
+
{
|
1053
|
+
//u8 *aSortOrder;
|
1054
|
+
//memcpy(pKeyInfo, zP4, nByte);
|
1055
|
+
//aSortOrder = pKeyInfo.aSortOrder;
|
1056
|
+
//if( aSortOrder ){
|
1057
|
+
// pKeyInfo.aSortOrder = (unsigned char*)&pKeyInfo.aColl[nField];
|
1058
|
+
// memcpy(pKeyInfo.aSortOrder, aSortOrder, nField);
|
1059
|
+
//}
|
1060
|
+
pKeyInfo = _p4.pKeyInfo.Copy();
|
1061
|
+
pOp.p4type = P4_KEYINFO;
|
1062
|
+
}
|
1063
|
+
else
|
1064
|
+
{
|
1065
|
+
//p.db.mallocFailed = 1;
|
1066
|
+
pOp.p4type = P4_NOTUSED;
|
1067
|
+
}
|
1068
|
+
pOp.p4.pKeyInfo = _p4.pKeyInfo;
|
1069
|
+
pOp.p4type = P4_KEYINFO;
|
1070
|
+
}
|
1071
|
+
else if ( n == P4_KEYINFO_HANDOFF || n == P4_KEYINFO_STATIC )
|
1072
|
+
{
|
1073
|
+
pOp.p4.pKeyInfo = _p4.pKeyInfo;
|
1074
|
+
pOp.p4type = P4_KEYINFO;
|
1075
|
+
}
|
1076
|
+
else if ( n == P4_FUNCDEF )
|
1077
|
+
{
|
1078
|
+
pOp.p4.pFunc = _p4.pFunc;
|
1079
|
+
pOp.p4type = P4_FUNCDEF;
|
1080
|
+
}
|
1081
|
+
else if ( n == P4_COLLSEQ )
|
1082
|
+
{
|
1083
|
+
pOp.p4.pColl = _p4.pColl;
|
1084
|
+
pOp.p4type = P4_COLLSEQ;
|
1085
|
+
}
|
1086
|
+
else if ( n == P4_DYNAMIC || n == P4_STATIC )
|
1087
|
+
{
|
1088
|
+
pOp.p4.z = _p4.z;
|
1089
|
+
pOp.p4type = P4_DYNAMIC;
|
1090
|
+
}
|
1091
|
+
else if ( n == P4_MEM )
|
1092
|
+
{
|
1093
|
+
pOp.p4.pMem = _p4.pMem;
|
1094
|
+
pOp.p4type = P4_MEM;
|
1095
|
+
}
|
1096
|
+
else if ( n == P4_INTARRAY )
|
1097
|
+
{
|
1098
|
+
pOp.p4.ai = _p4.ai;
|
1099
|
+
pOp.p4type = P4_INTARRAY;
|
1100
|
+
}
|
1101
|
+
else if ( n == P4_SUBPROGRAM )
|
1102
|
+
{
|
1103
|
+
pOp.p4.pProgram = _p4.pProgram;
|
1104
|
+
pOp.p4type = P4_SUBPROGRAM;
|
1105
|
+
}
|
1106
|
+
else if ( n == P4_VTAB )
|
1107
|
+
{
|
1108
|
+
pOp.p4.pVtab = _p4.pVtab;
|
1109
|
+
pOp.p4type = P4_VTAB;
|
1110
|
+
sqlite3VtabLock( _p4.pVtab );
|
1111
|
+
Debug.Assert( ( _p4.pVtab ).db == p.db );
|
1112
|
+
}
|
1113
|
+
else if ( n < 0 )
|
1114
|
+
{
|
1115
|
+
pOp.p4.p = _p4.p;
|
1116
|
+
pOp.p4type = n;
|
1117
|
+
}
|
1118
|
+
else
|
1119
|
+
{
|
1120
|
+
//if (n == 0) n = n = sqlite3Strlen30(zP4);
|
1121
|
+
pOp.p4.z = _p4.z;// sqlite3DbStrNDup(p.db, zP4, n);
|
1122
|
+
pOp.p4type = P4_DYNAMIC;
|
1123
|
+
}
|
1124
|
+
}
|
1125
|
+
|
1126
|
+
#if !NDEBUG
|
1127
|
+
/*
|
1128
|
+
** Change the comment on the the most recently coded instruction. Or
|
1129
|
+
** insert a No-op and add the comment to that new instruction. This
|
1130
|
+
** makes the code easier to read during debugging. None of this happens
|
1131
|
+
** in a production build.
|
1132
|
+
*/
|
1133
|
+
static void sqlite3VdbeComment( Vdbe p, string zFormat, params object[] ap )
|
1134
|
+
{
|
1135
|
+
// va_list ap;
|
1136
|
+
if ( null == p ) return;
|
1137
|
+
Debug.Assert( p.nOp > 0 || p.aOp == null );
|
1138
|
+
Debug.Assert( p.aOp == null || p.aOp[p.nOp - 1].zComment == null /* || p.db.mallocFailed != 0 */);
|
1139
|
+
if ( p.nOp != 0 )
|
1140
|
+
{
|
1141
|
+
string pz;// = p.aOp[p.nOp-1].zComment;
|
1142
|
+
va_start( ap, zFormat );
|
1143
|
+
//sqlite3DbFree(db, ref pz);
|
1144
|
+
pz = sqlite3VMPrintf( p.db, zFormat, ap );
|
1145
|
+
p.aOp[p.nOp - 1].zComment = pz;
|
1146
|
+
va_end( ap );
|
1147
|
+
}
|
1148
|
+
}
|
1149
|
+
static void sqlite3VdbeNoopComment( Vdbe p, string zFormat, params object[] ap )
|
1150
|
+
{
|
1151
|
+
//va_list ap;
|
1152
|
+
if ( null == p ) return;
|
1153
|
+
sqlite3VdbeAddOp0( p, OP_Noop );
|
1154
|
+
Debug.Assert( p.nOp > 0 || p.aOp == null );
|
1155
|
+
Debug.Assert( p.aOp == null || p.aOp[p.nOp - 1].zComment == null /* || p.db.mallocFailed != 0 */);
|
1156
|
+
if ( p.nOp != 0 )
|
1157
|
+
{
|
1158
|
+
string pz; // = p.aOp[p.nOp - 1].zComment;
|
1159
|
+
va_start( ap, zFormat );
|
1160
|
+
//sqlite3DbFree(db,ref pz);
|
1161
|
+
pz = sqlite3VMPrintf( p.db, zFormat, ap );
|
1162
|
+
p.aOp[p.nOp - 1].zComment = pz;
|
1163
|
+
va_end( ap );
|
1164
|
+
}
|
1165
|
+
}
|
1166
|
+
#else
|
1167
|
+
#endif //* NDEBUG */
|
1168
|
+
|
1169
|
+
|
1170
|
+
/*
|
1171
|
+
** Return the opcode for a given address. If the address is -1, then
|
1172
|
+
** return the most recently inserted opcode.
|
1173
|
+
**
|
1174
|
+
** If a memory allocation error has occurred prior to the calling of this
|
1175
|
+
** routine, then a pointer to a dummy VdbeOp will be returned. That opcode
|
1176
|
+
** is readable and writable, but it has no effect. The return of a dummy
|
1177
|
+
** opcode allows the call to continue functioning after a OOM fault without
|
1178
|
+
** having to check to see if the return from this routine is a valid pointer.
|
1179
|
+
**
|
1180
|
+
** About the #if SQLITE_OMIT_TRACE: Normally, this routine is never called
|
1181
|
+
** unless p->nOp>0. This is because in the absense of SQLITE_OMIT_TRACE,
|
1182
|
+
** an OP_Trace instruction is always inserted by sqlite3VdbeGet() as soon as
|
1183
|
+
** a new VDBE is created. So we are free to set addr to p->nOp-1 without
|
1184
|
+
** having to double-check to make sure that the result is non-negative. But
|
1185
|
+
** if SQLITE_OMIT_TRACE is defined, the OP_Trace is omitted and we do need to
|
1186
|
+
** check the value of p->nOp-1 before continuing.
|
1187
|
+
*/
|
1188
|
+
static VdbeOp sqlite3VdbeGetOp( Vdbe p, int addr )
|
1189
|
+
{
|
1190
|
+
Debug.Assert( p.magic == VDBE_MAGIC_INIT );
|
1191
|
+
if ( addr < 0 )
|
1192
|
+
{
|
1193
|
+
#if SQLITE_OMIT_TRACE
|
1194
|
+
VdbeOp dummy = new VdbeOp();
|
1195
|
+
if( p.nOp==0 ) return dummy;
|
1196
|
+
#endif
|
1197
|
+
addr = p.nOp - 1;
|
1198
|
+
}
|
1199
|
+
Debug.Assert( ( addr >= 0 && addr < p.nOp ) /* || p.db.mallocFailed != 0 */);
|
1200
|
+
//if ( p.db.mallocFailed != 0 )
|
1201
|
+
//{
|
1202
|
+
// return dummy;
|
1203
|
+
//}
|
1204
|
+
//else
|
1205
|
+
{
|
1206
|
+
return p.aOp[addr];
|
1207
|
+
}
|
1208
|
+
}
|
1209
|
+
|
1210
|
+
#if !SQLITE_OMIT_EXPLAIN || !NDEBUG || VDBE_PROFILE || SQLITE_DEBUG
|
1211
|
+
/*
|
1212
|
+
** Compute a string that describes the P4 parameter for an opcode.
|
1213
|
+
** Use zTemp for any required temporary buffer space.
|
1214
|
+
*/
|
1215
|
+
static string displayP4( Op pOp, string zBuffer, int nTemp )
|
1216
|
+
{
|
1217
|
+
StringBuilder zTemp = new StringBuilder( 100 );
|
1218
|
+
Debug.Assert( nTemp >= 20 );
|
1219
|
+
switch ( pOp.p4type )
|
1220
|
+
{
|
1221
|
+
case P4_KEYINFO_STATIC:
|
1222
|
+
case P4_KEYINFO:
|
1223
|
+
{
|
1224
|
+
int i, j;
|
1225
|
+
KeyInfo pKeyInfo = pOp.p4.pKeyInfo;
|
1226
|
+
sqlite3_snprintf( nTemp, ref zTemp, "keyinfo(%d", pKeyInfo.nField );
|
1227
|
+
i = sqlite3Strlen30( zTemp );
|
1228
|
+
for ( j = 0; j < pKeyInfo.nField; j++ )
|
1229
|
+
{
|
1230
|
+
CollSeq pColl = pKeyInfo.aColl[j];
|
1231
|
+
if ( pColl != null )
|
1232
|
+
{
|
1233
|
+
int n = sqlite3Strlen30( pColl.zName );
|
1234
|
+
if ( i + n > nTemp )
|
1235
|
+
{
|
1236
|
+
zTemp.Append( ",..." ); // memcpy( &zTemp[i], ",...", 4 );
|
1237
|
+
break;
|
1238
|
+
}
|
1239
|
+
zTemp.Append( "," );// zTemp[i++] = ',';
|
1240
|
+
if ( pKeyInfo.aSortOrder != null && pKeyInfo.aSortOrder[j] != 0 )
|
1241
|
+
{
|
1242
|
+
zTemp.Append( "-" );// zTemp[i++] = '-';
|
1243
|
+
}
|
1244
|
+
zTemp.Append( pColl.zName );// memcpy( &zTemp[i], pColl.zName, n + 1 );
|
1245
|
+
i += n;
|
1246
|
+
}
|
1247
|
+
else if ( i + 4 < nTemp )
|
1248
|
+
{
|
1249
|
+
zTemp.Append( ",nil" );// memcpy( &zTemp[i], ",nil", 4 );
|
1250
|
+
i += 4;
|
1251
|
+
}
|
1252
|
+
}
|
1253
|
+
zTemp.Append( ")" );// zTemp[i++] = ')';
|
1254
|
+
//zTemp[i] = 0;
|
1255
|
+
Debug.Assert( i < nTemp );
|
1256
|
+
break;
|
1257
|
+
}
|
1258
|
+
case P4_COLLSEQ:
|
1259
|
+
{
|
1260
|
+
CollSeq pColl = pOp.p4.pColl;
|
1261
|
+
sqlite3_snprintf( nTemp, ref zTemp, "collseq(%.20s)", ( pColl != null ? pColl.zName : "null" ) );
|
1262
|
+
break;
|
1263
|
+
}
|
1264
|
+
case P4_FUNCDEF:
|
1265
|
+
{
|
1266
|
+
FuncDef pDef = pOp.p4.pFunc;
|
1267
|
+
sqlite3_snprintf( nTemp, ref zTemp, "%s(%d)", pDef.zName, pDef.nArg );
|
1268
|
+
break;
|
1269
|
+
}
|
1270
|
+
case P4_INT64:
|
1271
|
+
{
|
1272
|
+
sqlite3_snprintf( nTemp, ref zTemp, "%lld", pOp.p4.pI64 );
|
1273
|
+
break;
|
1274
|
+
}
|
1275
|
+
case P4_INT32:
|
1276
|
+
{
|
1277
|
+
sqlite3_snprintf( nTemp, ref zTemp, "%d", pOp.p4.i );
|
1278
|
+
break;
|
1279
|
+
}
|
1280
|
+
case P4_REAL:
|
1281
|
+
{
|
1282
|
+
sqlite3_snprintf( nTemp, ref zTemp, "%.16g", pOp.p4.pReal );
|
1283
|
+
break;
|
1284
|
+
}
|
1285
|
+
case P4_MEM:
|
1286
|
+
{
|
1287
|
+
Mem pMem = pOp.p4.pMem;
|
1288
|
+
Debug.Assert( ( pMem.flags & MEM_Null ) == 0 );
|
1289
|
+
if ( ( pMem.flags & MEM_Str ) != 0 )
|
1290
|
+
{
|
1291
|
+
zTemp.Append( pMem.z );
|
1292
|
+
}
|
1293
|
+
else if ( ( pMem.flags & MEM_Int ) != 0 )
|
1294
|
+
{
|
1295
|
+
sqlite3_snprintf( nTemp, ref zTemp, "%lld", pMem.u.i );
|
1296
|
+
}
|
1297
|
+
else if ( ( pMem.flags & MEM_Real ) != 0 )
|
1298
|
+
{
|
1299
|
+
sqlite3_snprintf( nTemp, ref zTemp, "%.16g", pMem.r );
|
1300
|
+
}
|
1301
|
+
else
|
1302
|
+
{
|
1303
|
+
Debug.Assert( ( pMem.flags & MEM_Blob ) != 0 );
|
1304
|
+
zTemp = new StringBuilder( "(blob)" );
|
1305
|
+
}
|
1306
|
+
break;
|
1307
|
+
}
|
1308
|
+
#if ! SQLITE_OMIT_VIRTUALTABLE
|
1309
|
+
case P4_VTAB: {
|
1310
|
+
sqlite3_vtab pVtab = pOp.p4.pVtab.pVtab;
|
1311
|
+
sqlite3_snprintf(nTemp, ref zTemp, "vtab:%p:%p", pVtab, pVtab.pModule);
|
1312
|
+
break;
|
1313
|
+
}
|
1314
|
+
#endif
|
1315
|
+
case P4_INTARRAY:
|
1316
|
+
{
|
1317
|
+
sqlite3_snprintf( nTemp, ref zTemp, "intarray" );
|
1318
|
+
break;
|
1319
|
+
}
|
1320
|
+
case P4_SUBPROGRAM:
|
1321
|
+
{
|
1322
|
+
sqlite3_snprintf( nTemp, ref zTemp, "program" );
|
1323
|
+
break;
|
1324
|
+
}
|
1325
|
+
default:
|
1326
|
+
{
|
1327
|
+
if ( pOp.p4.z != null ) zTemp.Append( pOp.p4.z );
|
1328
|
+
//if ( zTemp == null )
|
1329
|
+
//{
|
1330
|
+
// zTemp = "";
|
1331
|
+
//}
|
1332
|
+
break;
|
1333
|
+
}
|
1334
|
+
}
|
1335
|
+
Debug.Assert( zTemp != null );
|
1336
|
+
return zTemp.ToString();
|
1337
|
+
}
|
1338
|
+
#endif
|
1339
|
+
|
1340
|
+
/*
|
1341
|
+
** Declare to the Vdbe that the BTree object at db.aDb[i] is used.
|
1342
|
+
*/
|
1343
|
+
static void sqlite3VdbeUsesBtree( Vdbe p, int i )
|
1344
|
+
{
|
1345
|
+
int mask;
|
1346
|
+
Debug.Assert( i >= 0 && i < p.db.nDb && i < sizeof( u32 ) * 8 );
|
1347
|
+
Debug.Assert( i < sizeof( int ) * 8 );
|
1348
|
+
mask = (int)( (u32)1 ) << i;
|
1349
|
+
if ( ( p.btreeMask & mask ) == 0 )
|
1350
|
+
{
|
1351
|
+
p.btreeMask |= mask;
|
1352
|
+
sqlite3BtreeMutexArrayInsert( p.aMutex, p.db.aDb[i].pBt );
|
1353
|
+
}
|
1354
|
+
}
|
1355
|
+
|
1356
|
+
|
1357
|
+
#if VDBE_PROFILE || SQLITE_DEBUG
|
1358
|
+
/*
|
1359
|
+
** Print a single opcode. This routine is used for debugging only.
|
1360
|
+
*/
|
1361
|
+
static void sqlite3VdbePrintOp( FILE pOut, int pc, Op pOp )
|
1362
|
+
{
|
1363
|
+
string zP4;
|
1364
|
+
string zPtr = null;
|
1365
|
+
string zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X %s\n";
|
1366
|
+
if ( pOut == null ) pOut = System.Console.Out;
|
1367
|
+
zP4 = displayP4( pOp, zPtr, 50 );
|
1368
|
+
string zOut = "";
|
1369
|
+
sqlite3_snprintf( 999, ref zOut, zFormat1, pc,
|
1370
|
+
sqlite3OpcodeName( pOp.opcode ), pOp.p1, pOp.p2, pOp.p3, zP4, pOp.p5,
|
1371
|
+
#if SQLITE_DEBUG
|
1372
|
+
pOp.zComment != null ? pOp.zComment : ""
|
1373
|
+
#else
|
1374
|
+
""
|
1375
|
+
#endif
|
1376
|
+
);
|
1377
|
+
pOut.Write( zOut );
|
1378
|
+
//fflush(pOut);
|
1379
|
+
}
|
1380
|
+
#endif
|
1381
|
+
|
1382
|
+
/*
|
1383
|
+
** Release an array of N Mem elements
|
1384
|
+
*/
|
1385
|
+
static void releaseMemArray( Mem[] p, int N )
|
1386
|
+
{
|
1387
|
+
releaseMemArray( p, 0, N );
|
1388
|
+
}
|
1389
|
+
static void releaseMemArray( Mem[] p, int starting, int N )
|
1390
|
+
{
|
1391
|
+
if ( p != null && p.Length > starting && p[starting] != null && N != 0 )
|
1392
|
+
{
|
1393
|
+
Mem pEnd;
|
1394
|
+
sqlite3 db = p[starting].db;
|
1395
|
+
//u8 malloc_failed = db.mallocFailed;
|
1396
|
+
for ( int i = starting; i < N; i++ )//pEnd = p[N] ; p < pEnd ; p++ )
|
1397
|
+
{
|
1398
|
+
pEnd = p[i];
|
1399
|
+
Debug.Assert( //( p[1] ) == pEnd ||
|
1400
|
+
N == 1 || p[starting].db == p[starting + 1].db );
|
1401
|
+
|
1402
|
+
/* This block is really an inlined version of sqlite3VdbeMemRelease()
|
1403
|
+
** that takes advantage of the fact that the memory cell value is
|
1404
|
+
** being set to NULL after releasing any dynamic resources.
|
1405
|
+
**
|
1406
|
+
** The justification for duplicating code is that according to
|
1407
|
+
** callgrind, this causes a certain test case to hit the CPU 4.7
|
1408
|
+
** percent less (x86 linux, gcc version 4.1.2, -O6) than if
|
1409
|
+
** sqlite3MemRelease() were called from here. With -O2, this jumps
|
1410
|
+
** to 6.6 percent. The test case is inserting 1000 rows into a table
|
1411
|
+
** with no indexes using a single prepared INSERT statement, bind()
|
1412
|
+
** and reset(). Inserts are grouped into a transaction.
|
1413
|
+
*/
|
1414
|
+
if ( pEnd != null )
|
1415
|
+
{
|
1416
|
+
if ( ( pEnd.flags & ( MEM_Agg | MEM_Dyn | MEM_Frame | MEM_RowSet ) ) != 0 )
|
1417
|
+
{
|
1418
|
+
sqlite3VdbeMemRelease( pEnd );
|
1419
|
+
}
|
1420
|
+
//else if ( pEnd.zMalloc != null )
|
1421
|
+
//{
|
1422
|
+
// sqlite3DbFree( db, ref pEnd.zMalloc );
|
1423
|
+
// pEnd.zMalloc = 0;
|
1424
|
+
//}
|
1425
|
+
pEnd.z = null;
|
1426
|
+
pEnd.n = 0;
|
1427
|
+
pEnd.flags = MEM_Null;
|
1428
|
+
sqlite3_free( ref pEnd._Mem );
|
1429
|
+
sqlite3_free( ref pEnd.zBLOB);
|
1430
|
+
}
|
1431
|
+
}
|
1432
|
+
// db.mallocFailed = malloc_failed;
|
1433
|
+
}
|
1434
|
+
}
|
1435
|
+
|
1436
|
+
/*
|
1437
|
+
** Delete a VdbeFrame object and its contents. VdbeFrame objects are
|
1438
|
+
** allocated by the OP_Program opcode in sqlite3VdbeExec().
|
1439
|
+
*/
|
1440
|
+
static void sqlite3VdbeFrameDelete( VdbeFrame p )
|
1441
|
+
{
|
1442
|
+
int i;
|
1443
|
+
//Mem[] aMem = VdbeFrameMem(p);
|
1444
|
+
VdbeCursor[] apCsr = p.aChildCsr;// (VdbeCursor)aMem[p.nChildMem];
|
1445
|
+
for ( i = 0; i < p.nChildCsr; i++ )
|
1446
|
+
{
|
1447
|
+
sqlite3VdbeFreeCursor( p.v, apCsr[i] );
|
1448
|
+
}
|
1449
|
+
releaseMemArray(p.aChildMem, p.nChildMem);
|
1450
|
+
p = null;// sqlite3DbFree( p.v.db, p );
|
1451
|
+
}
|
1452
|
+
|
1453
|
+
#if ! SQLITE_OMIT_EXPLAIN
|
1454
|
+
/*
|
1455
|
+
** Give a listing of the program in the virtual machine.
|
1456
|
+
**
|
1457
|
+
** The interface is the same as sqlite3VdbeExec(). But instead of
|
1458
|
+
** running the code, it invokes the callback once for each instruction.
|
1459
|
+
** This feature is used to implement "EXPLAIN".
|
1460
|
+
**
|
1461
|
+
** When p.explain==1, each instruction is listed. When
|
1462
|
+
** p.explain==2, only OP_Explain instructions are listed and these
|
1463
|
+
** are shown in a different format. p.explain==2 is used to implement
|
1464
|
+
** EXPLAIN QUERY PLAN.
|
1465
|
+
**
|
1466
|
+
** When p->explain==1, first the main program is listed, then each of
|
1467
|
+
** the trigger subprograms are listed one by one.
|
1468
|
+
*/
|
1469
|
+
static int sqlite3VdbeList(
|
1470
|
+
Vdbe p /* The VDBE */
|
1471
|
+
)
|
1472
|
+
{
|
1473
|
+
int nRow; /* Stop when row count reaches this */
|
1474
|
+
int nSub = 0; /* Number of sub-vdbes seen so far */
|
1475
|
+
SubProgram[] apSub = null; /* Array of sub-vdbes */
|
1476
|
+
Mem pSub = null; /* Memory cell hold array of subprogs */
|
1477
|
+
sqlite3 db = p.db; /* The database connection */
|
1478
|
+
int i; /* Loop counter */
|
1479
|
+
int rc = SQLITE_OK; /* Return code */
|
1480
|
+
if ( p.pResultSet == null ) p.pResultSet = new Mem[0];//Mem* pMem = p.pResultSet = p.aMem[1]; /* First Mem of result set */
|
1481
|
+
Mem pMem;
|
1482
|
+
Debug.Assert( p.explain != 0 );
|
1483
|
+
Debug.Assert( p.magic == VDBE_MAGIC_RUN );
|
1484
|
+
Debug.Assert( p.rc == SQLITE_OK || p.rc == SQLITE_BUSY || p.rc == SQLITE_NOMEM );
|
1485
|
+
/* Even though this opcode does not use dynamic strings for
|
1486
|
+
** the result, result columns may become dynamic if the user calls
|
1487
|
+
** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
|
1488
|
+
*/
|
1489
|
+
releaseMemArray( p.pResultSet, 8 );
|
1490
|
+
|
1491
|
+
//if ( p.rc == SQLITE_NOMEM )
|
1492
|
+
//{
|
1493
|
+
// /* This happens if a malloc() inside a call to sqlite3_column_text() or
|
1494
|
+
// ** sqlite3_column_text16() failed. */
|
1495
|
+
// db.mallocFailed = 1;
|
1496
|
+
// return SQLITE_ERROR;
|
1497
|
+
//}
|
1498
|
+
|
1499
|
+
/* When the number of output rows reaches nRow, that means the
|
1500
|
+
** listing has finished and sqlite3_step() should return SQLITE_DONE.
|
1501
|
+
** nRow is the sum of the number of rows in the main program, plus
|
1502
|
+
** the sum of the number of rows in all trigger subprograms encountered
|
1503
|
+
** so far. The nRow value will increase as new trigger subprograms are
|
1504
|
+
** encountered, but p->pc will eventually catch up to nRow.
|
1505
|
+
*/
|
1506
|
+
nRow = p.nOp;
|
1507
|
+
int i_pMem;
|
1508
|
+
if ( p.explain == 1 )
|
1509
|
+
{
|
1510
|
+
/* The first 8 memory cells are used for the result set. So we will
|
1511
|
+
** commandeer the 9th cell to use as storage for an array of pointers
|
1512
|
+
** to trigger subprograms. The VDBE is guaranteed to have at least 9
|
1513
|
+
** cells. */
|
1514
|
+
Debug.Assert( p.nMem > 9 );
|
1515
|
+
pSub = p.aMem[9];
|
1516
|
+
if ( ( pSub.flags & MEM_Blob ) != 0 )
|
1517
|
+
{
|
1518
|
+
/* On the first call to sqlite3_step(), pSub will hold a NULL. It is
|
1519
|
+
** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
|
1520
|
+
apSub = p.aMem[9]._SubProgram; // apSub = (SubProgram**)pSub->z;
|
1521
|
+
nSub = apSub.Length;// pSub->n / sizeof( Vdbe* );
|
1522
|
+
}
|
1523
|
+
for ( i = 0; i < nSub; i++ )
|
1524
|
+
{
|
1525
|
+
nRow += apSub[i].nOp;
|
1526
|
+
}
|
1527
|
+
}
|
1528
|
+
|
1529
|
+
i_pMem = 0; if ( i_pMem >= p.pResultSet.Length ) Array.Resize( ref p.pResultSet, 8 + p.pResultSet.Length );
|
1530
|
+
{
|
1531
|
+
p.pResultSet[i_pMem] = sqlite3Malloc( p.pResultSet[i_pMem] );
|
1532
|
+
}
|
1533
|
+
pMem = p.pResultSet[i_pMem++];
|
1534
|
+
do
|
1535
|
+
{
|
1536
|
+
i = p.pc++;
|
1537
|
+
} while ( i < nRow && p.explain == 2 && p.aOp[i].opcode != OP_Explain );
|
1538
|
+
if ( i >= nRow )
|
1539
|
+
{
|
1540
|
+
p.rc = SQLITE_OK;
|
1541
|
+
rc = SQLITE_DONE;
|
1542
|
+
}
|
1543
|
+
else if ( db.u1.isInterrupted )
|
1544
|
+
{
|
1545
|
+
p.rc = SQLITE_INTERRUPT;
|
1546
|
+
rc = SQLITE_ERROR;
|
1547
|
+
sqlite3SetString( ref p.zErrMsg, db, sqlite3ErrStr( p.rc ) );
|
1548
|
+
}
|
1549
|
+
else
|
1550
|
+
{
|
1551
|
+
string z;
|
1552
|
+
Op pOp;
|
1553
|
+
if ( i < p.nOp )
|
1554
|
+
{
|
1555
|
+
/* The output line number is small enough that we are still in the
|
1556
|
+
** main program. */
|
1557
|
+
pOp = p.aOp[i];
|
1558
|
+
}
|
1559
|
+
else
|
1560
|
+
{
|
1561
|
+
/* We are currently listing subprograms. Figure out which one and
|
1562
|
+
** pick up the appropriate opcode. */
|
1563
|
+
int j;
|
1564
|
+
i -= p.nOp;
|
1565
|
+
for ( j = 0; i >= apSub[j].nOp; j++ )
|
1566
|
+
{
|
1567
|
+
i -= apSub[j].nOp;
|
1568
|
+
}
|
1569
|
+
pOp = apSub[j].aOp[i];
|
1570
|
+
}
|
1571
|
+
if ( p.explain == 1 )
|
1572
|
+
{
|
1573
|
+
pMem.flags = MEM_Int;
|
1574
|
+
pMem.type = SQLITE_INTEGER;
|
1575
|
+
pMem.u.i = i; /* Program counter */
|
1576
|
+
if ( p.pResultSet[i_pMem] == null )
|
1577
|
+
{
|
1578
|
+
p.pResultSet[i_pMem] = sqlite3Malloc( p.pResultSet[i_pMem] );
|
1579
|
+
}
|
1580
|
+
pMem = p.pResultSet[i_pMem++]; //pMem++;
|
1581
|
+
|
1582
|
+
/* When an OP_Program opcode is encounter (the only opcode that has
|
1583
|
+
** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
|
1584
|
+
** kept in p->aMem[9].z to hold the new program - assuming this subprogram
|
1585
|
+
** has not already been seen.
|
1586
|
+
*/
|
1587
|
+
pMem.flags = MEM_Static | MEM_Str | MEM_Term;
|
1588
|
+
pMem.z = sqlite3OpcodeName( pOp.opcode ); /* Opcode */
|
1589
|
+
Debug.Assert( pMem.z != null );
|
1590
|
+
pMem.n = sqlite3Strlen30( pMem.z );
|
1591
|
+
pMem.type = SQLITE_TEXT;
|
1592
|
+
pMem.enc = SQLITE_UTF8;
|
1593
|
+
if ( p.pResultSet[i_pMem] == null )
|
1594
|
+
{
|
1595
|
+
p.pResultSet[i_pMem] = sqlite3Malloc( p.pResultSet[i_pMem] );
|
1596
|
+
}
|
1597
|
+
pMem = p.pResultSet[i_pMem++]; //pMem++;
|
1598
|
+
if ( pOp.p4type == P4_SUBPROGRAM )
|
1599
|
+
{
|
1600
|
+
//Debugger.Break(); // TODO
|
1601
|
+
//int nByte = 0;//(nSub+1)*sizeof(SubProgram*);
|
1602
|
+
int j;
|
1603
|
+
for ( j = 0; j < nSub; j++ )
|
1604
|
+
{
|
1605
|
+
if ( apSub[j] == pOp.p4.pProgram ) break;
|
1606
|
+
}
|
1607
|
+
if ( j == nSub )
|
1608
|
+
{// && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, 1) ){
|
1609
|
+
Array.Resize( ref apSub, nSub + 1 );
|
1610
|
+
pSub._SubProgram = apSub;// (SubProgram)pSub.z;
|
1611
|
+
apSub[nSub++] = pOp.p4.pProgram;
|
1612
|
+
pSub.flags |= MEM_Blob;
|
1613
|
+
pSub.n = 0;//nSub*sizeof(SubProgram*);
|
1614
|
+
}
|
1615
|
+
}
|
1616
|
+
}
|
1617
|
+
|
1618
|
+
pMem.flags = MEM_Int;
|
1619
|
+
pMem.u.i = pOp.p1; /* P1 */
|
1620
|
+
pMem.type = SQLITE_INTEGER;
|
1621
|
+
if ( p.pResultSet[i_pMem] == null )
|
1622
|
+
{
|
1623
|
+
p.pResultSet[i_pMem] = sqlite3Malloc( p.pResultSet[i_pMem] );
|
1624
|
+
}
|
1625
|
+
pMem = p.pResultSet[i_pMem++]; //pMem++;
|
1626
|
+
|
1627
|
+
pMem.flags = MEM_Int;
|
1628
|
+
pMem.u.i = pOp.p2; /* P2 */
|
1629
|
+
pMem.type = SQLITE_INTEGER;
|
1630
|
+
if ( p.pResultSet[i_pMem] == null )
|
1631
|
+
{
|
1632
|
+
p.pResultSet[i_pMem] = sqlite3Malloc( p.pResultSet[i_pMem] );
|
1633
|
+
}
|
1634
|
+
pMem = p.pResultSet[i_pMem++]; //pMem++;
|
1635
|
+
|
1636
|
+
if ( p.explain == 1 )
|
1637
|
+
{
|
1638
|
+
pMem.flags = MEM_Int;
|
1639
|
+
pMem.u.i = pOp.p3; /* P3 */
|
1640
|
+
pMem.type = SQLITE_INTEGER;
|
1641
|
+
if ( p.pResultSet[i_pMem] == null )
|
1642
|
+
{
|
1643
|
+
p.pResultSet[i_pMem] = sqlite3Malloc( p.pResultSet[i_pMem] );
|
1644
|
+
}
|
1645
|
+
pMem = p.pResultSet[i_pMem++]; //pMem++;
|
1646
|
+
}
|
1647
|
+
|
1648
|
+
//if ( sqlite3VdbeMemGrow( pMem, 32, 0 ) != 0 )
|
1649
|
+
//{ /* P4 */
|
1650
|
+
// Debug.Assert( p.db.mallocFailed != 0 );
|
1651
|
+
// return SQLITE_ERROR;
|
1652
|
+
//}
|
1653
|
+
pMem.flags = MEM_Dyn | MEM_Str | MEM_Term;
|
1654
|
+
z = displayP4( pOp, pMem.z, 32 );
|
1655
|
+
if ( z != pMem.z )
|
1656
|
+
{
|
1657
|
+
sqlite3VdbeMemSetStr( pMem, z, -1, SQLITE_UTF8, null );
|
1658
|
+
}
|
1659
|
+
else
|
1660
|
+
{
|
1661
|
+
Debug.Assert( pMem.z != null );
|
1662
|
+
pMem.n = sqlite3Strlen30( pMem.z );
|
1663
|
+
pMem.enc = SQLITE_UTF8;
|
1664
|
+
}
|
1665
|
+
pMem.type = SQLITE_TEXT;
|
1666
|
+
if ( p.pResultSet[i_pMem] == null )
|
1667
|
+
{
|
1668
|
+
p.pResultSet[i_pMem] = sqlite3Malloc( p.pResultSet[i_pMem] );
|
1669
|
+
}
|
1670
|
+
pMem = p.pResultSet[i_pMem++]; //pMem++;
|
1671
|
+
|
1672
|
+
if ( p.explain == 1 )
|
1673
|
+
{
|
1674
|
+
//if ( sqlite3VdbeMemGrow( pMem, 4, 0 ) != 0 )
|
1675
|
+
//{
|
1676
|
+
// Debug.Assert( p.db.mallocFailed != 0 );
|
1677
|
+
// return SQLITE_ERROR;
|
1678
|
+
//}
|
1679
|
+
pMem.flags = MEM_Dyn | MEM_Str | MEM_Term;
|
1680
|
+
pMem.n = 2;
|
1681
|
+
pMem.z = pOp.p5.ToString( "x2" ); //sqlite3_snprintf( 3, pMem.z, "%.2x", pOp.p5 ); /* P5 */
|
1682
|
+
pMem.type = SQLITE_TEXT;
|
1683
|
+
pMem.enc = SQLITE_UTF8;
|
1684
|
+
if ( p.pResultSet[i_pMem] == null )
|
1685
|
+
{
|
1686
|
+
p.pResultSet[i_pMem] = sqlite3Malloc( p.pResultSet[i_pMem] );
|
1687
|
+
}
|
1688
|
+
pMem = p.pResultSet[i_pMem++]; // pMem++;
|
1689
|
+
|
1690
|
+
#if SQLITE_DEBUG
|
1691
|
+
if ( pOp.zComment != null )
|
1692
|
+
{
|
1693
|
+
pMem.flags = MEM_Str | MEM_Term;
|
1694
|
+
pMem.z = pOp.zComment;
|
1695
|
+
pMem.n = pMem.z == null ? 0 : sqlite3Strlen30( pMem.z );
|
1696
|
+
pMem.enc = SQLITE_UTF8;
|
1697
|
+
pMem.type = SQLITE_TEXT;
|
1698
|
+
}
|
1699
|
+
else
|
1700
|
+
#endif
|
1701
|
+
{
|
1702
|
+
pMem.flags = MEM_Null; /* Comment */
|
1703
|
+
pMem.type = SQLITE_NULL;
|
1704
|
+
}
|
1705
|
+
}
|
1706
|
+
|
1707
|
+
p.nResColumn = (u16)( 8 - 5 * ( p.explain - 1 ) );
|
1708
|
+
p.rc = SQLITE_OK;
|
1709
|
+
rc = SQLITE_ROW;
|
1710
|
+
}
|
1711
|
+
return rc;
|
1712
|
+
}
|
1713
|
+
#endif // * SQLITE_OMIT_EXPLAIN */
|
1714
|
+
|
1715
|
+
#if SQLITE_DEBUG
|
1716
|
+
/*
|
1717
|
+
** Print the SQL that was used to generate a VDBE program.
|
1718
|
+
*/
|
1719
|
+
static void sqlite3VdbePrintSql( Vdbe p )
|
1720
|
+
{
|
1721
|
+
int nOp = p.nOp;
|
1722
|
+
VdbeOp pOp;
|
1723
|
+
if ( nOp < 1 ) return;
|
1724
|
+
pOp = p.aOp[0];
|
1725
|
+
if ( pOp.opcode == OP_Trace && pOp.p4.z != null )
|
1726
|
+
{
|
1727
|
+
string z = pOp.p4.z;
|
1728
|
+
z = z.Trim();// while ( sqlite3Isspace( *(u8*)z ) ) z++;
|
1729
|
+
Console.Write( "SQL: [%s]\n", z );
|
1730
|
+
}
|
1731
|
+
}
|
1732
|
+
#endif
|
1733
|
+
|
1734
|
+
#if !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE
|
1735
|
+
/*
|
1736
|
+
** Print an IOTRACE message showing SQL content.
|
1737
|
+
*/
|
1738
|
+
static void sqlite3VdbeIOTraceSql( Vdbe p )
|
1739
|
+
{
|
1740
|
+
int nOp = p.nOp;
|
1741
|
+
VdbeOp pOp;
|
1742
|
+
if ( SQLite3IoTrace == false ) return;
|
1743
|
+
if ( nOp < 1 ) return;
|
1744
|
+
pOp = p.aOp[0];
|
1745
|
+
if ( pOp.opcode == OP_Trace && pOp.p4.z != null )
|
1746
|
+
{
|
1747
|
+
int i, j;
|
1748
|
+
string z = "";//char z[1000];
|
1749
|
+
sqlite3_snprintf( 1000, ref z, "%s", pOp.p4.z );
|
1750
|
+
//for(i=0; sqlite3Isspace(z[i]); i++){}
|
1751
|
+
//for(j=0; z[i]; i++){
|
1752
|
+
//if( sqlite3Isspace(z[i]) ){
|
1753
|
+
//if( z[i-1]!=' ' ){
|
1754
|
+
//z[j++] = ' ';
|
1755
|
+
//}
|
1756
|
+
//}else{
|
1757
|
+
//z[j++] = z[i];
|
1758
|
+
//}
|
1759
|
+
//}
|
1760
|
+
//z[j] = 0;
|
1761
|
+
//z = z.Trim( z );
|
1762
|
+
sqlite3IoTrace( "SQL %s\n", z.Trim() );
|
1763
|
+
}
|
1764
|
+
}
|
1765
|
+
#endif // * !SQLITE_OMIT_TRACE && SQLITE_ENABLE_IOTRACE */
|
1766
|
+
|
1767
|
+
/*
|
1768
|
+
** Allocate space from a fixed size buffer and return a pointer to
|
1769
|
+
** that space. If insufficient space is available, return NULL.
|
1770
|
+
**
|
1771
|
+
** The pBuf parameter is the initial value of a pointer which will
|
1772
|
+
** receive the new memory. pBuf is normally NULL. If pBuf is not
|
1773
|
+
** NULL, it means that memory space has already been allocated and that
|
1774
|
+
** this routine should not allocate any new memory. When pBuf is not
|
1775
|
+
** NULL simply return pBuf. Only allocate new memory space when pBuf
|
1776
|
+
** is NULL.
|
1777
|
+
**
|
1778
|
+
** nByte is the number of bytes of space needed.
|
1779
|
+
**
|
1780
|
+
** *ppFrom points to available space and pEnd points to the end of the
|
1781
|
+
** available space. When space is allocated, *ppFrom is advanced past
|
1782
|
+
** the end of the allocated space.
|
1783
|
+
**
|
1784
|
+
** *pnByte is a counter of the number of bytes of space that have failed
|
1785
|
+
** to allocate. If there is insufficient space in *ppFrom to satisfy the
|
1786
|
+
** request, then increment *pnByte by the amount of the request.
|
1787
|
+
*/
|
1788
|
+
//static void* allocSpace(
|
1789
|
+
// void* pBuf, /* Where return pointer will be stored */
|
1790
|
+
// int nByte, /* Number of bytes to allocate */
|
1791
|
+
// u8** ppFrom, /* IN/OUT: Allocate from *ppFrom */
|
1792
|
+
// u8* pEnd, /* Pointer to 1 byte past the end of *ppFrom buffer */
|
1793
|
+
// int* pnByte /* If allocation cannot be made, increment *pnByte */
|
1794
|
+
//)
|
1795
|
+
//{
|
1796
|
+
// assert(EIGHT_BYTE_ALIGNMENT(*ppFrom));
|
1797
|
+
// if (pBuf) return pBuf;
|
1798
|
+
// nByte = ROUND8(nByte);
|
1799
|
+
// if (&(*ppFrom)[nByte] <= pEnd)
|
1800
|
+
// {
|
1801
|
+
// pBuf = (void*)*ppFrom;
|
1802
|
+
// *ppFrom += nByte;
|
1803
|
+
// }
|
1804
|
+
// else
|
1805
|
+
// {
|
1806
|
+
// *pnByte += nByte;
|
1807
|
+
// }
|
1808
|
+
// return pBuf;
|
1809
|
+
//}
|
1810
|
+
|
1811
|
+
/*
|
1812
|
+
** Prepare a virtual machine for execution. This involves things such
|
1813
|
+
** as allocating stack space and initializing the program counter.
|
1814
|
+
** After the VDBE has be prepped, it can be executed by one or more
|
1815
|
+
** calls to sqlite3VdbeExec().
|
1816
|
+
**
|
1817
|
+
** This is the only way to move a VDBE from VDBE_MAGIC_INIT to
|
1818
|
+
** VDBE_MAGIC_RUN.
|
1819
|
+
**
|
1820
|
+
** This function may be called more than once on a single virtual machine.
|
1821
|
+
** The first call is made while compiling the SQL statement. Subsequent
|
1822
|
+
** calls are made as part of the process of resetting a statement to be
|
1823
|
+
** re-executed (from a call to sqlite3_reset()). The nVar, nMem, nCursor
|
1824
|
+
** and isExplain parameters are only passed correct values the first time
|
1825
|
+
** the function is called. On subsequent calls, from sqlite3_reset(), nVar
|
1826
|
+
** is passed -1 and nMem, nCursor and isExplain are all passed zero.
|
1827
|
+
*/
|
1828
|
+
static void sqlite3VdbeMakeReady(
|
1829
|
+
Vdbe p, /* The VDBE */
|
1830
|
+
int nVar, /* Number of '?' see in the SQL statement */
|
1831
|
+
int nMem, /* Number of memory cells to allocate */
|
1832
|
+
int nCursor, /* Number of cursors to allocate */
|
1833
|
+
int nArg, /* Maximum number of args in SubPrograms */
|
1834
|
+
int isExplain, /* True if the EXPLAIN keywords is present */
|
1835
|
+
int usesStmtJournal /* True to set Vdbe.usesStmtJournal */
|
1836
|
+
)
|
1837
|
+
{
|
1838
|
+
int n;
|
1839
|
+
sqlite3 db = p.db;
|
1840
|
+
|
1841
|
+
Debug.Assert( p != null );
|
1842
|
+
Debug.Assert( p.magic == VDBE_MAGIC_INIT );
|
1843
|
+
|
1844
|
+
/* There should be at least one opcode.
|
1845
|
+
*/
|
1846
|
+
Debug.Assert( p.nOp > 0 );
|
1847
|
+
|
1848
|
+
/* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
|
1849
|
+
p.magic = VDBE_MAGIC_RUN;
|
1850
|
+
|
1851
|
+
/* For each cursor required, also allocate a memory cell. Memory
|
1852
|
+
** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
|
1853
|
+
** the vdbe program. Instead they are used to allocate space for
|
1854
|
+
** VdbeCursor/BtCursor structures. The blob of memory associated with
|
1855
|
+
** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1)
|
1856
|
+
** stores the blob of memory associated with cursor 1, etc.
|
1857
|
+
**
|
1858
|
+
** See also: allocateCursor().
|
1859
|
+
*/
|
1860
|
+
nMem += nCursor;
|
1861
|
+
|
1862
|
+
/* Allocate space for memory registers, SQL variables, VDBE cursors and
|
1863
|
+
** an array to marshal SQL function arguments in. This is only done the
|
1864
|
+
** first time this function is called for a given VDBE, not when it is
|
1865
|
+
** being called from sqlite3_reset() to reset the virtual machine.
|
1866
|
+
*/
|
1867
|
+
if ( nVar >= 0 /* && ALWAYS(db->mallocFailed==0) */ )
|
1868
|
+
{
|
1869
|
+
//u8* zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for alloation */
|
1870
|
+
//u8* zEnd = (u8*)&p->aOp[p->nOpAlloc]; /* First byte past available mem */
|
1871
|
+
int nByte; /* How much extra memory needed */
|
1872
|
+
resolveP2Values( p, ref nArg );
|
1873
|
+
p.usesStmtJournal = usesStmtJournal != 0;
|
1874
|
+
if ( isExplain != 0 && nMem < 10 )
|
1875
|
+
{
|
1876
|
+
nMem = 10;
|
1877
|
+
}
|
1878
|
+
//memset(zCsr, 0, zEnd-zCsr);
|
1879
|
+
//zCsr += ( zCsr - (u8*)0 ) & 7;
|
1880
|
+
//assert( EIGHT_BYTE_ALIGNMENT( zCsr ) );
|
1881
|
+
//
|
1882
|
+
// C# -- Replace allocation with individual Dims
|
1883
|
+
//
|
1884
|
+
/* Memory for registers, parameters, cursor, etc, is allocated in two
|
1885
|
+
** passes. On the first pass, we try to reuse unused space at the
|
1886
|
+
** end of the opcode array. If we are unable to satisfy all memory
|
1887
|
+
** requirements by reusing the opcode array tail, then the second
|
1888
|
+
** pass will fill in the rest using a fresh allocation.
|
1889
|
+
**
|
1890
|
+
** This two-pass approach that reuses as much memory as possible from
|
1891
|
+
** the leftover space at the end of the opcode array can significantly
|
1892
|
+
** reduce the amount of memory held by a prepared statement.
|
1893
|
+
*/
|
1894
|
+
//do
|
1895
|
+
//{
|
1896
|
+
// nByte = 0;
|
1897
|
+
// p->aMem = allocSpace(p->aMem, nMem * sizeof(Mem), &zCsr, zEnd, &nByte);
|
1898
|
+
// p->aVar = allocSpace(p->aVar, nVar * sizeof(Mem), &zCsr, zEnd, &nByte);
|
1899
|
+
// p->apArg = allocSpace(p->apArg, nArg * sizeof(Mem*), &zCsr, zEnd, &nByte);
|
1900
|
+
// p->azVar = allocSpace(p->azVar, nVar * sizeof(char*), &zCsr, zEnd, &nByte);
|
1901
|
+
// p->apCsr = allocSpace(p->apCsr, nCursor * sizeof(VdbeCursor*),
|
1902
|
+
// &zCsr, zEnd, &nByte);
|
1903
|
+
// if (nByte)
|
1904
|
+
// {
|
1905
|
+
// p->pFree = sqlite3DbMallocZero(db, nByte);
|
1906
|
+
// }
|
1907
|
+
// zCsr = p->pFree;
|
1908
|
+
// zEnd = &zCsr[nByte];
|
1909
|
+
//} while (nByte && !db->mallocFailed);
|
1910
|
+
|
1911
|
+
|
1912
|
+
// C# -- Replace allocation with individual Dims
|
1913
|
+
// aMem is 1 based, so allocate 1 extra cell under C#
|
1914
|
+
p.aMem = new Mem[nMem + 1];
|
1915
|
+
for ( n = 0; n <= nMem; n++ )
|
1916
|
+
{
|
1917
|
+
p.aMem[n] = sqlite3Malloc( p.aMem[n] );
|
1918
|
+
p.aMem[n].db = db;
|
1919
|
+
}
|
1920
|
+
//p.aMem--; /* aMem[] goes from 1..nMem */
|
1921
|
+
p.nMem = nMem; /* not from 0..nMem-1 */
|
1922
|
+
//
|
1923
|
+
p.aVar = new Mem[nVar == 0 ? 1 : nVar ];
|
1924
|
+
for ( n = 0; n < nVar; n++ )
|
1925
|
+
{
|
1926
|
+
p.aVar[n] = sqlite3Malloc(p.aVar[n] );
|
1927
|
+
}
|
1928
|
+
p.nVar = (ynVar)nVar;
|
1929
|
+
p.okVar = 0;
|
1930
|
+
//
|
1931
|
+
p.apArg = new Mem[nArg == 0 ? 1 : nArg];//p.apArg = (Mem**)p.aVar[nVar];
|
1932
|
+
//
|
1933
|
+
|
1934
|
+
p.azVar = new string[nArg == 0 ? 1 : nArg]; //p.azVar = (char**)p.apArg[nArg];
|
1935
|
+
for ( n = 0; n < nArg; n++ )
|
1936
|
+
{ p.azVar[n] = ""; }
|
1937
|
+
//
|
1938
|
+
p.apCsr = new VdbeCursor[nCursor == 0 ? 1 : nCursor];//p.apCsr = (VdbeCursor**)p.azVar[nVar];
|
1939
|
+
p.apCsr[0] = new VdbeCursor();
|
1940
|
+
p.nCursor = (u16)nCursor;
|
1941
|
+
if ( p.aVar != null )
|
1942
|
+
{
|
1943
|
+
p.nVar = (ynVar)nVar;
|
1944
|
+
//
|
1945
|
+
for ( n = 0; n < nVar; n++ )
|
1946
|
+
{
|
1947
|
+
p.aVar[n].flags = MEM_Null;
|
1948
|
+
p.aVar[n].db = db;
|
1949
|
+
}
|
1950
|
+
}
|
1951
|
+
if ( p.aMem != null )
|
1952
|
+
{
|
1953
|
+
//p.aMem--; /* aMem[] goes from 1..nMem */
|
1954
|
+
p.nMem = nMem; /* not from 0..nMem-1 */
|
1955
|
+
for ( n = 0; n <= nMem; n++ )
|
1956
|
+
{
|
1957
|
+
p.aMem[n].flags = MEM_Null;
|
1958
|
+
p.aMem[n].n = 0;
|
1959
|
+
p.aMem[n].z = null;
|
1960
|
+
p.aMem[n].zBLOB = null;
|
1961
|
+
p.aMem[n].db = db;
|
1962
|
+
}
|
1963
|
+
}
|
1964
|
+
}
|
1965
|
+
|
1966
|
+
#if SQLITE_DEBUG
|
1967
|
+
for ( n = 1; n < p.nMem; n++ )
|
1968
|
+
{
|
1969
|
+
Debug.Assert( p.aMem[n].db == db );
|
1970
|
+
}
|
1971
|
+
#endif
|
1972
|
+
|
1973
|
+
p.pc = -1;
|
1974
|
+
p.rc = SQLITE_OK;
|
1975
|
+
p.errorAction = OE_Abort;
|
1976
|
+
p.explain |= isExplain;
|
1977
|
+
p.magic = VDBE_MAGIC_RUN;
|
1978
|
+
p.nChange = 0;
|
1979
|
+
p.cacheCtr = 1;
|
1980
|
+
p.minWriteFileFormat = 255;
|
1981
|
+
p.iStatement = 0;
|
1982
|
+
#if VDBE_PROFILE
|
1983
|
+
{
|
1984
|
+
int i;
|
1985
|
+
for ( i = 0 ; i < p.nOp ; i++ )
|
1986
|
+
{
|
1987
|
+
p.aOp[i].cnt = 0;
|
1988
|
+
p.aOp[i].cycles = 0;
|
1989
|
+
}
|
1990
|
+
}
|
1991
|
+
#endif
|
1992
|
+
}
|
1993
|
+
|
1994
|
+
/*
|
1995
|
+
** Close a VDBE cursor and release all the resources that cursor
|
1996
|
+
** happens to hold.
|
1997
|
+
*/
|
1998
|
+
static void sqlite3VdbeFreeCursor( Vdbe p, VdbeCursor pCx )
|
1999
|
+
{
|
2000
|
+
if ( pCx == null )
|
2001
|
+
{
|
2002
|
+
return;
|
2003
|
+
}
|
2004
|
+
|
2005
|
+
if ( pCx.pBt != null )
|
2006
|
+
{
|
2007
|
+
sqlite3BtreeClose( ref pCx.pBt );
|
2008
|
+
/* The pCx.pCursor will be close automatically, if it exists, by
|
2009
|
+
** the call above. */
|
2010
|
+
}
|
2011
|
+
else if ( pCx.pCursor != null )
|
2012
|
+
{
|
2013
|
+
sqlite3BtreeCloseCursor( pCx.pCursor );
|
2014
|
+
sqlite3MemFreeBtCursor( ref pCx.pCursor );
|
2015
|
+
}
|
2016
|
+
#if ! SQLITE_OMIT_VIRTUALTABLE
|
2017
|
+
if( pCx.pVtabCursor ){
|
2018
|
+
sqlite3_vtab_cursor pVtabCursor = pCx.pVtabCursor;
|
2019
|
+
const sqlite3_module pModule = pCx.pModule;
|
2020
|
+
p.inVtabMethod = 1;
|
2021
|
+
pModule.xClose(pVtabCursor);
|
2022
|
+
p.inVtabMethod = 0;
|
2023
|
+
}
|
2024
|
+
#endif
|
2025
|
+
}
|
2026
|
+
/*
|
2027
|
+
** Copy the values stored in the VdbeFrame structure to its Vdbe. This
|
2028
|
+
** is used, for example, when a trigger sub-program is halted to restore
|
2029
|
+
** control to the main program.
|
2030
|
+
*/
|
2031
|
+
static int sqlite3VdbeFrameRestore( VdbeFrame pFrame )
|
2032
|
+
{
|
2033
|
+
Vdbe v = pFrame.v;
|
2034
|
+
v.aOp = pFrame.aOp;
|
2035
|
+
v.nOp = pFrame.nOp;
|
2036
|
+
v.aMem = pFrame.aMem;
|
2037
|
+
v.nMem = pFrame.nMem;
|
2038
|
+
v.apCsr = pFrame.apCsr;
|
2039
|
+
v.nCursor = pFrame.nCursor;
|
2040
|
+
v.db.lastRowid = pFrame.lastRowid;
|
2041
|
+
v.nChange = pFrame.nChange;
|
2042
|
+
return pFrame.pc;
|
2043
|
+
}
|
2044
|
+
|
2045
|
+
/*
|
2046
|
+
** Close all cursors.
|
2047
|
+
**
|
2048
|
+
** Also release any dynamic memory held by the VM in the Vdbe.aMem memory
|
2049
|
+
** cell array. This is necessary as the memory cell array may contain
|
2050
|
+
** pointers to VdbeFrame objects, which may in turn contain pointers to
|
2051
|
+
** open cursors.
|
2052
|
+
*/
|
2053
|
+
static void closeAllCursors( Vdbe p )
|
2054
|
+
{
|
2055
|
+
if ( p.pFrame != null )
|
2056
|
+
{
|
2057
|
+
VdbeFrame pFrame = p.pFrame;
|
2058
|
+
for ( pFrame = p.pFrame; pFrame.pParent != null; pFrame = pFrame.pParent ) ;
|
2059
|
+
sqlite3VdbeFrameRestore( pFrame );
|
2060
|
+
}
|
2061
|
+
p.pFrame = null;
|
2062
|
+
p.nFrame = 0;
|
2063
|
+
|
2064
|
+
if ( p.apCsr != null )
|
2065
|
+
{
|
2066
|
+
int i;
|
2067
|
+
for ( i = 0; i < p.nCursor; i++ )
|
2068
|
+
{
|
2069
|
+
VdbeCursor pC = p.apCsr[i];
|
2070
|
+
if ( pC != null )
|
2071
|
+
{
|
2072
|
+
sqlite3VdbeFreeCursor( p, pC );
|
2073
|
+
p.apCsr[i] = null;
|
2074
|
+
}
|
2075
|
+
}
|
2076
|
+
}
|
2077
|
+
if ( p.aMem != null )
|
2078
|
+
{
|
2079
|
+
releaseMemArray( p.aMem, 1, p.nMem );
|
2080
|
+
}
|
2081
|
+
}
|
2082
|
+
/*
|
2083
|
+
** Clean up the VM after execution.
|
2084
|
+
**
|
2085
|
+
** This routine will automatically close any cursors, lists, and/or
|
2086
|
+
** sorters that were left open. It also deletes the values of
|
2087
|
+
** variables in the aVar[] array.
|
2088
|
+
*/
|
2089
|
+
static void Cleanup( Vdbe p )
|
2090
|
+
{
|
2091
|
+
sqlite3 db = p.db;
|
2092
|
+
#if SQLITE_DEBUG
|
2093
|
+
/* Execute assert() statements to ensure that the Vdbe.apCsr[] and
|
2094
|
+
** Vdbe.aMem[] arrays have already been cleaned up. */
|
2095
|
+
int i;
|
2096
|
+
//TODO for(i=0; i<p.nCursor; i++) Debug.Assert( p.apCsr==null || p.apCsr[i]==null );
|
2097
|
+
for ( i = 1; i <= p.nMem; i++ ) Debug.Assert( p.aMem != null || p.aMem[i].flags == MEM_Null );
|
2098
|
+
#endif
|
2099
|
+
|
2100
|
+
sqlite3DbFree( db, ref p.zErrMsg );
|
2101
|
+
p.pResultSet = null;
|
2102
|
+
}
|
2103
|
+
|
2104
|
+
/*
|
2105
|
+
** Set the number of result columns that will be returned by this SQL
|
2106
|
+
** statement. This is now set at compile time, rather than during
|
2107
|
+
** execution of the vdbe program so that sqlite3_column_count() can
|
2108
|
+
** be called on an SQL statement before sqlite3_step().
|
2109
|
+
*/
|
2110
|
+
static void sqlite3VdbeSetNumCols( Vdbe p, int nResColumn )
|
2111
|
+
{
|
2112
|
+
Mem pColName;
|
2113
|
+
int n;
|
2114
|
+
sqlite3 db = p.db;
|
2115
|
+
|
2116
|
+
releaseMemArray( p.aColName, p.nResColumn * COLNAME_N );
|
2117
|
+
sqlite3DbFree( db, ref p.aColName );
|
2118
|
+
n = nResColumn * COLNAME_N;
|
2119
|
+
p.nResColumn = (u16)nResColumn;
|
2120
|
+
p.aColName = new Mem[n];// (Mem*)sqlite3DbMallocZero(db, Mem.Length * n);
|
2121
|
+
//if (p.aColName == 0) return;
|
2122
|
+
while ( n-- > 0 )
|
2123
|
+
{
|
2124
|
+
p.aColName[n] = sqlite3Malloc( p.aColName[n] );
|
2125
|
+
pColName = p.aColName[n];
|
2126
|
+
pColName.flags = MEM_Null;
|
2127
|
+
pColName.db = p.db;
|
2128
|
+
}
|
2129
|
+
}
|
2130
|
+
|
2131
|
+
/*
|
2132
|
+
** Set the name of the idx'th column to be returned by the SQL statement.
|
2133
|
+
** zName must be a pointer to a nul terminated string.
|
2134
|
+
**
|
2135
|
+
** This call must be made after a call to sqlite3VdbeSetNumCols().
|
2136
|
+
**
|
2137
|
+
** The final parameter, xDel, must be one of SQLITE_DYNAMIC, SQLITE_STATIC
|
2138
|
+
** or SQLITE_TRANSIENT. If it is SQLITE_DYNAMIC, then the buffer pointed
|
2139
|
+
** to by zName will be freed by sqlite3DbFree() when the vdbe is destroyed.
|
2140
|
+
*/
|
2141
|
+
|
2142
|
+
|
2143
|
+
static int sqlite3VdbeSetColName(
|
2144
|
+
Vdbe p, /* Vdbe being configured */
|
2145
|
+
int idx, /* Index of column zName applies to */
|
2146
|
+
int var, /* One of the COLNAME_* constants */
|
2147
|
+
string zName, /* Pointer to buffer containing name */
|
2148
|
+
dxDel xDel /* Memory management strategy for zName */
|
2149
|
+
)
|
2150
|
+
{
|
2151
|
+
int rc;
|
2152
|
+
Mem pColName;
|
2153
|
+
Debug.Assert( idx < p.nResColumn );
|
2154
|
+
Debug.Assert( var < COLNAME_N );
|
2155
|
+
//if ( p.db.mallocFailed != 0 )
|
2156
|
+
//{
|
2157
|
+
// Debug.Assert( null == zName || xDel != SQLITE_DYNAMIC );
|
2158
|
+
// return SQLITE_NOMEM;
|
2159
|
+
//}
|
2160
|
+
Debug.Assert( p.aColName != null );
|
2161
|
+
pColName = p.aColName[idx + var * p.nResColumn];
|
2162
|
+
rc = sqlite3VdbeMemSetStr( pColName, zName, -1, SQLITE_UTF8, xDel );
|
2163
|
+
Debug.Assert( rc != 0 || null == zName || ( pColName.flags & MEM_Term ) != 0 );
|
2164
|
+
return rc;
|
2165
|
+
}
|
2166
|
+
|
2167
|
+
/*
|
2168
|
+
** A read or write transaction may or may not be active on database handle
|
2169
|
+
** db. If a transaction is active, commit it. If there is a
|
2170
|
+
** write-transaction spanning more than one database file, this routine
|
2171
|
+
** takes care of the master journal trickery.
|
2172
|
+
*/
|
2173
|
+
static int vdbeCommit( sqlite3 db, Vdbe p )
|
2174
|
+
{
|
2175
|
+
int i;
|
2176
|
+
int nTrans = 0; /* Number of databases with an active write-transaction */
|
2177
|
+
int rc = SQLITE_OK;
|
2178
|
+
bool needXcommit = false;
|
2179
|
+
|
2180
|
+
#if SQLITE_OMIT_VIRTUALTABLE
|
2181
|
+
/* With this option, sqlite3VtabSync() is defined to be simply
|
2182
|
+
** SQLITE_OK so p is not used.
|
2183
|
+
*/
|
2184
|
+
UNUSED_PARAMETER( p );
|
2185
|
+
#endif
|
2186
|
+
/* Before doing anything else, call the xSync() callback for any
|
2187
|
+
** virtual module tables written in this transaction. This has to
|
2188
|
+
** be done before determining whether a master journal file is
|
2189
|
+
** required, as an xSync() callback may add an attached database
|
2190
|
+
** to the transaction.
|
2191
|
+
*/
|
2192
|
+
rc = sqlite3VtabSync( db, p.zErrMsg );
|
2193
|
+
if ( rc != SQLITE_OK )
|
2194
|
+
{
|
2195
|
+
return rc;
|
2196
|
+
}
|
2197
|
+
|
2198
|
+
/* This loop determines (a) if the commit hook should be invoked and
|
2199
|
+
** (b) how many database files have open write transactions, not
|
2200
|
+
** including the temp database. (b) is important because if more than
|
2201
|
+
** one database file has an open write transaction, a master journal
|
2202
|
+
** file is required for an atomic commit.
|
2203
|
+
*/
|
2204
|
+
for ( i = 0; i < db.nDb; i++ )
|
2205
|
+
{
|
2206
|
+
Btree pBt = db.aDb[i].pBt;
|
2207
|
+
if ( sqlite3BtreeIsInTrans( pBt ) )
|
2208
|
+
{
|
2209
|
+
needXcommit = true;
|
2210
|
+
if ( i != 1 ) nTrans++;
|
2211
|
+
}
|
2212
|
+
}
|
2213
|
+
|
2214
|
+
/* If there are any write-transactions at all, invoke the commit hook */
|
2215
|
+
if ( needXcommit && db.xCommitCallback != null )
|
2216
|
+
{
|
2217
|
+
rc = db.xCommitCallback( db.pCommitArg );
|
2218
|
+
if ( rc != 0 )
|
2219
|
+
{
|
2220
|
+
return SQLITE_CONSTRAINT;
|
2221
|
+
}
|
2222
|
+
}
|
2223
|
+
|
2224
|
+
/* The simple case - no more than one database file (not counting the
|
2225
|
+
** TEMP database) has a transaction active. There is no need for the
|
2226
|
+
** master-journal.
|
2227
|
+
**
|
2228
|
+
** If the return value of sqlite3BtreeGetFilename() is a zero length
|
2229
|
+
** string, it means the main database is :memory: or a temp file. In
|
2230
|
+
** that case we do not support atomic multi-file commits, so use the
|
2231
|
+
** simple case then too.
|
2232
|
+
*/
|
2233
|
+
if ( 0 == sqlite3Strlen30( sqlite3BtreeGetFilename( db.aDb[0].pBt ) )
|
2234
|
+
|| nTrans <= 1 )
|
2235
|
+
{
|
2236
|
+
for ( i = 0; rc == SQLITE_OK && i < db.nDb; i++ )
|
2237
|
+
{
|
2238
|
+
Btree pBt = db.aDb[i].pBt;
|
2239
|
+
if ( pBt != null )
|
2240
|
+
{
|
2241
|
+
rc = sqlite3BtreeCommitPhaseOne( pBt, null );
|
2242
|
+
}
|
2243
|
+
}
|
2244
|
+
|
2245
|
+
/* Do the commit only if all databases successfully complete phase 1.
|
2246
|
+
** If one of the BtreeCommitPhaseOne() calls fails, this indicates an
|
2247
|
+
** IO error while deleting or truncating a journal file. It is unlikely,
|
2248
|
+
** but could happen. In this case abandon processing and return the error.
|
2249
|
+
*/
|
2250
|
+
for ( i = 0; rc == SQLITE_OK && i < db.nDb; i++ )
|
2251
|
+
{
|
2252
|
+
Btree pBt = db.aDb[i].pBt;
|
2253
|
+
if ( pBt != null )
|
2254
|
+
{
|
2255
|
+
rc = sqlite3BtreeCommitPhaseTwo( pBt );
|
2256
|
+
}
|
2257
|
+
}
|
2258
|
+
if ( rc == SQLITE_OK )
|
2259
|
+
{
|
2260
|
+
sqlite3VtabCommit( db );
|
2261
|
+
}
|
2262
|
+
}
|
2263
|
+
|
2264
|
+
/* The complex case - There is a multi-file write-transaction active.
|
2265
|
+
** This requires a master journal file to ensure the transaction is
|
2266
|
+
** committed atomicly.
|
2267
|
+
*/
|
2268
|
+
#if ! SQLITE_OMIT_DISKIO
|
2269
|
+
else
|
2270
|
+
{
|
2271
|
+
sqlite3_vfs pVfs = db.pVfs;
|
2272
|
+
bool needSync = false;
|
2273
|
+
string zMaster = ""; /* File-name for the master journal */
|
2274
|
+
string zMainFile = sqlite3BtreeGetFilename( db.aDb[0].pBt );
|
2275
|
+
sqlite3_file pMaster = null;
|
2276
|
+
i64 offset = 0;
|
2277
|
+
int res = 0;
|
2278
|
+
|
2279
|
+
/* Select a master journal file name */
|
2280
|
+
do
|
2281
|
+
{
|
2282
|
+
i64 iRandom = 0;
|
2283
|
+
sqlite3DbFree( db, ref zMaster );
|
2284
|
+
sqlite3_randomness( sizeof( u32 ), ref iRandom );//random.Length
|
2285
|
+
zMaster = sqlite3MPrintf( db, "%s-mj%08X", zMainFile, iRandom & 0x7fffffff );
|
2286
|
+
//if (!zMaster)
|
2287
|
+
//{
|
2288
|
+
// return SQLITE_NOMEM;
|
2289
|
+
//}
|
2290
|
+
rc = sqlite3OsAccess( pVfs, zMaster, SQLITE_ACCESS_EXISTS, ref res );
|
2291
|
+
} while ( rc == SQLITE_OK && res == 1 );
|
2292
|
+
if ( rc == SQLITE_OK )
|
2293
|
+
{
|
2294
|
+
/* Open the master journal. */
|
2295
|
+
rc = sqlite3OsOpenMalloc( ref pVfs, zMaster, pMaster,
|
2296
|
+
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
|
2297
|
+
SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_MASTER_JOURNAL, ref rc
|
2298
|
+
);
|
2299
|
+
} if ( rc != SQLITE_OK )
|
2300
|
+
{
|
2301
|
+
sqlite3DbFree( db, ref zMaster );
|
2302
|
+
return rc;
|
2303
|
+
}
|
2304
|
+
|
2305
|
+
/* Write the name of each database file in the transaction into the new
|
2306
|
+
** master journal file. If an error occurs at this point close
|
2307
|
+
** and delete the master journal file. All the individual journal files
|
2308
|
+
** still have 'null' as the master journal pointer, so they will roll
|
2309
|
+
** back independently if a failure occurs.
|
2310
|
+
*/
|
2311
|
+
for ( i = 0; i < db.nDb; i++ )
|
2312
|
+
{
|
2313
|
+
Btree pBt = db.aDb[i].pBt;
|
2314
|
+
if ( sqlite3BtreeIsInTrans( pBt ) )
|
2315
|
+
{
|
2316
|
+
string zFile = sqlite3BtreeGetJournalname( pBt );
|
2317
|
+
if ( String.IsNullOrEmpty( zFile ) )// zFile == 0 || zFile[0] == 0)
|
2318
|
+
{
|
2319
|
+
continue; /* Ignore TEMP and :memory: databases */
|
2320
|
+
}
|
2321
|
+
if ( !needSync && 0 == sqlite3BtreeSyncDisabled( pBt ) )
|
2322
|
+
{
|
2323
|
+
needSync = true;
|
2324
|
+
}
|
2325
|
+
rc = sqlite3OsWrite( pMaster, Encoding.UTF8.GetBytes( zFile ), sqlite3Strlen30( zFile ), offset );
|
2326
|
+
offset += sqlite3Strlen30( zFile );
|
2327
|
+
if ( rc != SQLITE_OK )
|
2328
|
+
{
|
2329
|
+
sqlite3OsCloseFree( pMaster );
|
2330
|
+
sqlite3OsDelete( pVfs, zMaster, 0 );
|
2331
|
+
sqlite3DbFree( db, ref zMaster );
|
2332
|
+
return rc;
|
2333
|
+
}
|
2334
|
+
}
|
2335
|
+
}
|
2336
|
+
|
2337
|
+
/* Sync the master journal file. If the IOCAP_SEQUENTIAL device
|
2338
|
+
** flag is set this is not required.
|
2339
|
+
*/
|
2340
|
+
if ( needSync
|
2341
|
+
&& 0 == ( sqlite3OsDeviceCharacteristics( pMaster ) & SQLITE_IOCAP_SEQUENTIAL )
|
2342
|
+
&& SQLITE_OK != ( rc = sqlite3OsSync( pMaster, SQLITE_SYNC_NORMAL ) )
|
2343
|
+
)
|
2344
|
+
{
|
2345
|
+
sqlite3OsCloseFree( pMaster );
|
2346
|
+
sqlite3OsDelete( pVfs, zMaster, 0 );
|
2347
|
+
sqlite3DbFree( db, ref zMaster );
|
2348
|
+
return rc;
|
2349
|
+
}
|
2350
|
+
|
2351
|
+
/* Sync all the db files involved in the transaction. The same call
|
2352
|
+
** sets the master journal pointer in each individual journal. If
|
2353
|
+
** an error occurs here, do not delete the master journal file.
|
2354
|
+
**
|
2355
|
+
** If the error occurs during the first call to
|
2356
|
+
** sqlite3BtreeCommitPhaseOne(), then there is a chance that the
|
2357
|
+
** master journal file will be orphaned. But we cannot delete it,
|
2358
|
+
** in case the master journal file name was written into the journal
|
2359
|
+
** file before the failure occurred.
|
2360
|
+
*/
|
2361
|
+
for ( i = 0; rc == SQLITE_OK && i < db.nDb; i++ )
|
2362
|
+
{
|
2363
|
+
Btree pBt = db.aDb[i].pBt;
|
2364
|
+
if ( pBt != null )
|
2365
|
+
{
|
2366
|
+
rc = sqlite3BtreeCommitPhaseOne( pBt, zMaster );
|
2367
|
+
}
|
2368
|
+
}
|
2369
|
+
sqlite3OsCloseFree( pMaster );
|
2370
|
+
if ( rc != SQLITE_OK )
|
2371
|
+
{
|
2372
|
+
sqlite3DbFree( db, ref zMaster );
|
2373
|
+
return rc;
|
2374
|
+
}
|
2375
|
+
|
2376
|
+
/* Delete the master journal file. This commits the transaction. After
|
2377
|
+
** doing this the directory is synced again before any individual
|
2378
|
+
** transaction files are deleted.
|
2379
|
+
*/
|
2380
|
+
rc = sqlite3OsDelete( pVfs, zMaster, 1 );
|
2381
|
+
sqlite3DbFree( db, ref zMaster );
|
2382
|
+
if ( rc != 0 )
|
2383
|
+
{
|
2384
|
+
return rc;
|
2385
|
+
}
|
2386
|
+
|
2387
|
+
/* All files and directories have already been synced, so the following
|
2388
|
+
** calls to sqlite3BtreeCommitPhaseTwo() are only closing files and
|
2389
|
+
** deleting or truncating journals. If something goes wrong while
|
2390
|
+
** this is happening we don't really care. The integrity of the
|
2391
|
+
** transaction is already guaranteed, but some stray 'cold' journals
|
2392
|
+
** may be lying around. Returning an error code won't help matters.
|
2393
|
+
*/
|
2394
|
+
#if SQLITE_TEST
|
2395
|
+
disable_simulated_io_errors();
|
2396
|
+
#endif
|
2397
|
+
sqlite3BeginBenignMalloc();
|
2398
|
+
for ( i = 0; i < db.nDb; i++ )
|
2399
|
+
{
|
2400
|
+
Btree pBt = db.aDb[i].pBt;
|
2401
|
+
if ( pBt != null )
|
2402
|
+
{
|
2403
|
+
sqlite3BtreeCommitPhaseTwo( pBt );
|
2404
|
+
}
|
2405
|
+
}
|
2406
|
+
sqlite3EndBenignMalloc();
|
2407
|
+
#if SQLITE_TEST
|
2408
|
+
enable_simulated_io_errors();
|
2409
|
+
#endif
|
2410
|
+
sqlite3VtabCommit( db );
|
2411
|
+
}
|
2412
|
+
#endif
|
2413
|
+
|
2414
|
+
return rc;
|
2415
|
+
}
|
2416
|
+
|
2417
|
+
/*
|
2418
|
+
** This routine checks that the sqlite3.activeVdbeCnt count variable
|
2419
|
+
** matches the number of vdbe's in the list sqlite3.pVdbe that are
|
2420
|
+
** currently active. An Debug.Assertion fails if the two counts do not match.
|
2421
|
+
** This is an internal self-check only - it is not an essential processing
|
2422
|
+
** step.
|
2423
|
+
**
|
2424
|
+
** This is a no-op if NDEBUG is defined.
|
2425
|
+
*/
|
2426
|
+
#if !NDEBUG
|
2427
|
+
static void checkActiveVdbeCnt( sqlite3 db )
|
2428
|
+
{
|
2429
|
+
Vdbe p;
|
2430
|
+
int cnt = 0;
|
2431
|
+
int nWrite = 0;
|
2432
|
+
p = db.pVdbe;
|
2433
|
+
while ( p != null )
|
2434
|
+
{
|
2435
|
+
if ( p.magic == VDBE_MAGIC_RUN && p.pc >= 0 )
|
2436
|
+
{
|
2437
|
+
cnt++;
|
2438
|
+
if ( p.readOnly == false ) nWrite++;
|
2439
|
+
}
|
2440
|
+
p = p.pNext;
|
2441
|
+
}
|
2442
|
+
Debug.Assert( cnt == db.activeVdbeCnt );
|
2443
|
+
Debug.Assert( nWrite == db.writeVdbeCnt );
|
2444
|
+
}
|
2445
|
+
#else
|
2446
|
+
//#define checkActiveVdbeCnt(x)
|
2447
|
+
static void checkActiveVdbeCnt( sqlite3 db ){}
|
2448
|
+
#endif
|
2449
|
+
|
2450
|
+
/*
|
2451
|
+
** For every Btree that in database connection db which
|
2452
|
+
** has been modified, "trip" or invalidate each cursor in
|
2453
|
+
** that Btree might have been modified so that the cursor
|
2454
|
+
** can never be used again. This happens when a rollback
|
2455
|
+
*** occurs. We have to trip all the other cursors, even
|
2456
|
+
** cursor from other VMs in different database connections,
|
2457
|
+
** so that none of them try to use the data at which they
|
2458
|
+
** were pointing and which now may have been changed due
|
2459
|
+
** to the rollback.
|
2460
|
+
**
|
2461
|
+
** Remember that a rollback can delete tables complete and
|
2462
|
+
** reorder rootpages. So it is not sufficient just to save
|
2463
|
+
** the state of the cursor. We have to invalidate the cursor
|
2464
|
+
** so that it is never used again.
|
2465
|
+
*/
|
2466
|
+
static void invalidateCursorsOnModifiedBtrees( sqlite3 db )
|
2467
|
+
{
|
2468
|
+
int i;
|
2469
|
+
for ( i = 0; i < db.nDb; i++ )
|
2470
|
+
{
|
2471
|
+
Btree p = db.aDb[i].pBt;
|
2472
|
+
if ( p != null && sqlite3BtreeIsInTrans( p ) )
|
2473
|
+
{
|
2474
|
+
sqlite3BtreeTripAllCursors( p, SQLITE_ABORT );
|
2475
|
+
}
|
2476
|
+
}
|
2477
|
+
}
|
2478
|
+
|
2479
|
+
/*
|
2480
|
+
** If the Vdbe passed as the first argument opened a statement-transaction,
|
2481
|
+
** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
|
2482
|
+
** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement
|
2483
|
+
** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the
|
2484
|
+
** statement transaction is commtted.
|
2485
|
+
**
|
2486
|
+
** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
|
2487
|
+
** Otherwise SQLITE_OK.
|
2488
|
+
*/
|
2489
|
+
static int sqlite3VdbeCloseStatement( Vdbe p, int eOp )
|
2490
|
+
{
|
2491
|
+
sqlite3 db = p.db;
|
2492
|
+
int rc = SQLITE_OK;
|
2493
|
+
/* If p->iStatement is greater than zero, then this Vdbe opened a
|
2494
|
+
** statement transaction that should be closed here. The only exception
|
2495
|
+
** is that an IO error may have occured, causing an emergency rollback.
|
2496
|
+
** In this case (db->nStatement==0), and there is nothing to do.
|
2497
|
+
*/
|
2498
|
+
if ( db.nStatement != 0 && p.iStatement != 0 )
|
2499
|
+
{
|
2500
|
+
int i;
|
2501
|
+
int iSavepoint = p.iStatement - 1;
|
2502
|
+
|
2503
|
+
Debug.Assert( eOp == SAVEPOINT_ROLLBACK || eOp == SAVEPOINT_RELEASE );
|
2504
|
+
Debug.Assert( db.nStatement > 0 );
|
2505
|
+
Debug.Assert( p.iStatement == ( db.nStatement + db.nSavepoint ) );
|
2506
|
+
|
2507
|
+
for ( i = 0; i < db.nDb; i++ )
|
2508
|
+
{
|
2509
|
+
int rc2 = SQLITE_OK;
|
2510
|
+
Btree pBt = db.aDb[i].pBt;
|
2511
|
+
if ( pBt != null )
|
2512
|
+
{
|
2513
|
+
if ( eOp == SAVEPOINT_ROLLBACK )
|
2514
|
+
{
|
2515
|
+
rc2 = sqlite3BtreeSavepoint( pBt, SAVEPOINT_ROLLBACK, iSavepoint );
|
2516
|
+
}
|
2517
|
+
if ( rc2 == SQLITE_OK )
|
2518
|
+
{
|
2519
|
+
rc2 = sqlite3BtreeSavepoint( pBt, SAVEPOINT_RELEASE, iSavepoint );
|
2520
|
+
}
|
2521
|
+
if ( rc == SQLITE_OK )
|
2522
|
+
{
|
2523
|
+
rc = rc2;
|
2524
|
+
}
|
2525
|
+
}
|
2526
|
+
}
|
2527
|
+
db.nStatement--;
|
2528
|
+
p.iStatement = 0;
|
2529
|
+
|
2530
|
+
/* If the statement transaction is being rolled back, also restore the
|
2531
|
+
** database handles deferred constraint counter to the value it had when
|
2532
|
+
** the statement transaction was opened. */
|
2533
|
+
if ( eOp == SAVEPOINT_ROLLBACK )
|
2534
|
+
{
|
2535
|
+
db.nDeferredCons = p.nStmtDefCons;
|
2536
|
+
}
|
2537
|
+
}
|
2538
|
+
return rc;
|
2539
|
+
}
|
2540
|
+
|
2541
|
+
/*
|
2542
|
+
** If SQLite is compiled to support shared-cache mode and to be threadsafe,
|
2543
|
+
** this routine obtains the mutex associated with each BtShared structure
|
2544
|
+
** that may be accessed by the VM passed as an argument. In doing so it
|
2545
|
+
** sets the BtShared.db member of each of the BtShared structures, ensuring
|
2546
|
+
** that the correct busy-handler callback is invoked if required.
|
2547
|
+
**
|
2548
|
+
** If SQLite is not threadsafe but does support shared-cache mode, then
|
2549
|
+
** sqlite3BtreeEnterAll() is invoked to set the BtShared.db variables
|
2550
|
+
** of all of BtShared structures accessible via the database handle
|
2551
|
+
** associated with the VM. Of course only a subset of these structures
|
2552
|
+
** will be accessed by the VM, and we could use Vdbe.btreeMask to figure
|
2553
|
+
** that subset out, but there is no advantage to doing so.
|
2554
|
+
**
|
2555
|
+
** If SQLite is not threadsafe and does not support shared-cache mode, this
|
2556
|
+
** function is a no-op.
|
2557
|
+
*/
|
2558
|
+
#if !SQLITE_OMIT_SHARED_CACHE
|
2559
|
+
static void sqlite3VdbeMutexArrayEnter(Vdbe p){
|
2560
|
+
#if SQLITE_THREADSAFE
|
2561
|
+
sqlite3BtreeMutexArrayEnter(&p->aMutex);
|
2562
|
+
#else
|
2563
|
+
sqlite3BtreeEnterAll(p.db);
|
2564
|
+
#endif
|
2565
|
+
}
|
2566
|
+
#endif
|
2567
|
+
|
2568
|
+
/*
|
2569
|
+
** This function is called when a transaction opened by the database
|
2570
|
+
** handle associated with the VM passed as an argument is about to be
|
2571
|
+
** committed. If there are outstanding deferred foreign key constraint
|
2572
|
+
** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
|
2573
|
+
**
|
2574
|
+
** If there are outstanding FK violations and this function returns
|
2575
|
+
** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT and write
|
2576
|
+
** an error message to it. Then return SQLITE_ERROR.
|
2577
|
+
*/
|
2578
|
+
#if !SQLITE_OMIT_FOREIGN_KEY
|
2579
|
+
static int sqlite3VdbeCheckFk( Vdbe p, int deferred )
|
2580
|
+
{
|
2581
|
+
sqlite3 db = p.db;
|
2582
|
+
if ( ( deferred != 0 && db.nDeferredCons > 0 ) || ( 0 == deferred && p.nFkConstraint > 0 ) )
|
2583
|
+
{
|
2584
|
+
p.rc = SQLITE_CONSTRAINT;
|
2585
|
+
p.errorAction = OE_Abort;
|
2586
|
+
sqlite3SetString( ref p.zErrMsg, db, "foreign key constraint failed" );
|
2587
|
+
return SQLITE_ERROR;
|
2588
|
+
}
|
2589
|
+
return SQLITE_OK;
|
2590
|
+
}
|
2591
|
+
#endif
|
2592
|
+
|
2593
|
+
/*
|
2594
|
+
** This routine is called the when a VDBE tries to halt. If the VDBE
|
2595
|
+
** has made changes and is in autocommit mode, then commit those
|
2596
|
+
** changes. If a rollback is needed, then do the rollback.
|
2597
|
+
**
|
2598
|
+
** This routine is the only way to move the state of a VM from
|
2599
|
+
** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT. It is harmless to
|
2600
|
+
** call this on a VM that is in the SQLITE_MAGIC_HALT state.
|
2601
|
+
**
|
2602
|
+
** Return an error code. If the commit could not complete because of
|
2603
|
+
** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it
|
2604
|
+
** means the close did not happen and needs to be repeated.
|
2605
|
+
*/
|
2606
|
+
static int sqlite3VdbeHalt( Vdbe p )
|
2607
|
+
{
|
2608
|
+
int rc; /* Used to store transient return codes */
|
2609
|
+
sqlite3 db = p.db;
|
2610
|
+
|
2611
|
+
/* This function contains the logic that determines if a statement or
|
2612
|
+
** transaction will be committed or rolled back as a result of the
|
2613
|
+
** execution of this virtual machine.
|
2614
|
+
**
|
2615
|
+
** If any of the following errors occur:
|
2616
|
+
**
|
2617
|
+
** SQLITE_NOMEM
|
2618
|
+
** SQLITE_IOERR
|
2619
|
+
** SQLITE_FULL
|
2620
|
+
** SQLITE_INTERRUPT
|
2621
|
+
**
|
2622
|
+
** Then the internal cache might have been left in an inconsistent
|
2623
|
+
** state. We need to rollback the statement transaction, if there is
|
2624
|
+
** one, or the complete transaction if there is no statement transaction.
|
2625
|
+
*/
|
2626
|
+
|
2627
|
+
//if ( p.db.mallocFailed != 0 )
|
2628
|
+
//{
|
2629
|
+
// p.rc = SQLITE_NOMEM;
|
2630
|
+
//}
|
2631
|
+
closeAllCursors( p );
|
2632
|
+
if ( p.magic != VDBE_MAGIC_RUN )
|
2633
|
+
{
|
2634
|
+
return SQLITE_OK;
|
2635
|
+
}
|
2636
|
+
checkActiveVdbeCnt( db );
|
2637
|
+
|
2638
|
+
/* No commit or rollback needed if the program never started */
|
2639
|
+
if ( p.pc >= 0 )
|
2640
|
+
{
|
2641
|
+
int mrc; /* Primary error code from p.rc */
|
2642
|
+
int eStatementOp = 0;
|
2643
|
+
bool isSpecialError = false; /* Set to true if a 'special' error */
|
2644
|
+
|
2645
|
+
/* Lock all btrees used by the statement */
|
2646
|
+
sqlite3VdbeMutexArrayEnter( p );
|
2647
|
+
/* Check for one of the special errors */
|
2648
|
+
mrc = p.rc & 0xff;
|
2649
|
+
Debug.Assert( p.rc != SQLITE_IOERR_BLOCKED ); /* This error no longer exists */
|
2650
|
+
isSpecialError = mrc == SQLITE_NOMEM || mrc == SQLITE_IOERR
|
2651
|
+
|| mrc == SQLITE_INTERRUPT || mrc == SQLITE_FULL;
|
2652
|
+
if ( isSpecialError )
|
2653
|
+
{
|
2654
|
+
/* If the query was read-only, we need do no rollback at all. Otherwise,
|
2655
|
+
** proceed with the special handling.
|
2656
|
+
*/
|
2657
|
+
if ( !p.readOnly || mrc != SQLITE_INTERRUPT )
|
2658
|
+
{
|
2659
|
+
if ( ( mrc == SQLITE_NOMEM || mrc == SQLITE_FULL ) && p.usesStmtJournal )
|
2660
|
+
{
|
2661
|
+
eStatementOp = SAVEPOINT_ROLLBACK;
|
2662
|
+
}
|
2663
|
+
else
|
2664
|
+
{
|
2665
|
+
/* We are forced to roll back the active transaction. Before doing
|
2666
|
+
** so, abort any other statements this handle currently has active.
|
2667
|
+
*/
|
2668
|
+
invalidateCursorsOnModifiedBtrees( db );
|
2669
|
+
sqlite3RollbackAll( db );
|
2670
|
+
sqlite3CloseSavepoints( db );
|
2671
|
+
db.autoCommit = 1;
|
2672
|
+
}
|
2673
|
+
}
|
2674
|
+
}
|
2675
|
+
|
2676
|
+
/* Check for immediate foreign key violations. */
|
2677
|
+
if ( p.rc == SQLITE_OK )
|
2678
|
+
{
|
2679
|
+
sqlite3VdbeCheckFk( p, 0 );
|
2680
|
+
}
|
2681
|
+
|
2682
|
+
/* If the auto-commit flag is set and this is the only active writer
|
2683
|
+
** VM, then we do either a commit or rollback of the current transaction.
|
2684
|
+
**
|
2685
|
+
** Note: This block also runs if one of the special errors handled
|
2686
|
+
** above has occurred.
|
2687
|
+
*/
|
2688
|
+
if ( !sqlite3VtabInSync( db )
|
2689
|
+
&& db.autoCommit != 0
|
2690
|
+
&& db.writeVdbeCnt == ( ( p.readOnly == false ) ? 1 : 0 )
|
2691
|
+
)
|
2692
|
+
{
|
2693
|
+
if ( p.rc == SQLITE_OK || ( p.errorAction == OE_Fail && !isSpecialError ) )
|
2694
|
+
{
|
2695
|
+
if ( sqlite3VdbeCheckFk( p, 1 ) != 0 )
|
2696
|
+
{
|
2697
|
+
sqlite3BtreeMutexArrayLeave( p.aMutex );
|
2698
|
+
return SQLITE_ERROR;
|
2699
|
+
}
|
2700
|
+
/* The auto-commit flag is true, the vdbe program was successful
|
2701
|
+
** or hit an 'OR FAIL' constraint and there are no deferred foreign
|
2702
|
+
** key constraints to hold up the transaction. This means a commit
|
2703
|
+
** is required. */
|
2704
|
+
rc = vdbeCommit( db, p );
|
2705
|
+
if ( rc == SQLITE_BUSY )
|
2706
|
+
{
|
2707
|
+
sqlite3BtreeMutexArrayLeave( p.aMutex );
|
2708
|
+
return SQLITE_BUSY;
|
2709
|
+
}
|
2710
|
+
else if ( rc != SQLITE_OK )
|
2711
|
+
{
|
2712
|
+
p.rc = rc;
|
2713
|
+
sqlite3RollbackAll( db );
|
2714
|
+
}
|
2715
|
+
else
|
2716
|
+
{
|
2717
|
+
db.nDeferredCons = 0;
|
2718
|
+
sqlite3CommitInternalChanges( db );
|
2719
|
+
}
|
2720
|
+
}
|
2721
|
+
else
|
2722
|
+
{
|
2723
|
+
sqlite3RollbackAll( db );
|
2724
|
+
}
|
2725
|
+
db.nStatement = 0;
|
2726
|
+
}
|
2727
|
+
else if ( eStatementOp == 0 )
|
2728
|
+
{
|
2729
|
+
if ( p.rc == SQLITE_OK || p.errorAction == OE_Fail )
|
2730
|
+
{
|
2731
|
+
eStatementOp = SAVEPOINT_RELEASE;
|
2732
|
+
}
|
2733
|
+
else if ( p.errorAction == OE_Abort )
|
2734
|
+
{
|
2735
|
+
eStatementOp = SAVEPOINT_ROLLBACK;
|
2736
|
+
}
|
2737
|
+
else
|
2738
|
+
{
|
2739
|
+
invalidateCursorsOnModifiedBtrees( db );
|
2740
|
+
sqlite3RollbackAll( db );
|
2741
|
+
sqlite3CloseSavepoints( db );
|
2742
|
+
db.autoCommit = 1;
|
2743
|
+
}
|
2744
|
+
}
|
2745
|
+
|
2746
|
+
/* If eStatementOp is non-zero, then a statement transaction needs to
|
2747
|
+
** be committed or rolled back. Call sqlite3VdbeCloseStatement() to
|
2748
|
+
** do so. If this operation returns an error, and the current statement
|
2749
|
+
** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the
|
2750
|
+
** current statement error code.
|
2751
|
+
**
|
2752
|
+
** Note that sqlite3VdbeCloseStatement() can only fail if eStatementOp
|
2753
|
+
** is SAVEPOINT_ROLLBACK. But if p->rc==SQLITE_OK then eStatementOp
|
2754
|
+
** must be SAVEPOINT_RELEASE. Hence the NEVER(p->rc==SQLITE_OK) in
|
2755
|
+
** the following code.
|
2756
|
+
*/
|
2757
|
+
if (eStatementOp != 0)
|
2758
|
+
{
|
2759
|
+
rc = sqlite3VdbeCloseStatement( p, eStatementOp );
|
2760
|
+
if ( rc != 0 && (NEVER( p.rc == SQLITE_OK) || p.rc == SQLITE_CONSTRAINT ) )
|
2761
|
+
{
|
2762
|
+
p.rc = rc;
|
2763
|
+
sqlite3DbFree( db, ref p.zErrMsg );
|
2764
|
+
p.zErrMsg = null;
|
2765
|
+
}
|
2766
|
+
}
|
2767
|
+
|
2768
|
+
/* If this was an INSERT, UPDATE or DELETE and no statement transaction
|
2769
|
+
** has been rolled back, update the database connection change-counter.
|
2770
|
+
*/
|
2771
|
+
if ( p.changeCntOn )
|
2772
|
+
{
|
2773
|
+
if ( eStatementOp != SAVEPOINT_ROLLBACK )
|
2774
|
+
{
|
2775
|
+
sqlite3VdbeSetChanges( db, p.nChange );
|
2776
|
+
}
|
2777
|
+
else
|
2778
|
+
{
|
2779
|
+
sqlite3VdbeSetChanges( db, 0 );
|
2780
|
+
}
|
2781
|
+
p.nChange = 0;
|
2782
|
+
}
|
2783
|
+
|
2784
|
+
/* Rollback or commit any schema changes that occurred. */
|
2785
|
+
if ( p.rc != SQLITE_OK && ( db.flags & SQLITE_InternChanges ) != 0 )
|
2786
|
+
{
|
2787
|
+
sqlite3ResetInternalSchema( db, 0 );
|
2788
|
+
db.flags = ( db.flags | SQLITE_InternChanges );
|
2789
|
+
}
|
2790
|
+
|
2791
|
+
/* Release the locks */
|
2792
|
+
sqlite3BtreeMutexArrayLeave( p.aMutex );
|
2793
|
+
}
|
2794
|
+
|
2795
|
+
/* We have successfully halted and closed the VM. Record this fact. */
|
2796
|
+
if ( p.pc >= 0 )
|
2797
|
+
{
|
2798
|
+
db.activeVdbeCnt--;
|
2799
|
+
if ( !p.readOnly )
|
2800
|
+
{
|
2801
|
+
db.writeVdbeCnt--;
|
2802
|
+
}
|
2803
|
+
Debug.Assert( db.activeVdbeCnt >= db.writeVdbeCnt );
|
2804
|
+
}
|
2805
|
+
p.magic = VDBE_MAGIC_HALT;
|
2806
|
+
checkActiveVdbeCnt( db );
|
2807
|
+
//if ( p.db.mallocFailed != 0 )
|
2808
|
+
//{
|
2809
|
+
// p.rc = SQLITE_NOMEM;
|
2810
|
+
//}
|
2811
|
+
/* If the auto-commit flag is set to true, then any locks that were held
|
2812
|
+
** by connection db have now been released. Call sqlite3ConnectionUnlocked()
|
2813
|
+
** to invoke any required unlock-notify callbacks.
|
2814
|
+
*/
|
2815
|
+
if ( db.autoCommit != 0 )
|
2816
|
+
{
|
2817
|
+
sqlite3ConnectionUnlocked( db );
|
2818
|
+
}
|
2819
|
+
|
2820
|
+
Debug.Assert( db.activeVdbeCnt > 0 || db.autoCommit == 0 || db.nStatement == 0 );
|
2821
|
+
return SQLITE_OK;
|
2822
|
+
}
|
2823
|
+
|
2824
|
+
|
2825
|
+
/*
|
2826
|
+
** Each VDBE holds the result of the most recent sqlite3_step() call
|
2827
|
+
** in p.rc. This routine sets that result back to SQLITE_OK.
|
2828
|
+
*/
|
2829
|
+
static void sqlite3VdbeResetStepResult( Vdbe p )
|
2830
|
+
{
|
2831
|
+
p.rc = SQLITE_OK;
|
2832
|
+
}
|
2833
|
+
|
2834
|
+
/*
|
2835
|
+
** Clean up a VDBE after execution but do not delete the VDBE just yet.
|
2836
|
+
** Write any error messages into pzErrMsg. Return the result code.
|
2837
|
+
**
|
2838
|
+
** After this routine is run, the VDBE should be ready to be executed
|
2839
|
+
** again.
|
2840
|
+
**
|
2841
|
+
** To look at it another way, this routine resets the state of the
|
2842
|
+
** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to
|
2843
|
+
** VDBE_MAGIC_INIT.
|
2844
|
+
*/
|
2845
|
+
static int sqlite3VdbeReset( Vdbe p )
|
2846
|
+
{
|
2847
|
+
sqlite3 db;
|
2848
|
+
db = p.db;
|
2849
|
+
|
2850
|
+
/* If the VM did not run to completion or if it encountered an
|
2851
|
+
** error, then it might not have been halted properly. So halt
|
2852
|
+
** it now.
|
2853
|
+
*/
|
2854
|
+
sqlite3VdbeHalt( p );
|
2855
|
+
|
2856
|
+
/* If the VDBE has be run even partially, then transfer the error code
|
2857
|
+
** and error message from the VDBE into the main database structure. But
|
2858
|
+
** if the VDBE has just been set to run but has not actually executed any
|
2859
|
+
** instructions yet, leave the main database error information unchanged.
|
2860
|
+
*/
|
2861
|
+
if ( p.pc >= 0 )
|
2862
|
+
{
|
2863
|
+
//if ( p.zErrMsg != 0 ) // Always exists under C#
|
2864
|
+
{
|
2865
|
+
sqlite3BeginBenignMalloc();
|
2866
|
+
sqlite3ValueSetStr( db.pErr, -1, p.zErrMsg == null ? "" : p.zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT );
|
2867
|
+
sqlite3EndBenignMalloc();
|
2868
|
+
db.errCode = p.rc;
|
2869
|
+
sqlite3DbFree( db, ref p.zErrMsg );
|
2870
|
+
p.zErrMsg = "";
|
2871
|
+
}
|
2872
|
+
//else if ( p.rc != 0 )
|
2873
|
+
//{
|
2874
|
+
// sqlite3Error( db, p.rc, 0 );
|
2875
|
+
//}
|
2876
|
+
//else
|
2877
|
+
//{
|
2878
|
+
// sqlite3Error( db, SQLITE_OK, 0 );
|
2879
|
+
//}
|
2880
|
+
if (p.runOnlyOnce != 0) p.expired = true;
|
2881
|
+
}
|
2882
|
+
else if ( p.rc != 0 && p.expired )
|
2883
|
+
{
|
2884
|
+
/* The expired flag was set on the VDBE before the first call
|
2885
|
+
** to sqlite3_step(). For consistency (since sqlite3_step() was
|
2886
|
+
** called), set the database error in this case as well.
|
2887
|
+
*/
|
2888
|
+
sqlite3Error( db, p.rc, 0 );
|
2889
|
+
sqlite3ValueSetStr( db.pErr, -1, p.zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT );
|
2890
|
+
sqlite3DbFree( db, ref p.zErrMsg );
|
2891
|
+
p.zErrMsg = "";
|
2892
|
+
}
|
2893
|
+
|
2894
|
+
/* Reclaim all memory used by the VDBE
|
2895
|
+
*/
|
2896
|
+
Cleanup( p );
|
2897
|
+
|
2898
|
+
/* Save profiling information from this VDBE run.
|
2899
|
+
*/
|
2900
|
+
#if VDBE_PROFILE && TODO
|
2901
|
+
{
|
2902
|
+
FILE *out = fopen("vdbe_profile.out", "a");
|
2903
|
+
if( out ){
|
2904
|
+
int i;
|
2905
|
+
fprintf(out, "---- ");
|
2906
|
+
for(i=0; i<p.nOp; i++){
|
2907
|
+
fprintf(out, "%02x", p.aOp[i].opcode);
|
2908
|
+
}
|
2909
|
+
fprintf(out, "\n");
|
2910
|
+
for(i=0; i<p.nOp; i++){
|
2911
|
+
fprintf(out, "%6d %10lld %8lld ",
|
2912
|
+
p.aOp[i].cnt,
|
2913
|
+
p.aOp[i].cycles,
|
2914
|
+
p.aOp[i].cnt>0 ? p.aOp[i].cycles/p.aOp[i].cnt : 0
|
2915
|
+
);
|
2916
|
+
sqlite3VdbePrintOp(out, i, p.aOp[i]);
|
2917
|
+
}
|
2918
|
+
fclose(out);
|
2919
|
+
}
|
2920
|
+
}
|
2921
|
+
#endif
|
2922
|
+
p.magic = VDBE_MAGIC_INIT;
|
2923
|
+
return p.rc & db.errMask;
|
2924
|
+
}
|
2925
|
+
|
2926
|
+
/*
|
2927
|
+
** Clean up and delete a VDBE after execution. Return an integer which is
|
2928
|
+
** the result code. Write any error message text into pzErrMsg.
|
2929
|
+
*/
|
2930
|
+
static int sqlite3VdbeFinalize( Vdbe p )
|
2931
|
+
{
|
2932
|
+
int rc = SQLITE_OK;
|
2933
|
+
if ( p.magic == VDBE_MAGIC_RUN || p.magic == VDBE_MAGIC_HALT )
|
2934
|
+
{
|
2935
|
+
rc = sqlite3VdbeReset( p );
|
2936
|
+
Debug.Assert( ( rc & p.db.errMask ) == rc );
|
2937
|
+
}
|
2938
|
+
sqlite3VdbeDelete( ref p );
|
2939
|
+
return rc;
|
2940
|
+
}
|
2941
|
+
|
2942
|
+
/*
|
2943
|
+
** Call the destructor for each auxdata entry in pVdbeFunc for which
|
2944
|
+
** the corresponding bit in mask is clear. Auxdata entries beyond 31
|
2945
|
+
** are always destroyed. To destroy all auxdata entries, call this
|
2946
|
+
** routine with mask==0.
|
2947
|
+
*/
|
2948
|
+
static void sqlite3VdbeDeleteAuxData( VdbeFunc pVdbeFunc, int mask )
|
2949
|
+
{
|
2950
|
+
int i;
|
2951
|
+
for ( i = 0; i < pVdbeFunc.nAux; i++ )
|
2952
|
+
{
|
2953
|
+
AuxData pAux = pVdbeFunc.apAux[i];
|
2954
|
+
if ( ( i > 31 || ( mask & ( ( (u32)1 ) << i ) ) == 0 && pAux.pAux != null ) )
|
2955
|
+
{
|
2956
|
+
if ( pAux.xDelete != null )
|
2957
|
+
{
|
2958
|
+
pAux.xDelete( ref pAux.pAux );
|
2959
|
+
}
|
2960
|
+
pAux.pAux = null;
|
2961
|
+
}
|
2962
|
+
}
|
2963
|
+
}
|
2964
|
+
|
2965
|
+
/*
|
2966
|
+
** Delete an entire VDBE.
|
2967
|
+
*/
|
2968
|
+
static void sqlite3VdbeDelete( ref Vdbe p )
|
2969
|
+
{
|
2970
|
+
sqlite3 db;
|
2971
|
+
if ( NEVER( p == null ) ) return;
|
2972
|
+
Cleanup( p );
|
2973
|
+
db = p.db;
|
2974
|
+
if ( p.pPrev != null )
|
2975
|
+
{
|
2976
|
+
p.pPrev.pNext = p.pNext;
|
2977
|
+
}
|
2978
|
+
else
|
2979
|
+
{
|
2980
|
+
Debug.Assert( db.pVdbe == p );
|
2981
|
+
db.pVdbe = p.pNext;
|
2982
|
+
}
|
2983
|
+
if ( p.pNext != null )
|
2984
|
+
{
|
2985
|
+
p.pNext.pPrev = p.pPrev;
|
2986
|
+
}
|
2987
|
+
releaseMemArray( p.aVar, p.nVar );
|
2988
|
+
releaseMemArray( p.aColName, p.nResColumn * COLNAME_N );
|
2989
|
+
vdbeFreeOpArray( db, ref p.aOp, p.nOp );
|
2990
|
+
sqlite3DbFree( db, ref p.aLabel );
|
2991
|
+
sqlite3DbFree( db, ref p.aColName );
|
2992
|
+
sqlite3DbFree( db, ref p.zSql );
|
2993
|
+
p.magic = VDBE_MAGIC_DEAD;
|
2994
|
+
sqlite3DbFree( db, ref p.pFree );
|
2995
|
+
p.db = null;
|
2996
|
+
if (p.aMem != null) releaseMemArray(p.aMem, p.aMem.Length);
|
2997
|
+
if (p.apArg != null) releaseMemArray(p.apArg, p.apArg.Length);
|
2998
|
+
sqlite3DbFree( db, ref p );
|
2999
|
+
}
|
3000
|
+
|
3001
|
+
/*
|
3002
|
+
** Make sure the cursor p is ready to read or write the row to which it
|
3003
|
+
** was last positioned. Return an error code if an OOM fault or I/O error
|
3004
|
+
** prevents us from positioning the cursor to its correct position.
|
3005
|
+
**
|
3006
|
+
** If a MoveTo operation is pending on the given cursor, then do that
|
3007
|
+
** MoveTo now. If no move is pending, check to see if the row has been
|
3008
|
+
** deleted out from under the cursor and if it has, mark the row as
|
3009
|
+
** a NULL row.
|
3010
|
+
**
|
3011
|
+
** If the cursor is already pointing to the correct row and that row has
|
3012
|
+
** not been deleted out from under the cursor, then this routine is a no-op.
|
3013
|
+
*/
|
3014
|
+
static int sqlite3VdbeCursorMoveto( VdbeCursor p )
|
3015
|
+
{
|
3016
|
+
if ( p.deferredMoveto )
|
3017
|
+
{
|
3018
|
+
int res = 0; int rc;
|
3019
|
+
#if SQLITE_TEST
|
3020
|
+
//extern int sqlite3_search_count;
|
3021
|
+
#endif
|
3022
|
+
Debug.Assert( p.isTable );
|
3023
|
+
rc = sqlite3BtreeMovetoUnpacked( p.pCursor, null, p.movetoTarget, 0, ref res );
|
3024
|
+
if ( rc != 0 ) return rc;
|
3025
|
+
p.lastRowid = p.movetoTarget;
|
3026
|
+
p.rowidIsValid = ALWAYS( res == 0 ) ? true : false;
|
3027
|
+
if ( NEVER( res < 0 ) )
|
3028
|
+
{
|
3029
|
+
rc = sqlite3BtreeNext( p.pCursor, ref res );
|
3030
|
+
if ( rc != 0 ) return rc;
|
3031
|
+
}
|
3032
|
+
#if SQLITE_TEST
|
3033
|
+
sqlite3_search_count.iValue++;
|
3034
|
+
#endif
|
3035
|
+
p.deferredMoveto = false;
|
3036
|
+
p.cacheStatus = CACHE_STALE;
|
3037
|
+
}
|
3038
|
+
else if ( ALWAYS( p.pCursor != null ) )
|
3039
|
+
{
|
3040
|
+
int hasMoved = 0;
|
3041
|
+
int rc = sqlite3BtreeCursorHasMoved( p.pCursor, ref hasMoved );
|
3042
|
+
if ( rc != 0 ) return rc;
|
3043
|
+
if ( hasMoved != 0 )
|
3044
|
+
{
|
3045
|
+
p.cacheStatus = CACHE_STALE;
|
3046
|
+
p.nullRow = true;
|
3047
|
+
}
|
3048
|
+
}
|
3049
|
+
return SQLITE_OK;
|
3050
|
+
}
|
3051
|
+
|
3052
|
+
/*
|
3053
|
+
** The following functions:
|
3054
|
+
**
|
3055
|
+
** sqlite3VdbeSerialType()
|
3056
|
+
** sqlite3VdbeSerialTypeLen()
|
3057
|
+
** sqlite3VdbeSerialLen()
|
3058
|
+
** sqlite3VdbeSerialPut()
|
3059
|
+
** sqlite3VdbeSerialGet()
|
3060
|
+
**
|
3061
|
+
** encapsulate the code that serializes values for storage in SQLite
|
3062
|
+
** data and index records. Each serialized value consists of a
|
3063
|
+
** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned
|
3064
|
+
** integer, stored as a varint.
|
3065
|
+
**
|
3066
|
+
** In an SQLite index record, the serial type is stored directly before
|
3067
|
+
** the blob of data that it corresponds to. In a table record, all serial
|
3068
|
+
** types are stored at the start of the record, and the blobs of data at
|
3069
|
+
** the end. Hence these functions allow the caller to handle the
|
3070
|
+
** serial-type and data blob seperately.
|
3071
|
+
**
|
3072
|
+
** The following table describes the various storage classes for data:
|
3073
|
+
**
|
3074
|
+
** serial type bytes of data type
|
3075
|
+
** -------------- --------------- ---------------
|
3076
|
+
** 0 0 NULL
|
3077
|
+
** 1 1 signed integer
|
3078
|
+
** 2 2 signed integer
|
3079
|
+
** 3 3 signed integer
|
3080
|
+
** 4 4 signed integer
|
3081
|
+
** 5 6 signed integer
|
3082
|
+
** 6 8 signed integer
|
3083
|
+
** 7 8 IEEE float
|
3084
|
+
** 8 0 Integer constant 0
|
3085
|
+
** 9 0 Integer constant 1
|
3086
|
+
** 10,11 reserved for expansion
|
3087
|
+
** N>=12 and even (N-12)/2 BLOB
|
3088
|
+
** N>=13 and odd (N-13)/2 text
|
3089
|
+
**
|
3090
|
+
** The 8 and 9 types were added in 3.3.0, file format 4. Prior versions
|
3091
|
+
** of SQLite will not understand those serial types.
|
3092
|
+
*/
|
3093
|
+
|
3094
|
+
/*
|
3095
|
+
** Return the serial-type for the value stored in pMem.
|
3096
|
+
*/
|
3097
|
+
static u32 sqlite3VdbeSerialType( Mem pMem, int file_format )
|
3098
|
+
{
|
3099
|
+
int flags = pMem.flags;
|
3100
|
+
int n;
|
3101
|
+
|
3102
|
+
if ( ( flags & MEM_Null ) != 0 )
|
3103
|
+
{
|
3104
|
+
return 0;
|
3105
|
+
}
|
3106
|
+
if ( ( flags & MEM_Int ) != 0 )
|
3107
|
+
{
|
3108
|
+
/* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
|
3109
|
+
const i64 MAX_6BYTE = ( ( ( (i64)0x00008000 ) << 32 ) - 1 );
|
3110
|
+
i64 i = pMem.u.i;
|
3111
|
+
u64 u;
|
3112
|
+
if ( file_format >= 4 && ( i & 1 ) == i )
|
3113
|
+
{
|
3114
|
+
return 8 + (u32)i;
|
3115
|
+
}
|
3116
|
+
u = (ulong)( i < 0 ? -i : i );
|
3117
|
+
if ( u <= 127 ) return 1;
|
3118
|
+
if ( u <= 32767 ) return 2;
|
3119
|
+
if ( u <= 8388607 ) return 3;
|
3120
|
+
if ( u <= 2147483647 ) return 4;
|
3121
|
+
if ( u <= MAX_6BYTE ) return 5;
|
3122
|
+
return 6;
|
3123
|
+
}
|
3124
|
+
if ( ( flags & MEM_Real ) != 0 )
|
3125
|
+
{
|
3126
|
+
return 7;
|
3127
|
+
}
|
3128
|
+
Debug.Assert( /* pMem.db.mallocFailed != 0 || */ ( flags & ( MEM_Str | MEM_Blob ) ) != 0 );
|
3129
|
+
n = pMem.n;
|
3130
|
+
if ( ( flags & MEM_Zero ) != 0 )
|
3131
|
+
{
|
3132
|
+
n += pMem.u.nZero;
|
3133
|
+
}
|
3134
|
+
else if ( ( flags & MEM_Blob ) != 0 )
|
3135
|
+
{
|
3136
|
+
n = pMem.zBLOB != null ? pMem.zBLOB.Length : pMem.z != null ? pMem.z.Length : 0;
|
3137
|
+
}
|
3138
|
+
else
|
3139
|
+
{
|
3140
|
+
if ( pMem.z != null ) n = Encoding.UTF8.GetByteCount( pMem.n < pMem.z.Length ? pMem.z.Substring( 0, pMem.n ) : pMem.z );
|
3141
|
+
else n = pMem.zBLOB.Length;
|
3142
|
+
pMem.n = n;
|
3143
|
+
}
|
3144
|
+
|
3145
|
+
Debug.Assert( n >= 0 );
|
3146
|
+
return (u32)( ( n * 2 ) + 12 + ( ( ( flags & MEM_Str ) != 0 ) ? 1 : 0 ) );
|
3147
|
+
}
|
3148
|
+
|
3149
|
+
/*
|
3150
|
+
** Return the length of the data corresponding to the supplied serial-type.
|
3151
|
+
*/
|
3152
|
+
static u32 sqlite3VdbeSerialTypeLen( u32 serial_type )
|
3153
|
+
{
|
3154
|
+
if ( serial_type >= 12 )
|
3155
|
+
{
|
3156
|
+
return (u32)( ( serial_type - 12 ) / 2 );
|
3157
|
+
}
|
3158
|
+
else
|
3159
|
+
{
|
3160
|
+
u32[] aSize = new u32[] { 0, 1, 2, 3, 4, 6, 8, 8, 0, 0, 0, 0 };
|
3161
|
+
return aSize[serial_type];
|
3162
|
+
}
|
3163
|
+
}
|
3164
|
+
|
3165
|
+
/*
|
3166
|
+
** If we are on an architecture with mixed-endian floating
|
3167
|
+
** points (ex: ARM7) then swap the lower 4 bytes with the
|
3168
|
+
** upper 4 bytes. Return the result.
|
3169
|
+
**
|
3170
|
+
** For most architectures, this is a no-op.
|
3171
|
+
**
|
3172
|
+
** (later): It is reported to me that the mixed-endian problem
|
3173
|
+
** on ARM7 is an issue with GCC, not with the ARM7 chip. It seems
|
3174
|
+
** that early versions of GCC stored the two words of a 64-bit
|
3175
|
+
** float in the wrong order. And that error has been propagated
|
3176
|
+
** ever since. The blame is not necessarily with GCC, though.
|
3177
|
+
** GCC might have just copying the problem from a prior compiler.
|
3178
|
+
** I am also told that newer versions of GCC that follow a different
|
3179
|
+
** ABI get the byte order right.
|
3180
|
+
**
|
3181
|
+
** Developers using SQLite on an ARM7 should compile and run their
|
3182
|
+
** application using -DSQLITE_DEBUG=1 at least once. With DEBUG
|
3183
|
+
** enabled, some Debug.Asserts below will ensure that the byte order of
|
3184
|
+
** floating point values is correct.
|
3185
|
+
**
|
3186
|
+
** (2007-08-30) Frank van Vugt has studied this problem closely
|
3187
|
+
** and has send his findings to the SQLite developers. Frank
|
3188
|
+
** writes that some Linux kernels offer floating point hardware
|
3189
|
+
** emulation that uses only 32-bit mantissas instead of a full
|
3190
|
+
** 48-bits as required by the IEEE standard. (This is the
|
3191
|
+
** CONFIG_FPE_FASTFPE option.) On such systems, floating point
|
3192
|
+
** byte swapping becomes very complicated. To avoid problems,
|
3193
|
+
** the necessary byte swapping is carried out using a 64-bit integer
|
3194
|
+
** rather than a 64-bit float. Frank assures us that the code here
|
3195
|
+
** works for him. We, the developers, have no way to independently
|
3196
|
+
** verify this, but Frank seems to know what he is talking about
|
3197
|
+
** so we trust him.
|
3198
|
+
*/
|
3199
|
+
#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
3200
|
+
//static u64 floatSwap(u64 in){
|
3201
|
+
// union {
|
3202
|
+
// u64 r;
|
3203
|
+
// u32 i[2];
|
3204
|
+
// } u;
|
3205
|
+
// u32 t;
|
3206
|
+
|
3207
|
+
// u.r = in;
|
3208
|
+
// t = u.i[0];
|
3209
|
+
// u.i[0] = u.i[1];
|
3210
|
+
// u.i[1] = t;
|
3211
|
+
// return u.r;
|
3212
|
+
//}
|
3213
|
+
//# define swapMixedEndianFloat(X) X = floatSwap(X)
|
3214
|
+
#else
|
3215
|
+
//# define swapMixedEndianFloat(X)
|
3216
|
+
#endif
|
3217
|
+
|
3218
|
+
/*
|
3219
|
+
** Write the serialized data blob for the value stored in pMem into
|
3220
|
+
** buf. It is assumed that the caller has allocated sufficient space.
|
3221
|
+
** Return the number of bytes written.
|
3222
|
+
**
|
3223
|
+
** nBuf is the amount of space left in buf[]. nBuf must always be
|
3224
|
+
** large enough to hold the entire field. Except, if the field is
|
3225
|
+
** a blob with a zero-filled tail, then buf[] might be just the right
|
3226
|
+
** size to hold everything except for the zero-filled tail. If buf[]
|
3227
|
+
** is only big enough to hold the non-zero prefix, then only write that
|
3228
|
+
** prefix into buf[]. But if buf[] is large enough to hold both the
|
3229
|
+
** prefix and the tail then write the prefix and set the tail to all
|
3230
|
+
** zeros.
|
3231
|
+
**
|
3232
|
+
** Return the number of bytes actually written into buf[]. The number
|
3233
|
+
** of bytes in the zero-filled tail is included in the return value only
|
3234
|
+
** if those bytes were zeroed in buf[].
|
3235
|
+
*/
|
3236
|
+
static u32 sqlite3VdbeSerialPut( byte[] buf, int offset, int nBuf, Mem pMem, int file_format )
|
3237
|
+
{
|
3238
|
+
u32 serial_type = sqlite3VdbeSerialType( pMem, file_format );
|
3239
|
+
u32 len;
|
3240
|
+
|
3241
|
+
/* Integer and Real */
|
3242
|
+
if ( serial_type <= 7 && serial_type > 0 )
|
3243
|
+
{
|
3244
|
+
u64 v;
|
3245
|
+
u32 i;
|
3246
|
+
if ( serial_type == 7 )
|
3247
|
+
{
|
3248
|
+
//Debug.Assert( sizeof( v) == sizeof(pMem.r));
|
3249
|
+
v = (ulong)BitConverter.ToInt64(BitConverter.GetBytes(pMem.r), 0);/// memcpy( &v, pMem.r, v ).Length;
|
3250
|
+
#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
3251
|
+
swapMixedEndianFloat( v );
|
3252
|
+
#endif
|
3253
|
+
}
|
3254
|
+
else
|
3255
|
+
{
|
3256
|
+
v = (ulong)pMem.u.i;
|
3257
|
+
}
|
3258
|
+
len = i = sqlite3VdbeSerialTypeLen( serial_type );
|
3259
|
+
Debug.Assert( len <= (u32)nBuf );
|
3260
|
+
while ( i-- != 0 )
|
3261
|
+
{
|
3262
|
+
buf[offset + i] = (u8)( v & 0xFF );
|
3263
|
+
v >>= 8;
|
3264
|
+
}
|
3265
|
+
return len;
|
3266
|
+
}
|
3267
|
+
|
3268
|
+
/* String or blob */
|
3269
|
+
if ( serial_type >= 12 )
|
3270
|
+
{
|
3271
|
+
Debug.Assert( pMem.n + ( ( pMem.flags & MEM_Zero ) != 0 ? pMem.u.nZero : 0 ) == (int)sqlite3VdbeSerialTypeLen( serial_type ) );
|
3272
|
+
Debug.Assert( pMem.n <= nBuf );
|
3273
|
+
if ( ( len = (u32)pMem.n ) != 0 )
|
3274
|
+
if ( pMem.zBLOB == null && String.IsNullOrEmpty( pMem.z ) )
|
3275
|
+
{ }
|
3276
|
+
else if ( ( pMem.flags & MEM_Blob ) != 0 || pMem.z == null )
|
3277
|
+
Buffer.BlockCopy( pMem.zBLOB, 0, buf, offset, (int)len );//memcpy( buf, pMem.z, len );
|
3278
|
+
else
|
3279
|
+
Buffer.BlockCopy( Encoding.UTF8.GetBytes( pMem.z ), 0, buf, offset, (int)len );//memcpy( buf, pMem.z, len );
|
3280
|
+
if ( ( pMem.flags & MEM_Zero ) != 0 )
|
3281
|
+
{
|
3282
|
+
len += (u32)pMem.u.nZero;
|
3283
|
+
Debug.Assert( nBuf >= 0 );
|
3284
|
+
if ( len > (u32)nBuf )
|
3285
|
+
{
|
3286
|
+
len = (u32)nBuf;
|
3287
|
+
}
|
3288
|
+
Array.Clear( buf, offset + pMem.n, (int)( len - pMem.n ) );// memset( &buf[pMem.n], 0, len - pMem.n );
|
3289
|
+
}
|
3290
|
+
return len;
|
3291
|
+
}
|
3292
|
+
|
3293
|
+
/* NULL or constants 0 or 1 */
|
3294
|
+
return 0;
|
3295
|
+
}
|
3296
|
+
|
3297
|
+
/*
|
3298
|
+
** Deserialize the data blob pointed to by buf as serial type serial_type
|
3299
|
+
** and store the result in pMem. Return the number of bytes read.
|
3300
|
+
*/
|
3301
|
+
static u32 sqlite3VdbeSerialGet(
|
3302
|
+
byte[] buf, /* Buffer to deserialize from */
|
3303
|
+
int offset, /* Offset into Buffer */
|
3304
|
+
u32 serial_type, /* Serial type to deserialize */
|
3305
|
+
Mem pMem /* Memory cell to write value into */
|
3306
|
+
)
|
3307
|
+
{
|
3308
|
+
switch ( serial_type )
|
3309
|
+
{
|
3310
|
+
case 10: /* Reserved for future use */
|
3311
|
+
case 11: /* Reserved for future use */
|
3312
|
+
case 0:
|
3313
|
+
{ /* NULL */
|
3314
|
+
pMem.flags = MEM_Null;
|
3315
|
+
pMem.n = 0;
|
3316
|
+
pMem.z = null;
|
3317
|
+
pMem.zBLOB = null;
|
3318
|
+
break;
|
3319
|
+
}
|
3320
|
+
case 1:
|
3321
|
+
{ /* 1-byte signed integer */
|
3322
|
+
pMem.u.i = (sbyte)buf[offset + 0];
|
3323
|
+
pMem.flags = MEM_Int;
|
3324
|
+
return 1;
|
3325
|
+
}
|
3326
|
+
case 2:
|
3327
|
+
{ /* 2-byte signed integer */
|
3328
|
+
pMem.u.i = (int)( ( ( (sbyte)buf[offset + 0] ) << 8 ) | buf[offset + 1] );
|
3329
|
+
pMem.flags = MEM_Int;
|
3330
|
+
return 2;
|
3331
|
+
}
|
3332
|
+
case 3:
|
3333
|
+
{ /* 3-byte signed integer */
|
3334
|
+
pMem.u.i = (int)( ( ( (sbyte)buf[offset + 0] ) << 16 ) | ( buf[offset + 1] << 8 ) | buf[offset + 2] );
|
3335
|
+
pMem.flags = MEM_Int;
|
3336
|
+
return 3;
|
3337
|
+
}
|
3338
|
+
case 4:
|
3339
|
+
{ /* 4-byte signed integer */
|
3340
|
+
pMem.u.i = (int)( ( (sbyte)buf[offset + 0] << 24 ) | ( buf[offset + 1] << 16 ) | ( buf[offset + 2] << 8 ) | buf[offset + 3] );
|
3341
|
+
pMem.flags = MEM_Int;
|
3342
|
+
return 4;
|
3343
|
+
}
|
3344
|
+
case 5:
|
3345
|
+
{ /* 6-byte signed integer */
|
3346
|
+
u64 x = (ulong)( ( ( (sbyte)buf[offset + 0] ) << 8 ) | buf[offset + 1] );
|
3347
|
+
u32 y = (u32)( ( buf[offset + 2] << 24 ) | ( buf[offset + 3] << 16 ) | ( buf[offset + 4] << 8 ) | buf[offset + 5] );
|
3348
|
+
x = ( x << 32 ) | y;
|
3349
|
+
pMem.u.i = (i64)x;
|
3350
|
+
pMem.flags = MEM_Int;
|
3351
|
+
return 6;
|
3352
|
+
}
|
3353
|
+
case 6: /* 8-byte signed integer */
|
3354
|
+
case 7:
|
3355
|
+
{ /* IEEE floating point */
|
3356
|
+
u64 x;
|
3357
|
+
u32 y;
|
3358
|
+
#if !NDEBUG && !SQLITE_OMIT_FLOATING_POINT
|
3359
|
+
/* Verify that integers and floating point values use the same
|
3360
|
+
** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
|
3361
|
+
** defined that 64-bit floating point values really are mixed
|
3362
|
+
** endian.
|
3363
|
+
*/
|
3364
|
+
const u64 t1 = ( (u64)0x3ff00000 ) << 32;
|
3365
|
+
const double r1 = 1.0;
|
3366
|
+
u64 t2 = t1;
|
3367
|
+
#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
3368
|
+
swapMixedEndianFloat(t2);
|
3369
|
+
#endif
|
3370
|
+
Debug.Assert( sizeof( double ) == sizeof( u64 ) && memcmp( BitConverter.GetBytes( r1 ), BitConverter.GetBytes( t2 ), sizeof( double ) ) == 0 );//Debug.Assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, t2, sizeof(r1))==0 );
|
3371
|
+
#endif
|
3372
|
+
|
3373
|
+
x = (u64)( ( buf[offset + 0] << 24 ) | ( buf[offset + 1] << 16 ) | ( buf[offset + 2] << 8 ) | buf[offset + 3] );
|
3374
|
+
y = (u32)( ( buf[offset + 4] << 24 ) | ( buf[offset + 5] << 16 ) | ( buf[offset + 6] << 8 ) | buf[offset + 7] );
|
3375
|
+
x = ( x << 32 ) | y;
|
3376
|
+
if ( serial_type == 6 )
|
3377
|
+
{
|
3378
|
+
pMem.u.i = (i64)x;
|
3379
|
+
pMem.flags = MEM_Int;
|
3380
|
+
}
|
3381
|
+
else
|
3382
|
+
{
|
3383
|
+
Debug.Assert( sizeof( i64 ) == 8 && sizeof( double ) == 8 );
|
3384
|
+
#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
3385
|
+
swapMixedEndianFloat(x);
|
3386
|
+
#endif
|
3387
|
+
pMem.r = BitConverter.ToDouble(BitConverter.GetBytes((long)x), 0);// memcpy(pMem.r, x, sizeof(x))
|
3388
|
+
pMem.flags = (u16)( sqlite3IsNaN( pMem.r ) ? MEM_Null : MEM_Real );
|
3389
|
+
}
|
3390
|
+
return 8;
|
3391
|
+
}
|
3392
|
+
case 8: /* Integer 0 */
|
3393
|
+
case 9:
|
3394
|
+
{ /* Integer 1 */
|
3395
|
+
pMem.u.i = serial_type - 8;
|
3396
|
+
pMem.flags = MEM_Int;
|
3397
|
+
return 0;
|
3398
|
+
}
|
3399
|
+
default:
|
3400
|
+
{
|
3401
|
+
u32 len = ( serial_type - 12 ) / 2;
|
3402
|
+
pMem.n = (int)len;
|
3403
|
+
pMem.xDel = null;
|
3404
|
+
if ( ( serial_type & 0x01 ) != 0 )
|
3405
|
+
{
|
3406
|
+
pMem.flags = MEM_Str | MEM_Ephem;
|
3407
|
+
pMem.z = Encoding.UTF8.GetString( buf, offset, (int)len );//memcpy( buf, pMem.z, len );
|
3408
|
+
pMem.n = pMem.z.Length;
|
3409
|
+
pMem.zBLOB = null;
|
3410
|
+
}
|
3411
|
+
else
|
3412
|
+
{
|
3413
|
+
pMem.z = null;
|
3414
|
+
pMem.zBLOB = sqlite3Malloc((int)len);
|
3415
|
+
pMem.flags = MEM_Blob | MEM_Ephem;
|
3416
|
+
Buffer.BlockCopy( buf, offset, pMem.zBLOB, 0, (int)len );//memcpy( buf, pMem.z, len );
|
3417
|
+
}
|
3418
|
+
return len;
|
3419
|
+
}
|
3420
|
+
}
|
3421
|
+
return 0;
|
3422
|
+
}
|
3423
|
+
|
3424
|
+
static int sqlite3VdbeSerialGet(
|
3425
|
+
byte[] buf, /* Buffer to deserialize from */
|
3426
|
+
u32 serial_type, /* Serial type to deserialize */
|
3427
|
+
Mem pMem /* Memory cell to write value into */
|
3428
|
+
)
|
3429
|
+
{
|
3430
|
+
switch ( serial_type )
|
3431
|
+
{
|
3432
|
+
case 10: /* Reserved for future use */
|
3433
|
+
case 11: /* Reserved for future use */
|
3434
|
+
case 0:
|
3435
|
+
{ /* NULL */
|
3436
|
+
pMem.flags = MEM_Null;
|
3437
|
+
break;
|
3438
|
+
}
|
3439
|
+
case 1:
|
3440
|
+
{ /* 1-byte signed integer */
|
3441
|
+
pMem.u.i = (sbyte)buf[0];
|
3442
|
+
pMem.flags = MEM_Int;
|
3443
|
+
return 1;
|
3444
|
+
}
|
3445
|
+
case 2:
|
3446
|
+
{ /* 2-byte signed integer */
|
3447
|
+
pMem.u.i = (int)( ( ( buf[0] ) << 8 ) | buf[1] );
|
3448
|
+
pMem.flags = MEM_Int;
|
3449
|
+
return 2;
|
3450
|
+
}
|
3451
|
+
case 3:
|
3452
|
+
{ /* 3-byte signed integer */
|
3453
|
+
pMem.u.i = (int)( ( ( buf[0] ) << 16 ) | ( buf[1] << 8 ) | buf[2] );
|
3454
|
+
pMem.flags = MEM_Int;
|
3455
|
+
return 3;
|
3456
|
+
}
|
3457
|
+
case 4:
|
3458
|
+
{ /* 4-byte signed integer */
|
3459
|
+
pMem.u.i = (int)( ( buf[0] << 24 ) | ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] );
|
3460
|
+
pMem.flags = MEM_Int;
|
3461
|
+
return 4;
|
3462
|
+
}
|
3463
|
+
case 5:
|
3464
|
+
{ /* 6-byte signed integer */
|
3465
|
+
u64 x = (ulong)( ( ( buf[0] ) << 8 ) | buf[1] );
|
3466
|
+
u32 y = (u32)( ( buf[2] << 24 ) | ( buf[3] << 16 ) | ( buf[4] << 8 ) | buf[5] );
|
3467
|
+
x = ( x << 32 ) | y;
|
3468
|
+
pMem.u.i = (i64)x;
|
3469
|
+
pMem.flags = MEM_Int;
|
3470
|
+
return 6;
|
3471
|
+
}
|
3472
|
+
case 6: /* 8-byte signed integer */
|
3473
|
+
case 7:
|
3474
|
+
{ /* IEEE floating point */
|
3475
|
+
u64 x;
|
3476
|
+
u32 y;
|
3477
|
+
#if !NDEBUG && !SQLITE_OMIT_FLOATING_POINT
|
3478
|
+
/* Verify that integers and floating point values use the same
|
3479
|
+
** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
|
3480
|
+
** defined that 64-bit floating point values really are mixed
|
3481
|
+
** endian.
|
3482
|
+
*/
|
3483
|
+
const u64 t1 = ( (u64)0x3ff00000 ) << 32;
|
3484
|
+
const double r1 = 1.0;
|
3485
|
+
u64 t2 = t1;
|
3486
|
+
#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
3487
|
+
swapMixedEndianFloat(t2);
|
3488
|
+
#endif
|
3489
|
+
Debug.Assert( sizeof( double ) == sizeof( u64 ) && memcmp( BitConverter.GetBytes( r1 ), BitConverter.GetBytes( t2 ), sizeof( double ) ) == 0 );//Debug.Assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, t2, sizeof(r1))==0 );
|
3490
|
+
#endif
|
3491
|
+
|
3492
|
+
x = (u64)( ( buf[0] << 24 ) | ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] );
|
3493
|
+
y = (u32)( ( buf[4] << 24 ) | ( buf[5] << 16 ) | ( buf[6] << 8 ) | buf[7] );
|
3494
|
+
x = ( x << 32 ) | y;
|
3495
|
+
if ( serial_type == 6 )
|
3496
|
+
{
|
3497
|
+
pMem.u.i = (i64)x;
|
3498
|
+
pMem.flags = MEM_Int;
|
3499
|
+
}
|
3500
|
+
else
|
3501
|
+
{
|
3502
|
+
Debug.Assert( sizeof( i64 ) == 8 && sizeof( double ) == 8 );
|
3503
|
+
#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
3504
|
+
swapMixedEndianFloat(x);
|
3505
|
+
#endif
|
3506
|
+
pMem.r = BitConverter.ToDouble(BitConverter.GetBytes((long)x), 0);// memcpy(pMem.r, x, sizeof(x))
|
3507
|
+
pMem.flags = MEM_Real;
|
3508
|
+
}
|
3509
|
+
return 8;
|
3510
|
+
}
|
3511
|
+
case 8: /* Integer 0 */
|
3512
|
+
case 9:
|
3513
|
+
{ /* Integer 1 */
|
3514
|
+
pMem.u.i = serial_type - 8;
|
3515
|
+
pMem.flags = MEM_Int;
|
3516
|
+
return 0;
|
3517
|
+
}
|
3518
|
+
default:
|
3519
|
+
{
|
3520
|
+
int len = (int)( ( serial_type - 12 ) / 2 );
|
3521
|
+
pMem.xDel = null;
|
3522
|
+
if ( ( serial_type & 0x01 ) != 0 )
|
3523
|
+
{
|
3524
|
+
pMem.flags = MEM_Str | MEM_Ephem;
|
3525
|
+
pMem.z = Encoding.UTF8.GetString( buf, 0, len );//memcpy( buf, pMem.z, len );
|
3526
|
+
pMem.n = pMem.z.Length;// len;
|
3527
|
+
pMem.zBLOB = null;
|
3528
|
+
}
|
3529
|
+
else
|
3530
|
+
{
|
3531
|
+
pMem.flags = MEM_Blob | MEM_Ephem;
|
3532
|
+
pMem.zBLOB = sqlite3Malloc(len);
|
3533
|
+
buf.CopyTo( pMem.zBLOB, 0 );
|
3534
|
+
pMem.n = len;// len;
|
3535
|
+
pMem.z = null;
|
3536
|
+
}
|
3537
|
+
return len;
|
3538
|
+
}
|
3539
|
+
}
|
3540
|
+
return 0;
|
3541
|
+
}
|
3542
|
+
|
3543
|
+
/*
|
3544
|
+
** Given the nKey-byte encoding of a record in pKey[], parse the
|
3545
|
+
** record into a UnpackedRecord structure. Return a pointer to
|
3546
|
+
** that structure.
|
3547
|
+
**
|
3548
|
+
** The calling function might provide szSpace bytes of memory
|
3549
|
+
** space at pSpace. This space can be used to hold the returned
|
3550
|
+
** VDbeParsedRecord structure if it is large enough. If it is
|
3551
|
+
** not big enough, space is obtained from sqlite3Malloc().
|
3552
|
+
**
|
3553
|
+
** The returned structure should be closed by a call to
|
3554
|
+
** sqlite3VdbeDeleteUnpackedRecord().
|
3555
|
+
*/
|
3556
|
+
static UnpackedRecord sqlite3VdbeRecordUnpack(
|
3557
|
+
KeyInfo pKeyInfo, /* Information about the record format */
|
3558
|
+
int nKey, /* Size of the binary record */
|
3559
|
+
byte[] pKey, /* The binary record */
|
3560
|
+
UnpackedRecord pSpace, // char *pSpace, /* Unaligned space available to hold the object */
|
3561
|
+
int szSpace /* Size of pSpace[] in bytes */
|
3562
|
+
)
|
3563
|
+
{
|
3564
|
+
byte[] aKey = pKey;
|
3565
|
+
UnpackedRecord p; /* The unpacked record that we will return */
|
3566
|
+
int nByte; /* Memory space needed to hold p, in bytes */
|
3567
|
+
int d;
|
3568
|
+
u32 idx;
|
3569
|
+
int u; /* Unsigned loop counter */
|
3570
|
+
int szHdr = 0;
|
3571
|
+
Mem pMem;
|
3572
|
+
int nOff; /* Increase pSpace by this much to 8-byte align it */
|
3573
|
+
|
3574
|
+
/*
|
3575
|
+
** We want to shift the pointer pSpace up such that it is 8-byte aligned.
|
3576
|
+
** Thus, we need to calculate a value, nOff, between 0 and 7, to shift
|
3577
|
+
** it by. If pSpace is already 8-byte aligned, nOff should be zero.
|
3578
|
+
*/
|
3579
|
+
//nOff = ( 8 - ( SQLITE_PTR_TO_INT( pSpace ) & 7 ) ) & 7;
|
3580
|
+
//pSpace += nOff;
|
3581
|
+
//szSpace -= nOff;
|
3582
|
+
//nByte = ROUND8( sizeof( UnpackedRecord ) ) + sizeof( Mem ) * ( pKeyInfo->nField + 1 );
|
3583
|
+
//if ( nByte > szSpace)
|
3584
|
+
//{
|
3585
|
+
// p = new UnpackedRecord();//sqlite3DbMallocRaw(pKeyInfo.db, nByte);
|
3586
|
+
// if ( p == null ) return null;
|
3587
|
+
// p.flags = UNPACKED_NEED_FREE | UNPACKED_NEED_DESTROY;
|
3588
|
+
//}
|
3589
|
+
//else
|
3590
|
+
{
|
3591
|
+
p = pSpace;//(UnpackedRecord*)pSpace;
|
3592
|
+
p.flags = UNPACKED_NEED_DESTROY;
|
3593
|
+
}
|
3594
|
+
p.pKeyInfo = pKeyInfo;
|
3595
|
+
p.nField = (u16)( pKeyInfo.nField + 1 );
|
3596
|
+
//p->aMem = pMem = (Mem*)&( (char*)p )[ROUND8( sizeof( UnpackedRecord ) )];
|
3597
|
+
//assert( EIGHT_BYTE_ALIGNMENT( pMem ) );
|
3598
|
+
p.aMem = new Mem[p.nField + 1];
|
3599
|
+
idx = (u32)getVarint32( aKey, 0, ref szHdr );// GetVarint( aKey, szHdr );
|
3600
|
+
d = (int)szHdr;
|
3601
|
+
u = 0;
|
3602
|
+
while ( idx < (int)szHdr && u < p.nField && d <= nKey )
|
3603
|
+
{
|
3604
|
+
p.aMem[u] = sqlite3Malloc(p.aMem[u]);
|
3605
|
+
pMem = p.aMem[u];
|
3606
|
+
u32 serial_type = 0;
|
3607
|
+
|
3608
|
+
idx += (u32)getVarint32( aKey, idx, ref serial_type );// GetVarint( aKey + idx, serial_type );
|
3609
|
+
pMem.enc = pKeyInfo.enc;
|
3610
|
+
pMem.db = pKeyInfo.db;
|
3611
|
+
pMem.flags = 0;
|
3612
|
+
//pMem.zMalloc = null;
|
3613
|
+
d += (int)sqlite3VdbeSerialGet( aKey, d, serial_type, pMem );
|
3614
|
+
//pMem++;
|
3615
|
+
u++;
|
3616
|
+
}
|
3617
|
+
Debug.Assert( u <= pKeyInfo.nField + 1 );
|
3618
|
+
p.nField = (u16)u;
|
3619
|
+
return p;// (void*)p;
|
3620
|
+
}
|
3621
|
+
|
3622
|
+
/*
|
3623
|
+
** This routine destroys a UnpackedRecord object.
|
3624
|
+
*/
|
3625
|
+
static void sqlite3VdbeDeleteUnpackedRecord( UnpackedRecord p )
|
3626
|
+
{
|
3627
|
+
int i;
|
3628
|
+
Mem pMem;
|
3629
|
+
Debug.Assert( p != null );
|
3630
|
+
Debug.Assert( ( p.flags & UNPACKED_NEED_DESTROY ) != 0 );
|
3631
|
+
//for ( i = 0, pMem = p->aMem ; i < p->nField ; i++, pMem++ )
|
3632
|
+
//{
|
3633
|
+
// /* The unpacked record is always constructed by the
|
3634
|
+
// ** sqlite3VdbeUnpackRecord() function above, which makes all
|
3635
|
+
// ** strings and blobs static. And none of the elements are
|
3636
|
+
// ** ever transformed, so there is never anything to delete.
|
3637
|
+
// */
|
3638
|
+
// if ( NEVER( pMem->zMalloc ) ) sqlite3VdbeMemRelease( pMem );
|
3639
|
+
//}
|
3640
|
+
if ( ( p.flags & UNPACKED_NEED_FREE ) != 0 )
|
3641
|
+
{
|
3642
|
+
sqlite3DbFree( p.pKeyInfo.db, ref p.aMem );
|
3643
|
+
p = null;
|
3644
|
+
}
|
3645
|
+
}
|
3646
|
+
|
3647
|
+
/*
|
3648
|
+
** This function compares the two table rows or index records
|
3649
|
+
** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
|
3650
|
+
** or positive integer if key1 is less than, equal to or
|
3651
|
+
** greater than key2. The {nKey1, pKey1} key must be a blob
|
3652
|
+
** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
|
3653
|
+
** key must be a parsed key such as obtained from
|
3654
|
+
** sqlite3VdbeParseRecord.
|
3655
|
+
**
|
3656
|
+
** Key1 and Key2 do not have to contain the same number of fields.
|
3657
|
+
** The key with fewer fields is usually compares less than the
|
3658
|
+
** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set
|
3659
|
+
** and the common prefixes are equal, then key1 is less than key2.
|
3660
|
+
** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are
|
3661
|
+
** equal, then the keys are considered to be equal and
|
3662
|
+
** the parts beyond the common prefix are ignored.
|
3663
|
+
**
|
3664
|
+
** If the UNPACKED_IGNORE_ROWID flag is set, then the last byte of
|
3665
|
+
** the header of pKey1 is ignored. It is assumed that pKey1 is
|
3666
|
+
** an index key, and thus ends with a rowid value. The last byte
|
3667
|
+
** of the header will therefore be the serial type of the rowid:
|
3668
|
+
** one of 1, 2, 3, 4, 5, 6, 8, or 9 - the integer serial types.
|
3669
|
+
** The serial type of the final rowid will always be a single byte.
|
3670
|
+
** By ignoring this last byte of the header, we force the comparison
|
3671
|
+
** to ignore the rowid at the end of key1.
|
3672
|
+
*/
|
3673
|
+
|
3674
|
+
static Mem mem1 = new Mem();
|
3675
|
+
// ALTERNATE FORM for C#
|
3676
|
+
static int sqlite3VdbeRecordCompare(
|
3677
|
+
int nKey1, byte[] pKey1, /* Left key */
|
3678
|
+
UnpackedRecord pPKey2 /* Right key */
|
3679
|
+
)
|
3680
|
+
{
|
3681
|
+
return sqlite3VdbeRecordCompare( nKey1, pKey1, 0, pPKey2 );
|
3682
|
+
}
|
3683
|
+
|
3684
|
+
static int sqlite3VdbeRecordCompare(
|
3685
|
+
int nKey1, byte[] pKey1, /* Left key */
|
3686
|
+
int offset,
|
3687
|
+
UnpackedRecord pPKey2 /* Right key */
|
3688
|
+
)
|
3689
|
+
{
|
3690
|
+
int d1; /* Offset into aKey[] of next data element */
|
3691
|
+
u32 idx1; /* Offset into aKey[] of next header element */
|
3692
|
+
u32 szHdr1; /* Number of bytes in header */
|
3693
|
+
int i = 0;
|
3694
|
+
int nField;
|
3695
|
+
int rc = 0;
|
3696
|
+
|
3697
|
+
//byte[] aKey1 = new byte[pKey1.Length - offset];
|
3698
|
+
//Buffer.BlockCopy( pKey1, offset, aKey1, 0, aKey1.Length );
|
3699
|
+
KeyInfo pKeyInfo;
|
3700
|
+
|
3701
|
+
pKeyInfo = pPKey2.pKeyInfo;
|
3702
|
+
mem1.enc = pKeyInfo.enc;
|
3703
|
+
mem1.db = pKeyInfo.db;
|
3704
|
+
/* mem1.flags = 0; // Will be initialized by sqlite3VdbeSerialGet() */
|
3705
|
+
// VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
|
3706
|
+
|
3707
|
+
/* Compilers may complain that mem1.u.i is potentially uninitialized.
|
3708
|
+
** We could initialize it, as shown here, to silence those complaints.
|
3709
|
+
** But in fact, mem1.u.i will never actually be used initialized, and doing
|
3710
|
+
** the unnecessary initialization has a measurable negative performance
|
3711
|
+
** impact, since this routine is a very high runner. And so, we choose
|
3712
|
+
** to ignore the compiler warnings and leave this variable uninitialized.
|
3713
|
+
*/
|
3714
|
+
/* mem1.u.i = 0; // not needed, here to silence compiler warning */
|
3715
|
+
|
3716
|
+
idx1 = (u32)((szHdr1 = pKey1[offset]) <= 0x7f ? 1 : getVarint32(pKey1, offset, ref szHdr1));// GetVarint( aKey1, szHdr1 );
|
3717
|
+
d1 = (int)szHdr1;
|
3718
|
+
if ( ( pPKey2.flags & UNPACKED_IGNORE_ROWID ) != 0 )
|
3719
|
+
{
|
3720
|
+
szHdr1--;
|
3721
|
+
}
|
3722
|
+
nField = pKeyInfo.nField;
|
3723
|
+
while ( idx1 < szHdr1 && i < pPKey2.nField )
|
3724
|
+
{
|
3725
|
+
u32 serial_type1;
|
3726
|
+
|
3727
|
+
/* Read the serial types for the next element in each key. */
|
3728
|
+
idx1 += (u32)((serial_type1 = pKey1[offset + idx1]) <= 0x7f ? 1 : getVarint32(pKey1,(uint)( offset+idx1), ref serial_type1)); //GetVarint( aKey1 + idx1, serial_type1 );
|
3729
|
+
if ( d1 >= nKey1 && sqlite3VdbeSerialTypeLen( serial_type1 ) > 0 ) break;
|
3730
|
+
|
3731
|
+
/* Extract the values to be compared.
|
3732
|
+
*/
|
3733
|
+
d1 += (int)sqlite3VdbeSerialGet(pKey1,offset+ d1, serial_type1, mem1);//sqlite3VdbeSerialGet( aKey1, d1, serial_type1, mem1 );
|
3734
|
+
|
3735
|
+
/* Do the comparison
|
3736
|
+
*/
|
3737
|
+
rc = sqlite3MemCompare( mem1, pPKey2.aMem[i], i < nField ? pKeyInfo.aColl[i] : null );
|
3738
|
+
if ( rc != 0 )
|
3739
|
+
{
|
3740
|
+
//Debug.Assert( mem1.zMalloc==null ); /* See comment below */
|
3741
|
+
|
3742
|
+
/* Invert the result if we are using DESC sort order. */
|
3743
|
+
if ( pKeyInfo.aSortOrder != null && i < nField && pKeyInfo.aSortOrder[i] != 0 )
|
3744
|
+
{
|
3745
|
+
rc = -rc;
|
3746
|
+
}
|
3747
|
+
|
3748
|
+
/* If the PREFIX_SEARCH flag is set and all fields except the final
|
3749
|
+
** rowid field were equal, then clear the PREFIX_SEARCH flag and set
|
3750
|
+
** pPKey2->rowid to the value of the rowid field in (pKey1, nKey1).
|
3751
|
+
** This is used by the OP_IsUnique opcode.
|
3752
|
+
*/
|
3753
|
+
if ( ( pPKey2.flags & UNPACKED_PREFIX_SEARCH ) != 0 && i == ( pPKey2.nField - 1 ) )
|
3754
|
+
{
|
3755
|
+
Debug.Assert( idx1 == szHdr1 && rc != 0 );
|
3756
|
+
Debug.Assert( ( mem1.flags & MEM_Int ) != 0 );
|
3757
|
+
pPKey2.flags = (ushort)( pPKey2.flags & ~UNPACKED_PREFIX_SEARCH );
|
3758
|
+
pPKey2.rowid = mem1.u.i;
|
3759
|
+
}
|
3760
|
+
|
3761
|
+
return rc;
|
3762
|
+
}
|
3763
|
+
i++;
|
3764
|
+
}
|
3765
|
+
|
3766
|
+
/* No memory allocation is ever used on mem1. Prove this using
|
3767
|
+
** the following assert(). If the assert() fails, it indicates a
|
3768
|
+
** memory leak and a need to call sqlite3VdbeMemRelease(&mem1).
|
3769
|
+
*/
|
3770
|
+
//Debug.Assert( mem1.zMalloc==null );
|
3771
|
+
|
3772
|
+
/* rc==0 here means that one of the keys ran out of fields and
|
3773
|
+
** all the fields up to that point were equal. If the UNPACKED_INCRKEY
|
3774
|
+
** flag is set, then break the tie by treating key2 as larger.
|
3775
|
+
** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes
|
3776
|
+
** are considered to be equal. Otherwise, the longer key is the
|
3777
|
+
** larger. As it happens, the pPKey2 will always be the longer
|
3778
|
+
** if there is a difference.
|
3779
|
+
*/
|
3780
|
+
Debug.Assert( rc == 0 );
|
3781
|
+
if ( ( pPKey2.flags & UNPACKED_INCRKEY ) != 0 )
|
3782
|
+
{
|
3783
|
+
rc = -1;
|
3784
|
+
}
|
3785
|
+
else if ( ( pPKey2.flags & UNPACKED_PREFIX_MATCH ) != 0 )
|
3786
|
+
{
|
3787
|
+
/* Leave rc==0 */
|
3788
|
+
}
|
3789
|
+
else if ( idx1 < szHdr1 )
|
3790
|
+
{
|
3791
|
+
rc = 1;
|
3792
|
+
}
|
3793
|
+
return rc;
|
3794
|
+
}
|
3795
|
+
|
3796
|
+
/*
|
3797
|
+
** pCur points at an index entry created using the OP_MakeRecord opcode.
|
3798
|
+
** Read the rowid (the last field in the record) and store it in *rowid.
|
3799
|
+
** Return SQLITE_OK if everything works, or an error code otherwise.
|
3800
|
+
**
|
3801
|
+
** pCur might be pointing to text obtained from a corrupt database file.
|
3802
|
+
** So the content cannot be trusted. Do appropriate checks on the content.
|
3803
|
+
*/
|
3804
|
+
static int sqlite3VdbeIdxRowid( sqlite3 db, BtCursor pCur, ref i64 rowid )
|
3805
|
+
{
|
3806
|
+
i64 nCellKey = 0;
|
3807
|
+
int rc;
|
3808
|
+
u32 szHdr = 0; /* Size of the header */
|
3809
|
+
u32 typeRowid = 0; /* Serial type of the rowid */
|
3810
|
+
u32 lenRowid; /* Size of the rowid */
|
3811
|
+
Mem m = null;
|
3812
|
+
Mem v = null;
|
3813
|
+
v = sqlite3Malloc( v);
|
3814
|
+
UNUSED_PARAMETER(db);
|
3815
|
+
|
3816
|
+
/* Get the size of the index entry. Only indices entries of less
|
3817
|
+
** than 2GiB are support - anything large must be database corruption.
|
3818
|
+
** Any corruption is detected in sqlite3BtreeParseCellPtr(), though, so
|
3819
|
+
** this code can safely assume that nCellKey is 32-bits
|
3820
|
+
*/
|
3821
|
+
Debug.Assert( sqlite3BtreeCursorIsValid( pCur ) );
|
3822
|
+
rc = sqlite3BtreeKeySize( pCur, ref nCellKey );
|
3823
|
+
Debug.Assert( rc == SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
|
3824
|
+
Debug.Assert( ( (u32)nCellKey & SQLITE_MAX_U32 ) == (u64)nCellKey );
|
3825
|
+
|
3826
|
+
/* Read in the complete content of the index entry */
|
3827
|
+
m = sqlite3Malloc( m );
|
3828
|
+
// memset(&m, 0, sizeof(m));
|
3829
|
+
rc = sqlite3VdbeMemFromBtree( pCur, 0, (int)nCellKey, true, m );
|
3830
|
+
if ( rc != 0 )
|
3831
|
+
{
|
3832
|
+
return rc;
|
3833
|
+
}
|
3834
|
+
|
3835
|
+
/* The index entry must begin with a header size */
|
3836
|
+
getVarint32( m.zBLOB, 0, ref szHdr );
|
3837
|
+
testcase( szHdr == 3 );
|
3838
|
+
testcase( szHdr == m.n );
|
3839
|
+
if ( unlikely( szHdr < 3 || (int)szHdr > m.n ) )
|
3840
|
+
{
|
3841
|
+
goto idx_rowid_corruption;
|
3842
|
+
}
|
3843
|
+
|
3844
|
+
/* The last field of the index should be an integer - the ROWID.
|
3845
|
+
** Verify that the last entry really is an integer. */
|
3846
|
+
getVarint32( m.zBLOB, szHdr - 1, ref typeRowid );
|
3847
|
+
testcase( typeRowid == 1 );
|
3848
|
+
testcase( typeRowid == 2 );
|
3849
|
+
testcase( typeRowid == 3 );
|
3850
|
+
testcase( typeRowid == 4 );
|
3851
|
+
testcase( typeRowid == 5 );
|
3852
|
+
testcase( typeRowid == 6 );
|
3853
|
+
testcase( typeRowid == 8 );
|
3854
|
+
testcase( typeRowid == 9 );
|
3855
|
+
if ( unlikely( typeRowid < 1 || typeRowid > 9 || typeRowid == 7 ) )
|
3856
|
+
{
|
3857
|
+
goto idx_rowid_corruption;
|
3858
|
+
}
|
3859
|
+
lenRowid = (u32)sqlite3VdbeSerialTypeLen( typeRowid );
|
3860
|
+
testcase( (u32)m.n == szHdr + lenRowid );
|
3861
|
+
if ( unlikely( (u32)m.n < szHdr + lenRowid ) )
|
3862
|
+
{
|
3863
|
+
goto idx_rowid_corruption;
|
3864
|
+
}
|
3865
|
+
|
3866
|
+
/* Fetch the integer off the end of the index record */
|
3867
|
+
sqlite3VdbeSerialGet( m.zBLOB, (int)( m.n - lenRowid ), typeRowid, v );
|
3868
|
+
rowid = v.u.i;
|
3869
|
+
sqlite3VdbeMemRelease( m );
|
3870
|
+
return SQLITE_OK;
|
3871
|
+
|
3872
|
+
/* Jump here if database corruption is detected after m has been
|
3873
|
+
** allocated. Free the m object and return SQLITE_CORRUPT. */
|
3874
|
+
idx_rowid_corruption:
|
3875
|
+
//testcase( m.zMalloc != 0 );
|
3876
|
+
sqlite3VdbeMemRelease( m );
|
3877
|
+
return SQLITE_CORRUPT_BKPT();
|
3878
|
+
}
|
3879
|
+
|
3880
|
+
/*
|
3881
|
+
** Compare the key of the index entry that cursor pC is pointing to against
|
3882
|
+
** the key string in pUnpacked. Write into *pRes a number
|
3883
|
+
** that is negative, zero, or positive if pC is less than, equal to,
|
3884
|
+
** or greater than pUnpacked. Return SQLITE_OK on success.
|
3885
|
+
**
|
3886
|
+
** pUnpacked is either created without a rowid or is truncated so that it
|
3887
|
+
** omits the rowid at the end. The rowid at the end of the index entry
|
3888
|
+
** is ignored as well. Hence, this routine only compares the prefixes
|
3889
|
+
** of the keys prior to the final rowid, not the entire key.
|
3890
|
+
*/
|
3891
|
+
static int sqlite3VdbeIdxKeyCompare(
|
3892
|
+
VdbeCursor pC, /* The cursor to compare against */
|
3893
|
+
UnpackedRecord pUnpacked, /* Unpacked version of key to compare against */
|
3894
|
+
ref int res /* Write the comparison result here */
|
3895
|
+
)
|
3896
|
+
{
|
3897
|
+
i64 nCellKey = 0;
|
3898
|
+
int rc;
|
3899
|
+
BtCursor pCur = pC.pCursor;
|
3900
|
+
Mem m = null;
|
3901
|
+
|
3902
|
+
Debug.Assert( sqlite3BtreeCursorIsValid( pCur ) );
|
3903
|
+
rc = sqlite3BtreeKeySize( pCur, ref nCellKey );
|
3904
|
+
Debug.Assert( rc == SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
|
3905
|
+
/* nCellKey will always be between 0 and 0xffffffff because of the say
|
3906
|
+
** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
|
3907
|
+
if ( nCellKey <= 0 || nCellKey > 0x7fffffff )
|
3908
|
+
{
|
3909
|
+
res = 0;
|
3910
|
+
return SQLITE_CORRUPT_BKPT();
|
3911
|
+
}
|
3912
|
+
|
3913
|
+
m = sqlite3Malloc( m );
|
3914
|
+
// memset(&m, 0, sizeof(m));
|
3915
|
+
rc = sqlite3VdbeMemFromBtree( pC.pCursor, 0, (int)nCellKey, true, m );
|
3916
|
+
if ( rc != 0 )
|
3917
|
+
{
|
3918
|
+
return rc;
|
3919
|
+
}
|
3920
|
+
Debug.Assert( ( pUnpacked.flags & UNPACKED_IGNORE_ROWID ) != 0 );
|
3921
|
+
res = sqlite3VdbeRecordCompare( m.n, m.zBLOB, pUnpacked );
|
3922
|
+
sqlite3VdbeMemRelease( m );
|
3923
|
+
return SQLITE_OK;
|
3924
|
+
}
|
3925
|
+
|
3926
|
+
/*
|
3927
|
+
** This routine sets the value to be returned by subsequent calls to
|
3928
|
+
** sqlite3_changes() on the database handle 'db'.
|
3929
|
+
*/
|
3930
|
+
static void sqlite3VdbeSetChanges( sqlite3 db, int nChange )
|
3931
|
+
{
|
3932
|
+
Debug.Assert( sqlite3_mutex_held( db.mutex ) );
|
3933
|
+
db.nChange = nChange;
|
3934
|
+
db.nTotalChange += nChange;
|
3935
|
+
}
|
3936
|
+
|
3937
|
+
/*
|
3938
|
+
** Set a flag in the vdbe to update the change counter when it is finalised
|
3939
|
+
** or reset.
|
3940
|
+
*/
|
3941
|
+
static void sqlite3VdbeCountChanges( Vdbe v )
|
3942
|
+
{
|
3943
|
+
v.changeCntOn = true;
|
3944
|
+
}
|
3945
|
+
|
3946
|
+
/*
|
3947
|
+
** Mark every prepared statement associated with a database connection
|
3948
|
+
** as expired.
|
3949
|
+
**
|
3950
|
+
** An expired statement means that recompilation of the statement is
|
3951
|
+
** recommend. Statements expire when things happen that make their
|
3952
|
+
** programs obsolete. Removing user-defined functions or collating
|
3953
|
+
** sequences, or changing an authorization function are the types of
|
3954
|
+
** things that make prepared statements obsolete.
|
3955
|
+
*/
|
3956
|
+
static void sqlite3ExpirePreparedStatements( sqlite3 db )
|
3957
|
+
{
|
3958
|
+
Vdbe p;
|
3959
|
+
for ( p = db.pVdbe; p != null; p = p.pNext )
|
3960
|
+
{
|
3961
|
+
p.expired = true;
|
3962
|
+
}
|
3963
|
+
}
|
3964
|
+
|
3965
|
+
/*
|
3966
|
+
** Return the database associated with the Vdbe.
|
3967
|
+
*/
|
3968
|
+
static sqlite3 sqlite3VdbeDb( Vdbe v )
|
3969
|
+
{
|
3970
|
+
return v.db;
|
3971
|
+
}
|
3972
|
+
/*
|
3973
|
+
** Return a pointer to an sqlite3_value structure containing the value bound
|
3974
|
+
** parameter iVar of VM v. Except, if the value is an SQL NULL, return
|
3975
|
+
** 0 instead. Unless it is NULL, apply affinity aff (one of the SQLITE_AFF_*
|
3976
|
+
** constants) to the value before returning it.
|
3977
|
+
**
|
3978
|
+
** The returned value must be freed by the caller using sqlite3ValueFree().
|
3979
|
+
*/
|
3980
|
+
static sqlite3_value sqlite3VdbeGetValue( Vdbe v, int iVar, u8 aff )
|
3981
|
+
{
|
3982
|
+
Debug.Assert( iVar > 0 );
|
3983
|
+
if ( v != null )
|
3984
|
+
{
|
3985
|
+
Mem pMem = v.aVar[iVar - 1];
|
3986
|
+
if ( 0 == ( pMem.flags & MEM_Null ) )
|
3987
|
+
{
|
3988
|
+
sqlite3_value pRet = sqlite3ValueNew( v.db );
|
3989
|
+
if ( pRet != null )
|
3990
|
+
{
|
3991
|
+
sqlite3VdbeMemCopy( (Mem)pRet, pMem );
|
3992
|
+
sqlite3ValueApplyAffinity( pRet, (char)aff, SQLITE_UTF8 );
|
3993
|
+
sqlite3VdbeMemStoreType( (Mem)pRet );
|
3994
|
+
}
|
3995
|
+
return pRet;
|
3996
|
+
}
|
3997
|
+
}
|
3998
|
+
return null;
|
3999
|
+
}
|
4000
|
+
|
4001
|
+
/*
|
4002
|
+
** Configure SQL variable iVar so that binding a new value to it signals
|
4003
|
+
** to sqlite3_reoptimize() that re-preparing the statement may result
|
4004
|
+
** in a better query plan.
|
4005
|
+
*/
|
4006
|
+
static void sqlite3VdbeSetVarmask( Vdbe v, int iVar )
|
4007
|
+
{
|
4008
|
+
Debug.Assert( iVar > 0 );
|
4009
|
+
if ( iVar > 32 )
|
4010
|
+
{
|
4011
|
+
v.expmask = 0xffffffff;
|
4012
|
+
}
|
4013
|
+
else
|
4014
|
+
{
|
4015
|
+
v.expmask |= ( (u32)1 << ( iVar - 1 ) );
|
4016
|
+
}
|
4017
|
+
}
|
4018
|
+
}
|
4019
|
+
}
|