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.
Files changed (623) hide show
  1. data/CHANGELOG +18 -0
  2. data/CREDITS +38 -0
  3. data/README.md +2 -2
  4. data/Rakefile +60 -2
  5. data/bin/set-rhodes-sdk.bat +1 -0
  6. data/doc/application.txt +11 -0
  7. data/doc/build.txt +156 -39
  8. data/doc/configuration.txt +1 -10
  9. data/doc/connect-to-web-services.txt +6 -6
  10. data/doc/device-caps.txt +48 -5
  11. data/doc/extensions.txt +8 -1
  12. data/doc/rhom.txt +16 -0
  13. data/doc/synchronization.txt +56 -14
  14. data/doc/ui.txt +23 -2
  15. data/installer/instant-rhodes.nsi +6 -6
  16. data/lib/extensions/barcode/ext/barcode/platform/iphone/Barcode.xcodeproj/project.pbxproj +4 -2
  17. data/lib/extensions/barcode/ext/barcode/platform/wm/Rakefile +1 -1
  18. data/lib/extensions/digest-md5/ext/Rakefile +3 -3
  19. data/lib/extensions/digest-md5/ext/build +0 -1
  20. data/lib/extensions/digest-sha1/ext/Rakefile +1 -1
  21. data/lib/extensions/digest-sha1/ext/build +0 -1
  22. data/lib/extensions/digest/ext/Rakefile +3 -3
  23. data/lib/extensions/digest/ext/build +0 -1
  24. data/lib/extensions/fcntl/ext/Rakefile +1 -1
  25. data/lib/extensions/mspec/mspec/guards/guard.rb +4 -0
  26. data/lib/extensions/mspec/mspec/helpers/environment.rb +4 -0
  27. data/lib/extensions/nfc/ext.yml +2 -0
  28. data/lib/extensions/nfc/ext/build +12 -0
  29. data/lib/extensions/nfc/ext/build.bat +8 -0
  30. data/lib/extensions/nfc/ext/nfc/platform/android/AndroidManifest.xml +25 -0
  31. data/lib/extensions/nfc/ext/nfc/platform/android/Rakefile +94 -0
  32. data/lib/extensions/nfc/ext/nfc/platform/android/ext_build.files +4 -0
  33. data/lib/extensions/nfc/ext/nfc/platform/android/jni/src/nfc.cpp +404 -0
  34. data/lib/extensions/nfc/ext/nfc/platform/android/src/com/nfc/Nfc.java +138 -0
  35. data/lib/extensions/nfc/ext/nfc/platform/android/src/com/nfc/NfcMessage.java +34 -0
  36. data/lib/extensions/nfc/ext/nfc/platform/android/src/com/nfc/NfcMessagePack.java +33 -0
  37. data/lib/extensions/nfc/ext/nfc/platform/android/src/com/nfc/NfcRecord.java +149 -0
  38. data/lib/extensions/nfc/ext/nfc/shared/ruby/nfc.i +22 -0
  39. data/lib/extensions/nfc/ext/nfc/shared/ruby/nfc_wrap.c +2034 -0
  40. data/lib/extensions/nfc/nfc.rb +120 -0
  41. data/lib/extensions/rholang/{lang_ca.rb → rholang/lang_ca.rb} +0 -0
  42. data/lib/extensions/rholang/{lang_cf.rb → rholang/lang_cf.rb} +0 -0
  43. data/lib/extensions/rholang/{lang_chef.rb → rholang/lang_chef.rb} +0 -0
  44. data/lib/extensions/rholang/{lang_cs.rb → rholang/lang_cs.rb} +0 -0
  45. data/lib/extensions/rholang/{lang_da.rb → rholang/lang_da.rb} +0 -0
  46. data/lib/extensions/rholang/{lang_de.rb → rholang/lang_de.rb} +0 -0
  47. data/lib/extensions/rholang/{lang_es.rb → rholang/lang_es.rb} +0 -0
  48. data/lib/extensions/rholang/{lang_es_ar.rb → rholang/lang_es_ar.rb} +0 -0
  49. data/lib/extensions/rholang/{lang_fi.rb → rholang/lang_fi.rb} +0 -0
  50. data/lib/extensions/rholang/{lang_fr.rb → rholang/lang_fr.rb} +0 -0
  51. data/lib/extensions/rholang/{lang_it.rb → rholang/lang_it.rb} +0 -0
  52. data/lib/extensions/rholang/{lang_ko.rb → rholang/lang_ko.rb} +0 -0
  53. data/lib/extensions/rholang/{lang_nl.rb → rholang/lang_nl.rb} +0 -0
  54. data/lib/extensions/rholang/{lang_no.rb → rholang/lang_no.rb} +0 -0
  55. data/lib/extensions/rholang/{lang_pt.rb → rholang/lang_pt.rb} +0 -0
  56. data/lib/extensions/rholang/{lang_pt_br.rb → rholang/lang_pt_br.rb} +0 -0
  57. data/lib/extensions/rholang/{lang_ru.rb → rholang/lang_ru.rb} +0 -0
  58. data/lib/extensions/rholang/{lang_se.rb → rholang/lang_se.rb} +0 -0
  59. data/lib/extensions/rholang/{lang_sr.rb → rholang/lang_sr.rb} +0 -0
  60. data/lib/extensions/rholang/{rhoerror_ru.rb → rholang/rhoerror_ru.rb} +0 -0
  61. data/lib/extensions/rholang/{rhomsg_ru.rb → rholang/rhomsg_ru.rb} +0 -0
  62. data/lib/framework/date/format.rb +2 -0
  63. data/lib/framework/dateOrig.rb +17 -8
  64. data/lib/framework/rational18.rb +532 -0
  65. data/lib/framework/res/back_btn.wp7.png +0 -0
  66. data/lib/framework/res/blue_pushpin.wp7.png +0 -0
  67. data/lib/framework/res/blue_pushpin_small.wp7.png +0 -0
  68. data/lib/framework/res/callout.wp7.png +0 -0
  69. data/lib/framework/res/callout_link.wp7.png +0 -0
  70. data/lib/framework/res/esri.wp7.png +0 -0
  71. data/lib/framework/res/forward_btn.wp7.png +0 -0
  72. data/lib/framework/res/home_btn.wp7.png +0 -0
  73. data/lib/framework/res/options_btn.wp7.png +0 -0
  74. data/lib/framework/res/refresh_btn.wp7.png +0 -0
  75. data/lib/framework/rho/render.rb +8 -1
  76. data/lib/framework/rho/rho.rb +30 -7
  77. data/lib/framework/rho/rhoapplication.rb +9 -4
  78. data/lib/framework/rho/rhofsconnector.rb +5 -1
  79. data/lib/framework/rho/rhotabbar.rb +8 -0
  80. data/lib/framework/rho/rhotoolbar.rb +1 -1
  81. data/lib/framework/rho/rhoviewhelpers.rb +18 -1
  82. data/lib/framework/rhodes.rb +1 -1
  83. data/lib/framework/rhoframework.rb +46 -1
  84. data/lib/framework/rholang/localization_simplified.rb +17 -16
  85. data/lib/framework/rhom/rhom_db_adapter.rb +2 -2
  86. data/lib/framework/rhom/rhom_object_factory.rb +115 -12
  87. data/lib/framework/rhosystem.rb +135 -0
  88. data/lib/framework/version.rb +1 -1
  89. data/lib/rhodes.rb +1 -1
  90. data/lib/test/apps/rhoconfig.txt +23 -23
  91. data/platform/android/Rhodes/AndroidManifest.full.xml +101 -0
  92. data/platform/android/Rhodes/AndroidManifest.xml +10 -15
  93. data/platform/android/Rhodes/default.properties +11 -0
  94. data/platform/android/Rhodes/gen/com/rhomobile/rhodes/R.java +59 -53
  95. data/platform/android/Rhodes/jni/include/rhodes.h +1 -0
  96. data/platform/android/Rhodes/jni/include/rhodes/jni/com_rhomobile_rhodes_RhodesApplication.h +21 -0
  97. data/platform/android/Rhodes/jni/include/rhodes/jni/com_rhomobile_rhodes_alert_PopupActivity.h +21 -0
  98. data/platform/android/Rhodes/jni/include/rhodes/jni/com_rhomobile_rhodes_file_RhoFileApi.h +10 -2
  99. data/platform/android/Rhodes/jni/src/alert.cpp +2 -1
  100. data/platform/android/Rhodes/jni/src/datetimepicker.cpp +2 -0
  101. data/platform/android/Rhodes/jni/src/fileapi.cpp +671 -84
  102. data/platform/android/Rhodes/jni/src/nativebar.cpp +18 -0
  103. data/platform/android/Rhodes/jni/src/rhodes.cpp +92 -1
  104. data/platform/android/Rhodes/res/values/styles.xml +7 -0
  105. data/platform/android/Rhodes/src/com/rhomobile/rhodes/BaseActivity.java +35 -2
  106. data/platform/android/Rhodes/src/com/rhomobile/rhodes/Capabilities.java +12 -13
  107. data/platform/android/Rhodes/src/com/rhomobile/rhodes/LocalFileProvider.java +130 -0
  108. data/platform/android/Rhodes/src/com/rhomobile/rhodes/NativeBar.java +6 -0
  109. data/platform/android/Rhodes/src/com/rhomobile/rhodes/PushReceiver.java +5 -1
  110. data/platform/android/Rhodes/src/com/rhomobile/rhodes/PushService.java +6 -2
  111. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhoMenu.java +7 -36
  112. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhodesActivity.java +43 -20
  113. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhodesApplication.java +2 -0
  114. data/platform/android/Rhodes/src/com/rhomobile/rhodes/RhodesService.java +63 -28
  115. data/platform/android/Rhodes/src/com/rhomobile/rhodes/Utils.java +2 -2
  116. data/platform/android/Rhodes/src/com/rhomobile/rhodes/WebView.java +6 -2
  117. data/platform/android/Rhodes/src/com/rhomobile/rhodes/alert/Alert.java +19 -282
  118. data/platform/android/Rhodes/src/com/rhomobile/rhodes/alert/PopupActivity.java +354 -0
  119. data/platform/android/Rhodes/src/com/rhomobile/rhodes/datetime/DateTimePickerScreen.java +4 -0
  120. data/platform/android/Rhodes/src/com/rhomobile/rhodes/event/EventStore.java +1 -2
  121. data/platform/android/Rhodes/src/com/rhomobile/rhodes/file/RhoFileApi.java +71 -5
  122. data/platform/android/Rhodes/src/com/rhomobile/rhodes/geolocation/GeoLocationImpl.java +107 -37
  123. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/SimpleMainView.java +10 -7
  124. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mainview/TabbedMainView.java +156 -56
  125. data/platform/android/Rhodes/src/com/rhomobile/rhodes/mapview/MapView.java +0 -1
  126. data/platform/android/Rhodes/src/com/rhomobile/rhodes/phonebook/ContactAccessorNew.java +40 -32
  127. data/platform/android/Rhodes/src/com/rhomobile/rhodes/signature/SignatureView.java +1 -0
  128. data/platform/android/Rhodes/src/com/rhomobile/rhodes/uri/ExternalHttpHandler.java +14 -6
  129. data/platform/android/Rhodes/src/com/rhomobile/rhodes/uri/LocalFileHandler.java +46 -0
  130. data/platform/android/Rhodes/src/com/rhomobile/rhodes/uri/MailUriHandler.java +4 -24
  131. data/platform/android/Rhodes/src/com/rhomobile/rhodes/uri/UriHandler.java +3 -1
  132. data/platform/android/build/RhodesSRC_build.files +28 -25
  133. data/platform/android/build/android.rake +230 -54
  134. data/platform/android/build/androidcommon.rb +1 -1
  135. data/platform/android/build/librhocommon_build.files +1 -0
  136. data/platform/bb/Hsqldb/BlackBerry_App_Descriptor.xml +20 -0
  137. data/platform/bb/Hsqldb/src/com/rho/db/HsqlDBResult.java +1 -5
  138. data/platform/bb/Hsqldb/src/com/rho/db/HsqlDBStorage.java +6 -1
  139. data/platform/bb/Hsqldb/src/org/hsqldb/rowio/RowOutputBase.java +1 -1
  140. data/platform/bb/Hsqldb/src/org/hsqldb/rowio/RowOutputBinary.java +1 -1
  141. data/platform/bb/RubyVM/BlackBerry_App_Descriptor.xml +20 -0
  142. data/platform/bb/RubyVM/src/com/rho/IRhoRubyHelper.java +2 -0
  143. data/platform/bb/RubyVM/src/com/rho/RhoLogOutputSink.java +0 -1
  144. data/platform/bb/RubyVM/src/com/rho/RhoLogger.java +12 -10
  145. data/platform/bb/RubyVM/src/com/rho/RhoThread.java +16 -0
  146. data/platform/bb/RubyVM/src/com/rho/RhoTimer.java +89 -0
  147. data/platform/bb/RubyVM/src/com/rho/RhodesApp.java +20 -13
  148. data/platform/bb/RubyVM/src/com/rho/SplashScreen.java +1 -2
  149. data/platform/bb/RubyVM/src/com/rho/ThreadQueue.java +2 -2
  150. data/platform/bb/RubyVM/src/com/rho/TimeInterval.java +5 -0
  151. data/platform/bb/RubyVM/src/com/rho/db/DBAdapter.java +54 -48
  152. data/platform/bb/RubyVM/src/com/rho/db/IDBResult.java +0 -1
  153. data/platform/bb/RubyVM/src/com/rho/db/IDBStorage.java +1 -0
  154. data/platform/bb/RubyVM/src/com/rho/net/AsyncHttp.java +1 -1
  155. data/platform/bb/RubyVM/src/com/rho/sync/ClientRegister.java +1 -1
  156. data/platform/bb/RubyVM/src/com/rho/sync/JSONStructIterator.java +1 -1
  157. data/platform/bb/RubyVM/src/com/rho/sync/SyncEngine.java +16 -8
  158. data/platform/bb/RubyVM/src/com/rho/sync/SyncNotify.java +2 -2
  159. data/platform/bb/RubyVM/src/com/rho/sync/SyncSource.java +52 -29
  160. data/platform/bb/RubyVM/src/com/rho/sync/SyncThread.java +1 -3
  161. data/platform/bb/build/RubyVM_build.files +1 -0
  162. data/platform/bb/build/bb.rake +29 -9
  163. data/platform/bb/rhodes/BlackBerry_App_Descriptor.xml +23 -0
  164. data/platform/bb/rhodes/platform/5.0/com/rho/RhodesApplicationPlatform.java +1 -1
  165. data/platform/bb/rhodes/platform/5.0/com/rho/db/SqliteCopyResult.java +0 -4
  166. data/platform/bb/rhodes/platform/5.0/com/rho/db/SqliteResult.java +13 -20
  167. data/platform/bb/rhodes/platform/5.0/com/rho/db/SqliteStorage.java +183 -157
  168. data/platform/bb/rhodes/src/com/rho/RhoRubyHelper.java +22 -0
  169. data/platform/bb/rhodes/src/com/rho/RhodesApplicationPlatform.java +1 -1
  170. data/platform/bb/rhodes/src/com/rho/db/SqliteCopyResult.java +0 -4
  171. data/platform/bb/rhodes/src/com/rho/db/SqliteResult.java +13 -20
  172. data/platform/bb/rhodes/src/com/rho/db/SqliteStorage.java +183 -157
  173. data/platform/bb/rhodes/src/com/rho/rubyext/System.java +46 -1
  174. data/platform/bb/rhodes/src/rhomobile/RhodesApplication.java +8 -1
  175. data/platform/bb/rhodes/src/rhomobile/camera/CameraFilesListener.java +13 -3
  176. data/platform/iphone/Classes/AppManager/AppManager.h +5 -1
  177. data/platform/iphone/Classes/AppManager/AppManager.m +170 -7
  178. data/platform/iphone/Classes/DateTimePicker.m +14 -1
  179. data/platform/iphone/Classes/DateTimePickerDelegate.h +2 -0
  180. data/platform/iphone/Classes/DateTimePickerDelegate.m +36 -2
  181. data/platform/iphone/Classes/NativeBar.h +1 -0
  182. data/platform/iphone/Classes/NativeBar.m +15 -3
  183. data/platform/iphone/Classes/Phonebook/phonebook.m +8 -9
  184. data/platform/iphone/Classes/Rhodes.m +50 -6
  185. data/platform/iphone/Classes/SimpleMainView.m +7 -6
  186. data/platform/iphone/Classes/SplitView/RightViewController.h +3 -1
  187. data/platform/iphone/Classes/SplitView/RightViewController.m +14 -1
  188. data/platform/iphone/Classes/TabbedMainView.h +4 -0
  189. data/platform/iphone/Classes/TabbedMainView.m +43 -26
  190. data/platform/iphone/Info.plist +1 -1
  191. data/platform/iphone/RhoLib/RhoLib.xcodeproj/project.pbxproj +4 -0
  192. data/platform/iphone/curl/curl.xcodeproj/project.pbxproj +3 -3
  193. data/platform/iphone/rbuild/iphone.rake +168 -119
  194. data/platform/iphone/rhoextlib/rhoextlib.xcodeproj/project.pbxproj +4 -2
  195. data/platform/iphone/rhorubylib/rhorubylib.xcodeproj/project.pbxproj +3 -3
  196. data/platform/iphone/rhorunner.xcodeproj/project.pbxproj +2 -2
  197. data/platform/iphone/rhosynclib/rhosynclib.xcodeproj/project.pbxproj +3 -3
  198. data/platform/shared/SyncClient/SyncClient.cpp +20 -8
  199. data/platform/shared/SyncClient/SyncClient.h +2 -1
  200. data/platform/shared/common/RhoDefs.h +4 -0
  201. data/platform/shared/common/RhoPort.h +22 -0
  202. data/platform/shared/common/RhoStd.h +5 -0
  203. data/platform/shared/common/RhoTime.cpp +73 -0
  204. data/platform/shared/common/RhoTime.h +26 -53
  205. data/platform/shared/common/RhodesApp.cpp +29 -28
  206. data/platform/shared/common/RhodesApp.h +4 -1
  207. data/platform/shared/common/StringConverter.h +37 -10
  208. data/platform/shared/common/app_build_capabilities.h +2 -0
  209. data/platform/shared/common/rhoparams.cpp +25 -12
  210. data/platform/shared/common/rhoparams.h +10 -8
  211. data/platform/shared/db/DBAdapter.cpp +0 -22
  212. data/platform/shared/json/RJSONTokener.c +15 -23
  213. data/platform/shared/net/AsyncHttp.cpp +9 -8
  214. data/platform/shared/net/HttpServer.cpp +61 -19
  215. data/platform/shared/net/HttpServer.h +2 -0
  216. data/platform/shared/ruby/ext/datetimepicker/datetimepicker.i +3 -0
  217. data/platform/shared/ruby/ext/datetimepicker/datetimepicker_wrap.c +151 -402
  218. data/platform/shared/ruby/ext/nativebar/nativebar.i +3 -0
  219. data/platform/shared/ruby/ext/nativebar/nativebar_wrap.c +154 -403
  220. data/platform/shared/ruby/ext/rho/rhoruby.c +4 -0
  221. data/platform/shared/ruby/ext/rho/rhoruby.h +2 -0
  222. data/platform/shared/ruby/ext/system/system.i +8 -0
  223. data/platform/shared/ruby/ext/system/system_wrap.c +80 -5
  224. data/platform/shared/ruby/file.c +6 -4
  225. data/platform/shared/ruby/gc.c +1 -1
  226. data/platform/shared/ruby/linux/ruby/config.h +7 -2
  227. data/platform/shared/ruby/missing/acosh.c +3 -3
  228. data/platform/shared/ruby/wince/_time.h +1 -1
  229. data/platform/shared/ruby/wince/stdlib.c +1 -1
  230. data/platform/shared/ruby/wince/string_wce.c +2 -2
  231. data/platform/shared/ruby/wince/sys/timeb.c +1 -0
  232. data/platform/shared/ruby/wince/time_wce.c +8 -0
  233. data/platform/shared/ruby/wince/wince.c +7 -7
  234. data/platform/shared/ruby/wince/wince.h +22 -0
  235. data/platform/shared/rubyext/System.cpp +19 -1
  236. data/platform/shared/sqlite/sqlite3.c +18993 -8129
  237. data/platform/shared/sqlite/sqlite3.h +953 -358
  238. data/platform/shared/sqlite/sqlite3ext.h +42 -0
  239. data/platform/shared/sync/SyncEngine.cpp +10 -0
  240. data/platform/shared/sync/SyncSource.cpp +41 -19
  241. data/platform/shared/sync/SyncSource.h +1 -1
  242. data/platform/shared/tcmalloc/rhomem.h +7 -2
  243. data/platform/shared/tcmalloc/windows/port.h +2 -0
  244. data/platform/shared/unzip/unzip.cpp +1 -0
  245. data/platform/shared/xruby/src/com/xruby/compiler/parser/RubyParser.java +11 -1
  246. data/platform/wm/RhoLib/RhoLib.vcproj +182 -24
  247. data/platform/wm/build/wm.rake +16 -3
  248. data/platform/wm/rhodes.sln +106 -113
  249. data/platform/wm/rhodes/Alert.cpp +6 -7
  250. data/platform/wm/rhodes/AppManager.cpp +8 -17
  251. data/platform/wm/rhodes/DateTimePicker.cpp +3 -0
  252. data/platform/wm/rhodes/DateTimePicker.h +2 -0
  253. data/platform/wm/rhodes/MainWindow.cpp +36 -16
  254. data/platform/wm/rhodes/MainWindow.h +6 -3
  255. data/platform/wm/rhodes/OutlookApp.cpp +3 -3
  256. data/platform/wm/rhodes/Rhodes.cpp +46 -27
  257. data/platform/wm/rhodes/Rhodes.rc +16 -3
  258. data/platform/wm/rhodes/RingtoneManager.cpp +7 -7
  259. data/platform/wm/rhodes/RingtoneManager.h +1 -1
  260. data/platform/wm/rhodes/Utils.cpp +2 -1
  261. data/platform/wm/rhodes/bluetooth/Bluetooth.cpp +1 -13
  262. data/platform/wm/rhodes/bluetooth/Bluetooth.h +1 -2
  263. data/platform/wm/rhodes/camera/Camera.cpp +6 -12
  264. data/platform/wm/rhodes/phonebook/phonebook.cpp +11 -11
  265. data/platform/wm/rhodes/phonebook/phonebook.h +1 -1
  266. data/platform/wm/rhodes/resource.h +3 -1
  267. data/platform/wm/rhodes/rho/net/NetRequestImpl.cpp +7 -5
  268. data/platform/wm/rhodes/rho/rubyext/GeoLocationImpl.cpp +6 -6
  269. data/platform/wm/rhodes/rho/rubyext/GeoLocationImpl.h +1 -1
  270. data/platform/wm/rhodes/rho/rubyext/NativeToolbar.cpp +6 -1
  271. data/platform/wm/rhodes/rho/rubyext/SystemImpl.cpp +84 -19
  272. data/platform/wm/rhodes/rho/rubyext/calendar.cpp +2 -2
  273. data/platform/wm/rhodes/rhodes.vcproj +316 -73
  274. data/platform/wm/rhodes/signature/Signature.cpp +336 -6
  275. data/platform/wm/rhodes/signature/Signature.h +55 -0
  276. data/platform/wm/rhodes/stdafx.h +7 -4
  277. data/platform/wm/rubylib/rubylib.vcproj +261 -91
  278. data/platform/wm/sqlite3/sqlite3.vcproj +223 -69
  279. data/platform/wm/syncengine/syncengine.vcproj +220 -66
  280. data/platform/wm/tcmalloc/tcmalloc.vcproj +197 -43
  281. data/platform/wp7/IronRuby/Languages/Ruby/Ruby/Builtins/ConsoleStream.cs +107 -0
  282. data/platform/wp7/IronRuby/Languages/Ruby/Ruby/Runtime/Loader.cs +1037 -0
  283. data/platform/wp7/IronRuby/Languages/Ruby/Ruby/Runtime/RubyUtils.cs +1476 -0
  284. data/platform/wp7/RhoAppRunner/Program.cs +55 -0
  285. data/platform/wp7/RhoAppRunner/Properties/AssemblyInfo.cs +36 -0
  286. data/platform/wp7/RhoAppRunner/RhoAppRunner.csproj +69 -0
  287. data/platform/wp7/RhoRubyExtGen/GenerateInitializers.cmd +7 -0
  288. data/platform/wp7/RhoRubyExtGen/Properties/AssemblyInfo.cs +36 -0
  289. data/platform/wp7/RhoRubyExtGen/RhoAsyncHttp.cs +38 -0
  290. data/platform/wp7/RhoRubyExtGen/RhoDatabase.cs +93 -0
  291. data/platform/wp7/RhoRubyExtGen/RhoJSON.cs +37 -0
  292. data/platform/wp7/RhoRubyExtGen/RhoNativeBar.cs +106 -0
  293. data/platform/wp7/RhoRubyExtGen/RhoRubyExtGen.csproj +75 -0
  294. data/platform/wp7/RhoRubyExtGen/RhoSyncEngine.cs +123 -0
  295. data/platform/wp7/RhoRubyExtGen/RhoWebView.cs +42 -0
  296. data/platform/wp7/RhoRubyLib/Initializers.Generated.cs +309 -0
  297. data/platform/wp7/RhoRubyLib/Properties/AssemblyInfo.cs +36 -0
  298. data/platform/wp7/RhoRubyLib/RhoAppAdapter.cs +96 -0
  299. data/platform/wp7/RhoRubyLib/RhoRuby.cs +296 -0
  300. data/platform/wp7/RhoRubyLib/RhoRubyLib.csproj +155 -0
  301. data/platform/wp7/RhoRubyLib/WP_PlatformAdaptationLayer.cs +107 -0
  302. data/platform/wp7/RhoRubyLib/common/IInputStream.cs +21 -0
  303. data/platform/wp7/RhoRubyLib/common/Mutex.cs +30 -0
  304. data/platform/wp7/RhoRubyLib/common/RhoConf.cs +389 -0
  305. data/platform/wp7/RhoRubyLib/common/RhoEmptyProfiler.cs +27 -0
  306. data/platform/wp7/RhoRubyLib/common/RhoFile.cs +332 -0
  307. data/platform/wp7/RhoRubyLib/common/RhoFilePath.cs +89 -0
  308. data/platform/wp7/RhoRubyLib/common/RhoParamArray.cs +33 -0
  309. data/platform/wp7/RhoRubyLib/common/RhoParams.cs +66 -0
  310. data/platform/wp7/RhoRubyLib/common/RhoProfiler.cs +145 -0
  311. data/platform/wp7/RhoRubyLib/common/RhoResourceMap.cs +68 -0
  312. data/platform/wp7/RhoRubyLib/common/RhoStd.cs +205 -0
  313. data/platform/wp7/RhoRubyLib/common/RhoThread.cs +114 -0
  314. data/platform/wp7/RhoRubyLib/common/RhodesApp.cs +504 -0
  315. data/platform/wp7/RhoRubyLib/common/ThreadQueue.cs +199 -0
  316. data/platform/wp7/RhoRubyLib/common/TimeInterval.cs +56 -0
  317. data/platform/wp7/RhoRubyLib/common/Tokenizer.cs +52 -0
  318. data/platform/wp7/RhoRubyLib/db/DBAdapter.cs +1129 -0
  319. data/platform/wp7/RhoRubyLib/db/DBAttrManager.cs +92 -0
  320. data/platform/wp7/RhoRubyLib/db/DBException.cs +35 -0
  321. data/platform/wp7/RhoRubyLib/db/IDBCallback.cs +10 -0
  322. data/platform/wp7/RhoRubyLib/db/IDBResult.cs +33 -0
  323. data/platform/wp7/RhoRubyLib/db/IDBStorage.cs +32 -0
  324. data/platform/wp7/RhoRubyLib/db/SqliteCopyResult.cs +79 -0
  325. data/platform/wp7/RhoRubyLib/db/SqliteResult.cs +267 -0
  326. data/platform/wp7/RhoRubyLib/db/SqliteStorage.cs +319 -0
  327. data/platform/wp7/RhoRubyLib/json/JSONArrayIterator.cs +63 -0
  328. data/platform/wp7/RhoRubyLib/json/JSONEntry.cs +96 -0
  329. data/platform/wp7/RhoRubyLib/json/JSONStructIterator.cs +77 -0
  330. data/platform/wp7/RhoRubyLib/json/JsonParser.cs +483 -0
  331. data/platform/wp7/RhoRubyLib/json/RJSONTokener.cs +406 -0
  332. data/platform/wp7/RhoRubyLib/logging/IRhoLogSink.cs +12 -0
  333. data/platform/wp7/RhoRubyLib/logging/RhoLogConf.cs +161 -0
  334. data/platform/wp7/RhoRubyLib/logging/RhoLogFileSink.cs +174 -0
  335. data/platform/wp7/RhoRubyLib/logging/RhoLogger.cs +320 -0
  336. data/platform/wp7/RhoRubyLib/net/AsyncHttp.cs +362 -0
  337. data/platform/wp7/RhoRubyLib/net/HttpServer.cs +466 -0
  338. data/platform/wp7/RhoRubyLib/net/NetRequest.cs +717 -0
  339. data/platform/wp7/RhoRubyLib/net/NetResponse.cs +64 -0
  340. data/platform/wp7/RhoRubyLib/net/URI.cs +187 -0
  341. data/platform/wp7/RhoRubyLib/rubyext/RhoAsyncHttp.cs +43 -0
  342. data/platform/wp7/RhoRubyLib/rubyext/RhoDatabase.cs +177 -0
  343. data/platform/wp7/RhoRubyLib/rubyext/RhoJSON.cs +39 -0
  344. data/platform/wp7/RhoRubyLib/rubyext/RhoKernelOps.cs +19 -0
  345. data/platform/wp7/RhoRubyLib/rubyext/RhoNativeBar.cs +117 -0
  346. data/platform/wp7/RhoRubyLib/rubyext/RhoSyncEngine.cs +199 -0
  347. data/platform/wp7/RhoRubyLib/rubyext/RhoWebView.cs +49 -0
  348. data/platform/wp7/RhoRubyLib/sync/ClientRegister.cs +142 -0
  349. data/platform/wp7/RhoRubyLib/sync/ISyncProtocol.cs +23 -0
  350. data/platform/wp7/RhoRubyLib/sync/ISyncStatusListener.cs +10 -0
  351. data/platform/wp7/RhoRubyLib/sync/SyncEngine.cs +1051 -0
  352. data/platform/wp7/RhoRubyLib/sync/SyncNotify.cs +651 -0
  353. data/platform/wp7/RhoRubyLib/sync/SyncProtocol_3.cs +79 -0
  354. data/platform/wp7/RhoRubyLib/sync/SyncSource.cs +1105 -0
  355. data/platform/wp7/RhoRubyLib/sync/SyncThread.cs +301 -0
  356. data/platform/wp7/WPApplication.sln +50 -0
  357. data/platform/wp7/WPApplication/App.xaml +19 -0
  358. data/platform/wp7/WPApplication/App.xaml.cs +211 -0
  359. data/platform/wp7/WPApplication/ApplicationIcon.png +0 -0
  360. data/platform/wp7/WPApplication/Background.png +0 -0
  361. data/platform/wp7/WPApplication/MainPage.xaml +44 -0
  362. data/platform/wp7/WPApplication/MainPage.xaml.cs +132 -0
  363. data/platform/wp7/WPApplication/Properties/AppManifest.xml +6 -0
  364. data/platform/wp7/WPApplication/Properties/AssemblyInfo.cs +35 -0
  365. data/platform/wp7/WPApplication/Properties/WMAppManifest.xml +32 -0
  366. data/platform/wp7/WPApplication/SplashScreenImage.jpg +0 -0
  367. data/platform/wp7/WPApplication/WPApplication.csproj +201 -0
  368. data/platform/wp7/WPApplication/WP_PlatformAdaptationLayer.cs +88 -0
  369. data/platform/wp7/WPApplication/app_manifest.txt +1 -0
  370. data/platform/wp7/WPApplication/readme.htm +40 -0
  371. data/platform/wp7/WPApplication/readme2.htm +37 -0
  372. data/platform/wp7/WPApplication/rho/apps/app/Model1/edit.bb.erb +29 -0
  373. data/platform/wp7/WPApplication/rho/apps/app/Model1/edit.erb +32 -0
  374. data/platform/wp7/WPApplication/rho/apps/app/Model1/index.bb.erb +21 -0
  375. data/platform/wp7/WPApplication/rho/apps/app/Model1/index.erb +26 -0
  376. data/platform/wp7/WPApplication/rho/apps/app/Model1/model1.rb +10 -0
  377. data/platform/wp7/WPApplication/rho/apps/app/Model1/model1_controller.rb +58 -0
  378. data/platform/wp7/WPApplication/rho/apps/app/Model1/new.bb.erb +29 -0
  379. data/platform/wp7/WPApplication/rho/apps/app/Model1/new.erb +31 -0
  380. data/platform/wp7/WPApplication/rho/apps/app/Model1/show.bb.erb +26 -0
  381. data/platform/wp7/WPApplication/rho/apps/app/Model1/show.erb +28 -0
  382. data/platform/wp7/WPApplication/rho/apps/app/Settings/controller.rb +75 -0
  383. data/platform/wp7/WPApplication/rho/apps/app/Settings/home.bb.erb +17 -0
  384. data/platform/wp7/WPApplication/rho/apps/app/Settings/home.erb +20 -0
  385. data/platform/wp7/WPApplication/rho/apps/app/Settings/index.bb.erb +32 -0
  386. data/platform/wp7/WPApplication/rho/apps/app/Settings/index.erb +30 -0
  387. data/platform/wp7/WPApplication/rho/apps/app/Settings/login.bb.erb +35 -0
  388. data/platform/wp7/WPApplication/rho/apps/app/Settings/login.erb +27 -0
  389. data/platform/wp7/WPApplication/rho/apps/app/Settings/reset.bb.erb +15 -0
  390. data/platform/wp7/WPApplication/rho/apps/app/Settings/reset.erb +17 -0
  391. data/platform/wp7/WPApplication/rho/apps/app/Settings/wait.bb.erb +3 -0
  392. data/platform/wp7/WPApplication/rho/apps/app/Settings/wait.erb +5 -0
  393. data/platform/wp7/WPApplication/rho/apps/app/application.rb +16 -0
  394. data/platform/wp7/WPApplication/rho/apps/app/helpers/application_helper.rb +126 -0
  395. data/platform/wp7/WPApplication/rho/apps/app/helpers/browser_helper.rb +18 -0
  396. data/platform/wp7/WPApplication/rho/apps/app/index.bb.erb +26 -0
  397. data/platform/wp7/WPApplication/rho/apps/app/index.erb +26 -0
  398. data/platform/wp7/WPApplication/rho/apps/app/layout.erb +45 -0
  399. data/platform/wp7/WPApplication/rho/apps/app/loading.html +11 -0
  400. data/platform/wp7/WPApplication/rho/apps/app_manifest.txt +1 -0
  401. data/platform/wp7/WPApplication/rho/apps/public/css/android.css +330 -0
  402. data/platform/wp7/WPApplication/rho/apps/public/css/blackberry.css +115 -0
  403. data/platform/wp7/WPApplication/rho/apps/public/css/iphone.css +410 -0
  404. data/platform/wp7/WPApplication/rho/apps/public/css/windows_mobile.css +222 -0
  405. data/platform/wp7/WPApplication/rho/apps/public/images/IUI_LICENSE.txt +21 -0
  406. data/platform/wp7/WPApplication/rho/apps/public/images/android/btn_check_off.png +0 -0
  407. data/platform/wp7/WPApplication/rho/apps/public/images/android/btn_check_on.png +0 -0
  408. data/platform/wp7/WPApplication/rho/apps/public/images/android/btn_radio_off.png +0 -0
  409. data/platform/wp7/WPApplication/rho/apps/public/images/android/btn_radio_on.png +0 -0
  410. data/platform/wp7/WPApplication/rho/apps/public/images/android/disclosure.png +0 -0
  411. data/platform/wp7/WPApplication/rho/apps/public/images/android/ic_menu_more.png +0 -0
  412. data/platform/wp7/WPApplication/rho/apps/public/images/backButton.png +0 -0
  413. data/platform/wp7/WPApplication/rho/apps/public/images/blueButton.png +0 -0
  414. data/platform/wp7/WPApplication/rho/apps/public/images/cancel.png +0 -0
  415. data/platform/wp7/WPApplication/rho/apps/public/images/grayButton.png +0 -0
  416. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/disclosure.png +0 -0
  417. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/disclosure_detail.png +0 -0
  418. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/backButton.png +0 -0
  419. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/blueButton.png +0 -0
  420. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/cancel.png +0 -0
  421. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/chevron.png +0 -0
  422. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/grayButton.png +0 -0
  423. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/listArrowSel.png +0 -0
  424. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/listGroup.png +0 -0
  425. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/loading.gif +0 -0
  426. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/on_off.png +0 -0
  427. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/pinstripes.png +0 -0
  428. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/selection.png +0 -0
  429. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/thumb.png +0 -0
  430. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/toggle.png +0 -0
  431. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/toggleOn.png +0 -0
  432. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/toolButton.png +0 -0
  433. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/toolbar.png +0 -0
  434. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/jqtouch/whiteButton.png +0 -0
  435. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/radiobutton.png +0 -0
  436. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/select.png +0 -0
  437. data/platform/wp7/WPApplication/rho/apps/public/images/iphone/switch.png +0 -0
  438. data/platform/wp7/WPApplication/rho/apps/public/images/iui-logo-touch-icon.png +0 -0
  439. data/platform/wp7/WPApplication/rho/apps/public/images/listArrow.png +0 -0
  440. data/platform/wp7/WPApplication/rho/apps/public/images/listArrowDown.png +0 -0
  441. data/platform/wp7/WPApplication/rho/apps/public/images/listArrowSel.png +0 -0
  442. data/platform/wp7/WPApplication/rho/apps/public/images/listGroup.png +0 -0
  443. data/platform/wp7/WPApplication/rho/apps/public/images/loading.gif +0 -0
  444. data/platform/wp7/WPApplication/rho/apps/public/images/pinstripes.png +0 -0
  445. data/platform/wp7/WPApplication/rho/apps/public/images/right_button.png +0 -0
  446. data/platform/wp7/WPApplication/rho/apps/public/images/selection.png +0 -0
  447. data/platform/wp7/WPApplication/rho/apps/public/images/thumb.png +0 -0
  448. data/platform/wp7/WPApplication/rho/apps/public/images/toggle.png +0 -0
  449. data/platform/wp7/WPApplication/rho/apps/public/images/toggleOn.png +0 -0
  450. data/platform/wp7/WPApplication/rho/apps/public/images/toolButton.png +0 -0
  451. data/platform/wp7/WPApplication/rho/apps/public/images/toolButton_new.png +0 -0
  452. data/platform/wp7/WPApplication/rho/apps/public/images/toolbar.png +0 -0
  453. data/platform/wp7/WPApplication/rho/apps/public/images/whiteButton.png +0 -0
  454. data/platform/wp7/WPApplication/rho/apps/public/jqtouch/jqtouch-iphone.css +9 -0
  455. data/platform/wp7/WPApplication/rho/apps/public/jqtouch/jqtouch.css +374 -0
  456. data/platform/wp7/WPApplication/rho/apps/public/jqtouch/jqtouch.js +742 -0
  457. data/platform/wp7/WPApplication/rho/apps/public/jqtouch/jqtouch.transitions.js +60 -0
  458. data/platform/wp7/WPApplication/rho/apps/public/jqtouch/jquery.1.3.2.min.js +19 -0
  459. data/platform/wp7/WPApplication/rho/apps/public/js/application.js +1 -0
  460. data/platform/wp7/WPApplication/rho/apps/public/js/rho.js +4 -0
  461. data/platform/wp7/WPApplication/rho/apps/public/js/rhogeolocation-wm.js +59 -0
  462. data/platform/wp7/WPApplication/rho/apps/public/js/rhogeolocation.js +11 -0
  463. data/platform/wp7/WPApplication/rho/apps/rhoconfig.txt +32 -0
  464. data/platform/wp7/WPApplication/rhoconfig.txt +32 -0
  465. data/platform/wp7/WPApplication/windows_mobile.css +222 -0
  466. data/platform/wp7/build/wp.rake +261 -0
  467. data/platform/wp7/rhodes.sln +79 -0
  468. data/platform/wp7/rhodes/App.xaml +19 -0
  469. data/platform/wp7/rhodes/App.xaml.cs +144 -0
  470. data/platform/wp7/rhodes/Background.png +0 -0
  471. data/platform/wp7/rhodes/MainPage.xaml +44 -0
  472. data/platform/wp7/rhodes/MainPage.xaml.cs +98 -0
  473. data/platform/wp7/rhodes/Properties/AppManifest.xml +6 -0
  474. data/platform/wp7/rhodes/Properties/AssemblyInfo.cs +35 -0
  475. data/platform/wp7/rhodes/Properties/WMAppManifest.xml +31 -0
  476. data/platform/wp7/rhodes/Rhodes.csproj +127 -0
  477. data/platform/wp7/rhodes/SplashScreenImage.jpg +0 -0
  478. data/platform/wp7/rhodes/icon.png +0 -0
  479. data/platform/wp7/sqlite3/Properties/AssemblyInfo.cs +35 -0
  480. data/platform/wp7/sqlite3/SQLiteClient.cs +550 -0
  481. data/platform/wp7/sqlite3/SqliteWrapper/BtreeInt_h.cs +774 -0
  482. data/platform/wp7/sqlite3/SqliteWrapper/Btree_h.cs +280 -0
  483. data/platform/wp7/sqlite3/SqliteWrapper/ClassDiagram1.cd +1306 -0
  484. data/platform/wp7/sqlite3/SqliteWrapper/Delagates.cs +365 -0
  485. data/platform/wp7/sqlite3/SqliteWrapper/Hash_h.cs +133 -0
  486. data/platform/wp7/sqlite3/SqliteWrapper/VdbeInt_h.cs +620 -0
  487. data/platform/wp7/sqlite3/SqliteWrapper/Vdbe_h.cs +302 -0
  488. data/platform/wp7/sqlite3/SqliteWrapper/_Custom.cs +449 -0
  489. data/platform/wp7/sqlite3/SqliteWrapper/alter_c.cs +872 -0
  490. data/platform/wp7/sqlite3/SqliteWrapper/analyze_c.cs +757 -0
  491. data/platform/wp7/sqlite3/SqliteWrapper/attach_c.cs +628 -0
  492. data/platform/wp7/sqlite3/SqliteWrapper/auth_c.cs +268 -0
  493. data/platform/wp7/sqlite3/SqliteWrapper/backup_c.cs +737 -0
  494. data/platform/wp7/sqlite3/SqliteWrapper/bitvec_c.cs +509 -0
  495. data/platform/wp7/sqlite3/SqliteWrapper/btmutex_c.cs +379 -0
  496. data/platform/wp7/sqlite3/SqliteWrapper/btree_c.cs +9138 -0
  497. data/platform/wp7/sqlite3/SqliteWrapper/build_c.cs +4189 -0
  498. data/platform/wp7/sqlite3/SqliteWrapper/callback_c.cs +548 -0
  499. data/platform/wp7/sqlite3/SqliteWrapper/complete_c.cs +342 -0
  500. data/platform/wp7/sqlite3/SqliteWrapper/ctime_cs.cs +408 -0
  501. data/platform/wp7/sqlite3/SqliteWrapper/date_c.cs +1317 -0
  502. data/platform/wp7/sqlite3/SqliteWrapper/delete_c.cs +726 -0
  503. data/platform/wp7/sqlite3/SqliteWrapper/expr_c.cs +4406 -0
  504. data/platform/wp7/sqlite3/SqliteWrapper/fault_c.cs +115 -0
  505. data/platform/wp7/sqlite3/SqliteWrapper/fkey_c.cs +1330 -0
  506. data/platform/wp7/sqlite3/SqliteWrapper/func_c.cs +2025 -0
  507. data/platform/wp7/sqlite3/SqliteWrapper/global_c.cs +228 -0
  508. data/platform/wp7/sqlite3/SqliteWrapper/hash_c.cs +351 -0
  509. data/platform/wp7/sqlite3/SqliteWrapper/hwtime_c.cs +101 -0
  510. data/platform/wp7/sqlite3/SqliteWrapper/insert_c.cs +2122 -0
  511. data/platform/wp7/sqlite3/SqliteWrapper/journal_c.cs +247 -0
  512. data/platform/wp7/sqlite3/SqliteWrapper/keywordhash_h.cs +302 -0
  513. data/platform/wp7/sqlite3/SqliteWrapper/legacy_c.cs +223 -0
  514. data/platform/wp7/sqlite3/SqliteWrapper/loadext_c.cs +683 -0
  515. data/platform/wp7/sqlite3/SqliteWrapper/main_c.cs +2716 -0
  516. data/platform/wp7/sqlite3/SqliteWrapper/malloc_c.cs +977 -0
  517. data/platform/wp7/sqlite3/SqliteWrapper/mem_Pool.cs +394 -0
  518. data/platform/wp7/sqlite3/SqliteWrapper/memjournal_c.cs +315 -0
  519. data/platform/wp7/sqlite3/SqliteWrapper/mutex_c.cs +182 -0
  520. data/platform/wp7/sqlite3/SqliteWrapper/mutex_h.cs +91 -0
  521. data/platform/wp7/sqlite3/SqliteWrapper/mutex_noop_c.cs +202 -0
  522. data/platform/wp7/sqlite3/SqliteWrapper/mutex_w32.cs +344 -0
  523. data/platform/wp7/sqlite3/SqliteWrapper/notify_c.cs +347 -0
  524. data/platform/wp7/sqlite3/SqliteWrapper/opcodes_c.cs +171 -0
  525. data/platform/wp7/sqlite3/SqliteWrapper/opcodes_h.cs +346 -0
  526. data/platform/wp7/sqlite3/SqliteWrapper/os_c.cs +367 -0
  527. data/platform/wp7/sqlite3/SqliteWrapper/os_common_h.cs +174 -0
  528. data/platform/wp7/sqlite3/SqliteWrapper/os_h.cs +295 -0
  529. data/platform/wp7/sqlite3/SqliteWrapper/os_win_c.cs +1255 -0
  530. data/platform/wp7/sqlite3/SqliteWrapper/pager_c.cs +6078 -0
  531. data/platform/wp7/sqlite3/SqliteWrapper/pager_h.cs +188 -0
  532. data/platform/wp7/sqlite3/SqliteWrapper/parse_c.cs +4045 -0
  533. data/platform/wp7/sqlite3/SqliteWrapper/parse_h.cs +331 -0
  534. data/platform/wp7/sqlite3/SqliteWrapper/pcache1_c.cs +969 -0
  535. data/platform/wp7/sqlite3/SqliteWrapper/pcache_c.cs +712 -0
  536. data/platform/wp7/sqlite3/SqliteWrapper/pcache_h.cs +213 -0
  537. data/platform/wp7/sqlite3/SqliteWrapper/pragma_c.cs +1767 -0
  538. data/platform/wp7/sqlite3/SqliteWrapper/prepare_c.cs +1015 -0
  539. data/platform/wp7/sqlite3/SqliteWrapper/printf_c.cs +1300 -0
  540. data/platform/wp7/sqlite3/SqliteWrapper/random_c.cs +201 -0
  541. data/platform/wp7/sqlite3/SqliteWrapper/resolve_c.cs +1396 -0
  542. data/platform/wp7/sqlite3/SqliteWrapper/rowset_c.cs +519 -0
  543. data/platform/wp7/sqlite3/SqliteWrapper/select_c.cs +4878 -0
  544. data/platform/wp7/sqlite3/SqliteWrapper/sqlite3_h.cs +6253 -0
  545. data/platform/wp7/sqlite3/SqliteWrapper/sqlite3ext_h.cs +397 -0
  546. data/platform/wp7/sqlite3/SqliteWrapper/sqliteInt_h.cs +4075 -0
  547. data/platform/wp7/sqlite3/SqliteWrapper/sqliteLimit_h.cs +214 -0
  548. data/platform/wp7/sqlite3/SqliteWrapper/sqliteicu_h.cs +39 -0
  549. data/platform/wp7/sqlite3/SqliteWrapper/status_c.cs +155 -0
  550. data/platform/wp7/sqlite3/SqliteWrapper/table_c.cs +222 -0
  551. data/platform/wp7/sqlite3/SqliteWrapper/tokenize_c.cs +673 -0
  552. data/platform/wp7/sqlite3/SqliteWrapper/trigger_c.cs +1219 -0
  553. data/platform/wp7/sqlite3/SqliteWrapper/update_c.cs +766 -0
  554. data/platform/wp7/sqlite3/SqliteWrapper/utf_c.cs +612 -0
  555. data/platform/wp7/sqlite3/SqliteWrapper/util_c.cs +1476 -0
  556. data/platform/wp7/sqlite3/SqliteWrapper/vacuum_c.cs +382 -0
  557. data/platform/wp7/sqlite3/SqliteWrapper/vdbe_c.cs +6566 -0
  558. data/platform/wp7/sqlite3/SqliteWrapper/vdbeapi_c.cs +1557 -0
  559. data/platform/wp7/sqlite3/SqliteWrapper/vdbeaux_c.cs +4019 -0
  560. data/platform/wp7/sqlite3/SqliteWrapper/vdbeblob_c.cs +396 -0
  561. data/platform/wp7/sqlite3/SqliteWrapper/vdbemem_c.cs +1480 -0
  562. data/platform/wp7/sqlite3/SqliteWrapper/vdbetrace_c.cs +181 -0
  563. data/platform/wp7/sqlite3/SqliteWrapper/vtab_c.cs +957 -0
  564. data/platform/wp7/sqlite3/SqliteWrapper/walker_c.cs +174 -0
  565. data/platform/wp7/sqlite3/SqliteWrapper/where_c.cs +4651 -0
  566. data/platform/wp7/sqlite3/sqlite3.csproj +155 -0
  567. data/rakefile.rb +60 -2
  568. data/res/build-tools/7za.exe +0 -0
  569. data/res/build-tools/RhoAppRunner.exe +0 -0
  570. data/res/build-tools/xruby-0.3.3.jar +0 -0
  571. data/res/generators/rhogen.rb +9 -1
  572. data/res/generators/templates/application/app/Settings/reset.erb +1 -1
  573. data/res/generators/templates/application/app/layout.erb +17 -10
  574. data/res/generators/templates/application/build.yml +5 -3
  575. data/res/generators/templates/application/public/jqtouch/changes.txt +20 -0
  576. data/res/generators/templates/application/public/jqtouch/jqtouch.js +12 -4
  577. data/res/generators/templates/application/public/jqtouch/jquery.1.3.2.min.js +1 -1
  578. data/res/generators/templates/application/public/js/wp7.js +7 -0
  579. data/res/generators/templates/model/controller.rb +5 -6
  580. data/rhobuild.yml.example +1 -0
  581. data/rhodes.gemspec +2 -1
  582. data/spec/framework_spec/app/spec/core/dir/close_spec.rb +1 -1
  583. data/spec/framework_spec/app/spec/core/dir/shared/pwd.rb +13 -11
  584. data/spec/framework_spec/app/spec/core/env/shared/store.rb +12 -10
  585. data/spec/framework_spec/app/spec/core/env/update_spec.rb +1 -0
  586. data/spec/framework_spec/app/spec/core/file/expand_path_spec.rb +3 -2
  587. data/spec/framework_spec/app/spec/core/file/fixtures/file_types.rb +7 -1
  588. data/spec/framework_spec/app/spec/core/file/flock_spec.rb +8 -1
  589. data/spec/framework_spec/app/spec/core/file/ftype_spec.rb +5 -3
  590. data/spec/framework_spec/app/spec/core/file/lchmod_spec.rb +1 -1
  591. data/spec/framework_spec/app/spec/core/file/setgid_spec.rb +1 -1
  592. data/spec/framework_spec/app/spec/core/file/setuid_spec.rb +1 -1
  593. data/spec/framework_spec/app/spec/core/file/stat/ftype_spec.rb +6 -4
  594. data/spec/framework_spec/app/spec/core/file/truncate_spec.rb +5 -1
  595. data/spec/framework_spec/app/spec/core/float/to_s_spec.rb +1 -1
  596. data/spec/framework_spec/app/spec/core/process/gid_spec.rb +5 -3
  597. data/spec/framework_spec/app/spec/core/process/groups_spec.rb +11 -9
  598. data/spec/framework_spec/app/spec/core/process/uid_spec.rb +5 -3
  599. data/spec/framework_spec/app/spec/language/execution_spec.rb +10 -6
  600. data/spec/framework_spec/app/spec/shared/file/directory.rb +6 -1
  601. data/spec/framework_spec/app/spec/shared/file/executable.rb +7 -1
  602. data/spec/framework_spec/app/spec/shared/file/file.rb +6 -1
  603. data/spec/framework_spec/app/spec/shared/file/readable.rb +13 -4
  604. data/spec/framework_spec/app/spec/shared/file/writable.rb +6 -1
  605. data/spec/phone_spec/app/spec/rho_controller_spec.rb +11 -0
  606. data/spec/phone_spec/app/spec/rho_spec.rb +11 -0
  607. data/spec/phone_spec/app/spec/rhom_object_spec.rb +102 -6
  608. data/spec/phone_spec/app/spec/string/end_with_spec.rb +4 -1
  609. data/spec/phone_spec/app/spec/string/slice_spec.rb +5 -1
  610. data/spec/phone_spec/app/spec/string/start_with_spec.rb +4 -0
  611. data/spec/phone_spec/app/spec/syncengine_spec.rb +73 -6
  612. data/spec/phone_spec/app/spec_runner.rb +7 -3
  613. metadata +380 -41
  614. data/Manifest.txt +0 -5819
  615. data/platform/bb/Hsqldb/Hsqldb.cso +0 -5
  616. data/platform/bb/Hsqldb/Hsqldb.jdp +0 -197
  617. data/platform/bb/RhoBundle/RhoBundle.cso +0 -5
  618. data/platform/bb/RhoBundle/RhoBundle.jdp +0 -42
  619. data/platform/bb/RubyVM/RubyVM.cso +0 -5
  620. data/platform/bb/RubyVM/RubyVM.jdp +0 -467
  621. data/platform/bb/rhodes/rhodes.csl +0 -3
  622. data/platform/bb/rhodes/rhodes.cso +0 -5
  623. data/platform/bb/rhodes/rhodes.jdp +0 -104
@@ -0,0 +1,174 @@
1
+ using System;
2
+ using System.Diagnostics;
3
+ using System.Text;
4
+
5
+ using Bitmask = System.UInt64;
6
+ using u32 = System.UInt32;
7
+
8
+ namespace Community.CsharpSqlite
9
+ {
10
+ public partial class Sqlite3
11
+ {
12
+ /*
13
+ ** 2008 August 16
14
+ **
15
+ ** The author disclaims copyright to this source code. In place of
16
+ ** a legal notice, here is a blessing:
17
+ **
18
+ ** May you do good and not evil.
19
+ ** May you find forgiveness for yourself and forgive others.
20
+ ** May you share freely, never taking more than you give.
21
+ **
22
+ *************************************************************************
23
+ ** This file contains routines used for walking the parser tree for
24
+ ** an SQL statement.
25
+ *************************************************************************
26
+ ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
27
+ ** C#-SQLite is an independent reimplementation of the SQLite software library
28
+ **
29
+ ** SQLITE_SOURCE_ID: 2009-12-07 16:39:13 1ed88e9d01e9eda5cbc622e7614277f29bcc551c
30
+ **
31
+ ** $Header$
32
+ *************************************************************************
33
+ */
34
+ //#include "sqliteInt.h"
35
+ //#include <stdlib.h>
36
+ //#include <string.h>
37
+
38
+
39
+ /*
40
+ ** Walk an expression tree. Invoke the callback once for each node
41
+ ** of the expression, while decending. (In other words, the callback
42
+ ** is invoked before visiting children.)
43
+ **
44
+ ** The return value from the callback should be one of the WRC_*
45
+ ** constants to specify how to proceed with the walk.
46
+ **
47
+ ** WRC_Continue Continue descending down the tree.
48
+ **
49
+ ** WRC_Prune Do not descend into child nodes. But allow
50
+ ** the walk to continue with sibling nodes.
51
+ **
52
+ ** WRC_Abort Do no more callbacks. Unwind the stack and
53
+ ** return the top-level walk call.
54
+ **
55
+ ** The return value from this routine is WRC_Abort to abandon the tree walk
56
+ ** and WRC_Continue to continue.
57
+ */
58
+ static int sqlite3WalkExpr( Walker pWalker, ref Expr pExpr )
59
+ {
60
+ int rc;
61
+ if ( pExpr == null ) return WRC_Continue;
62
+ testcase( ExprHasProperty( pExpr, EP_TokenOnly ) );
63
+ testcase( ExprHasProperty( pExpr, EP_Reduced ) );
64
+ rc = pWalker.xExprCallback( pWalker, ref pExpr );
65
+ if ( rc == WRC_Continue
66
+ && !ExprHasAnyProperty( pExpr, EP_TokenOnly ) )
67
+ {
68
+ if ( sqlite3WalkExpr( pWalker, ref pExpr.pLeft ) != 0 ) return WRC_Abort;
69
+ if ( sqlite3WalkExpr( pWalker, ref pExpr.pRight ) != 0 ) return WRC_Abort;
70
+ if ( ExprHasProperty( pExpr, EP_xIsSelect ) )
71
+ {
72
+ if ( sqlite3WalkSelect( pWalker, pExpr.x.pSelect ) != 0 ) return WRC_Abort;
73
+ }
74
+ else
75
+ {
76
+ if ( sqlite3WalkExprList( pWalker, pExpr.x.pList ) != 0 ) return WRC_Abort;
77
+ }
78
+ }
79
+ return rc & WRC_Abort;
80
+ }
81
+
82
+ /*
83
+ ** Call sqlite3WalkExpr() for every expression in list p or until
84
+ ** an abort request is seen.
85
+ */
86
+ static int sqlite3WalkExprList( Walker pWalker, ExprList p )
87
+ {
88
+ int i;
89
+ ExprList_item pItem;
90
+ if ( p != null )
91
+ {
92
+ for ( i = p.nExpr; i > 0; i-- )
93
+ {//, pItem++){
94
+ pItem = p.a[p.nExpr - i];
95
+ if ( sqlite3WalkExpr( pWalker, ref pItem.pExpr ) != 0 ) return WRC_Abort;
96
+ }
97
+ }
98
+ return WRC_Continue;
99
+ }
100
+
101
+ /*
102
+ ** Walk all expressions associated with SELECT statement p. Do
103
+ ** not invoke the SELECT callback on p, but do (of course) invoke
104
+ ** any expr callbacks and SELECT callbacks that come from subqueries.
105
+ ** Return WRC_Abort or WRC_Continue.
106
+ */
107
+ static int sqlite3WalkSelectExpr( Walker pWalker, Select p )
108
+ {
109
+ if ( sqlite3WalkExprList( pWalker, p.pEList ) != 0 ) return WRC_Abort;
110
+ if ( sqlite3WalkExpr( pWalker, ref p.pWhere ) != 0 ) return WRC_Abort;
111
+ if ( sqlite3WalkExprList( pWalker, p.pGroupBy ) != 0 ) return WRC_Abort;
112
+ if ( sqlite3WalkExpr( pWalker, ref p.pHaving ) != 0 ) return WRC_Abort;
113
+ if ( sqlite3WalkExprList( pWalker, p.pOrderBy ) != 0 ) return WRC_Abort;
114
+ if ( sqlite3WalkExpr( pWalker, ref p.pLimit ) != 0 ) return WRC_Abort;
115
+ if ( sqlite3WalkExpr( pWalker, ref p.pOffset ) != 0 ) return WRC_Abort;
116
+ return WRC_Continue;
117
+ }
118
+
119
+ /*
120
+ ** Walk the parse trees associated with all subqueries in the
121
+ ** FROM clause of SELECT statement p. Do not invoke the select
122
+ ** callback on p, but do invoke it on each FROM clause subquery
123
+ ** and on any subqueries further down in the tree. Return
124
+ ** WRC_Abort or WRC_Continue;
125
+ */
126
+ static int sqlite3WalkSelectFrom( Walker pWalker, Select p )
127
+ {
128
+ SrcList pSrc;
129
+ int i;
130
+ SrcList_item pItem;
131
+
132
+ pSrc = p.pSrc;
133
+ if ( ALWAYS( pSrc ) )
134
+ {
135
+ for ( i = pSrc.nSrc; i > 0; i-- )// pItem++ )
136
+ {
137
+ pItem = pSrc.a[pSrc.nSrc - i];
138
+ if ( sqlite3WalkSelect( pWalker, pItem.pSelect ) != 0 )
139
+ {
140
+ return WRC_Abort;
141
+ }
142
+ }
143
+ }
144
+ return WRC_Continue;
145
+ }
146
+
147
+ /*
148
+ ** Call sqlite3WalkExpr() for every expression in Select statement p.
149
+ ** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
150
+ ** on the compound select chain, p.pPrior.
151
+ **
152
+ ** Return WRC_Continue under normal conditions. Return WRC_Abort if
153
+ ** there is an abort request.
154
+ **
155
+ ** If the Walker does not have an xSelectCallback() then this routine
156
+ ** is a no-op returning WRC_Continue.
157
+ */
158
+ static int sqlite3WalkSelect( Walker pWalker, Select p )
159
+ {
160
+ int rc;
161
+ if ( p == null || pWalker.xSelectCallback == null ) return WRC_Continue;
162
+ rc = WRC_Continue;
163
+ while ( p != null )
164
+ {
165
+ rc = pWalker.xSelectCallback( pWalker, p );
166
+ if ( rc != 0 ) break;
167
+ if ( sqlite3WalkSelectExpr( pWalker, p ) != 0 ) return WRC_Abort;
168
+ if ( sqlite3WalkSelectFrom( pWalker, p ) != 0 ) return WRC_Abort;
169
+ p = p.pPrior;
170
+ }
171
+ return rc & WRC_Abort;
172
+ }
173
+ }
174
+ }
@@ -0,0 +1,4651 @@
1
+ using System;
2
+ using System.Diagnostics;
3
+ using System.Text;
4
+
5
+ using Bitmask = System.UInt64;
6
+
7
+ using i16 = System.Int16;
8
+ using u8 = System.Byte;
9
+ using u16 = System.UInt16;
10
+ using u32 = System.UInt32;
11
+
12
+ namespace Community.CsharpSqlite
13
+ {
14
+ using sqlite3_value = Sqlite3.Mem;
15
+ public partial class Sqlite3
16
+ {
17
+ /*
18
+ ** 2001 September 15
19
+ **
20
+ ** The author disclaims copyright to this source code. In place of
21
+ ** a legal notice, here is a blessing:
22
+ **
23
+ ** May you do good and not evil.
24
+ ** May you find forgiveness for yourself and forgive others.
25
+ ** May you share freely, never taking more than you give.
26
+ **
27
+ *************************************************************************
28
+ ** This module contains C code that generates VDBE code used to process
29
+ ** the WHERE clause of SQL statements. This module is responsible for
30
+ ** generating the code that loops through a table looking for applicable
31
+ ** rows. Indices are selected and used to speed the search when doing
32
+ ** so is applicable. Because this module is responsible for selecting
33
+ ** indices, you might also think of this module as the "query optimizer".
34
+ *************************************************************************
35
+ ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
36
+ ** C#-SQLite is an independent reimplementation of the SQLite software library
37
+ **
38
+ ** SQLITE_SOURCE_ID: 2010-03-09 19:31:43 4ae453ea7be69018d8c16eb8dabe05617397dc4d
39
+ **
40
+ ** $Header$
41
+ *************************************************************************
42
+ */
43
+ //#include "sqliteInt.h"
44
+
45
+ /*
46
+ ** Trace output macros
47
+ */
48
+ #if (SQLITE_TEST) && (SQLITE_DEBUG)
49
+ static bool sqlite3WhereTrace = false;
50
+ #endif
51
+ #if (SQLITE_TEST) && (SQLITE_DEBUG) && TRACE
52
+ //# define WHERETRACE(X) if(sqlite3WhereTrace) sqlite3DebugPrintf X
53
+ static void WHERETRACE( string X, params object[] ap ) { if ( sqlite3WhereTrace ) sqlite3DebugPrintf( X, ap ); }
54
+ #else
55
+ //# define WHERETRACE(X)
56
+ static void WHERETRACE(string X, params object[] ap) { }
57
+ #endif
58
+
59
+ /* Forward reference
60
+ */
61
+ //typedef struct WhereClause WhereClause;
62
+ //typedef struct WhereMaskSet WhereMaskSet;
63
+ //typedef struct WhereOrInfo WhereOrInfo;
64
+ //typedef struct WhereAndInfo WhereAndInfo;
65
+ //typedef struct WhereCost WhereCost;
66
+
67
+ /*
68
+ ** The query generator uses an array of instances of this structure to
69
+ ** help it analyze the subexpressions of the WHERE clause. Each WHERE
70
+ ** clause subexpression is separated from the others by AND operators,
71
+ ** usually, or sometimes subexpressions separated by OR.
72
+ **
73
+ ** All WhereTerms are collected into a single WhereClause structure.
74
+ ** The following identity holds:
75
+ **
76
+ ** WhereTerm.pWC.a[WhereTerm.idx] == WhereTerm
77
+ **
78
+ ** When a term is of the form:
79
+ **
80
+ ** X <op> <expr>
81
+ **
82
+ ** where X is a column name and <op> is one of certain operators,
83
+ ** then WhereTerm.leftCursor and WhereTerm.u.leftColumn record the
84
+ ** cursor number and column number for X. WhereTerm.eOperator records
85
+ ** the <op> using a bitmask encoding defined by WO_xxx below. The
86
+ ** use of a bitmask encoding for the operator allows us to search
87
+ ** quickly for terms that match any of several different operators.
88
+ **
89
+ ** A WhereTerm might also be two or more subterms connected by OR:
90
+ **
91
+ ** (t1.X <op> <expr>) OR (t1.Y <op> <expr>) OR ....
92
+ **
93
+ ** In this second case, wtFlag as the TERM_ORINFO set and eOperator==WO_OR
94
+ ** and the WhereTerm.u.pOrInfo field points to auxiliary information that
95
+ ** is collected about the
96
+ **
97
+ ** If a term in the WHERE clause does not match either of the two previous
98
+ ** categories, then eOperator==0. The WhereTerm.pExpr field is still set
99
+ ** to the original subexpression content and wtFlags is set up appropriately
100
+ ** but no other fields in the WhereTerm object are meaningful.
101
+ **
102
+ ** When eOperator!=0, prereqRight and prereqAll record sets of cursor numbers,
103
+ ** but they do so indirectly. A single WhereMaskSet structure translates
104
+ ** cursor number into bits and the translated bit is stored in the prereq
105
+ ** fields. The translation is used in order to maximize the number of
106
+ ** bits that will fit in a Bitmask. The VDBE cursor numbers might be
107
+ ** spread out over the non-negative integers. For example, the cursor
108
+ ** numbers might be 3, 8, 9, 10, 20, 23, 41, and 45. The WhereMaskSet
109
+ ** translates these sparse cursor numbers into consecutive integers
110
+ ** beginning with 0 in order to make the best possible use of the available
111
+ ** bits in the Bitmask. So, in the example above, the cursor numbers
112
+ ** would be mapped into integers 0 through 7.
113
+ **
114
+ ** The number of terms in a join is limited by the number of bits
115
+ ** in prereqRight and prereqAll. The default is 64 bits, hence SQLite
116
+ ** is only able to process joins with 64 or fewer tables.
117
+ */
118
+ //typedef struct WhereTerm WhereTerm;
119
+ public class WhereTerm
120
+ {
121
+ public Expr pExpr; /* Pointer to the subexpression that is this term */
122
+ public int iParent; /* Disable pWC.a[iParent] when this term disabled */
123
+ public int leftCursor; /* Cursor number of X in "X <op> <expr>" */
124
+ public class _u
125
+ {
126
+ public int leftColumn; /* Column number of X in "X <op> <expr>" */
127
+ public WhereOrInfo pOrInfo; /* Extra information if eOperator==WO_OR */
128
+ public WhereAndInfo pAndInfo; /* Extra information if eOperator==WO_AND */
129
+ }
130
+ public _u u = new _u();
131
+ public u16 eOperator; /* A WO_xx value describing <op> */
132
+ public u8 wtFlags; /* TERM_xxx bit flags. See below */
133
+ public u8 nChild; /* Number of children that must disable us */
134
+ public WhereClause pWC; /* The clause this term is part of */
135
+ public Bitmask prereqRight; /* Bitmask of tables used by pExpr.pRight */
136
+ public Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */
137
+ };
138
+
139
+ /*
140
+ ** Allowed values of WhereTerm.wtFlags
141
+ */
142
+ //#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(db, ref pExpr) */
143
+ //#define TERM_VIRTUAL 0x02 /* Added by the optimizer. Do not code */
144
+ //#define TERM_CODED 0x04 /* This term is already coded */
145
+ //#define TERM_COPIED 0x08 /* Has a child */
146
+ //#define TERM_ORINFO 0x10 /* Need to free the WhereTerm.u.pOrInfo object */
147
+ //#define TERM_ANDINFO 0x20 /* Need to free the WhereTerm.u.pAndInfo obj */
148
+ //#define TERM_OR_OK 0x40 /* Used during OR-clause processing */
149
+ const int TERM_DYNAMIC = 0x01; /* Need to call sqlite3ExprDelete(db, ref pExpr) */
150
+ const int TERM_VIRTUAL = 0x02; /* Added by the optimizer. Do not code */
151
+ const int TERM_CODED = 0x04; /* This term is already coded */
152
+ const int TERM_COPIED = 0x08; /* Has a child */
153
+ const int TERM_ORINFO = 0x10; /* Need to free the WhereTerm.u.pOrInfo object */
154
+ const int TERM_ANDINFO = 0x20; /* Need to free the WhereTerm.u.pAndInfo obj */
155
+ const int TERM_OR_OK = 0x40; /* Used during OR-clause processing */
156
+ /*
157
+ ** An instance of the following structure holds all information about a
158
+ ** WHERE clause. Mostly this is a container for one or more WhereTerms.
159
+ */
160
+ public class WhereClause
161
+ {
162
+ public Parse pParse; /* The parser context */
163
+ public WhereMaskSet pMaskSet; /* Mapping of table cursor numbers to bitmasks */
164
+ public Bitmask vmask; /* Bitmask identifying virtual table cursors */
165
+ public u8 op; /* Split operator. TK_AND or TK_OR */
166
+ public int nTerm; /* Number of terms */
167
+ public int nSlot; /* Number of entries in a[] */
168
+ public WhereTerm[] a; /* Each a[] describes a term of the WHERE cluase */
169
+ #if (SQLITE_SMALL_STACK)
170
+ public WhereTerm[] aStatic = new WhereTerm[1]; /* Initial static space for a[] */
171
+ #else
172
+ public WhereTerm[] aStatic = new WhereTerm[8]; /* Initial static space for a[] */
173
+ #endif
174
+
175
+ public void CopyTo(WhereClause wc)
176
+ {
177
+ wc.pParse = this.pParse;
178
+ wc.pMaskSet = new WhereMaskSet();
179
+ this.pMaskSet.CopyTo(wc.pMaskSet);
180
+ wc.op = this.op;
181
+ wc.nTerm = this.nTerm;
182
+ wc.nSlot = this.nSlot;
183
+ wc.a = (WhereTerm[])this.a.Clone();
184
+ wc.aStatic = (WhereTerm[])this.aStatic.Clone();
185
+ }
186
+ };
187
+
188
+ /*
189
+ ** A WhereTerm with eOperator==WO_OR has its u.pOrInfo pointer set to
190
+ ** a dynamically allocated instance of the following structure.
191
+ */
192
+ public class WhereOrInfo
193
+ {
194
+ public WhereClause wc = new WhereClause();/* Decomposition into subterms */
195
+ public Bitmask indexable; /* Bitmask of all indexable tables in the clause */
196
+ };
197
+
198
+ /*
199
+ ** A WhereTerm with eOperator==WO_AND has its u.pAndInfo pointer set to
200
+ ** a dynamically allocated instance of the following structure.
201
+ */
202
+ public class WhereAndInfo
203
+ {
204
+ public WhereClause wc = new WhereClause(); /* The subexpression broken out */
205
+ };
206
+
207
+ /*
208
+ ** An instance of the following structure keeps track of a mapping
209
+ ** between VDBE cursor numbers and bits of the bitmasks in WhereTerm.
210
+ **
211
+ ** The VDBE cursor numbers are small integers contained in
212
+ ** SrcList_item.iCursor and Expr.iTable fields. For any given WHERE
213
+ ** clause, the cursor numbers might not begin with 0 and they might
214
+ ** contain gaps in the numbering sequence. But we want to make maximum
215
+ ** use of the bits in our bitmasks. This structure provides a mapping
216
+ ** from the sparse cursor numbers into consecutive integers beginning
217
+ ** with 0.
218
+ **
219
+ ** If WhereMaskSet.ix[A]==B it means that The A-th bit of a Bitmask
220
+ ** corresponds VDBE cursor number B. The A-th bit of a bitmask is 1<<A.
221
+ **
222
+ ** For example, if the WHERE clause expression used these VDBE
223
+ ** cursors: 4, 5, 8, 29, 57, 73. Then the WhereMaskSet structure
224
+ ** would map those cursor numbers into bits 0 through 5.
225
+ **
226
+ ** Note that the mapping is not necessarily ordered. In the example
227
+ ** above, the mapping might go like this: 4.3, 5.1, 8.2, 29.0,
228
+ ** 57.5, 73.4. Or one of 719 other combinations might be used. It
229
+ ** does not really matter. What is important is that sparse cursor
230
+ ** numbers all get mapped into bit numbers that begin with 0 and contain
231
+ ** no gaps.
232
+ */
233
+ public class WhereMaskSet
234
+ {
235
+ public int n; /* Number of Debug.Assigned cursor values */
236
+ public int[] ix = new int[BMS]; /* Cursor Debug.Assigned to each bit */
237
+
238
+ public void CopyTo(WhereMaskSet wms)
239
+ {
240
+ wms.n = this.n;
241
+ wms.ix = (int[])this.ix.Clone();
242
+ }
243
+ }
244
+
245
+ /*
246
+ ** A WhereCost object records a lookup strategy and the estimated
247
+ ** cost of pursuing that strategy.
248
+ */
249
+ public class WhereCost
250
+ {
251
+ public WherePlan plan = new WherePlan();/* The lookup strategy */
252
+ public double rCost; /* Overall cost of pursuing this search strategy */
253
+ public double nRow; /* Estimated number of output rows */
254
+ public Bitmask used; /* Bitmask of cursors used by this plan */
255
+
256
+ public void Clear()
257
+ {
258
+ plan.Clear();
259
+ rCost = 0;
260
+ nRow = 0;
261
+ used = 0;
262
+ }
263
+ };
264
+
265
+ /*
266
+ ** Bitmasks for the operators that indices are able to exploit. An
267
+ ** OR-ed combination of these values can be used when searching for
268
+ ** terms in the where clause.
269
+ */
270
+ //#define WO_IN 0x001
271
+ //#define WO_EQ 0x002
272
+ //#define WO_LT (WO_EQ<<(TK_LT-TK_EQ))
273
+ //#define WO_LE (WO_EQ<<(TK_LE-TK_EQ))
274
+ //#define WO_GT (WO_EQ<<(TK_GT-TK_EQ))
275
+ //#define WO_GE (WO_EQ<<(TK_GE-TK_EQ))
276
+ //#define WO_MATCH 0x040
277
+ //#define WO_ISNULL 0x080
278
+ //#define WO_OR 0x100 /* Two or more OR-connected terms */
279
+ //#define WO_AND 0x200 /* Two or more AND-connected terms */
280
+
281
+ //#define WO_ALL 0xfff /* Mask of all possible WO_* values */
282
+ //#define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */
283
+ const int WO_IN = 0x001;
284
+ const int WO_EQ = 0x002;
285
+ const int WO_LT = (WO_EQ << (TK_LT - TK_EQ));
286
+ const int WO_LE = (WO_EQ << (TK_LE - TK_EQ));
287
+ const int WO_GT = (WO_EQ << (TK_GT - TK_EQ));
288
+ const int WO_GE = (WO_EQ << (TK_GE - TK_EQ));
289
+ const int WO_MATCH = 0x040;
290
+ const int WO_ISNULL = 0x080;
291
+ const int WO_OR = 0x100; /* Two or more OR-connected terms */
292
+ const int WO_AND = 0x200; /* Two or more AND-connected terms */
293
+
294
+ const int WO_ALL = 0xfff; /* Mask of all possible WO_* values */
295
+ const int WO_SINGLE = 0x0ff; /* Mask of all non-compound WO_* values */
296
+ /*
297
+ ** Value for wsFlags returned by bestIndex() and stored in
298
+ ** WhereLevel.wsFlags. These flags determine which search
299
+ ** strategies are appropriate.
300
+ **
301
+ ** The least significant 12 bits is reserved as a mask for WO_ values above.
302
+ ** The WhereLevel.wsFlags field is usually set to WO_IN|WO_EQ|WO_ISNULL.
303
+ ** But if the table is the right table of a left join, WhereLevel.wsFlags
304
+ ** is set to WO_IN|WO_EQ. The WhereLevel.wsFlags field can then be used as
305
+ ** the "op" parameter to findTerm when we are resolving equality constraints.
306
+ ** ISNULL constraints will then not be used on the right table of a left
307
+ ** join. Tickets #2177 and #2189.
308
+ */
309
+ //#define WHERE_ROWID_EQ 0x00001000 /* rowid=EXPR or rowid IN (...) */
310
+ //#define WHERE_ROWID_RANGE 0x00002000 /* rowid<EXPR and/or rowid>EXPR */
311
+ //#define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) or x IS NULL */
312
+ //#define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */
313
+ //#define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */
314
+ //#define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */
315
+ //#define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */
316
+ //#define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */
317
+ //#define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */
318
+ //#define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */
319
+ //#define WHERE_IDX_ONLY 0x00800000 /* Use index only - omit table */
320
+ //#define WHERE_ORDERBY 0x01000000 /* Output will appear in correct order */
321
+ //#define WHERE_REVERSE 0x02000000 /* Scan in reverse order */
322
+ //#define WHERE_UNIQUE 0x04000000 /* Selects no more than one row */
323
+ //#define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
324
+ //#define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
325
+ const int WHERE_ROWID_EQ = 0x00001000; /* rowid=EXPR or rowid IN (...) */
326
+ const int WHERE_ROWID_RANGE = 0x00002000; /* rowid<EXPR and/or rowid>EXPR */
327
+ const int WHERE_COLUMN_EQ = 0x00010000; /* x=EXPR or x IN (...) */
328
+ const int WHERE_COLUMN_RANGE = 0x00020000; /* x<EXPR and/or x>EXPR */
329
+ const int WHERE_COLUMN_IN = 0x00040000; /* x IN (...) */
330
+ const int WHERE_COLUMN_NULL = 0x00080000; /* x IS NULL */
331
+ const int WHERE_INDEXED = 0x000f0000; /* Anything that uses an index */
332
+ const int WHERE_IN_ABLE = 0x000f1000; /* Able to support an IN operator */
333
+ const int WHERE_TOP_LIMIT = 0x00100000; /* x<EXPR or x<=EXPR constraint */
334
+ const int WHERE_BTM_LIMIT = 0x00200000; /* x>EXPR or x>=EXPR constraint */
335
+ const int WHERE_IDX_ONLY = 0x00800000; /* Use index only - omit table */
336
+ const int WHERE_ORDERBY = 0x01000000; /* Output will appear in correct order */
337
+ const int WHERE_REVERSE = 0x02000000; /* Scan in reverse order */
338
+ const int WHERE_UNIQUE = 0x04000000; /* Selects no more than one row */
339
+ const int WHERE_VIRTUALTABLE = 0x08000000; /* Use virtual-table processing */
340
+ const int WHERE_MULTI_OR = 0x10000000; /* OR using multiple indices */
341
+
342
+ /*
343
+ ** Initialize a preallocated WhereClause structure.
344
+ */
345
+ static void whereClauseInit(
346
+ WhereClause pWC, /* The WhereClause to be initialized */
347
+ Parse pParse, /* The parsing context */
348
+ WhereMaskSet pMaskSet /* Mapping from table cursor numbers to bitmasks */
349
+ )
350
+ {
351
+ pWC.pParse = pParse;
352
+ pWC.pMaskSet = pMaskSet;
353
+ pWC.nTerm = 0;
354
+ pWC.nSlot = ArraySize(pWC.aStatic) - 1;
355
+ pWC.a = pWC.aStatic;
356
+ pWC.vmask = 0;
357
+ }
358
+
359
+ /* Forward reference */
360
+ //static void whereClauseClear(WhereClause);
361
+
362
+ /*
363
+ ** Deallocate all memory Debug.Associated with a WhereOrInfo object.
364
+ */
365
+ static void whereOrInfoDelete(sqlite3 db, WhereOrInfo p)
366
+ {
367
+ whereClauseClear(p.wc);
368
+ sqlite3DbFree(db, ref p);
369
+ }
370
+
371
+ /*
372
+ ** Deallocate all memory Debug.Associated with a WhereAndInfo object.
373
+ */
374
+ static void whereAndInfoDelete(sqlite3 db, WhereAndInfo p)
375
+ {
376
+ whereClauseClear(p.wc);
377
+ sqlite3DbFree(db, ref p);
378
+ }
379
+
380
+ /*
381
+ ** Deallocate a WhereClause structure. The WhereClause structure
382
+ ** itself is not freed. This routine is the inverse of whereClauseInit().
383
+ */
384
+ static void whereClauseClear(WhereClause pWC)
385
+ {
386
+ int i;
387
+ WhereTerm a;
388
+ sqlite3 db = pWC.pParse.db;
389
+ for (i = pWC.nTerm - 1; i >= 0; i--)//, a++)
390
+ {
391
+ a = pWC.a[i];
392
+ if ((a.wtFlags & TERM_DYNAMIC) != 0)
393
+ {
394
+ sqlite3ExprDelete(db, ref a.pExpr);
395
+ }
396
+ if ((a.wtFlags & TERM_ORINFO) != 0)
397
+ {
398
+ whereOrInfoDelete(db, a.u.pOrInfo);
399
+ }
400
+ else if ((a.wtFlags & TERM_ANDINFO) != 0)
401
+ {
402
+ whereAndInfoDelete(db, a.u.pAndInfo);
403
+ }
404
+ }
405
+ if (pWC.a != pWC.aStatic)
406
+ {
407
+ sqlite3DbFree(db, ref pWC.a);
408
+ }
409
+ }
410
+
411
+ /*
412
+ ** Add a single new WhereTerm entry to the WhereClause object pWC.
413
+ ** The new WhereTerm object is constructed from Expr p and with wtFlags.
414
+ ** The index in pWC.a[] of the new WhereTerm is returned on success.
415
+ ** 0 is returned if the new WhereTerm could not be added due to a memory
416
+ ** allocation error. The memory allocation failure will be recorded in
417
+ ** the db.mallocFailed flag so that higher-level functions can detect it.
418
+ **
419
+ ** This routine will increase the size of the pWC.a[] array as necessary.
420
+ **
421
+ ** If the wtFlags argument includes TERM_DYNAMIC, then responsibility
422
+ ** for freeing the expression p is Debug.Assumed by the WhereClause object pWC.
423
+ ** This is true even if this routine fails to allocate a new WhereTerm.
424
+ **
425
+ ** WARNING: This routine might reallocate the space used to store
426
+ ** WhereTerms. All pointers to WhereTerms should be invalidated after
427
+ ** calling this routine. Such pointers may be reinitialized by referencing
428
+ ** the pWC.a[] array.
429
+ */
430
+ static int whereClauseInsert(WhereClause pWC, Expr p, u8 wtFlags)
431
+ {
432
+ WhereTerm pTerm;
433
+ int idx;
434
+ if (pWC.nTerm >= pWC.nSlot)
435
+ {
436
+ //WhereTerm pOld = pWC.a;
437
+ sqlite3 db = pWC.pParse.db;
438
+ Array.Resize(ref pWC.a, pWC.nSlot * 2);
439
+ //pWC.a = sqlite3DbMallocRaw(db, sizeof(pWC.a[0])*pWC.nSlot*2 );
440
+ //if( pWC.a==null ){
441
+ // if( wtFlags & TERM_DYNAMIC ){
442
+ // sqlite3ExprDelete(db, ref p);
443
+ // }
444
+ // pWC.a = pOld;
445
+ // return 0;
446
+ //}
447
+ //memcpy(pWC.a, pOld, sizeof(pWC.a[0])*pWC.nTerm);
448
+ //if( pOld!=pWC.aStatic ){
449
+ // sqlite3DbFree(db, ref pOld);
450
+ //}
451
+ //pWC.nSlot = sqlite3DbMallocSize(db, pWC.a)/sizeof(pWC.a[0]);
452
+ pWC.nSlot = pWC.a.Length - 1;
453
+ }
454
+ pWC.a[idx = pWC.nTerm++] = new WhereTerm();
455
+ pTerm = pWC.a[idx];
456
+ pTerm.pExpr = p;
457
+ pTerm.wtFlags = wtFlags;
458
+ pTerm.pWC = pWC;
459
+ pTerm.iParent = -1;
460
+ return idx;
461
+ }
462
+
463
+ /*
464
+ ** This routine identifies subexpressions in the WHERE clause where
465
+ ** each subexpression is separated by the AND operator or some other
466
+ ** operator specified in the op parameter. The WhereClause structure
467
+ ** is filled with pointers to subexpressions. For example:
468
+ **
469
+ ** WHERE a=='hello' AND coalesce(b,11)<10 AND (c+12!=d OR c==22)
470
+ ** \________/ \_______________/ \________________/
471
+ ** slot[0] slot[1] slot[2]
472
+ **
473
+ ** The original WHERE clause in pExpr is unaltered. All this routine
474
+ ** does is make slot[] entries point to substructure within pExpr.
475
+ **
476
+ ** In the previous sentence and in the diagram, "slot[]" refers to
477
+ ** the WhereClause.a[] array. The slot[] array grows as needed to contain
478
+ ** all terms of the WHERE clause.
479
+ */
480
+ static void whereSplit(WhereClause pWC, Expr pExpr, int op)
481
+ {
482
+ pWC.op = (u8)op;
483
+ if (pExpr == null) return;
484
+ if (pExpr.op != op)
485
+ {
486
+ whereClauseInsert(pWC, pExpr, 0);
487
+ }
488
+ else
489
+ {
490
+ whereSplit(pWC, pExpr.pLeft, op);
491
+ whereSplit(pWC, pExpr.pRight, op);
492
+ }
493
+ }
494
+
495
+ /*
496
+ ** Initialize an expression mask set (a WhereMaskSet object)
497
+ */
498
+ //#define initMaskSet(P) memset(P, 0, sizeof(*P))
499
+
500
+ /*
501
+ ** Return the bitmask for the given cursor number. Return 0 if
502
+ ** iCursor is not in the set.
503
+ */
504
+ static Bitmask getMask(WhereMaskSet pMaskSet, int iCursor)
505
+ {
506
+ int i;
507
+ Debug.Assert(pMaskSet.n <= sizeof(Bitmask) * 8);
508
+ for (i = 0; i < pMaskSet.n; i++)
509
+ {
510
+ if (pMaskSet.ix[i] == iCursor)
511
+ {
512
+ return ((Bitmask)1) << i;
513
+ }
514
+ }
515
+ return 0;
516
+ }
517
+
518
+ /*
519
+ ** Create a new mask for cursor iCursor.
520
+ **
521
+ ** There is one cursor per table in the FROM clause. The number of
522
+ ** tables in the FROM clause is limited by a test early in the
523
+ ** sqlite3WhereBegin() routine. So we know that the pMaskSet.ix[]
524
+ ** array will never overflow.
525
+ */
526
+ static void createMask(WhereMaskSet pMaskSet, int iCursor)
527
+ {
528
+ Debug.Assert(pMaskSet.n < ArraySize(pMaskSet.ix));
529
+ pMaskSet.ix[pMaskSet.n++] = iCursor;
530
+ }
531
+
532
+ /*
533
+ ** This routine walks (recursively) an expression tree and generates
534
+ ** a bitmask indicating which tables are used in that expression
535
+ ** tree.
536
+ **
537
+ ** In order for this routine to work, the calling function must have
538
+ ** previously invoked sqlite3ResolveExprNames() on the expression. See
539
+ ** the header comment on that routine for additional information.
540
+ ** The sqlite3ResolveExprNames() routines looks for column names and
541
+ ** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
542
+ ** the VDBE cursor number of the table. This routine just has to
543
+ ** translate the cursor numbers into bitmask values and OR all
544
+ ** the bitmasks together.
545
+ */
546
+ //static Bitmask exprListTableUsage(WhereMaskSet*, ExprList);
547
+ //static Bitmask exprSelectTableUsage(WhereMaskSet*, Select);
548
+ static Bitmask exprTableUsage(WhereMaskSet pMaskSet, Expr p)
549
+ {
550
+ Bitmask mask = 0;
551
+ if (p == null) return 0;
552
+ if (p.op == TK_COLUMN)
553
+ {
554
+ mask = getMask(pMaskSet, p.iTable);
555
+ return mask;
556
+ }
557
+ mask = exprTableUsage(pMaskSet, p.pRight);
558
+ mask |= exprTableUsage(pMaskSet, p.pLeft);
559
+ if (ExprHasProperty(p, EP_xIsSelect))
560
+ {
561
+ mask |= exprSelectTableUsage(pMaskSet, p.x.pSelect);
562
+ }
563
+ else
564
+ {
565
+ mask |= exprListTableUsage(pMaskSet, p.x.pList);
566
+ }
567
+ return mask;
568
+ }
569
+ static Bitmask exprListTableUsage(WhereMaskSet pMaskSet, ExprList pList)
570
+ {
571
+ int i;
572
+ Bitmask mask = 0;
573
+ if (pList != null)
574
+ {
575
+ for (i = 0; i < pList.nExpr; i++)
576
+ {
577
+ mask |= exprTableUsage(pMaskSet, pList.a[i].pExpr);
578
+ }
579
+ }
580
+ return mask;
581
+ }
582
+ static Bitmask exprSelectTableUsage(WhereMaskSet pMaskSet, Select pS)
583
+ {
584
+ Bitmask mask = 0;
585
+ while (pS != null)
586
+ {
587
+ mask |= exprListTableUsage(pMaskSet, pS.pEList);
588
+ mask |= exprListTableUsage(pMaskSet, pS.pGroupBy);
589
+ mask |= exprListTableUsage(pMaskSet, pS.pOrderBy);
590
+ mask |= exprTableUsage(pMaskSet, pS.pWhere);
591
+ mask |= exprTableUsage(pMaskSet, pS.pHaving);
592
+ pS = pS.pPrior;
593
+ }
594
+ return mask;
595
+ }
596
+
597
+ /*
598
+ ** Return TRUE if the given operator is one of the operators that is
599
+ ** allowed for an indexable WHERE clause term. The allowed operators are
600
+ ** "=", "<", ">", "<=", ">=", and "IN".
601
+ */
602
+ static bool allowedOp(int op)
603
+ {
604
+ Debug.Assert(TK_GT > TK_EQ && TK_GT < TK_GE);
605
+ Debug.Assert(TK_LT > TK_EQ && TK_LT < TK_GE);
606
+ Debug.Assert(TK_LE > TK_EQ && TK_LE < TK_GE);
607
+ Debug.Assert(TK_GE == TK_EQ + 4);
608
+ return op == TK_IN || (op >= TK_EQ && op <= TK_GE) || op == TK_ISNULL;
609
+ }
610
+
611
+ /*
612
+ ** Swap two objects of type TYPE.
613
+ */
614
+ //#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
615
+
616
+ /*
617
+ ** Commute a comparison operator. Expressions of the form "X op Y"
618
+ ** are converted into "Y op X".
619
+ **
620
+ ** If a collation sequence is Debug.Associated with either the left or right
621
+ ** side of the comparison, it remains Debug.Associated with the same side after
622
+ ** the commutation. So "Y collate NOCASE op X" becomes
623
+ ** "X collate NOCASE op Y". This is because any collation sequence on
624
+ ** the left hand side of a comparison overrides any collation sequence
625
+ ** attached to the right. For the same reason the EP_ExpCollate flag
626
+ ** is not commuted.
627
+ */
628
+ static void exprCommute(Parse pParse, Expr pExpr)
629
+ {
630
+ u16 expRight = (u16)(pExpr.pRight.flags & EP_ExpCollate);
631
+ u16 expLeft = (u16)(pExpr.pLeft.flags & EP_ExpCollate);
632
+ Debug.Assert(allowedOp(pExpr.op) && pExpr.op != TK_IN);
633
+ pExpr.pRight.pColl = sqlite3ExprCollSeq(pParse, pExpr.pRight);
634
+ pExpr.pLeft.pColl = sqlite3ExprCollSeq(pParse, pExpr.pLeft);
635
+ SWAP(ref pExpr.pRight.pColl, ref pExpr.pLeft.pColl);
636
+ pExpr.pRight.flags = (u16)((pExpr.pRight.flags & ~EP_ExpCollate) | expLeft);
637
+ pExpr.pLeft.flags = (u16)((pExpr.pLeft.flags & ~EP_ExpCollate) | expRight);
638
+ SWAP(ref pExpr.pRight, ref pExpr.pLeft);
639
+ if (pExpr.op >= TK_GT)
640
+ {
641
+ Debug.Assert(TK_LT == TK_GT + 2);
642
+ Debug.Assert(TK_GE == TK_LE + 2);
643
+ Debug.Assert(TK_GT > TK_EQ);
644
+ Debug.Assert(TK_GT < TK_LE);
645
+ Debug.Assert(pExpr.op >= TK_GT && pExpr.op <= TK_GE);
646
+ pExpr.op = (u8)(((pExpr.op - TK_GT) ^ 2) + TK_GT);
647
+ }
648
+ }
649
+
650
+ /*
651
+ ** Translate from TK_xx operator to WO_xx bitmask.
652
+ */
653
+ static u16 operatorMask(int op)
654
+ {
655
+ u16 c;
656
+ Debug.Assert(allowedOp(op));
657
+ if (op == TK_IN)
658
+ {
659
+ c = WO_IN;
660
+ }
661
+ else if (op == TK_ISNULL)
662
+ {
663
+ c = WO_ISNULL;
664
+ }
665
+ else
666
+ {
667
+ Debug.Assert((WO_EQ << (op - TK_EQ)) < 0x7fff);
668
+ c = (u16)(WO_EQ << (op - TK_EQ));
669
+ }
670
+ Debug.Assert(op != TK_ISNULL || c == WO_ISNULL);
671
+ Debug.Assert(op != TK_IN || c == WO_IN);
672
+ Debug.Assert(op != TK_EQ || c == WO_EQ);
673
+ Debug.Assert(op != TK_LT || c == WO_LT);
674
+ Debug.Assert(op != TK_LE || c == WO_LE);
675
+ Debug.Assert(op != TK_GT || c == WO_GT);
676
+ Debug.Assert(op != TK_GE || c == WO_GE);
677
+ return c;
678
+ }
679
+
680
+ /*
681
+ ** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
682
+ ** where X is a reference to the iColumn of table iCur and <op> is one of
683
+ ** the WO_xx operator codes specified by the op parameter.
684
+ ** Return a pointer to the term. Return 0 if not found.
685
+ */
686
+ static WhereTerm findTerm(
687
+ WhereClause pWC, /* The WHERE clause to be searched */
688
+ int iCur, /* Cursor number of LHS */
689
+ int iColumn, /* Column number of LHS */
690
+ Bitmask notReady, /* RHS must not overlap with this mask */
691
+ u32 op, /* Mask of WO_xx values describing operator */
692
+ Index pIdx /* Must be compatible with this index, if not NULL */
693
+ )
694
+ {
695
+ WhereTerm pTerm;
696
+ int k;
697
+ Debug.Assert(iCur >= 0);
698
+ op &= WO_ALL;
699
+ for (k = pWC.nTerm; k != 0; k--)//, pTerm++)
700
+ {
701
+ pTerm = pWC.a[pWC.nTerm - k];
702
+ if (pTerm.leftCursor == iCur
703
+ && (pTerm.prereqRight & notReady) == 0
704
+ && pTerm.u.leftColumn == iColumn
705
+ && (pTerm.eOperator & op) != 0
706
+ )
707
+ {
708
+ if (pIdx != null && pTerm.eOperator != WO_ISNULL)
709
+ {
710
+ Expr pX = pTerm.pExpr;
711
+ CollSeq pColl;
712
+ char idxaff;
713
+ int j;
714
+ Parse pParse = pWC.pParse;
715
+
716
+ idxaff = pIdx.pTable.aCol[iColumn].affinity;
717
+ if (!sqlite3IndexAffinityOk(pX, idxaff)) continue;
718
+
719
+ /* Figure out the collation sequence required from an index for
720
+ ** it to be useful for optimising expression pX. Store this
721
+ ** value in variable pColl.
722
+ */
723
+ Debug.Assert(pX.pLeft != null);
724
+ pColl = sqlite3BinaryCompareCollSeq(pParse, pX.pLeft, pX.pRight);
725
+ Debug.Assert(pColl != null || pParse.nErr != 0);
726
+
727
+ for (j = 0; pIdx.aiColumn[j] != iColumn; j++)
728
+ {
729
+ if (NEVER(j >= pIdx.nColumn)) return null;
730
+ }
731
+ if (pColl != null && sqlite3StrICmp(pColl.zName, pIdx.azColl[j]) != 0) continue;
732
+ }
733
+ return pTerm;
734
+ }
735
+ }
736
+ return null;
737
+ }
738
+
739
+ /* Forward reference */
740
+ //static void exprAnalyze(SrcList*, WhereClause*, int);
741
+
742
+ /*
743
+ ** Call exprAnalyze on all terms in a WHERE clause.
744
+ **
745
+ **
746
+ */
747
+ static void exprAnalyzeAll(
748
+ SrcList pTabList, /* the FROM clause */
749
+ WhereClause pWC /* the WHERE clause to be analyzed */
750
+ )
751
+ {
752
+ int i;
753
+ for (i = pWC.nTerm - 1; i >= 0; i--)
754
+ {
755
+ exprAnalyze(pTabList, pWC, i);
756
+ }
757
+ }
758
+
759
+ #if !SQLITE_OMIT_LIKE_OPTIMIZATION
760
+ /*
761
+ ** Check to see if the given expression is a LIKE or GLOB operator that
762
+ ** can be optimized using inequality constraints. Return TRUE if it is
763
+ ** so and false if not.
764
+ **
765
+ ** In order for the operator to be optimizible, the RHS must be a string
766
+ ** literal that does not begin with a wildcard.
767
+ */
768
+ static int isLikeOrGlob(
769
+ Parse pParse, /* Parsing and code generating context */
770
+ Expr pExpr, /* Test this expression */
771
+ ref Expr ppPrefix, /* Pointer to TK_STRING expression with pattern prefix */
772
+ ref bool pisComplete, /* True if the only wildcard is % in the last character */
773
+ ref bool pnoCase /* True if uppercase is equivalent to lowercase */
774
+ )
775
+ {
776
+ string z = null; /* String on RHS of LIKE operator */
777
+ Expr pRight, pLeft; /* Right and left size of LIKE operator */
778
+ ExprList pList; /* List of operands to the LIKE operator */
779
+ int c = 0; /* One character in z[] */
780
+ int cnt; /* Number of non-wildcard prefix characters */
781
+ char[] wc = new char[3]; /* Wildcard characters */
782
+ CollSeq pColl; /* Collating sequence for LHS */
783
+ sqlite3 db = pParse.db; /* Data_base connection */
784
+ sqlite3_value pVal = null;
785
+ int op; /* Opcode of pRight */
786
+
787
+ if (!sqlite3IsLikeFunction(db, pExpr, ref pnoCase, wc))
788
+ {
789
+ return 0;
790
+ }
791
+ #if SQLITE_EBCDIC
792
+ if( pnoCase ) return 0;
793
+ #endif
794
+ pList = pExpr.x.pList;
795
+ pLeft = pList.a[1].pExpr;
796
+ if (pLeft.op != TK_COLUMN || sqlite3ExprAffinity(pLeft) != SQLITE_AFF_TEXT)
797
+ {
798
+ /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
799
+ ** be the name of an indexed column with TEXT affinity. */
800
+ return 0;
801
+ }
802
+ Debug.Assert(pLeft.iColumn != (-1)); /* Because IPK never has AFF_TEXT */
803
+ pColl = sqlite3ExprCollSeq(pParse, pLeft);
804
+ if ( pColl == null ) return 0; /* Happens when LHS has an undefined collation */
805
+ if ((pColl.type != SQLITE_COLL_BINARY || pnoCase) &&
806
+ (pColl.type != SQLITE_COLL_NOCASE || !pnoCase))
807
+ {
808
+ /* IMP: R-09003-32046 For the GLOB operator, the column must use the
809
+ ** default BINARY collating sequence.
810
+ ** IMP: R-41408-28306 For the LIKE operator, if case_sensitive_like mode
811
+ ** is enabled then the column must use the default BINARY collating
812
+ ** sequence, or if case_sensitive_like mode is disabled then the column
813
+ ** must use the built-in NOCASE collating sequence.
814
+ */
815
+ return 0;
816
+ }
817
+
818
+ pRight = pList.a[0].pExpr;
819
+ op = pRight.op;
820
+ if (op == TK_REGISTER)
821
+ {
822
+ op = pRight.op2;
823
+ }
824
+ if (op == TK_VARIABLE)
825
+ {
826
+ Vdbe pReprepare = pParse.pReprepare;
827
+ pVal = sqlite3VdbeGetValue(pReprepare, pRight.iColumn, (byte)SQLITE_AFF_NONE);
828
+ if (pVal != null && sqlite3_value_type(pVal) == SQLITE_TEXT)
829
+ {
830
+ z = sqlite3_value_text(pVal);
831
+ }
832
+ sqlite3VdbeSetVarmask(pParse.pVdbe, pRight.iColumn);
833
+ Debug.Assert(pRight.op == TK_VARIABLE || pRight.op == TK_REGISTER);
834
+ }
835
+ else if (op == TK_STRING)
836
+ {
837
+ z = pRight.u.zToken;
838
+ }
839
+ if (!String.IsNullOrEmpty(z))
840
+ {
841
+ cnt = 0;
842
+ while (cnt < z.Length && (c = z[cnt]) != 0 && c != wc[0] && c != wc[1] && c != wc[2])
843
+ {
844
+ cnt++;
845
+ }
846
+ if (cnt != 0 && c != 0 && 255 != (u8)z[cnt - 1])
847
+ {
848
+ Expr pPrefix;
849
+ pisComplete = cnt >= z.Length - 1 ? true : z[cnt] == wc[0] && z[cnt + 1] == 0;
850
+ pPrefix = sqlite3Expr(db, TK_STRING, z);
851
+ if (pPrefix != null) pPrefix.u.zToken = pPrefix.u.zToken.Substring(0, cnt);
852
+ ppPrefix = pPrefix;
853
+ if (op == TK_VARIABLE)
854
+ {
855
+ Vdbe v = pParse.pVdbe;
856
+ sqlite3VdbeSetVarmask(v, pRight.iColumn);
857
+ if (pisComplete && pRight.u.zToken.Length > 1)
858
+ {
859
+ /* If the rhs of the LIKE expression is a variable, and the current
860
+ ** value of the variable means there is no need to invoke the LIKE
861
+ ** function, then no OP_Variable will be added to the program.
862
+ ** This causes problems for the sqlite3_bind_parameter_name()
863
+ ** API. To workaround them, add a dummy OP_Variable here.
864
+ */
865
+ int r1 = sqlite3GetTempReg(pParse);
866
+ sqlite3ExprCodeTarget(pParse, pRight, r1);
867
+ sqlite3VdbeChangeP3(v, sqlite3VdbeCurrentAddr(v) - 1, 0);
868
+ sqlite3ReleaseTempReg(pParse, r1);
869
+ }
870
+ }
871
+ }
872
+ else
873
+ {
874
+ z = null;
875
+ }
876
+ }
877
+
878
+ sqlite3ValueFree(ref pVal);
879
+ return (z != null) ? 1 : 0;
880
+ }
881
+ #endif //* SQLITE_OMIT_LIKE_OPTIMIZATION */
882
+
883
+
884
+ #if !SQLITE_OMIT_VIRTUALTABLE
885
+ /*
886
+ ** Check to see if the given expression is of the form
887
+ **
888
+ ** column MATCH expr
889
+ **
890
+ ** If it is then return TRUE. If not, return FALSE.
891
+ */
892
+ static int isMatchOfColumn(
893
+ Expr pExpr /* Test this expression */
894
+ ){
895
+ ExprList pList;
896
+
897
+ if( pExpr.op!=TK_FUNCTION ){
898
+ return 0;
899
+ }
900
+ if(sqlite3StrICmp(pExpr.u.zToken,"match")!=0 ){
901
+ return 0;
902
+ }
903
+ pList = pExpr.x.pList;
904
+ if( pList.nExpr!=2 ){
905
+ return 0;
906
+ }
907
+ if( pList.a[1].pExpr.op != TK_COLUMN ){
908
+ return 0;
909
+ }
910
+ return 1;
911
+ }
912
+ #endif //* SQLITE_OMIT_VIRTUALTABLE */
913
+
914
+ /*
915
+ ** If the pBase expression originated in the ON or USING clause of
916
+ ** a join, then transfer the appropriate markings over to derived.
917
+ */
918
+ static void transferJoinMarkings(Expr pDerived, Expr pBase)
919
+ {
920
+ pDerived.flags = (u16)(pDerived.flags | pBase.flags & EP_FromJoin);
921
+ pDerived.iRightJoinTable = pBase.iRightJoinTable;
922
+ }
923
+
924
+ #if !(SQLITE_OMIT_OR_OPTIMIZATION) && !(SQLITE_OMIT_SUBQUERY)
925
+ /*
926
+ ** Analyze a term that consists of two or more OR-connected
927
+ ** subterms. So in:
928
+ **
929
+ ** ... WHERE (a=5) AND (b=7 OR c=9 OR d=13) AND (d=13)
930
+ ** ^^^^^^^^^^^^^^^^^^^^
931
+ **
932
+ ** This routine analyzes terms such as the middle term in the above example.
933
+ ** A WhereOrTerm object is computed and attached to the term under
934
+ ** analysis, regardless of the outcome of the analysis. Hence:
935
+ **
936
+ ** WhereTerm.wtFlags |= TERM_ORINFO
937
+ ** WhereTerm.u.pOrInfo = a dynamically allocated WhereOrTerm object
938
+ **
939
+ ** The term being analyzed must have two or more of OR-connected subterms.
940
+ ** A single subterm might be a set of AND-connected sub-subterms.
941
+ ** Examples of terms under analysis:
942
+ **
943
+ ** (A) t1.x=t2.y OR t1.x=t2.z OR t1.y=15 OR t1.z=t3.a+5
944
+ ** (B) x=expr1 OR expr2=x OR x=expr3
945
+ ** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15)
946
+ ** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*')
947
+ ** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6)
948
+ **
949
+ ** CASE 1:
950
+ **
951
+ ** If all subterms are of the form T.C=expr for some single column of C
952
+ ** a single table T (as shown in example B above) then create a new virtual
953
+ ** term that is an equivalent IN expression. In other words, if the term
954
+ ** being analyzed is:
955
+ **
956
+ ** x = expr1 OR expr2 = x OR x = expr3
957
+ **
958
+ ** then create a new virtual term like this:
959
+ **
960
+ ** x IN (expr1,expr2,expr3)
961
+ **
962
+ ** CASE 2:
963
+ **
964
+ ** If all subterms are indexable by a single table T, then set
965
+ **
966
+ ** WhereTerm.eOperator = WO_OR
967
+ ** WhereTerm.u.pOrInfo.indexable |= the cursor number for table T
968
+ **
969
+ ** A subterm is "indexable" if it is of the form
970
+ ** "T.C <op> <expr>" where C is any column of table T and
971
+ ** <op> is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN".
972
+ ** A subterm is also indexable if it is an AND of two or more
973
+ ** subsubterms at least one of which is indexable. Indexable AND
974
+ ** subterms have their eOperator set to WO_AND and they have
975
+ ** u.pAndInfo set to a dynamically allocated WhereAndTerm object.
976
+ **
977
+ ** From another point of view, "indexable" means that the subterm could
978
+ ** potentially be used with an index if an appropriate index exists.
979
+ ** This analysis does not consider whether or not the index exists; that
980
+ ** is something the bestIndex() routine will determine. This analysis
981
+ ** only looks at whether subterms appropriate for indexing exist.
982
+ **
983
+ ** All examples A through E above all satisfy case 2. But if a term
984
+ ** also statisfies case 1 (such as B) we know that the optimizer will
985
+ ** always prefer case 1, so in that case we pretend that case 2 is not
986
+ ** satisfied.
987
+ **
988
+ ** It might be the case that multiple tables are indexable. For example,
989
+ ** (E) above is indexable on tables P, Q, and R.
990
+ **
991
+ ** Terms that satisfy case 2 are candidates for lookup by using
992
+ ** separate indices to find rowids for each subterm and composing
993
+ ** the union of all rowids using a RowSet object. This is similar
994
+ ** to "bitmap indices" in other data_base engines.
995
+ **
996
+ ** OTHERWISE:
997
+ **
998
+ ** If neither case 1 nor case 2 apply, then leave the eOperator set to
999
+ ** zero. This term is not useful for search.
1000
+ */
1001
+ static void exprAnalyzeOrTerm(
1002
+ SrcList pSrc, /* the FROM clause */
1003
+ WhereClause pWC, /* the complete WHERE clause */
1004
+ int idxTerm /* Index of the OR-term to be analyzed */
1005
+ )
1006
+ {
1007
+ Parse pParse = pWC.pParse; /* Parser context */
1008
+ sqlite3 db = pParse.db; /* Data_base connection */
1009
+ WhereTerm pTerm = pWC.a[idxTerm]; /* The term to be analyzed */
1010
+ Expr pExpr = pTerm.pExpr; /* The expression of the term */
1011
+ WhereMaskSet pMaskSet = pWC.pMaskSet; /* Table use masks */
1012
+ int i; /* Loop counters */
1013
+ WhereClause pOrWc; /* Breakup of pTerm into subterms */
1014
+ WhereTerm pOrTerm; /* A Sub-term within the pOrWc */
1015
+ WhereOrInfo pOrInfo; /* Additional information Debug.Associated with pTerm */
1016
+ Bitmask chngToIN; /* Tables that might satisfy case 1 */
1017
+ Bitmask indexable; /* Tables that are indexable, satisfying case 2 */
1018
+
1019
+ /*
1020
+ ** Break the OR clause into its separate subterms. The subterms are
1021
+ ** stored in a WhereClause structure containing within the WhereOrInfo
1022
+ ** object that is attached to the original OR clause term.
1023
+ */
1024
+ Debug.Assert((pTerm.wtFlags & (TERM_DYNAMIC | TERM_ORINFO | TERM_ANDINFO)) == 0);
1025
+ Debug.Assert(pExpr.op == TK_OR);
1026
+ pTerm.u.pOrInfo = pOrInfo = new WhereOrInfo();//sqlite3DbMallocZero(db, sizeof(*pOrInfo));
1027
+ if (pOrInfo == null) return;
1028
+ pTerm.wtFlags |= TERM_ORINFO;
1029
+ pOrWc = pOrInfo.wc;
1030
+ whereClauseInit(pOrWc, pWC.pParse, pMaskSet);
1031
+ whereSplit(pOrWc, pExpr, TK_OR);
1032
+ exprAnalyzeAll(pSrc, pOrWc);
1033
+ // if ( db.mallocFailed != 0 ) return;
1034
+ Debug.Assert(pOrWc.nTerm >= 2);
1035
+
1036
+ /*
1037
+ ** Compute the set of tables that might satisfy cases 1 or 2.
1038
+ */
1039
+ indexable = ~(Bitmask)0;
1040
+ chngToIN = ~(pWC.vmask);
1041
+ for (i = pOrWc.nTerm - 1; i >= 0 && indexable != 0; i--)//, pOrTerm++ )
1042
+ {
1043
+ pOrTerm = pOrWc.a[i];
1044
+ if ((pOrTerm.eOperator & WO_SINGLE) == 0)
1045
+ {
1046
+ WhereAndInfo pAndInfo;
1047
+ Debug.Assert(pOrTerm.eOperator == 0);
1048
+ Debug.Assert((pOrTerm.wtFlags & (TERM_ANDINFO | TERM_ORINFO)) == 0);
1049
+ chngToIN = 0;
1050
+ pAndInfo = new WhereAndInfo();//sqlite3DbMallocRaw(db, sizeof(*pAndInfo));
1051
+ if (pAndInfo != null)
1052
+ {
1053
+ WhereClause pAndWC;
1054
+ WhereTerm pAndTerm;
1055
+ int j;
1056
+ Bitmask b = 0;
1057
+ pOrTerm.u.pAndInfo = pAndInfo;
1058
+ pOrTerm.wtFlags |= TERM_ANDINFO;
1059
+ pOrTerm.eOperator = WO_AND;
1060
+ pAndWC = pAndInfo.wc;
1061
+ whereClauseInit(pAndWC, pWC.pParse, pMaskSet);
1062
+ whereSplit(pAndWC, pOrTerm.pExpr, TK_AND);
1063
+ exprAnalyzeAll(pSrc, pAndWC);
1064
+ //testcase( db.mallocFailed );
1065
+ ////if ( 0 == db.mallocFailed )
1066
+ {
1067
+ for (j = 0; j < pAndWC.nTerm; j++)//, pAndTerm++ )
1068
+ {
1069
+ pAndTerm = pAndWC.a[j];
1070
+ Debug.Assert(pAndTerm.pExpr != null);
1071
+ if (allowedOp(pAndTerm.pExpr.op))
1072
+ {
1073
+ b |= getMask(pMaskSet, pAndTerm.leftCursor);
1074
+ }
1075
+ }
1076
+ }
1077
+ indexable &= b;
1078
+ }
1079
+ }
1080
+ else if ((pOrTerm.wtFlags & TERM_COPIED) != 0)
1081
+ {
1082
+ /* Skip this term for now. We revisit it when we process the
1083
+ ** corresponding TERM_VIRTUAL term */
1084
+ }
1085
+ else
1086
+ {
1087
+ Bitmask b;
1088
+ b = getMask(pMaskSet, pOrTerm.leftCursor);
1089
+ if ((pOrTerm.wtFlags & TERM_VIRTUAL) != 0)
1090
+ {
1091
+ WhereTerm pOther = pOrWc.a[pOrTerm.iParent];
1092
+ b |= getMask(pMaskSet, pOther.leftCursor);
1093
+ }
1094
+ indexable &= b;
1095
+ if (pOrTerm.eOperator != WO_EQ)
1096
+ {
1097
+ chngToIN = 0;
1098
+ }
1099
+ else
1100
+ {
1101
+ chngToIN &= b;
1102
+ }
1103
+ }
1104
+ }
1105
+
1106
+ /*
1107
+ ** Record the set of tables that satisfy case 2. The set might be
1108
+ ** empty.
1109
+ */
1110
+ pOrInfo.indexable = indexable;
1111
+ pTerm.eOperator = (u16)(indexable == 0 ? 0 : WO_OR);
1112
+
1113
+ /*
1114
+ ** chngToIN holds a set of tables that *might* satisfy case 1. But
1115
+ ** we have to do some additional checking to see if case 1 really
1116
+ ** is satisfied.
1117
+ **
1118
+ ** chngToIN will hold either 0, 1, or 2 bits. The 0-bit case means
1119
+ ** that there is no possibility of transforming the OR clause into an
1120
+ ** IN operator because one or more terms in the OR clause contain
1121
+ ** something other than == on a column in the single table. The 1-bit
1122
+ ** case means that every term of the OR clause is of the form
1123
+ ** "table.column=expr" for some single table. The one bit that is set
1124
+ ** will correspond to the common table. We still need to check to make
1125
+ ** sure the same column is used on all terms. The 2-bit case is when
1126
+ ** the all terms are of the form "table1.column=table2.column". It
1127
+ ** might be possible to form an IN operator with either table1.column
1128
+ ** or table2.column as the LHS if either is common to every term of
1129
+ ** the OR clause.
1130
+ **
1131
+ ** Note that terms of the form "table.column1=table.column2" (the
1132
+ ** same table on both sizes of the ==) cannot be optimized.
1133
+ */
1134
+ if (chngToIN != 0)
1135
+ {
1136
+ int okToChngToIN = 0; /* True if the conversion to IN is valid */
1137
+ int iColumn = -1; /* Column index on lhs of IN operator */
1138
+ int iCursor = -1; /* Table cursor common to all terms */
1139
+ int j = 0; /* Loop counter */
1140
+
1141
+ /* Search for a table and column that appears on one side or the
1142
+ ** other of the == operator in every subterm. That table and column
1143
+ ** will be recorded in iCursor and iColumn. There might not be any
1144
+ ** such table and column. Set okToChngToIN if an appropriate table
1145
+ ** and column is found but leave okToChngToIN false if not found.
1146
+ */
1147
+ for (j = 0; j < 2 && 0 == okToChngToIN; j++)
1148
+ {
1149
+ //pOrTerm = pOrWc.a;
1150
+ for (i = pOrWc.nTerm - 1; i >= 0; i--)//, pOrTerm++)
1151
+ {
1152
+ pOrTerm = pOrWc.a[pOrWc.nTerm - 1 - i];
1153
+ Debug.Assert(pOrTerm.eOperator == WO_EQ);
1154
+ pOrTerm.wtFlags = (u8)(pOrTerm.wtFlags & ~TERM_OR_OK);
1155
+ if (pOrTerm.leftCursor == iCursor)
1156
+ {
1157
+ /* This is the 2-bit case and we are on the second iteration and
1158
+ ** current term is from the first iteration. So skip this term. */
1159
+ Debug.Assert(j == 1);
1160
+ continue;
1161
+ }
1162
+ if ((chngToIN & getMask(pMaskSet, pOrTerm.leftCursor)) == 0)
1163
+ {
1164
+ /* This term must be of the form t1.a==t2.b where t2 is in the
1165
+ ** chngToIN set but t1 is not. This term will be either preceeded
1166
+ ** or follwed by an inverted copy (t2.b==t1.a). Skip this term
1167
+ ** and use its inversion. */
1168
+ testcase(pOrTerm.wtFlags & TERM_COPIED);
1169
+ testcase(pOrTerm.wtFlags & TERM_VIRTUAL);
1170
+ Debug.Assert((pOrTerm.wtFlags & (TERM_COPIED | TERM_VIRTUAL)) != 0);
1171
+ continue;
1172
+ }
1173
+ iColumn = pOrTerm.u.leftColumn;
1174
+ iCursor = pOrTerm.leftCursor;
1175
+ break;
1176
+ }
1177
+ if (i < 0)
1178
+ {
1179
+ /* No candidate table+column was found. This can only occur
1180
+ ** on the second iteration */
1181
+ Debug.Assert(j == 1);
1182
+ Debug.Assert((chngToIN & (chngToIN - 1)) == 0);
1183
+ Debug.Assert(chngToIN == getMask(pMaskSet, iCursor));
1184
+ break;
1185
+ }
1186
+ testcase(j == 1);
1187
+
1188
+ /* We have found a candidate table and column. Check to see if that
1189
+ ** table and column is common to every term in the OR clause */
1190
+ okToChngToIN = 1;
1191
+ for (; i >= 0 && okToChngToIN != 0; i--)//, pOrTerm++)
1192
+ {
1193
+ pOrTerm = pOrWc.a[pOrWc.nTerm - 1 - i];
1194
+ Debug.Assert(pOrTerm.eOperator == WO_EQ);
1195
+ if (pOrTerm.leftCursor != iCursor)
1196
+ {
1197
+ pOrTerm.wtFlags = (u8)(pOrTerm.wtFlags & ~TERM_OR_OK);
1198
+ }
1199
+ else if (pOrTerm.u.leftColumn != iColumn)
1200
+ {
1201
+ okToChngToIN = 0;
1202
+ }
1203
+ else
1204
+ {
1205
+ int affLeft, affRight;
1206
+ /* If the right-hand side is also a column, then the affinities
1207
+ ** of both right and left sides must be such that no type
1208
+ ** conversions are required on the right. (Ticket #2249)
1209
+ */
1210
+ affRight = sqlite3ExprAffinity(pOrTerm.pExpr.pRight);
1211
+ affLeft = sqlite3ExprAffinity(pOrTerm.pExpr.pLeft);
1212
+ if (affRight != 0 && affRight != affLeft)
1213
+ {
1214
+ okToChngToIN = 0;
1215
+ }
1216
+ else
1217
+ {
1218
+ pOrTerm.wtFlags |= TERM_OR_OK;
1219
+ }
1220
+ }
1221
+ }
1222
+ }
1223
+
1224
+ /* At this point, okToChngToIN is true if original pTerm satisfies
1225
+ ** case 1. In that case, construct a new virtual term that is
1226
+ ** pTerm converted into an IN operator.
1227
+ */
1228
+ if (okToChngToIN != 0)
1229
+ {
1230
+ Expr pDup; /* A transient duplicate expression */
1231
+ ExprList pList = null; /* The RHS of the IN operator */
1232
+ Expr pLeft = null; /* The LHS of the IN operator */
1233
+ Expr pNew; /* The complete IN operator */
1234
+
1235
+ for (i = pOrWc.nTerm - 1; i >= 0; i--)//, pOrTerm++)
1236
+ {
1237
+ pOrTerm = pOrWc.a[pOrWc.nTerm - 1 - i];
1238
+ if ((pOrTerm.wtFlags & TERM_OR_OK) == 0) continue;
1239
+ Debug.Assert(pOrTerm.eOperator == WO_EQ);
1240
+ Debug.Assert(pOrTerm.leftCursor == iCursor);
1241
+ Debug.Assert(pOrTerm.u.leftColumn == iColumn);
1242
+ pDup = sqlite3ExprDup(db, pOrTerm.pExpr.pRight, 0);
1243
+ pList = sqlite3ExprListAppend(pWC.pParse, pList, pDup);
1244
+ pLeft = pOrTerm.pExpr.pLeft;
1245
+ }
1246
+ Debug.Assert(pLeft != null);
1247
+ pDup = sqlite3ExprDup(db, pLeft, 0);
1248
+ pNew = sqlite3PExpr(pParse, TK_IN, pDup, null, null);
1249
+ if (pNew != null)
1250
+ {
1251
+ int idxNew;
1252
+ transferJoinMarkings(pNew, pExpr);
1253
+ Debug.Assert(!ExprHasProperty(pNew, EP_xIsSelect));
1254
+ pNew.x.pList = pList;
1255
+ idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL | TERM_DYNAMIC);
1256
+ testcase(idxNew == 0);
1257
+ exprAnalyze(pSrc, pWC, idxNew);
1258
+ pTerm = pWC.a[idxTerm];
1259
+ pWC.a[idxNew].iParent = idxTerm;
1260
+ pTerm.nChild = 1;
1261
+ }
1262
+ else
1263
+ {
1264
+ sqlite3ExprListDelete(db, ref pList);
1265
+ }
1266
+ pTerm.eOperator = 0; /* case 1 trumps case 2 */
1267
+ }
1268
+ }
1269
+ }
1270
+ #endif //* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */
1271
+
1272
+
1273
+ /*
1274
+ ** The input to this routine is an WhereTerm structure with only the
1275
+ ** "pExpr" field filled in. The job of this routine is to analyze the
1276
+ ** subexpression and populate all the other fields of the WhereTerm
1277
+ ** structure.
1278
+ **
1279
+ ** If the expression is of the form "<expr> <op> X" it gets commuted
1280
+ ** to the standard form of "X <op> <expr>".
1281
+ **
1282
+ ** If the expression is of the form "X <op> Y" where both X and Y are
1283
+ ** columns, then the original expression is unchanged and a new virtual
1284
+ ** term of the form "Y <op> X" is added to the WHERE clause and
1285
+ ** analyzed separately. The original term is marked with TERM_COPIED
1286
+ ** and the new term is marked with TERM_DYNAMIC (because it's pExpr
1287
+ ** needs to be freed with the WhereClause) and TERM_VIRTUAL (because it
1288
+ ** is a commuted copy of a prior term.) The original term has nChild=1
1289
+ ** and the copy has idxParent set to the index of the original term.
1290
+ */
1291
+ static void exprAnalyze(
1292
+ SrcList pSrc, /* the FROM clause */
1293
+ WhereClause pWC, /* the WHERE clause */
1294
+ int idxTerm /* Index of the term to be analyzed */
1295
+ )
1296
+ {
1297
+ WhereTerm pTerm; /* The term to be analyzed */
1298
+ WhereMaskSet pMaskSet; /* Set of table index masks */
1299
+ Expr pExpr; /* The expression to be analyzed */
1300
+ Bitmask prereqLeft; /* Prerequesites of the pExpr.pLeft */
1301
+ Bitmask prereqAll; /* Prerequesites of pExpr */
1302
+ Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */
1303
+ Expr pStr1 = null; /* RHS of LIKE/GLOB operator */
1304
+ bool isComplete = false; /* RHS of LIKE/GLOB ends with wildcard */
1305
+ bool noCase = false; /* LIKE/GLOB distinguishes case */
1306
+ int op; /* Top-level operator. pExpr.op */
1307
+ Parse pParse = pWC.pParse; /* Parsing context */
1308
+ sqlite3 db = pParse.db; /* Data_base connection */
1309
+
1310
+ //if ( db.mallocFailed != 0 )
1311
+ //{
1312
+ // return;
1313
+ //}
1314
+ pTerm = pWC.a[idxTerm];
1315
+ pMaskSet = pWC.pMaskSet;
1316
+ pExpr = pTerm.pExpr;
1317
+ prereqLeft = exprTableUsage(pMaskSet, pExpr.pLeft);
1318
+ op = pExpr.op;
1319
+ if (op == TK_IN)
1320
+ {
1321
+ Debug.Assert(pExpr.pRight == null);
1322
+ if (ExprHasProperty(pExpr, EP_xIsSelect))
1323
+ {
1324
+ pTerm.prereqRight = exprSelectTableUsage(pMaskSet, pExpr.x.pSelect);
1325
+ }
1326
+ else
1327
+ {
1328
+ pTerm.prereqRight = exprListTableUsage(pMaskSet, pExpr.x.pList);
1329
+ }
1330
+ }
1331
+ else if (op == TK_ISNULL)
1332
+ {
1333
+ pTerm.prereqRight = 0;
1334
+ }
1335
+ else
1336
+ {
1337
+ pTerm.prereqRight = exprTableUsage(pMaskSet, pExpr.pRight);
1338
+ }
1339
+ prereqAll = exprTableUsage(pMaskSet, pExpr);
1340
+ if (ExprHasProperty(pExpr, EP_FromJoin))
1341
+ {
1342
+ Bitmask x = getMask(pMaskSet, pExpr.iRightJoinTable);
1343
+ prereqAll |= x;
1344
+ extraRight = x - 1; /* ON clause terms may not be used with an index
1345
+ ** on left table of a LEFT JOIN. Ticket #3015 */
1346
+ }
1347
+ pTerm.prereqAll = prereqAll;
1348
+ pTerm.leftCursor = -1;
1349
+ pTerm.iParent = -1;
1350
+ pTerm.eOperator = 0;
1351
+ if (allowedOp(op) && (pTerm.prereqRight & prereqLeft) == 0)
1352
+ {
1353
+ Expr pLeft = pExpr.pLeft;
1354
+ Expr pRight = pExpr.pRight;
1355
+ if (pLeft.op == TK_COLUMN)
1356
+ {
1357
+ pTerm.leftCursor = pLeft.iTable;
1358
+ pTerm.u.leftColumn = pLeft.iColumn;
1359
+ pTerm.eOperator = operatorMask(op);
1360
+ }
1361
+ if (pRight != null && pRight.op == TK_COLUMN)
1362
+ {
1363
+ WhereTerm pNew;
1364
+ Expr pDup;
1365
+ if (pTerm.leftCursor >= 0)
1366
+ {
1367
+ int idxNew;
1368
+ pDup = sqlite3ExprDup(db, pExpr, 0);
1369
+ //if ( db.mallocFailed != 0 )
1370
+ //{
1371
+ // sqlite3ExprDelete( db, ref pDup );
1372
+ // return;
1373
+ //}
1374
+ idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL | TERM_DYNAMIC);
1375
+ if (idxNew == 0) return;
1376
+ pNew = pWC.a[idxNew];
1377
+ pNew.iParent = idxTerm;
1378
+ pTerm = pWC.a[idxTerm];
1379
+ pTerm.nChild = 1;
1380
+ pTerm.wtFlags |= TERM_COPIED;
1381
+ }
1382
+ else
1383
+ {
1384
+ pDup = pExpr;
1385
+ pNew = pTerm;
1386
+ }
1387
+ exprCommute(pParse, pDup);
1388
+ pLeft = pDup.pLeft;
1389
+ pNew.leftCursor = pLeft.iTable;
1390
+ pNew.u.leftColumn = pLeft.iColumn;
1391
+ testcase((prereqLeft | extraRight) != prereqLeft);
1392
+ pNew.prereqRight = prereqLeft | extraRight;
1393
+ pNew.prereqAll = prereqAll;
1394
+ pNew.eOperator = operatorMask(pDup.op);
1395
+ }
1396
+ }
1397
+
1398
+ #if !SQLITE_OMIT_BETWEEN_OPTIMIZATION
1399
+ /* If a term is the BETWEEN operator, create two new virtual terms
1400
+ ** that define the range that the BETWEEN implements. For example:
1401
+ **
1402
+ ** a BETWEEN b AND c
1403
+ **
1404
+ ** is converted into:
1405
+ **
1406
+ ** (a BETWEEN b AND c) AND (a>=b) AND (a<=c)
1407
+ **
1408
+ ** The two new terms are added onto the end of the WhereClause object.
1409
+ ** The new terms are "dynamic" and are children of the original BETWEEN
1410
+ ** term. That means that if the BETWEEN term is coded, the children are
1411
+ ** skipped. Or, if the children are satisfied by an index, the original
1412
+ ** BETWEEN term is skipped.
1413
+ */
1414
+ else if (pExpr.op == TK_BETWEEN && pWC.op == TK_AND)
1415
+ {
1416
+ ExprList pList = pExpr.x.pList;
1417
+ int i;
1418
+ u8[] ops = new u8[] { TK_GE, TK_LE };
1419
+ Debug.Assert(pList != null);
1420
+ Debug.Assert(pList.nExpr == 2);
1421
+ for (i = 0; i < 2; i++)
1422
+ {
1423
+ Expr pNewExpr;
1424
+ int idxNew;
1425
+ pNewExpr = sqlite3PExpr(pParse, ops[i],
1426
+ sqlite3ExprDup(db, pExpr.pLeft, 0),
1427
+ sqlite3ExprDup(db, pList.a[i].pExpr, 0), null);
1428
+ idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL | TERM_DYNAMIC);
1429
+ testcase(idxNew == 0);
1430
+ exprAnalyze(pSrc, pWC, idxNew);
1431
+ pTerm = pWC.a[idxTerm];
1432
+ pWC.a[idxNew].iParent = idxTerm;
1433
+ }
1434
+ pTerm.nChild = 2;
1435
+ }
1436
+ #endif //* SQLITE_OMIT_BETWEEN_OPTIMIZATION */
1437
+
1438
+ #if !(SQLITE_OMIT_OR_OPTIMIZATION) && !(SQLITE_OMIT_SUBQUERY)
1439
+ /* Analyze a term that is composed of two or more subterms connected by
1440
+ ** an OR operator.
1441
+ */
1442
+ else if (pExpr.op == TK_OR)
1443
+ {
1444
+ Debug.Assert(pWC.op == TK_AND);
1445
+ exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
1446
+ pTerm = pWC.a[idxTerm];
1447
+ }
1448
+ #endif //* SQLITE_OMIT_OR_OPTIMIZATION */
1449
+
1450
+ #if !SQLITE_OMIT_LIKE_OPTIMIZATION
1451
+ /* Add constraints to reduce the search space on a LIKE or GLOB
1452
+ ** operator.
1453
+ **
1454
+ ** A like pattern of the form "x LIKE 'abc%'" is changed into constraints
1455
+ **
1456
+ ** x>='abc' AND x<'abd' AND x LIKE 'abc%'
1457
+ **
1458
+ ** The last character of the prefix "abc" is incremented to form the
1459
+ ** termination condition "abd".
1460
+ */
1461
+ if (pWC.op == TK_AND
1462
+ && isLikeOrGlob(pParse, pExpr, ref pStr1, ref isComplete, ref noCase) != 0
1463
+ )
1464
+ {
1465
+ Expr pLeft; /* LHS of LIKE/GLOB operator */
1466
+ Expr pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */
1467
+ Expr pNewExpr1;
1468
+ Expr pNewExpr2;
1469
+ int idxNew1;
1470
+ int idxNew2;
1471
+
1472
+ pLeft = pExpr.x.pList.a[1].pExpr;
1473
+ pStr2 = sqlite3ExprDup(db, pStr1, 0);
1474
+ ////if ( 0 == db.mallocFailed )
1475
+ {
1476
+ int c, pC; /* Last character before the first wildcard */
1477
+ pC = pStr2.u.zToken[sqlite3Strlen30(pStr2.u.zToken) - 1];
1478
+ c = pC;
1479
+ if (noCase)
1480
+ {
1481
+ /* The point is to increment the last character before the first
1482
+ ** wildcard. But if we increment '@', that will push it into the
1483
+ ** alphabetic range where case conversions will mess up the
1484
+ ** inequality. To avoid this, make sure to also run the full
1485
+ ** LIKE on all candidate expressions by clearing the isComplete flag
1486
+ */
1487
+ if (c == 'A' - 1) isComplete = false;
1488
+ c = sqlite3UpperToLower[c];
1489
+ }
1490
+ pStr2.u.zToken = pStr2.u.zToken.Substring(0, sqlite3Strlen30(pStr2.u.zToken) - 1) + (char)(c + 1);// pC = c + 1;
1491
+ }
1492
+ pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db, pLeft, 0), pStr1, null);
1493
+ idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL | TERM_DYNAMIC);
1494
+ testcase(idxNew1 == 0);
1495
+ exprAnalyze(pSrc, pWC, idxNew1);
1496
+ pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprDup(db, pLeft, 0), pStr2, null);
1497
+ idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL | TERM_DYNAMIC);
1498
+ testcase(idxNew2 == 0);
1499
+ exprAnalyze(pSrc, pWC, idxNew2);
1500
+ pTerm = pWC.a[idxTerm];
1501
+ if (isComplete)
1502
+ {
1503
+ pWC.a[idxNew1].iParent = idxTerm;
1504
+ pWC.a[idxNew2].iParent = idxTerm;
1505
+ pTerm.nChild = 2;
1506
+ }
1507
+ }
1508
+ #endif //* SQLITE_OMIT_LIKE_OPTIMIZATION */
1509
+
1510
+ #if !SQLITE_OMIT_VIRTUALTABLE
1511
+ /* Add a WO_MATCH auxiliary term to the constraint set if the
1512
+ ** current expression is of the form: column MATCH expr.
1513
+ ** This information is used by the xBestIndex methods of
1514
+ ** virtual tables. The native query optimizer does not attempt
1515
+ ** to do anything with MATCH functions.
1516
+ */
1517
+ if ( isMatchOfColumn( pExpr ) )
1518
+ {
1519
+ int idxNew;
1520
+ Expr pRight, pLeft;
1521
+ WhereTerm pNewTerm;
1522
+ Bitmask prereqColumn, prereqExpr;
1523
+
1524
+ pRight = pExpr.x.pList.a[0].pExpr;
1525
+ pLeft = pExpr.x.pList.a[1].pExpr;
1526
+ prereqExpr = exprTableUsage( pMaskSet, pRight );
1527
+ prereqColumn = exprTableUsage( pMaskSet, pLeft );
1528
+ if ( ( prereqExpr & prereqColumn ) == null )
1529
+ {
1530
+ Expr pNewExpr;
1531
+ pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
1532
+ 0, sqlite3ExprDup(db, pRight, 0), 0);
1533
+ idxNew = whereClauseInsert( pWC, pNewExpr, TERM_VIRTUAL | TERM_DYNAMIC );
1534
+ testcase( idxNew == 0 );
1535
+ pNewTerm = pWC.a[idxNew];
1536
+ pNewTerm.prereqRight = prereqExpr;
1537
+ pNewTerm.leftCursor = pLeft.iTable;
1538
+ pNewTerm.u.leftColumn = pLeft.iColumn;
1539
+ pNewTerm.eOperator = WO_MATCH;
1540
+ pNewTerm.iParent = idxTerm;
1541
+ pTerm = pWC.a[idxTerm];
1542
+ pTerm.nChild = 1;
1543
+ pTerm.wtFlags |= TERM_COPIED;
1544
+ pNewTerm.prereqAll = pTerm.prereqAll;
1545
+ }
1546
+ }
1547
+ #endif //* SQLITE_OMIT_VIRTUALTABLE */
1548
+
1549
+ /* Prevent ON clause terms of a LEFT JOIN from being used to drive
1550
+ ** an index for tables to the left of the join.
1551
+ */
1552
+ pTerm.prereqRight |= extraRight;
1553
+ }
1554
+
1555
+ /*
1556
+ ** Return TRUE if any of the expressions in pList.a[iFirst...] contain
1557
+ ** a reference to any table other than the iBase table.
1558
+ */
1559
+ static bool referencesOtherTables(
1560
+ ExprList pList, /* Search expressions in ths list */
1561
+ WhereMaskSet pMaskSet, /* Mapping from tables to bitmaps */
1562
+ int iFirst, /* Be searching with the iFirst-th expression */
1563
+ int iBase /* Ignore references to this table */
1564
+ )
1565
+ {
1566
+ Bitmask allowed = ~getMask(pMaskSet, iBase);
1567
+ while (iFirst < pList.nExpr)
1568
+ {
1569
+ if ((exprTableUsage(pMaskSet, pList.a[iFirst++].pExpr) & allowed) != 0)
1570
+ {
1571
+ return true;
1572
+ }
1573
+ }
1574
+ return false;
1575
+ }
1576
+
1577
+
1578
+ /*
1579
+ ** This routine decides if pIdx can be used to satisfy the ORDER BY
1580
+ ** clause. If it can, it returns 1. If pIdx cannot satisfy the
1581
+ ** ORDER BY clause, this routine returns 0.
1582
+ **
1583
+ ** pOrderBy is an ORDER BY clause from a SELECT statement. pTab is the
1584
+ ** left-most table in the FROM clause of that same SELECT statement and
1585
+ ** the table has a cursor number of "_base". pIdx is an index on pTab.
1586
+ **
1587
+ ** nEqCol is the number of columns of pIdx that are used as equality
1588
+ ** constraints. Any of these columns may be missing from the ORDER BY
1589
+ ** clause and the match can still be a success.
1590
+ **
1591
+ ** All terms of the ORDER BY that match against the index must be either
1592
+ ** ASC or DESC. (Terms of the ORDER BY clause past the end of a UNIQUE
1593
+ ** index do not need to satisfy this constraint.) The pbRev value is
1594
+ ** set to 1 if the ORDER BY clause is all DESC and it is set to 0 if
1595
+ ** the ORDER BY clause is all ASC.
1596
+ */
1597
+ static bool isSortingIndex(
1598
+ Parse pParse, /* Parsing context */
1599
+ WhereMaskSet pMaskSet, /* Mapping from table cursor numbers to bitmaps */
1600
+ Index pIdx, /* The index we are testing */
1601
+ int _base, /* Cursor number for the table to be sorted */
1602
+ ExprList pOrderBy, /* The ORDER BY clause */
1603
+ int nEqCol, /* Number of index columns with == constraints */
1604
+ ref int pbRev /* Set to 1 if ORDER BY is DESC */
1605
+ )
1606
+ {
1607
+ int i, j; /* Loop counters */
1608
+ int sortOrder = 0; /* XOR of index and ORDER BY sort direction */
1609
+ int nTerm; /* Number of ORDER BY terms */
1610
+ ExprList_item pTerm; /* A term of the ORDER BY clause */
1611
+ sqlite3 db = pParse.db;
1612
+
1613
+ Debug.Assert(pOrderBy != null);
1614
+ nTerm = pOrderBy.nExpr;
1615
+ Debug.Assert(nTerm > 0);
1616
+
1617
+ /* Argument pIdx must either point to a 'real' named index structure,
1618
+ ** or an index structure allocated on the stack by bestBtreeIndex() to
1619
+ ** represent the rowid index that is part of every table. */
1620
+ Debug.Assert(!String.IsNullOrEmpty(pIdx.zName) || (pIdx.nColumn == 1 && pIdx.aiColumn[0] == -1));
1621
+
1622
+ /* Match terms of the ORDER BY clause against columns of
1623
+ ** the index.
1624
+ **
1625
+ ** Note that indices have pIdx.nColumn regular columns plus
1626
+ ** one additional column containing the rowid. The rowid column
1627
+ ** of the index is also allowed to match against the ORDER BY
1628
+ ** clause.
1629
+ */
1630
+ for (i = j = 0; j < nTerm && i <= pIdx.nColumn; i++)
1631
+ {
1632
+ pTerm = pOrderBy.a[j];
1633
+ Expr pExpr; /* The expression of the ORDER BY pTerm */
1634
+ CollSeq pColl; /* The collating sequence of pExpr */
1635
+ int termSortOrder; /* Sort order for this term */
1636
+ int iColumn; /* The i-th column of the index. -1 for rowid */
1637
+ int iSortOrder; /* 1 for DESC, 0 for ASC on the i-th index term */
1638
+ string zColl; /* Name of the collating sequence for i-th index term */
1639
+
1640
+ pExpr = pTerm.pExpr;
1641
+ if (pExpr.op != TK_COLUMN || pExpr.iTable != _base)
1642
+ {
1643
+ /* Can not use an index sort on anything that is not a column in the
1644
+ ** left-most table of the FROM clause */
1645
+ break;
1646
+ }
1647
+ pColl = sqlite3ExprCollSeq(pParse, pExpr);
1648
+ if (null == pColl)
1649
+ {
1650
+ pColl = db.pDfltColl;
1651
+ }
1652
+ if (!String.IsNullOrEmpty(pIdx.zName) && i < pIdx.nColumn)
1653
+ {
1654
+ iColumn = pIdx.aiColumn[i];
1655
+ if (iColumn == pIdx.pTable.iPKey)
1656
+ {
1657
+ iColumn = -1;
1658
+ }
1659
+ iSortOrder = pIdx.aSortOrder[i];
1660
+ zColl = pIdx.azColl[i];
1661
+ }
1662
+ else
1663
+ {
1664
+ iColumn = -1;
1665
+ iSortOrder = 0;
1666
+ zColl = pColl.zName;
1667
+ }
1668
+ if (pExpr.iColumn != iColumn || sqlite3StrICmp(pColl.zName, zColl) != 0)
1669
+ {
1670
+ /* Term j of the ORDER BY clause does not match column i of the index */
1671
+ if (i < nEqCol)
1672
+ {
1673
+ /* If an index column that is constrained by == fails to match an
1674
+ ** ORDER BY term, that is OK. Just ignore that column of the index
1675
+ */
1676
+ continue;
1677
+ }
1678
+ else if (i == pIdx.nColumn)
1679
+ {
1680
+ /* Index column i is the rowid. All other terms match. */
1681
+ break;
1682
+ }
1683
+ else
1684
+ {
1685
+ /* If an index column fails to match and is not constrained by ==
1686
+ ** then the index cannot satisfy the ORDER BY constraint.
1687
+ */
1688
+ return false;
1689
+ }
1690
+ }
1691
+ Debug.Assert(pIdx.aSortOrder != null || iColumn == -1);
1692
+ Debug.Assert(pTerm.sortOrder == 0 || pTerm.sortOrder == 1);
1693
+ Debug.Assert(iSortOrder == 0 || iSortOrder == 1);
1694
+ termSortOrder = iSortOrder ^ pTerm.sortOrder;
1695
+ if (i > nEqCol)
1696
+ {
1697
+ if (termSortOrder != sortOrder)
1698
+ {
1699
+ /* Indices can only be used if all ORDER BY terms past the
1700
+ ** equality constraints are all either DESC or ASC. */
1701
+ return false;
1702
+ }
1703
+ }
1704
+ else
1705
+ {
1706
+ sortOrder = termSortOrder;
1707
+ }
1708
+ j++;
1709
+ //pTerm++;
1710
+ if (iColumn < 0 && !referencesOtherTables(pOrderBy, pMaskSet, j, _base))
1711
+ {
1712
+ /* If the indexed column is the primary key and everything matches
1713
+ ** so far and none of the ORDER BY terms to the right reference other
1714
+ ** tables in the join, then we are Debug.Assured that the index can be used
1715
+ ** to sort because the primary key is unique and so none of the other
1716
+ ** columns will make any difference
1717
+ */
1718
+ j = nTerm;
1719
+ }
1720
+ }
1721
+
1722
+ pbRev = sortOrder != 0 ? 1 : 0;
1723
+ if (j >= nTerm)
1724
+ {
1725
+ /* All terms of the ORDER BY clause are covered by this index so
1726
+ ** this index can be used for sorting. */
1727
+ return true;
1728
+ }
1729
+ if (pIdx.onError != OE_None && i == pIdx.nColumn
1730
+ && !referencesOtherTables(pOrderBy, pMaskSet, j, _base))
1731
+ {
1732
+ /* All terms of this index match some prefix of the ORDER BY clause
1733
+ ** and the index is UNIQUE and no terms on the tail of the ORDER BY
1734
+ ** clause reference other tables in a join. If this is all true then
1735
+ ** the order by clause is superfluous. */
1736
+ return true;
1737
+ }
1738
+ return false;
1739
+ }
1740
+
1741
+ /*
1742
+ ** Prepare a crude estimate of the logarithm of the input value.
1743
+ ** The results need not be exact. This is only used for estimating
1744
+ ** the total cost of performing operations with O(logN) or O(NlogN)
1745
+ ** complexity. Because N is just a guess, it is no great tragedy if
1746
+ ** logN is a little off.
1747
+ */
1748
+ static double estLog(double N)
1749
+ {
1750
+ double logN = 1;
1751
+ double x = 10;
1752
+ while (N > x)
1753
+ {
1754
+ logN += 1;
1755
+ x *= 10;
1756
+ }
1757
+ return logN;
1758
+ }
1759
+
1760
+ /*
1761
+ ** Two routines for printing the content of an sqlite3_index_info
1762
+ ** structure. Used for testing and debugging only. If neither
1763
+ ** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines
1764
+ ** are no-ops.
1765
+ */
1766
+ #if !(SQLITE_OMIT_VIRTUALTABLE) && (SQLITE_DEBUG)
1767
+ static void TRACE_IDX_INPUTS( sqlite3_index_info p )
1768
+ {
1769
+ int i;
1770
+ if ( !sqlite3WhereTrace ) return;
1771
+ for ( i = 0 ; i < p.nConstraint ; i++ )
1772
+ {
1773
+ sqlite3DebugPrintf( " constraint[%d]: col=%d termid=%d op=%d usabled=%d\n",
1774
+ i,
1775
+ p.aConstraint[i].iColumn,
1776
+ p.aConstraint[i].iTermOffset,
1777
+ p.aConstraint[i].op,
1778
+ p.aConstraint[i].usable );
1779
+ }
1780
+ for ( i = 0 ; i < p.nOrderBy ; i++ )
1781
+ {
1782
+ sqlite3DebugPrintf( " orderby[%d]: col=%d desc=%d\n",
1783
+ i,
1784
+ p.aOrderBy[i].iColumn,
1785
+ p.aOrderBy[i].desc );
1786
+ }
1787
+ }
1788
+ static void TRACE_IDX_OUTPUTS( sqlite3_index_info p )
1789
+ {
1790
+ int i;
1791
+ if ( !sqlite3WhereTrace ) return;
1792
+ for ( i = 0 ; i < p.nConstraint ; i++ )
1793
+ {
1794
+ sqlite3DebugPrintf( " usage[%d]: argvIdx=%d omit=%d\n",
1795
+ i,
1796
+ p.aConstraintUsage[i].argvIndex,
1797
+ p.aConstraintUsage[i].omit );
1798
+ }
1799
+ sqlite3DebugPrintf( " idxNum=%d\n", p.idxNum );
1800
+ sqlite3DebugPrintf( " idxStr=%s\n", p.idxStr );
1801
+ sqlite3DebugPrintf( " orderByConsumed=%d\n", p.orderByConsumed );
1802
+ sqlite3DebugPrintf( " estimatedCost=%g\n", p.estimatedCost );
1803
+ }
1804
+ #else
1805
+ //#define TRACE_IDX_INPUTS(A)
1806
+ //#define TRACE_IDX_OUTPUTS(A)
1807
+ #endif
1808
+
1809
+ /*
1810
+ ** Required because bestIndex() is called by bestOrClauseIndex()
1811
+ */
1812
+ //static void bestIndex(
1813
+ //Parse*, WhereClause*, struct SrcList_item*, Bitmask, ExprList*, WhereCost*);
1814
+
1815
+ /*
1816
+ ** This routine attempts to find an scanning strategy that can be used
1817
+ ** to optimize an 'OR' expression that is part of a WHERE clause.
1818
+ **
1819
+ ** The table associated with FROM clause term pSrc may be either a
1820
+ ** regular B-Tree table or a virtual table.
1821
+ */
1822
+ static void bestOrClauseIndex(
1823
+ Parse pParse, /* The parsing context */
1824
+ WhereClause pWC, /* The WHERE clause */
1825
+ SrcList_item pSrc, /* The FROM clause term to search */
1826
+ Bitmask notReady, /* Mask of cursors that are not available */
1827
+ ExprList pOrderBy, /* The ORDER BY clause */
1828
+ WhereCost pCost /* Lowest cost query plan */
1829
+ )
1830
+ {
1831
+ #if !SQLITE_OMIT_OR_OPTIMIZATION
1832
+ int iCur = pSrc.iCursor; /* The cursor of the table to be accessed */
1833
+ Bitmask maskSrc = getMask(pWC.pMaskSet, iCur); /* Bitmask for pSrc */
1834
+ WhereTerm pWCEnd = pWC.a[pWC.nTerm]; /* End of pWC.a[] */
1835
+ WhereTerm pTerm; /* A single term of the WHERE clause */
1836
+
1837
+ /* Search the WHERE clause terms for a usable WO_OR term. */
1838
+ for (int _pt = 0; _pt < pWC.nTerm; _pt++)//<pWCEnd; pTerm++)
1839
+ {
1840
+ pTerm = pWC.a[_pt];
1841
+ if (pTerm.eOperator == WO_OR
1842
+ && ((pTerm.prereqAll & ~maskSrc) & notReady) == 0
1843
+ && (pTerm.u.pOrInfo.indexable & maskSrc) != 0
1844
+ )
1845
+ {
1846
+ WhereClause pOrWC = pTerm.u.pOrInfo.wc;
1847
+ WhereTerm pOrWCEnd = pOrWC.a[pOrWC.nTerm];
1848
+ WhereTerm pOrTerm;
1849
+ int flags = WHERE_MULTI_OR;
1850
+ double rTotal = 0;
1851
+ double nRow = 0;
1852
+ Bitmask used = 0;
1853
+
1854
+ for (int _pOrWC = 0; _pOrWC < pOrWC.nTerm; _pOrWC++)//pOrTerm = pOrWC.a ; pOrTerm < pOrWCEnd ; pOrTerm++ )
1855
+ {
1856
+ pOrTerm = pOrWC.a[_pOrWC];
1857
+ WhereCost sTermCost = null;
1858
+ #if (SQLITE_TEST) && (SQLITE_DEBUG)
1859
+ WHERETRACE("... Multi-index OR testing for term %d of %d....\n",
1860
+ _pOrWC, pOrWC.nTerm - _pOrWC//( pOrTerm - pOrWC.a ), ( pTerm - pWC.a )
1861
+ );
1862
+ #endif
1863
+ if (pOrTerm.eOperator == WO_AND)
1864
+ {
1865
+ WhereClause pAndWC = pOrTerm.u.pAndInfo.wc;
1866
+ bestIndex(pParse, pAndWC, pSrc, notReady, null, ref sTermCost);
1867
+ }
1868
+ else if (pOrTerm.leftCursor == iCur)
1869
+ {
1870
+ WhereClause tempWC = new WhereClause();
1871
+ tempWC.pParse = pWC.pParse;
1872
+ tempWC.pMaskSet = pWC.pMaskSet;
1873
+ tempWC.op = TK_AND;
1874
+ tempWC.a = new WhereTerm[2];
1875
+ tempWC.a[0] = pOrTerm;
1876
+ tempWC.nTerm = 1;
1877
+ bestIndex(pParse, tempWC, pSrc, notReady, null, ref sTermCost);
1878
+ }
1879
+ else
1880
+ {
1881
+ continue;
1882
+ }
1883
+ rTotal += sTermCost.rCost;
1884
+ nRow += sTermCost.nRow;
1885
+ used |= sTermCost.used;
1886
+ if (rTotal >= pCost.rCost) break;
1887
+ }
1888
+
1889
+ /* If there is an ORDER BY clause, increase the scan cost to account
1890
+ ** for the cost of the sort. */
1891
+ if (pOrderBy != null)
1892
+ {
1893
+ rTotal += nRow * estLog(nRow);
1894
+ #if (SQLITE_TEST) && (SQLITE_DEBUG)
1895
+ WHERETRACE("... sorting increases OR cost to %.9g\n", rTotal);
1896
+ #endif
1897
+ }
1898
+
1899
+ /* If the cost of scanning using this OR term for optimization is
1900
+ ** less than the current cost stored in pCost, replace the contents
1901
+ ** of pCost. */
1902
+ #if (SQLITE_TEST) && (SQLITE_DEBUG)
1903
+ WHERETRACE("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow);
1904
+ #endif
1905
+ if (rTotal < pCost.rCost)
1906
+ {
1907
+ pCost.rCost = rTotal;
1908
+ pCost.nRow = nRow;
1909
+ pCost.used = used;
1910
+ pCost.plan.wsFlags = (uint)flags;
1911
+ pCost.plan.u.pTerm = pTerm;
1912
+ }
1913
+ }
1914
+ }
1915
+ #endif //* SQLITE_OMIT_OR_OPTIMIZATION */
1916
+ }
1917
+
1918
+ #if !SQLITE_OMIT_VIRTUALTABLE
1919
+ /*
1920
+ ** Allocate and populate an sqlite3_index_info structure. It is the
1921
+ ** responsibility of the caller to eventually release the structure
1922
+ ** by passing the pointer returned by this function to //sqlite3_free().
1923
+ */
1924
+ static sqlite3_index_info *allocateIndexInfo(
1925
+ Parse *pParse,
1926
+ WhereClause *pWC,
1927
+ struct SrcList_item *pSrc,
1928
+ ExprList *pOrderBy
1929
+ ){
1930
+ int i, j;
1931
+ int nTerm;
1932
+ struct sqlite3_index_constraint *pIdxCons;
1933
+ struct sqlite3_index_orderby *pIdxOrderBy;
1934
+ struct sqlite3_index_constraint_usage *pUsage;
1935
+ WhereTerm *pTerm;
1936
+ int nOrderBy;
1937
+ sqlite3_index_info *pIdxInfo;
1938
+
1939
+ WHERETRACE("Recomputing index info for %s...\n", pSrc.pTab.zName);
1940
+
1941
+ /* Count the number of possible WHERE clause constraints referring
1942
+ ** to this virtual table */
1943
+ for(i=nTerm=0, pTerm=pWC.a; i<pWC.nTerm; i++, pTerm++){
1944
+ if( pTerm.leftCursor != pSrc.iCursor ) continue;
1945
+ Debug.Assert( (pTerm.eOperator&(pTerm.eOperator-1))==null );
1946
+ testcase( pTerm.eOperator==WO_IN );
1947
+ testcase( pTerm.eOperator==WO_ISNULL );
1948
+ if( pTerm.eOperator & (WO_IN|WO_ISNULL) ) continue;
1949
+ nTerm++;
1950
+ }
1951
+
1952
+ /* If the ORDER BY clause contains only columns in the current
1953
+ ** virtual table then allocate space for the aOrderBy part of
1954
+ ** the sqlite3_index_info structure.
1955
+ */
1956
+ nOrderBy = 0;
1957
+ if( pOrderBy ){
1958
+ for(i=0; i<pOrderBy.nExpr; i++){
1959
+ Expr pExpr = pOrderBy.a[i].pExpr;
1960
+ if( pExpr.op!=TK_COLUMN || pExpr.iTable!=pSrc.iCursor ) break;
1961
+ }
1962
+ if( i==pOrderBy.nExpr ){
1963
+ nOrderBy = pOrderBy.nExpr;
1964
+ }
1965
+ }
1966
+
1967
+ /* Allocate the sqlite3_index_info structure
1968
+ */
1969
+ pIdxInfo = new sqlite3_index_info();
1970
+ //sqlite3DbMallocZero(pParse.db, sizeof(*pIdxInfo)
1971
+ //+ (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
1972
+ //+ sizeof(*pIdxOrderBy)*nOrderBy );
1973
+ if( pIdxInfo==null ){
1974
+ sqlite3ErrorMsg(pParse, "out of memory");
1975
+ /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
1976
+ return 0;
1977
+ }
1978
+
1979
+ /* Initialize the structure. The sqlite3_index_info structure contains
1980
+ ** many fields that are declared "const" to prevent xBestIndex from
1981
+ ** changing them. We have to do some funky casting in order to
1982
+ ** initialize those fields.
1983
+ */
1984
+ pIdxCons = (sqlite3_index_constraint)pIdxInfo[1];
1985
+ pIdxOrderBy = (sqlite3_index_orderby)pIdxCons[nTerm];
1986
+ pUsage = (sqlite3_index_constraint_usage)pIdxOrderBy[nOrderBy];
1987
+ pIdxInfo.nConstraint = nTerm;
1988
+ pIdxInfo.nOrderBy = nOrderBy;
1989
+ pIdxInfo.aConstraint = pIdxCons;
1990
+ pIdxInfo.aOrderBy = pIdxOrderBy;
1991
+ pIdxInfo.aConstraintUsage =
1992
+ pUsage;
1993
+
1994
+ for(i=j=0, pTerm=pWC.a; i<pWC.nTerm; i++, pTerm++){
1995
+ if( pTerm.leftCursor != pSrc.iCursor ) continue;
1996
+ Debug.Assert( (pTerm.eOperator&(pTerm.eOperator-1))==null );
1997
+ testcase( pTerm.eOperator==WO_IN );
1998
+ testcase( pTerm.eOperator==WO_ISNULL );
1999
+ if( pTerm.eOperator & (WO_IN|WO_ISNULL) ) continue;
2000
+ pIdxCons[j].iColumn = pTerm.u.leftColumn;
2001
+ pIdxCons[j].iTermOffset = i;
2002
+ pIdxCons[j].op = (u8)pTerm.eOperator;
2003
+ /* The direct Debug.Assignment in the previous line is possible only because
2004
+ ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
2005
+ ** following Debug.Asserts verify this fact. */
2006
+ Debug.Assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
2007
+ Debug.Assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
2008
+ Debug.Assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
2009
+ Debug.Assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
2010
+ Debug.Assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
2011
+ Debug.Assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
2012
+ Debug.Assert( pTerm.eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
2013
+ j++;
2014
+ }
2015
+ for(i=0; i<nOrderBy; i++){
2016
+ Expr pExpr = pOrderBy.a[i].pExpr;
2017
+ pIdxOrderBy[i].iColumn = pExpr.iColumn;
2018
+ pIdxOrderBy[i].desc = pOrderBy.a[i].sortOrder;
2019
+ }
2020
+
2021
+ return pIdxInfo;
2022
+ }
2023
+
2024
+ /*
2025
+ ** The table object reference passed as the second argument to this function
2026
+ ** must represent a virtual table. This function invokes the xBestIndex()
2027
+ ** method of the virtual table with the sqlite3_index_info pointer passed
2028
+ ** as the argument.
2029
+ **
2030
+ ** If an error occurs, pParse is populated with an error message and a
2031
+ ** non-zero value is returned. Otherwise, 0 is returned and the output
2032
+ ** part of the sqlite3_index_info structure is left populated.
2033
+ **
2034
+ ** Whether or not an error is returned, it is the responsibility of the
2035
+ ** caller to eventually free p.idxStr if p.needToFreeIdxStr indicates
2036
+ ** that this is required.
2037
+ */
2038
+ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
2039
+ sqlite3_vtab *pVtab = sqlite3GetVTable(pParse.db, pTab).pVtab;
2040
+ int i;
2041
+ int rc;
2042
+
2043
+ WHERETRACE("xBestIndex for %s\n", pTab.zName);
2044
+ TRACE_IDX_INPUTS(p);
2045
+ rc = pVtab.pModule.xBestIndex(pVtab, p);
2046
+ TRACE_IDX_OUTPUTS(p);
2047
+
2048
+ if( rc!=SQLITE_OK ){
2049
+ if( rc==SQLITE_NOMEM ){
2050
+ pParse.db.mallocFailed = 1;
2051
+ }else if( !pVtab.zErrMsg ){
2052
+ sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
2053
+ }else{
2054
+ sqlite3ErrorMsg(pParse, "%s", pVtab.zErrMsg);
2055
+ }
2056
+ }
2057
+ sqlite3DbFree(pParse.db, pVtab.zErrMsg);
2058
+ pVtab.zErrMsg = 0;
2059
+
2060
+ for(i=0; i<p.nConstraint; i++){
2061
+ if( !p.aConstraint[i].usable && p.aConstraintUsage[i].argvIndex>0 ){
2062
+ sqlite3ErrorMsg(pParse,
2063
+ "table %s: xBestIndex returned an invalid plan", pTab.zName);
2064
+ }
2065
+ }
2066
+
2067
+ return pParse.nErr;
2068
+ }
2069
+
2070
+
2071
+ /*
2072
+ ** Compute the best index for a virtual table.
2073
+ **
2074
+ ** The best index is computed by the xBestIndex method of the virtual
2075
+ ** table module. This routine is really just a wrapper that sets up
2076
+ ** the sqlite3_index_info structure that is used to communicate with
2077
+ ** xBestIndex.
2078
+ **
2079
+ ** In a join, this routine might be called multiple times for the
2080
+ ** same virtual table. The sqlite3_index_info structure is created
2081
+ ** and initialized on the first invocation and reused on all subsequent
2082
+ ** invocations. The sqlite3_index_info structure is also used when
2083
+ ** code is generated to access the virtual table. The whereInfoDelete()
2084
+ ** routine takes care of freeing the sqlite3_index_info structure after
2085
+ ** everybody has finished with it.
2086
+ */
2087
+ static void bestVirtualIndex(
2088
+ Parse *pParse, /* The parsing context */
2089
+ WhereClause *pWC, /* The WHERE clause */
2090
+ struct SrcList_item *pSrc, /* The FROM clause term to search */
2091
+ Bitmask notReady, /* Mask of cursors that are not available */
2092
+ ExprList *pOrderBy, /* The order by clause */
2093
+ WhereCost *pCost, /* Lowest cost query plan */
2094
+ sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */
2095
+ ){
2096
+ Table *pTab = pSrc.pTab;
2097
+ sqlite3_index_info *pIdxInfo;
2098
+ struct sqlite3_index_constraint *pIdxCons;
2099
+ struct sqlite3_index_constraint_usage *pUsage;
2100
+ WhereTerm *pTerm;
2101
+ int i, j;
2102
+ int nOrderBy;
2103
+
2104
+ /* Make sure wsFlags is initialized to some sane value. Otherwise, if the
2105
+ ** malloc in allocateIndexInfo() fails and this function returns leaving
2106
+ ** wsFlags in an uninitialized state, the caller may behave unpredictably.
2107
+ */
2108
+ memset(pCost, 0, sizeof(*pCost));
2109
+ pCost.plan.wsFlags = WHERE_VIRTUALTABLE;
2110
+
2111
+ /* If the sqlite3_index_info structure has not been previously
2112
+ ** allocated and initialized, then allocate and initialize it now.
2113
+ */
2114
+ pIdxInfo = *ppIdxInfo;
2115
+ if( pIdxInfo==0 ){
2116
+ *ppIdxInfo = pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pOrderBy);
2117
+ }
2118
+ if( pIdxInfo==0 ){
2119
+ return;
2120
+ }
2121
+
2122
+ /* At this point, the sqlite3_index_info structure that pIdxInfo points
2123
+ ** to will have been initialized, either during the current invocation or
2124
+ ** during some prior invocation. Now we just have to customize the
2125
+ ** details of pIdxInfo for the current invocation and pDebug.Ass it to
2126
+ ** xBestIndex.
2127
+ */
2128
+
2129
+ /* The module name must be defined. Also, by this point there must
2130
+ ** be a pointer to an sqlite3_vtab structure. Otherwise
2131
+ ** sqlite3ViewGetColumnNames() would have picked up the error.
2132
+ */
2133
+ Debug.Assert( pTab.azModuleArg && pTab.azModuleArg[0] );
2134
+ Debug.Assert( sqlite3GetVTable(pParse.db, pTab) );
2135
+
2136
+ /* Set the aConstraint[].usable fields and initialize all
2137
+ ** output variables to zero.
2138
+ **
2139
+ ** aConstraint[].usable is true for constraints where the right-hand
2140
+ ** side contains only references to tables to the left of the current
2141
+ ** table. In other words, if the constraint is of the form:
2142
+ **
2143
+ ** column = expr
2144
+ **
2145
+ ** and we are evaluating a join, then the constraint on column is
2146
+ ** only valid if all tables referenced in expr occur to the left
2147
+ ** of the table containing column.
2148
+ **
2149
+ ** The aConstraints[] array contains entries for all constraints
2150
+ ** on the current table. That way we only have to compute it once
2151
+ ** even though we might try to pick the best index multiple times.
2152
+ ** For each attempt at picking an index, the order of tables in the
2153
+ ** join might be different so we have to recompute the usable flag
2154
+ ** each time.
2155
+ */
2156
+ pIdxCons = pIdxInfo.aConstraint;
2157
+ pUsage = pIdxInfo.aConstraintUsage;
2158
+ for(i=0; i<pIdxInfo.nConstraint; i++, pIdxCons++){
2159
+ j = pIdxCons.iTermOffset;
2160
+ pTerm = pWC.a[j];
2161
+ pIdxCons.usable = (pTerm.prereqRight&notReady) ? 0 : 1;
2162
+ pUsage[i] = new sqlite3_index_constraint_usage();
2163
+ }
2164
+ // memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo.nConstraint);
2165
+ if( pIdxInfo.needToFreeIdxStr ){
2166
+ //sqlite3_free(ref pIdxInfo.idxStr);
2167
+ }
2168
+ pIdxInfo.idxStr = 0;
2169
+ pIdxInfo.idxNum = 0;
2170
+ pIdxInfo.needToFreeIdxStr = 0;
2171
+ pIdxInfo.orderByConsumed = 0;
2172
+ /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
2173
+ pIdxInfo.estimatedCost = SQLITE_BIG_DBL / ((double)2);
2174
+ nOrderBy = pIdxInfo.nOrderBy;
2175
+ if( !pOrderBy ){
2176
+ pIdxInfo.nOrderBy = 0;
2177
+ }
2178
+
2179
+ if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
2180
+ return;
2181
+ }
2182
+
2183
+ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo.aConstraint;
2184
+ for(i=0; i<pIdxInfo.nConstraint; i++){
2185
+ if( pUsage[i].argvIndex>0 ){
2186
+ pCost.used |= pWC.a[pIdxCons[i].iTermOffset].prereqRight;
2187
+ }
2188
+ }
2189
+
2190
+ /* The cost is not allowed to be larger than SQLITE_BIG_DBL (the
2191
+ ** inital value of lowestCost in this loop. If it is, then the
2192
+ ** (cost<lowestCost) test below will never be true.
2193
+ **
2194
+ ** Use "(double)2" instead of "2.0" in case OMIT_FLOATING_POINT
2195
+ ** is defined.
2196
+ */
2197
+ if( (SQLITE_BIG_DBL/((double)2))<pIdxInfo.estimatedCost ){
2198
+ pCost.rCost = (SQLITE_BIG_DBL/((double)2));
2199
+ }else{
2200
+ pCost.rCost = pIdxInfo.estimatedCost;
2201
+ }
2202
+ pCost.plan.u.pVtabIdx = pIdxInfo;
2203
+ if( pIdxInfo.orderByConsumed ){
2204
+ pCost.plan.wsFlags |= WHERE_ORDERBY;
2205
+ }
2206
+ pCost.plan.nEq = 0;
2207
+ pIdxInfo.nOrderBy = nOrderBy;
2208
+
2209
+ /* Try to find a more efficient access pattern by using multiple indexes
2210
+ ** to optimize an OR expression within the WHERE clause.
2211
+ */
2212
+ bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
2213
+ }
2214
+ #endif //* SQLITE_OMIT_VIRTUALTABLE */
2215
+
2216
+ /*
2217
+ ** Argument pIdx is a pointer to an index structure that has an array of
2218
+ ** SQLITE_INDEX_SAMPLES evenly spaced samples of the first indexed column
2219
+ ** stored in Index.aSample. The domain of values stored in said column
2220
+ ** may be thought of as divided into (SQLITE_INDEX_SAMPLES+1) regions.
2221
+ ** Region 0 contains all values smaller than the first sample value. Region
2222
+ ** 1 contains values larger than or equal to the value of the first sample,
2223
+ ** but smaller than the value of the second. And so on.
2224
+ **
2225
+ ** If successful, this function determines which of the regions value
2226
+ ** pVal lies in, sets *piRegion to the region index (a value between 0
2227
+ ** and SQLITE_INDEX_SAMPLES+1, inclusive) and returns SQLITE_OK.
2228
+ ** Or, if an OOM occurs while converting text values between encodings,
2229
+ ** SQLITE_NOMEM is returned and *piRegion is undefined.
2230
+ */
2231
+ #if SQLITE_ENABLE_STAT2
2232
+ static int whereRangeRegion(
2233
+ Parse pParse, /* Database connection */
2234
+ Index pIdx, /* Index to consider domain of */
2235
+ sqlite3_value pVal, /* Value to consider */
2236
+ ref int piRegion /* OUT: Region of domain in which value lies */
2237
+ ){
2238
+ if( ALWAYS(pVal) ){
2239
+ IndexSample[] aSample = pIdx.aSample;
2240
+ int i = 0;
2241
+ int eType = sqlite3_value_type(pVal);
2242
+
2243
+ if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
2244
+ double r = sqlite3_value_double(pVal);
2245
+ for(i=0; i<SQLITE_INDEX_SAMPLES; i++){
2246
+ if( aSample[i].eType==SQLITE_NULL ) continue;
2247
+ if( aSample[i].eType>=SQLITE_TEXT || aSample[i].u.r>r ) break;
2248
+ }
2249
+ }else{
2250
+ sqlite3 db = pParse.db;
2251
+ CollSeq pColl;
2252
+ string z;
2253
+ int n;
2254
+
2255
+ /* pVal comes from sqlite3ValueFromExpr() so the type cannot be NULL */
2256
+ Debug.Assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
2257
+
2258
+ if( eType==SQLITE_BLOB ){
2259
+ z = Encoding.UTF8.GetString( sqlite3_value_blob( pVal ) );
2260
+ pColl = db.pDfltColl;
2261
+ Debug.Assert( pColl.enc==SQLITE_UTF8 );
2262
+ }else{
2263
+ pColl = sqlite3GetCollSeq(db, SQLITE_UTF8, null, pIdx.azColl[0]);
2264
+ if( pColl==null ){
2265
+ sqlite3ErrorMsg(pParse, "no such collation sequence: %s",
2266
+ pIdx.azColl);
2267
+ return SQLITE_ERROR;
2268
+ }
2269
+ z = sqlite3ValueText(pVal, pColl.enc);
2270
+ //if( !z ){
2271
+ // return SQLITE_NOMEM;
2272
+ //}
2273
+ Debug.Assert( z != "" && pColl != null && pColl.xCmp != null );
2274
+ }
2275
+ n = sqlite3ValueBytes(pVal, pColl.enc);
2276
+
2277
+ for(i=0; i<SQLITE_INDEX_SAMPLES; i++){
2278
+ int r;
2279
+ int eSampletype = aSample[i].eType;
2280
+ if( eSampletype==SQLITE_NULL || eSampletype<eType ) continue;
2281
+ if( (eSampletype!=eType) ) break;
2282
+ #if !SQLITE_OMIT_UTF16
2283
+ if( pColl.enc!=SQLITE_UTF8 ){
2284
+ int nSample;
2285
+ string zSample;
2286
+ zSample = sqlite3Utf8to16(
2287
+ db, pColl.enc, aSample[i].u.z, aSample[i].nByte, ref nSample
2288
+ );
2289
+ zSample = aSample[i].u.z;
2290
+ nSample = aSample[i].u.z.Length;
2291
+ //if( !zSample ){
2292
+ // assert( db.mallocFailed );
2293
+ // return SQLITE_NOMEM;
2294
+ //}
2295
+ r = pColl.xCmp(pColl.pUser, nSample, zSample, n, z);
2296
+ sqlite3DbFree(db, ref zSample);
2297
+ }else
2298
+ #endif
2299
+ }
2300
+ r = pColl.xCmp(pColl.pUser, aSample[i].nByte, aSample[i].u.z, n, z);
2301
+ if( r>0 ) break;
2302
+ }
2303
+ }
2304
+
2305
+ Debug.Assert( i>=0 && i<=SQLITE_INDEX_SAMPLES );
2306
+ piRegion = i;
2307
+ }
2308
+ return SQLITE_OK;
2309
+ }
2310
+ #endif //* #ifdef SQLITE_ENABLE_STAT2 */
2311
+
2312
+ /*
2313
+ ** If expression pExpr represents a literal value, set *pp to point to
2314
+ ** an sqlite3_value structure containing the same value, with affinity
2315
+ ** aff applied to it, before returning. It is the responsibility of the
2316
+ ** caller to eventually release this structure by passing it to
2317
+ ** sqlite3ValueFree().
2318
+ **
2319
+ ** If the current parse is a recompile (sqlite3Reprepare()) and pExpr
2320
+ ** is an SQL variable that currently has a non-NULL value bound to it,
2321
+ ** create an sqlite3_value structure containing this value, again with
2322
+ ** affinity aff applied to it, instead.
2323
+ **
2324
+ ** If neither of the above apply, set *pp to NULL.
2325
+ **
2326
+ ** If an error occurs, return an error code. Otherwise, SQLITE_OK.
2327
+ */
2328
+ #if SQLITE_ENABLE_STAT2
2329
+ static int valueFromExpr(
2330
+ Parse pParse,
2331
+ Expr pExpr,
2332
+ u8 aff,
2333
+ ref sqlite3_value pp
2334
+ ){
2335
+ /* The evalConstExpr() function will have already converted any TK_VARIABLE
2336
+ ** expression involved in an comparison into a TK_REGISTER. */
2337
+ assert( pExpr.op!=TK_VARIABLE );
2338
+ if( pExpr.op==TK_REGISTER && pExpr.op2==TK_VARIABLE ){
2339
+ int iVar = pExpr.iColumn;
2340
+ sqlite3VdbeSetVarmask(pParse.pVdbe, iVar);
2341
+ *pp = sqlite3VdbeGetValue(pParse.pReprepare, iVar, aff);
2342
+ return SQLITE_OK;
2343
+ }
2344
+ return sqlite3ValueFromExpr(pParse.db, pExpr, SQLITE_UTF8, aff, pp);
2345
+ }
2346
+ #endif
2347
+
2348
+ /*
2349
+ ** This function is used to estimate the number of rows that will be visited
2350
+ ** by scanning an index for a range of values. The range may have an upper
2351
+ ** bound, a lower bound, or both. The WHERE clause terms that set the upper
2352
+ ** and lower bounds are represented by pLower and pUpper respectively. For
2353
+ ** example, assuming that index p is on t1(a):
2354
+ **
2355
+ ** ... FROM t1 WHERE a > ? AND a < ? ...
2356
+ ** |_____| |_____|
2357
+ ** | |
2358
+ ** pLower pUpper
2359
+ **
2360
+ ** If either of the upper or lower bound is not present, then NULL is passed in
2361
+ ** place of the corresponding WhereTerm.
2362
+ **
2363
+ ** The nEq parameter is passed the index of the index column subject to the
2364
+ ** range constraint. Or, equivalently, the number of equality constraints
2365
+ ** optimized by the proposed index scan. For example, assuming index p is
2366
+ ** on t1(a, b), and the SQL query is:
2367
+ **
2368
+ ** ... FROM t1 WHERE a = ? AND b > ? AND b < ? ...
2369
+ **
2370
+ ** then nEq should be passed the value 1 (as the range restricted column,
2371
+ ** b, is the second left-most column of the index). Or, if the query is:
2372
+ **
2373
+ ** ... FROM t1 WHERE a > ? AND a < ? ...
2374
+ **
2375
+ ** then nEq should be passed 0.
2376
+ **
2377
+ ** The returned value is an integer between 1 and 100, inclusive. A return
2378
+ ** value of 1 indicates that the proposed range scan is expected to visit
2379
+ ** approximately 1/100th (1%) of the rows selected by the nEq equality
2380
+ ** constraints (if any). A return value of 100 indicates that it is expected
2381
+ ** that the range scan will visit every row (100%) selected by the equality
2382
+ ** constraints.
2383
+ **
2384
+ ** In the absence of sqlite_stat2 ANALYZE data, each range inequality
2385
+ ** reduces the search space by 2/3rds. Hence a single constraint (x>?)
2386
+ ** results in a return of 33 and a range constraint (x>? AND x<?) results
2387
+ ** in a return of 11.
2388
+ */
2389
+ static int whereRangeScanEst(
2390
+ Parse pParse, /* Parsing & code generating context */
2391
+ Index p, /* The index containing the range-compared column; "x" */
2392
+ int nEq, /* index into p.aCol[] of the range-compared column */
2393
+ WhereTerm pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
2394
+ WhereTerm pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
2395
+ ref int piEst /* OUT: Return value */
2396
+ )
2397
+ {
2398
+ int rc = SQLITE_OK;
2399
+
2400
+ #if SQLITE_ENABLE_STAT2
2401
+
2402
+ if( nEq==0 && p.aSample ){
2403
+ sqlite3_value *pLowerVal = 0;
2404
+ sqlite3_value *pUpperVal = 0;
2405
+ int iEst;
2406
+ int iLower = 0;
2407
+ int iUpper = SQLITE_INDEX_SAMPLES;
2408
+ u8 aff = p.pTable.aCol[p.aiColumn[0]].affinity;
2409
+
2410
+ if( pLower ){
2411
+ Expr *pExpr = pLower.pExpr.pRight;
2412
+ rc = valueFromExpr(pParse, pExpr, aff, &pLowerVal);
2413
+ }
2414
+ if( rc==SQLITE_OK && pUpper ){
2415
+ Expr *pExpr = pUpper.pExpr.pRight;
2416
+ rc = valueFromExpr(pParse, pExpr, aff, &pUpperVal);
2417
+ }
2418
+
2419
+ if( rc!=SQLITE_OK || (pLowerVal==0 && pUpperVal==0) ){
2420
+ sqlite3ValueFree(pLowerVal);
2421
+ sqlite3ValueFree(pUpperVal);
2422
+ goto range_est_fallback;
2423
+ }else if( pLowerVal==0 ){
2424
+ rc = whereRangeRegion(pParse, p, pUpperVal, &iUpper);
2425
+ if( pLower ) iLower = iUpper/2;
2426
+ }else if( pUpperVal==0 ){
2427
+ rc = whereRangeRegion(pParse, p, pLowerVal, &iLower);
2428
+ if( pUpper ) iUpper = (iLower + SQLITE_INDEX_SAMPLES + 1)/2;
2429
+ }else{
2430
+ rc = whereRangeRegion(pParse, p, pUpperVal, &iUpper);
2431
+ if( rc==SQLITE_OK ){
2432
+ rc = whereRangeRegion(pParse, p, pLowerVal, &iLower);
2433
+ }
2434
+ }
2435
+
2436
+ iEst = iUpper - iLower;
2437
+ testcase( iEst==SQLITE_INDEX_SAMPLES );
2438
+ assert( iEst<=SQLITE_INDEX_SAMPLES );
2439
+ if( iEst<1 ){
2440
+ iEst = 1;
2441
+ }
2442
+
2443
+ sqlite3ValueFree(pLowerVal);
2444
+ sqlite3ValueFree(pUpperVal);
2445
+ *piEst = (iEst * 100)/SQLITE_INDEX_SAMPLES;
2446
+ return rc;
2447
+ }
2448
+ range_est_fallback:
2449
+ #else
2450
+ UNUSED_PARAMETER(pParse);
2451
+ UNUSED_PARAMETER(p);
2452
+ UNUSED_PARAMETER(nEq);
2453
+ #endif
2454
+ Debug.Assert(pLower != null || pUpper != null);
2455
+ if (pLower != null && pUpper != null)
2456
+ {
2457
+ piEst = 11;
2458
+ }
2459
+ else
2460
+ {
2461
+ piEst = 33;
2462
+ }
2463
+ return rc;
2464
+ }
2465
+
2466
+
2467
+ /*
2468
+ ** Find the query plan for accessing a particular table. Write the
2469
+ ** best query plan and its cost into the WhereCost object supplied as the
2470
+ ** last parameter.
2471
+ **
2472
+ ** The lowest cost plan wins. The cost is an estimate of the amount of
2473
+ ** CPU and disk I/O need to process the request using the selected plan.
2474
+ ** Factors that influence cost include:
2475
+ **
2476
+ ** * The estimated number of rows that will be retrieved. (The
2477
+ ** fewer the better.)
2478
+ **
2479
+ ** * Whether or not sorting must occur.
2480
+ **
2481
+ ** * Whether or not there must be separate lookups in the
2482
+ ** index and in the main table.
2483
+ **
2484
+ ** If there was an INDEXED BY clause (pSrc.pIndex) attached to the table in
2485
+ ** the SQL statement, then this function only considers plans using the
2486
+ ** named index. If no such plan is found, then the returned cost is
2487
+ ** SQLITE_BIG_DBL. If a plan is found that uses the named index,
2488
+ ** then the cost is calculated in the usual way.
2489
+ **
2490
+ ** If a NOT INDEXED clause (pSrc.notIndexed!=0) was attached to the table
2491
+ ** in the SELECT statement, then no indexes are considered. However, the
2492
+ ** selected plan may still take advantage of the tables built-in rowid
2493
+ ** index.
2494
+ */
2495
+ static void bestBtreeIndex(
2496
+ Parse pParse, /* The parsing context */
2497
+ WhereClause pWC, /* The WHERE clause */
2498
+ SrcList_item pSrc, /* The FROM clause term to search */
2499
+ Bitmask notReady, /* Mask of cursors that are not available */
2500
+ ExprList pOrderBy, /* The ORDER BY clause */
2501
+ ref WhereCost pCost /* Lowest cost query plan */
2502
+ )
2503
+ {
2504
+ int iCur = pSrc.iCursor; /* The cursor of the table to be accessed */
2505
+ Index pProbe; /* An index we are evaluating */
2506
+ Index pIdx; /* Copy of pProbe, or zero for IPK index */
2507
+ u32 eqTermMask; /* Current mask of valid equality operators */
2508
+ u32 idxEqTermMask; /* Index mask of valid equality operators */
2509
+ Index sPk; /* A fake index object for the primary key */
2510
+ int[] aiRowEstPk = new int[2]; /* The aiRowEst[] value for the sPk index */
2511
+ int aiColumnPk = -1; /* The aColumn[] value for the sPk index */
2512
+ int wsFlagMask; /* Allowed flags in pCost.plan.wsFlag */
2513
+
2514
+ /* Initialize the cost to a worst-case value */
2515
+ if (pCost == null) pCost = new WhereCost();
2516
+ else pCost.Clear(); //memset(pCost, 0, sizeof(*pCost));
2517
+ pCost.rCost = SQLITE_BIG_DBL;
2518
+
2519
+ /* If the pSrc table is the right table of a LEFT JOIN then we may not
2520
+ ** use an index to satisfy IS NULL constraints on that table. This is
2521
+ ** because columns might end up being NULL if the table does not match -
2522
+ ** a circumstance which the index cannot help us discover. Ticket #2177.
2523
+ */
2524
+ if ((pSrc.jointype & JT_LEFT) != 0)
2525
+ {
2526
+ idxEqTermMask = WO_EQ | WO_IN;
2527
+ }
2528
+ else
2529
+ {
2530
+ idxEqTermMask = WO_EQ | WO_IN | WO_ISNULL;
2531
+ }
2532
+
2533
+ if (pSrc.pIndex != null)
2534
+ {
2535
+ /* An INDEXED BY clause specifies a particular index to use */
2536
+ pIdx = pProbe = pSrc.pIndex;
2537
+ wsFlagMask = ~(WHERE_ROWID_EQ | WHERE_ROWID_RANGE);
2538
+ eqTermMask = idxEqTermMask;
2539
+ }
2540
+ else
2541
+ {
2542
+ /* There is no INDEXED BY clause. Create a fake Index object to
2543
+ ** represent the primary key */
2544
+ Index pFirst; /* Any other index on the table */
2545
+ sPk = new Index(); // memset( &sPk, 0, sizeof( Index ) );
2546
+ sPk.aSortOrder = new byte[1];
2547
+ sPk.azColl = new string[1]; sPk.azColl[0] = "";
2548
+ sPk.nColumn = 1;
2549
+ sPk.aiColumn = new int[1];
2550
+ sPk.aiColumn[0] = aiColumnPk;
2551
+ sPk.aiRowEst = aiRowEstPk;
2552
+ aiRowEstPk[1] = 1;
2553
+ sPk.onError = OE_Replace;
2554
+ sPk.pTable = pSrc.pTab;
2555
+ pFirst = pSrc.pTab.pIndex;
2556
+ if (pSrc.notIndexed == 0)
2557
+ {
2558
+ sPk.pNext = pFirst;
2559
+ }
2560
+ /* The aiRowEstPk[0] is an estimate of the total number of rows in the
2561
+ ** table. Get this information from the ANALYZE information if it is
2562
+ ** available. If not available, assume the table 1 million rows in size.
2563
+ */
2564
+ if (pFirst != null)
2565
+ {
2566
+ Debug.Assert(pFirst.aiRowEst != null); /* Allocated together with pFirst */
2567
+ aiRowEstPk[0] = pFirst.aiRowEst[0];
2568
+ }
2569
+ else
2570
+ {
2571
+ aiRowEstPk[0] = 1000000;
2572
+ }
2573
+ pProbe = sPk;
2574
+ wsFlagMask = ~(
2575
+ WHERE_COLUMN_IN | WHERE_COLUMN_EQ | WHERE_COLUMN_NULL | WHERE_COLUMN_RANGE
2576
+ );
2577
+ eqTermMask = WO_EQ | WO_IN;
2578
+ pIdx = null;
2579
+ }
2580
+
2581
+ /* Loop over all indices looking for the best one to use
2582
+ */
2583
+ for (; pProbe != null; pIdx = pProbe = pProbe.pNext)
2584
+ {
2585
+ int[] aiRowEst = pProbe.aiRowEst;
2586
+ double cost; /* Cost of using pProbe */
2587
+ double nRow; /* Estimated number of rows in result set */
2588
+ int rev = 0; /* True to scan in reverse order */
2589
+ int wsFlags = 0;
2590
+ Bitmask used = 0;
2591
+
2592
+ /* The following variables are populated based on the properties of
2593
+ ** scan being evaluated. They are then used to determine the expected
2594
+ ** cost and number of rows returned.
2595
+ **
2596
+ ** nEq:
2597
+ ** Number of equality terms that can be implemented using the index.
2598
+ **
2599
+ ** nInMul:
2600
+ ** The "in-multiplier". This is an estimate of how many seek operations
2601
+ ** SQLite must perform on the index in question. For example, if the
2602
+ ** WHERE clause is:
2603
+ **
2604
+ ** WHERE a IN (1, 2, 3) AND b IN (4, 5, 6)
2605
+ **
2606
+ ** SQLite must perform 9 lookups on an index on (a, b), so nInMul is
2607
+ ** set to 9. Given the same schema and either of the following WHERE
2608
+ ** clauses:
2609
+ **
2610
+ ** WHERE a = 1
2611
+ ** WHERE a >= 2
2612
+ **
2613
+ ** nInMul is set to 1.
2614
+ **
2615
+ ** If there exists a WHERE term of the form "x IN (SELECT ...)", then
2616
+ ** the sub-select is assumed to return 25 rows for the purposes of
2617
+ ** determining nInMul.
2618
+ **
2619
+ ** bInEst:
2620
+ ** Set to true if there was at least one "x IN (SELECT ...)" term used
2621
+ ** in determining the value of nInMul.
2622
+ **
2623
+ ** nBound:
2624
+ ** An estimate on the amount of the table that must be searched. A
2625
+ ** value of 100 means the entire table is searched. Range constraints
2626
+ ** might reduce this to a value less than 100 to indicate that only
2627
+ ** a fraction of the table needs searching. In the absence of
2628
+ ** sqlite_stat2 ANALYZE data, a single inequality reduces the search
2629
+ ** space to 1/3rd its original size. So an x>? constraint reduces
2630
+ ** nBound to 33. Two constraints (x>? AND x<?) reduce nBound to 11.
2631
+ **
2632
+ ** bSort:
2633
+ ** Boolean. True if there is an ORDER BY clause that will require an
2634
+ ** external sort (i.e. scanning the index being evaluated will not
2635
+ ** correctly order records).
2636
+ **
2637
+ ** bLookup:
2638
+ ** Boolean. True if for each index entry visited a lookup on the
2639
+ ** corresponding table b-tree is required. This is always false
2640
+ ** for the rowid index. For other indexes, it is true unless all the
2641
+ ** columns of the table used by the SELECT statement are present in
2642
+ ** the index (such an index is sometimes described as a covering index).
2643
+ ** For example, given the index on (a, b), the second of the following
2644
+ ** two queries requires table b-tree lookups, but the first does not.
2645
+ **
2646
+ ** SELECT a, b FROM tbl WHERE a = 1;
2647
+ ** SELECT a, b, c FROM tbl WHERE a = 1;
2648
+ */
2649
+ int nEq;
2650
+ int bInEst = 0;
2651
+ int nInMul = 1;
2652
+ int nBound = 100;
2653
+ int bSort = 0;
2654
+ int bLookup = 0;
2655
+
2656
+ /* Determine the values of nEq and nInMul */
2657
+ for (nEq = 0; nEq < pProbe.nColumn; nEq++)
2658
+ {
2659
+ WhereTerm pTerm; /* A single term of the WHERE clause */
2660
+ int j = pProbe.aiColumn[nEq];
2661
+ pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pIdx);
2662
+ if (pTerm == null) break;
2663
+ wsFlags |= (WHERE_COLUMN_EQ | WHERE_ROWID_EQ);
2664
+ if ((pTerm.eOperator & WO_IN) != 0)
2665
+ {
2666
+ Expr pExpr = pTerm.pExpr;
2667
+ wsFlags |= WHERE_COLUMN_IN;
2668
+ if (ExprHasProperty(pExpr, EP_xIsSelect))
2669
+ {
2670
+ nInMul *= 25;
2671
+ bInEst = 1;
2672
+ }
2673
+ else if (pExpr.x.pList != null)
2674
+ {
2675
+ nInMul *= pExpr.x.pList.nExpr + 1;
2676
+ }
2677
+ }
2678
+ else if ((pTerm.eOperator & WO_ISNULL) != 0)
2679
+ {
2680
+ wsFlags |= WHERE_COLUMN_NULL;
2681
+ }
2682
+ used |= pTerm.prereqRight;
2683
+ }
2684
+
2685
+ /* Determine the value of nBound. */
2686
+ if (nEq < pProbe.nColumn)
2687
+ {
2688
+ int j = pProbe.aiColumn[nEq];
2689
+ if (findTerm(pWC, iCur, j, notReady, WO_LT | WO_LE | WO_GT | WO_GE, pIdx) != null)
2690
+ {
2691
+ WhereTerm pTop = findTerm(pWC, iCur, j, notReady, WO_LT | WO_LE, pIdx);
2692
+ WhereTerm pBtm = findTerm(pWC, iCur, j, notReady, WO_GT | WO_GE, pIdx);
2693
+ whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, ref nBound);
2694
+ if (pTop != null)
2695
+ {
2696
+ wsFlags |= WHERE_TOP_LIMIT;
2697
+ used |= pTop.prereqRight;
2698
+ }
2699
+ if (pBtm != null)
2700
+ {
2701
+ wsFlags |= WHERE_BTM_LIMIT;
2702
+ used |= pBtm.prereqRight;
2703
+ }
2704
+ wsFlags |= (WHERE_COLUMN_RANGE | WHERE_ROWID_RANGE);
2705
+ }
2706
+ }
2707
+ else if (pProbe.onError != OE_None)
2708
+ {
2709
+ testcase(wsFlags & WHERE_COLUMN_IN);
2710
+ testcase(wsFlags & WHERE_COLUMN_NULL);
2711
+ if ((wsFlags & (WHERE_COLUMN_IN | WHERE_COLUMN_NULL)) == 0)
2712
+ {
2713
+ wsFlags |= WHERE_UNIQUE;
2714
+ }
2715
+ }
2716
+
2717
+ /* If there is an ORDER BY clause and the index being considered will
2718
+ ** naturally scan rows in the required order, set the appropriate flags
2719
+ ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index
2720
+ ** will scan rows in a different order, set the bSort variable. */
2721
+ if (pOrderBy != null)
2722
+ {
2723
+ if ((wsFlags & (WHERE_COLUMN_IN | WHERE_COLUMN_NULL)) == 0
2724
+ && isSortingIndex(pParse, pWC.pMaskSet, pProbe, iCur, pOrderBy, nEq, ref rev)
2725
+ )
2726
+ {
2727
+ wsFlags |= WHERE_ROWID_RANGE | WHERE_COLUMN_RANGE | WHERE_ORDERBY;
2728
+ wsFlags |= (rev != 0 ? WHERE_REVERSE : 0);
2729
+ }
2730
+ else
2731
+ {
2732
+ bSort = 1;
2733
+ }
2734
+ }
2735
+
2736
+ /* If currently calculating the cost of using an index (not the IPK
2737
+ ** index), determine if all required column data may be obtained without
2738
+ ** seeking to entries in the main table (i.e. if the index is a covering
2739
+ ** index for this query). If it is, set the WHERE_IDX_ONLY flag in
2740
+ ** wsFlags. Otherwise, set the bLookup variable to true. */
2741
+ if (pIdx != null && wsFlags != 0)
2742
+ {
2743
+ Bitmask m = pSrc.colUsed;
2744
+ int j;
2745
+ for (j = 0; j < pIdx.nColumn; j++)
2746
+ {
2747
+ int x = pIdx.aiColumn[j];
2748
+ if (x < BMS - 1)
2749
+ {
2750
+ m &= ~(((Bitmask)1) << x);
2751
+ }
2752
+ }
2753
+ if (m == 0)
2754
+ {
2755
+ wsFlags |= WHERE_IDX_ONLY;
2756
+ }
2757
+ else
2758
+ {
2759
+ bLookup = 1;
2760
+ }
2761
+ }
2762
+
2763
+ /**** Begin adding up the cost of using this index (Needs improvements)
2764
+ **
2765
+ ** Estimate the number of rows of output. For an IN operator,
2766
+ ** do not let the estimate exceed half the rows in the table.
2767
+ */
2768
+ nRow = (double)(aiRowEst[nEq] * nInMul);
2769
+ if (bInEst != 0 && nRow * 2 > aiRowEst[0])
2770
+ {
2771
+ nRow = aiRowEst[0] / 2;
2772
+ nInMul = (int)(nRow / aiRowEst[nEq]);
2773
+ }
2774
+
2775
+ /* Assume constant cost to access a row and logarithmic cost to
2776
+ ** do a binary search. Hence, the initial cost is the number of output
2777
+ ** rows plus log2(table-size) times the number of binary searches.
2778
+ */
2779
+ cost = nRow + nInMul * estLog(aiRowEst[0]);
2780
+
2781
+ /* Adjust the number of rows and the cost downward to reflect rows
2782
+ ** that are excluded by range constraints.
2783
+ */
2784
+ nRow = (nRow * (double)nBound) / (double)100;
2785
+ cost = (cost * (double)nBound) / (double)100;
2786
+
2787
+ /* Add in the estimated cost of sorting the result
2788
+ */
2789
+ if (bSort != 0)
2790
+ {
2791
+ cost += cost * estLog(cost);
2792
+ }
2793
+
2794
+ /* If all information can be taken directly from the index, we avoid
2795
+ ** doing table lookups. This reduces the cost by half. (Not really -
2796
+ ** this needs to be fixed.)
2797
+ */
2798
+ if (pIdx != null && bLookup == 0)
2799
+ {
2800
+ cost /= (double)2;
2801
+ }
2802
+ /**** Cost of using this index has now been computed ****/
2803
+
2804
+ WHERETRACE(
2805
+ "tbl=%s idx=%s nEq=%d nInMul=%d nBound=%d bSort=%d bLookup=%d" +
2806
+ " wsFlags=%d (nRow=%.2f cost=%.2f)\n",
2807
+ pSrc.pTab.zName, (pIdx != null ? pIdx.zName : "ipk"),
2808
+ nEq, nInMul, nBound, bSort, bLookup, wsFlags, nRow, cost
2809
+ );
2810
+
2811
+ /* If this index is the best we have seen so far, then record this
2812
+ ** index and its cost in the pCost structure.
2813
+ */
2814
+ if ((null == pIdx || wsFlags != 0) && cost < pCost.rCost)
2815
+ {
2816
+ pCost.rCost = cost;
2817
+ pCost.nRow = nRow;
2818
+ pCost.used = used;
2819
+ pCost.plan.wsFlags = (uint)(wsFlags & wsFlagMask);
2820
+ pCost.plan.nEq = (uint)nEq;
2821
+ pCost.plan.u.pIdx = pIdx;
2822
+ }
2823
+
2824
+ /* If there was an INDEXED BY clause, then only that one index is
2825
+ ** considered. */
2826
+ if (pSrc.pIndex != null) break;
2827
+
2828
+ /* Reset masks for the next index in the loop */
2829
+ wsFlagMask = ~(WHERE_ROWID_EQ | WHERE_ROWID_RANGE);
2830
+ eqTermMask = idxEqTermMask;
2831
+ }
2832
+
2833
+ /* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag
2834
+ ** is set, then reverse the order that the index will be scanned
2835
+ ** in. This is used for application testing, to help find cases
2836
+ ** where application behaviour depends on the (undefined) order that
2837
+ ** SQLite outputs rows in in the absence of an ORDER BY clause. */
2838
+ if (null == pOrderBy && (pParse.db.flags & SQLITE_ReverseOrder) != 0)
2839
+ {
2840
+ pCost.plan.wsFlags |= WHERE_REVERSE;
2841
+ }
2842
+
2843
+ Debug.Assert(pOrderBy != null || (pCost.plan.wsFlags & WHERE_ORDERBY) == 0);
2844
+ Debug.Assert(pCost.plan.u.pIdx == null || (pCost.plan.wsFlags & WHERE_ROWID_EQ) == 0);
2845
+ Debug.Assert(pSrc.pIndex == null
2846
+ || pCost.plan.u.pIdx == null
2847
+ || pCost.plan.u.pIdx == pSrc.pIndex
2848
+ );
2849
+
2850
+ WHERETRACE("best index is: %s\n",
2851
+ (pCost.plan.u.pIdx != null ? pCost.plan.u.pIdx.zName : "ipk")
2852
+ );
2853
+
2854
+ bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
2855
+ pCost.plan.wsFlags |= (u32)eqTermMask;
2856
+ }
2857
+
2858
+
2859
+ /*
2860
+ ** Find the query plan for accessing table pSrc.pTab. Write the
2861
+ ** best query plan and its cost into the WhereCost object supplied
2862
+ ** as the last parameter. This function may calculate the cost of
2863
+ ** both real and virtual table scans.
2864
+ */
2865
+ static void bestIndex(
2866
+ Parse pParse, /* The parsing context */
2867
+ WhereClause pWC, /* The WHERE clause */
2868
+ SrcList_item pSrc, /* The FROM clause term to search */
2869
+ Bitmask notReady, /* Mask of cursors that are not available */
2870
+ ExprList pOrderBy, /* The ORDER BY clause */
2871
+ ref WhereCost pCost /* Lowest cost query plan */
2872
+ )
2873
+ {
2874
+ #if !SQLITE_OMIT_VIRTUALTABLE
2875
+ if ( IsVirtual( pSrc.pTab ) )
2876
+ {
2877
+ sqlite3_index_info p = null;
2878
+ bestVirtualIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost, p);
2879
+ if( p.needToFreeIdxStr !=0){
2880
+ //sqlite3_free(ref p.idxStr);
2881
+ }
2882
+ sqlite3DbFree(pParse.db, p);
2883
+ }
2884
+ else
2885
+ #endif
2886
+ {
2887
+ bestBtreeIndex(pParse, pWC, pSrc, notReady, pOrderBy, ref pCost);
2888
+ }
2889
+ }
2890
+
2891
+ /*
2892
+ ** Disable a term in the WHERE clause. Except, do not disable the term
2893
+ ** if it controls a LEFT OUTER JOIN and it did not originate in the ON
2894
+ ** or USING clause of that join.
2895
+ **
2896
+ ** Consider the term t2.z='ok' in the following queries:
2897
+ **
2898
+ ** (1) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok'
2899
+ ** (2) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok'
2900
+ ** (3) SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok'
2901
+ **
2902
+ ** The t2.z='ok' is disabled in the in (2) because it originates
2903
+ ** in the ON clause. The term is disabled in (3) because it is not part
2904
+ ** of a LEFT OUTER JOIN. In (1), the term is not disabled.
2905
+ **
2906
+ ** Disabling a term causes that term to not be tested in the inner loop
2907
+ ** of the join. Disabling is an optimization. When terms are satisfied
2908
+ ** by indices, we disable them to prevent redundant tests in the inner
2909
+ ** loop. We would get the correct results if nothing were ever disabled,
2910
+ ** but joins might run a little slower. The trick is to disable as much
2911
+ ** as we can without disabling too much. If we disabled in (1), we'd get
2912
+ ** the wrong answer. See ticket #813.
2913
+ */
2914
+ static void disableTerm(WhereLevel pLevel, WhereTerm pTerm)
2915
+ {
2916
+ if (pTerm != null
2917
+ && ALWAYS((pTerm.wtFlags & TERM_CODED) == 0)
2918
+ && (pLevel.iLeftJoin == 0 || ExprHasProperty(pTerm.pExpr, EP_FromJoin)))
2919
+ {
2920
+ pTerm.wtFlags |= TERM_CODED;
2921
+ if (pTerm.iParent >= 0)
2922
+ {
2923
+ WhereTerm pOther = pTerm.pWC.a[pTerm.iParent];
2924
+ if ((--pOther.nChild) == 0)
2925
+ {
2926
+ disableTerm(pLevel, pOther);
2927
+ }
2928
+ }
2929
+ }
2930
+ }
2931
+
2932
+ /*
2933
+ ** Code an OP_Affinity opcode to apply the column affinity string zAff
2934
+ ** to the n registers starting at base.
2935
+ **
2936
+ ** As an optimization, SQLITE_AFF_NONE entries (which are no-ops) at the
2937
+ ** beginning and end of zAff are ignored. If all entries in zAff are
2938
+ ** SQLITE_AFF_NONE, then no code gets generated.
2939
+ **
2940
+ ** This routine makes its own copy of zAff so that the caller is free
2941
+ ** to modify zAff after this routine returns.
2942
+ */
2943
+ static void codeApplyAffinity(Parse pParse, int _base, int n, string zAff)
2944
+ {
2945
+ Vdbe v = pParse.pVdbe;
2946
+ //if (zAff == 0)
2947
+ //{
2948
+ // assert(pParse.db.mallocFailed);
2949
+ // return;
2950
+ //}
2951
+ Debug.Assert(v != null);
2952
+ /* Adjust base and n to skip over SQLITE_AFF_NONE entries at the beginning
2953
+ ** and end of the affinity string.
2954
+ */
2955
+ while (n > 0 && zAff[0] == SQLITE_AFF_NONE)
2956
+ {
2957
+ n--;
2958
+ _base++;
2959
+ zAff = zAff.Substring(1);// zAff++;
2960
+ }
2961
+ while (n > 1 && zAff[n - 1] == SQLITE_AFF_NONE)
2962
+ {
2963
+ n--;
2964
+ }
2965
+
2966
+ /* Code the OP_Affinity opcode if there is anything left to do. */
2967
+ if (n > 0)
2968
+ {
2969
+ sqlite3VdbeAddOp2(v, OP_Affinity, _base, n);
2970
+ sqlite3VdbeChangeP4(v, -1, zAff, n);
2971
+ sqlite3ExprCacheAffinityChange(pParse, _base, n);
2972
+ }
2973
+ }
2974
+
2975
+ /*
2976
+ ** Generate code for a single equality term of the WHERE clause. An equality
2977
+ ** term can be either X=expr or X IN (...). pTerm is the term to be
2978
+ ** coded.
2979
+ **
2980
+ ** The current value for the constraint is left in register iReg.
2981
+ **
2982
+ ** For a constraint of the form X=expr, the expression is evaluated and its
2983
+ ** result is left on the stack. For constraints of the form X IN (...)
2984
+ ** this routine sets up a loop that will iterate over all values of X.
2985
+ */
2986
+ static int codeEqualityTerm(
2987
+ Parse pParse, /* The parsing context */
2988
+ WhereTerm pTerm, /* The term of the WHERE clause to be coded */
2989
+ WhereLevel pLevel, /* When level of the FROM clause we are working on */
2990
+ int iTarget /* Attempt to leave results in this register */
2991
+ )
2992
+ {
2993
+ Expr pX = pTerm.pExpr;
2994
+ Vdbe v = pParse.pVdbe;
2995
+ int iReg; /* Register holding results */
2996
+
2997
+ Debug.Assert(iTarget > 0);
2998
+ if (pX.op == TK_EQ)
2999
+ {
3000
+ iReg = sqlite3ExprCodeTarget(pParse, pX.pRight, iTarget);
3001
+ }
3002
+ else if (pX.op == TK_ISNULL)
3003
+ {
3004
+ iReg = iTarget;
3005
+ sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
3006
+ #if !SQLITE_OMIT_SUBQUERY
3007
+ }
3008
+ else
3009
+ {
3010
+ int eType;
3011
+ int iTab;
3012
+ InLoop pIn;
3013
+
3014
+ Debug.Assert(pX.op == TK_IN);
3015
+ iReg = iTarget;
3016
+ int iDummy = -1; eType = sqlite3FindInIndex(pParse, pX, ref iDummy);
3017
+ iTab = pX.iTable;
3018
+ sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
3019
+ Debug.Assert((pLevel.plan.wsFlags & WHERE_IN_ABLE) != 0);
3020
+ if (pLevel.u._in.nIn == 0)
3021
+ {
3022
+ pLevel.addrNxt = sqlite3VdbeMakeLabel(v);
3023
+ }
3024
+ pLevel.u._in.nIn++;
3025
+ if (pLevel.u._in.aInLoop == null) pLevel.u._in.aInLoop = new InLoop[pLevel.u._in.nIn];
3026
+ else Array.Resize(ref pLevel.u._in.aInLoop, pLevel.u._in.nIn);
3027
+ //sqlite3DbReallocOrFree(pParse.db, pLevel.u._in.aInLoop,
3028
+ // sizeof(pLevel.u._in.aInLoop[0])*pLevel.u._in.nIn);
3029
+ //pIn = pLevel.u._in.aInLoop;
3030
+ if (pLevel.u._in.aInLoop != null)//(pIn )
3031
+ {
3032
+ pLevel.u._in.aInLoop[pLevel.u._in.nIn - 1] = new InLoop();
3033
+ pIn = pLevel.u._in.aInLoop[pLevel.u._in.nIn - 1];//pIn++
3034
+ pIn.iCur = iTab;
3035
+ if (eType == IN_INDEX_ROWID)
3036
+ {
3037
+ pIn.addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg);
3038
+ }
3039
+ else
3040
+ {
3041
+ pIn.addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
3042
+ }
3043
+ sqlite3VdbeAddOp1(v, OP_IsNull, iReg);
3044
+ }
3045
+ else
3046
+ {
3047
+ pLevel.u._in.nIn = 0;
3048
+ }
3049
+ #endif
3050
+ }
3051
+ disableTerm(pLevel, pTerm);
3052
+ return iReg;
3053
+ }
3054
+
3055
+ /*
3056
+ ** Generate code for a single equality term of the WHERE clause. An equality
3057
+ ** term can be either X=expr or X IN (...). pTerm is the term to be
3058
+ ** coded.
3059
+ **
3060
+ ** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c).
3061
+ ** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10
3062
+ ** The index has as many as three equality constraints, but in this
3063
+ ** example, the third "c" value is an inequality. So only two
3064
+ ** constraints are coded. This routine will generate code to evaluate
3065
+ ** a==5 and b IN (1,2,3). The current values for a and b will be stored
3066
+ ** in consecutive registers and the index of the first register is returned.
3067
+ **
3068
+ ** In the example above nEq==2. But this subroutine works for any value
3069
+ ** of nEq including 0. If nEq==null, this routine is nearly a no-op.
3070
+ ** The only thing it does is allocate the pLevel.iMem memory cell and
3071
+ ** compute the affinity string.
3072
+ **
3073
+ ** This routine always allocates at least one memory cell and returns
3074
+ ** the index of that memory cell. The code that
3075
+ ** calls this routine will use that memory cell to store the termination
3076
+ ** key value of the loop. If one or more IN operators appear, then
3077
+ ** this routine allocates an additional nEq memory cells for internal
3078
+ ** use.
3079
+ **
3080
+ ** Before returning, *pzAff is set to point to a buffer containing a
3081
+ ** copy of the column affinity string of the index allocated using
3082
+ ** sqlite3DbMalloc(). Except, entries in the copy of the string associated
3083
+ ** with equality constraints that use NONE affinity are set to
3084
+ ** SQLITE_AFF_NONE. This is to deal with SQL such as the following:
3085
+ **
3086
+ ** CREATE TABLE t1(a TEXT PRIMARY KEY, b);
3087
+ ** SELECT ... FROM t1 AS t2, t1 WHERE t1.a = t2.b;
3088
+ **
3089
+ ** In the example above, the index on t1(a) has TEXT affinity. But since
3090
+ ** the right hand side of the equality constraint (t2.b) has NONE affinity,
3091
+ ** no conversion should be attempted before using a t2.b value as part of
3092
+ ** a key to search the index. Hence the first byte in the returned affinity
3093
+ ** string in this example would be set to SQLITE_AFF_NONE.
3094
+ */
3095
+ static int codeAllEqualityTerms(
3096
+ Parse pParse, /* Parsing context */
3097
+ WhereLevel pLevel, /* Which nested loop of the FROM we are coding */
3098
+ WhereClause pWC, /* The WHERE clause */
3099
+ Bitmask notReady, /* Which parts of FROM have not yet been coded */
3100
+ int nExtraReg, /* Number of extra registers to allocate */
3101
+ ref StringBuilder pzAff /* OUT: Set to point to affinity string */
3102
+ )
3103
+ {
3104
+ int nEq = (int)pLevel.plan.nEq; /* The number of == or IN constraints to code */
3105
+ Vdbe v = pParse.pVdbe; /* The vm under construction */
3106
+ Index pIdx; /* The index being used for this loop */
3107
+ int iCur = pLevel.iTabCur; /* The cursor of the table */
3108
+ WhereTerm pTerm; /* A single constraint term */
3109
+ int j; /* Loop counter */
3110
+ int regBase; /* Base register */
3111
+ int nReg; /* Number of registers to allocate */
3112
+ StringBuilder zAff; /* Affinity string to return */
3113
+
3114
+ /* This module is only called on query plans that use an index. */
3115
+ Debug.Assert((pLevel.plan.wsFlags & WHERE_INDEXED) != 0);
3116
+ pIdx = pLevel.plan.u.pIdx;
3117
+
3118
+ /* Figure out how many memory cells we will need then allocate them.
3119
+ */
3120
+ regBase = pParse.nMem + 1;
3121
+ nReg = (int)(pLevel.plan.nEq + nExtraReg);
3122
+ pParse.nMem += nReg;
3123
+
3124
+ zAff = new StringBuilder(sqlite3IndexAffinityStr(v, pIdx));//sqlite3DbStrDup(pParse.db, sqlite3IndexAffinityStr(v, pIdx));
3125
+ //if( !zAff ){
3126
+ // pParse.db.mallocFailed = 1;
3127
+ //}
3128
+
3129
+ /* Evaluate the equality constraints
3130
+ */
3131
+ Debug.Assert(pIdx.nColumn >= nEq);
3132
+ for (j = 0; j < nEq; j++)
3133
+ {
3134
+ int r1;
3135
+ int k = pIdx.aiColumn[j];
3136
+ pTerm = findTerm(pWC, iCur, k, notReady, pLevel.plan.wsFlags, pIdx);
3137
+ if (NEVER(pTerm == null)) break;
3138
+ Debug.Assert((pTerm.wtFlags & TERM_CODED) == 0);
3139
+ r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase + j);
3140
+ if (r1 != regBase + j)
3141
+ {
3142
+ if (nReg == 1)
3143
+ {
3144
+ sqlite3ReleaseTempReg(pParse, regBase);
3145
+ regBase = r1;
3146
+ }
3147
+ else
3148
+ {
3149
+ sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase + j);
3150
+ }
3151
+ }
3152
+ testcase(pTerm.eOperator & WO_ISNULL);
3153
+ testcase(pTerm.eOperator & WO_IN);
3154
+ if ((pTerm.eOperator & (WO_ISNULL | WO_IN)) == 0)
3155
+ {
3156
+ Expr pRight = pTerm.pExpr.pRight;
3157
+ sqlite3ExprCodeIsNullJump(v, pRight, regBase + j, pLevel.addrBrk);
3158
+ if (zAff.Length > 0)
3159
+ {
3160
+ if (sqlite3CompareAffinity(pRight, zAff[j]) == SQLITE_AFF_NONE)
3161
+ {
3162
+ zAff[j] = SQLITE_AFF_NONE;
3163
+ }
3164
+ if ((sqlite3ExprNeedsNoAffinityChange(pRight, zAff[j])) != 0)
3165
+ {
3166
+ zAff[j] = SQLITE_AFF_NONE;
3167
+ }
3168
+ }
3169
+ }
3170
+ }
3171
+ pzAff = zAff;
3172
+ return regBase;
3173
+ }
3174
+
3175
+ /*
3176
+ ** Generate code for the start of the iLevel-th loop in the WHERE clause
3177
+ ** implementation described by pWInfo.
3178
+ */
3179
+ static Bitmask codeOneLoopStart(
3180
+ WhereInfo pWInfo, /* Complete information about the WHERE clause */
3181
+ int iLevel, /* Which level of pWInfo.a[] should be coded */
3182
+ u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
3183
+ Bitmask notReady /* Which tables are currently available */
3184
+ )
3185
+ {
3186
+ int j, k; /* Loop counters */
3187
+ int iCur; /* The VDBE cursor for the table */
3188
+ int addrNxt; /* Where to jump to continue with the next IN case */
3189
+ int omitTable; /* True if we use the index only */
3190
+ int bRev; /* True if we need to scan in reverse order */
3191
+ WhereLevel pLevel; /* The where level to be coded */
3192
+ WhereClause pWC; /* Decomposition of the entire WHERE clause */
3193
+ WhereTerm pTerm; /* A WHERE clause term */
3194
+ Parse pParse; /* Parsing context */
3195
+ Vdbe v; /* The prepared stmt under constructions */
3196
+ SrcList_item pTabItem; /* FROM clause term being coded */
3197
+ int addrBrk; /* Jump here to break out of the loop */
3198
+ int addrCont; /* Jump here to continue with next cycle */
3199
+ int iRowidReg = 0; /* Rowid is stored in this register, if not zero */
3200
+ int iReleaseReg = 0; /* Temp register to free before returning */
3201
+
3202
+ pParse = pWInfo.pParse;
3203
+ v = pParse.pVdbe;
3204
+ pWC = pWInfo.pWC;
3205
+ pLevel = pWInfo.a[iLevel];
3206
+ pTabItem = pWInfo.pTabList.a[pLevel.iFrom];
3207
+ iCur = pTabItem.iCursor;
3208
+ bRev = (pLevel.plan.wsFlags & WHERE_REVERSE) != 0 ? 1 : 0;
3209
+ omitTable = ((pLevel.plan.wsFlags & WHERE_IDX_ONLY) != 0
3210
+ && (wctrlFlags & WHERE_FORCE_TABLE) == 0) ? 1 : 0;
3211
+
3212
+ /* Create labels for the "break" and "continue" instructions
3213
+ ** for the current loop. Jump to addrBrk to break out of a loop.
3214
+ ** Jump to cont to go immediately to the next iteration of the
3215
+ ** loop.
3216
+ **
3217
+ ** When there is an IN operator, we also have a "addrNxt" label that
3218
+ ** means to continue with the next IN value combination. When
3219
+ ** there are no IN operators in the constraints, the "addrNxt" label
3220
+ ** is the same as "addrBrk".
3221
+ */
3222
+ addrBrk = pLevel.addrBrk = pLevel.addrNxt = sqlite3VdbeMakeLabel(v);
3223
+ addrCont = pLevel.addrCont = sqlite3VdbeMakeLabel(v);
3224
+
3225
+ /* If this is the right table of a LEFT OUTER JOIN, allocate and
3226
+ ** initialize a memory cell that records if this table matches any
3227
+ ** row of the left table of the join.
3228
+ */
3229
+ if (pLevel.iFrom > 0 && (pTabItem.jointype & JT_LEFT) != 0)// Check value of pTabItem[0].jointype
3230
+ {
3231
+ pLevel.iLeftJoin = ++pParse.nMem;
3232
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel.iLeftJoin);
3233
+ #if SQLITE_DEBUG
3234
+ VdbeComment(v, "init LEFT JOIN no-match flag");
3235
+ #endif
3236
+ }
3237
+
3238
+ #if !SQLITE_OMIT_VIRTUALTABLE
3239
+ if ( ( pLevel.plan.wsFlags & WHERE_VIRTUALTABLE ) != null )
3240
+ {
3241
+ /* Case 0: The table is a virtual-table. Use the VFilter and VNext
3242
+ ** to access the data.
3243
+ */
3244
+ int iReg; /* P3 Value for OP_VFilter */
3245
+ sqlite3_index_info pVtabIdx = pLevel.plan.u.pVtabIdx;
3246
+ int nConstraint = pVtabIdx.nConstraint;
3247
+ sqlite3_index_constraint_usage* aUsage =
3248
+ pVtabIdx.aConstraintUsage;
3249
+ const sqlite3_index_constraint* aConstraint =
3250
+ pVtabIdx.aConstraint;
3251
+
3252
+ sqlite3ExprCachePush(pParse);
3253
+ iReg = sqlite3GetTempRange( pParse, nConstraint + 2 );
3254
+ for ( j = 1 ; j <= nConstraint ; j++ )
3255
+ {
3256
+ for ( k = 0 ; k < nConstraint ; k++ )
3257
+ {
3258
+ if ( aUsage[k].argvIndex == j )
3259
+ {
3260
+ int iTerm = aConstraint[k].iTermOffset;
3261
+ sqlite3ExprCode( pParse, pWC.a[iTerm].pExpr.pRight, iReg + j + 1 );
3262
+ break;
3263
+ }
3264
+ }
3265
+ if ( k == nConstraint ) break;
3266
+ }
3267
+ sqlite3VdbeAddOp2( v, OP_Integer, pVtabIdx.idxNum, iReg );
3268
+ sqlite3VdbeAddOp2( v, OP_Integer, j - 1, iReg + 1 );
3269
+ sqlite3VdbeAddOp4( v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx.idxStr,
3270
+ pVtabIdx.needToFreeIdxStr ? P4_MPRINTF : P4_STATIC );
3271
+ pVtabIdx.needToFreeIdxStr = 0;
3272
+ for ( j = 0 ; j < nConstraint ; j++ )
3273
+ {
3274
+ if ( aUsage[j].omit )
3275
+ {
3276
+ int iTerm = aConstraint[j].iTermOffset;
3277
+ disableTerm( pLevel, &pWC.a[iTerm] );
3278
+ }
3279
+ }
3280
+ pLevel.op = OP_VNext;
3281
+ pLevel.p1 = iCur;
3282
+ pLevel.p2 = sqlite3VdbeCurrentAddr( v );
3283
+ sqlite3ReleaseTempRange( pParse, iReg, nConstraint + 2 );
3284
+ sqlite3ExprCachePop(pParse, 1);
3285
+ }
3286
+ else
3287
+ #endif //* SQLITE_OMIT_VIRTUALTABLE */
3288
+
3289
+ if ((pLevel.plan.wsFlags & WHERE_ROWID_EQ) != 0)
3290
+ {
3291
+ /* Case 1: We can directly reference a single row using an
3292
+ ** equality comparison against the ROWID field. Or
3293
+ ** we reference multiple rows using a "rowid IN (...)"
3294
+ ** construct.
3295
+ */
3296
+ iReleaseReg = sqlite3GetTempReg(pParse);
3297
+ pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ | WO_IN, null);
3298
+ Debug.Assert(pTerm != null);
3299
+ Debug.Assert(pTerm.pExpr != null);
3300
+ Debug.Assert(pTerm.leftCursor == iCur);
3301
+ Debug.Assert(omitTable == 0);
3302
+ iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg);
3303
+ addrNxt = pLevel.addrNxt;
3304
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
3305
+ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
3306
+ sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
3307
+ #if SQLITE_DEBUG
3308
+ VdbeComment(v, "pk");
3309
+ #endif
3310
+ pLevel.op = OP_Noop;
3311
+ }
3312
+ else if ((pLevel.plan.wsFlags & WHERE_ROWID_RANGE) != 0)
3313
+ {
3314
+ /* Case 2: We have an inequality comparison against the ROWID field.
3315
+ */
3316
+ int testOp = OP_Noop;
3317
+ int start;
3318
+ int memEndValue = 0;
3319
+ WhereTerm pStart, pEnd;
3320
+
3321
+ Debug.Assert(omitTable == 0);
3322
+ pStart = findTerm(pWC, iCur, -1, notReady, WO_GT | WO_GE, null);
3323
+ pEnd = findTerm(pWC, iCur, -1, notReady, WO_LT | WO_LE, null);
3324
+ if (bRev != 0)
3325
+ {
3326
+ pTerm = pStart;
3327
+ pStart = pEnd;
3328
+ pEnd = pTerm;
3329
+ }
3330
+ if (pStart != null)
3331
+ {
3332
+ Expr pX; /* The expression that defines the start bound */
3333
+ int r1, rTemp = 0; /* Registers for holding the start boundary */
3334
+
3335
+ /* The following constant maps TK_xx codes into corresponding
3336
+ ** seek opcodes. It depends on a particular ordering of TK_xx
3337
+ */
3338
+ u8[] aMoveOp = new u8[]{
3339
+ /* TK_GT */ OP_SeekGt,
3340
+ /* TK_LE */ OP_SeekLe,
3341
+ /* TK_LT */ OP_SeekLt,
3342
+ /* TK_GE */ OP_SeekGe
3343
+ };
3344
+ Debug.Assert(TK_LE == TK_GT + 1); /* Make sure the ordering.. */
3345
+ Debug.Assert(TK_LT == TK_GT + 2); /* ... of the TK_xx values... */
3346
+ Debug.Assert(TK_GE == TK_GT + 3); /* ... is correcct. */
3347
+
3348
+ pX = pStart.pExpr;
3349
+ Debug.Assert(pX != null);
3350
+ Debug.Assert(pStart.leftCursor == iCur);
3351
+ r1 = sqlite3ExprCodeTemp(pParse, pX.pRight, ref rTemp);
3352
+ sqlite3VdbeAddOp3(v, aMoveOp[pX.op - TK_GT], iCur, addrBrk, r1);
3353
+ #if SQLITE_DEBUG
3354
+ VdbeComment(v, "pk");
3355
+ #endif
3356
+ sqlite3ExprCacheAffinityChange(pParse, r1, 1);
3357
+ sqlite3ReleaseTempReg(pParse, rTemp);
3358
+ disableTerm(pLevel, pStart);
3359
+ }
3360
+ else
3361
+ {
3362
+ sqlite3VdbeAddOp2(v, bRev != 0 ? OP_Last : OP_Rewind, iCur, addrBrk);
3363
+ }
3364
+ if (pEnd != null)
3365
+ {
3366
+ Expr pX;
3367
+ pX = pEnd.pExpr;
3368
+ Debug.Assert(pX != null);
3369
+ Debug.Assert(pEnd.leftCursor == iCur);
3370
+ memEndValue = ++pParse.nMem;
3371
+ sqlite3ExprCode(pParse, pX.pRight, memEndValue);
3372
+ if (pX.op == TK_LT || pX.op == TK_GT)
3373
+ {
3374
+ testOp = bRev != 0 ? OP_Le : OP_Ge;
3375
+ }
3376
+ else
3377
+ {
3378
+ testOp = bRev != 0 ? OP_Lt : OP_Gt;
3379
+ }
3380
+ disableTerm(pLevel, pEnd);
3381
+ }
3382
+ start = sqlite3VdbeCurrentAddr(v);
3383
+ pLevel.op = (u8)(bRev != 0 ? OP_Prev : OP_Next);
3384
+ pLevel.p1 = iCur;
3385
+ pLevel.p2 = start;
3386
+ pLevel.p5 = (u8)((pStart == null && pEnd == null) ? 1 : 0);
3387
+ if (testOp != OP_Noop)
3388
+ {
3389
+ iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
3390
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
3391
+ sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
3392
+ sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
3393
+ sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
3394
+ }
3395
+ }
3396
+ else if ((pLevel.plan.wsFlags & (WHERE_COLUMN_RANGE | WHERE_COLUMN_EQ)) != 0)
3397
+ {
3398
+ /* Case 3: A scan using an index.
3399
+ **
3400
+ ** The WHERE clause may contain zero or more equality
3401
+ ** terms ("==" or "IN" operators) that refer to the N
3402
+ ** left-most columns of the index. It may also contain
3403
+ ** inequality constraints (>, <, >= or <=) on the indexed
3404
+ ** column that immediately follows the N equalities. Only
3405
+ ** the right-most column can be an inequality - the rest must
3406
+ ** use the "==" and "IN" operators. For example, if the
3407
+ ** index is on (x,y,z), then the following clauses are all
3408
+ ** optimized:
3409
+ **
3410
+ ** x=5
3411
+ ** x=5 AND y=10
3412
+ ** x=5 AND y<10
3413
+ ** x=5 AND y>5 AND y<10
3414
+ ** x=5 AND y=5 AND z<=10
3415
+ **
3416
+ ** The z<10 term of the following cannot be used, only
3417
+ ** the x=5 term:
3418
+ **
3419
+ ** x=5 AND z<10
3420
+ **
3421
+ ** N may be zero if there are inequality constraints.
3422
+ ** If there are no inequality constraints, then N is at
3423
+ ** least one.
3424
+ **
3425
+ ** This case is also used when there are no WHERE clause
3426
+ ** constraints but an index is selected anyway, in order
3427
+ ** to force the output order to conform to an ORDER BY.
3428
+ */
3429
+ int[] aStartOp = new int[] {
3430
+ 0,
3431
+ 0,
3432
+ OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */
3433
+ OP_Last, /* 3: (!start_constraints && startEq && bRev) */
3434
+ OP_SeekGt, /* 4: (start_constraints && !startEq && !bRev) */
3435
+ OP_SeekLt, /* 5: (start_constraints && !startEq && bRev) */
3436
+ OP_SeekGe, /* 6: (start_constraints && startEq && !bRev) */
3437
+ OP_SeekLe /* 7: (start_constraints && startEq && bRev) */
3438
+ };
3439
+ int[] aEndOp = new int[] {
3440
+ OP_Noop, /* 0: (!end_constraints) */
3441
+ OP_IdxGE, /* 1: (end_constraints && !bRev) */
3442
+ OP_IdxLT /* 2: (end_constraints && bRev) */
3443
+ };
3444
+ int nEq = (int)pLevel.plan.nEq;
3445
+ int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */
3446
+ int regBase; /* Base register holding constraint values */
3447
+ int r1; /* Temp register */
3448
+ WhereTerm pRangeStart = null; /* Inequality constraint at range start */
3449
+ WhereTerm pRangeEnd = null; /* Inequality constraint at range end */
3450
+ int startEq; /* True if range start uses ==, >= or <= */
3451
+ int endEq; /* True if range end uses ==, >= or <= */
3452
+ int start_constraints; /* Start of range is constrained */
3453
+ int nConstraint; /* Number of constraint terms */
3454
+ Index pIdx; /* The index we will be using */
3455
+ int iIdxCur; /* The VDBE cursor for the index */
3456
+ int nExtraReg = 0; /* Number of extra registers needed */
3457
+ int op; /* Instruction opcode */
3458
+ StringBuilder zAff = null;
3459
+
3460
+ pIdx = pLevel.plan.u.pIdx;
3461
+ iIdxCur = pLevel.iIdxCur;
3462
+ k = pIdx.aiColumn[nEq]; /* Column for inequality constraints */
3463
+
3464
+ /* If this loop satisfies a sort order (pOrderBy) request that
3465
+ ** was pDebug.Assed to this function to implement a "SELECT min(x) ..."
3466
+ ** query, then the caller will only allow the loop to run for
3467
+ ** a single iteration. This means that the first row returned
3468
+ ** should not have a NULL value stored in 'x'. If column 'x' is
3469
+ ** the first one after the nEq equality constraints in the index,
3470
+ ** this requires some special handling.
3471
+ */
3472
+ if ((wctrlFlags & WHERE_ORDERBY_MIN) != 0
3473
+ && ((pLevel.plan.wsFlags & WHERE_ORDERBY) != 0)
3474
+ && (pIdx.nColumn > nEq)
3475
+ )
3476
+ {
3477
+ /* Debug.Assert( pOrderBy.nExpr==1 ); */
3478
+ /* Debug.Assert( pOrderBy.a[0].pExpr.iColumn==pIdx.aiColumn[nEq] ); */
3479
+ isMinQuery = 1;
3480
+ nExtraReg = 1;
3481
+ }
3482
+
3483
+ /* Find any inequality constraint terms for the start and end
3484
+ ** of the range.
3485
+ */
3486
+ if ((pLevel.plan.wsFlags & WHERE_TOP_LIMIT) != 0)
3487
+ {
3488
+ pRangeEnd = findTerm(pWC, iCur, k, notReady, (WO_LT | WO_LE), pIdx);
3489
+ nExtraReg = 1;
3490
+ }
3491
+ if ((pLevel.plan.wsFlags & WHERE_BTM_LIMIT) != 0)
3492
+ {
3493
+ pRangeStart = findTerm(pWC, iCur, k, notReady, (WO_GT | WO_GE), pIdx);
3494
+ nExtraReg = 1;
3495
+ }
3496
+
3497
+ /* Generate code to evaluate all constraint terms using == or IN
3498
+ ** and store the values of those terms in an array of registers
3499
+ ** starting at regBase.
3500
+ */
3501
+ regBase = codeAllEqualityTerms(
3502
+ pParse, pLevel, pWC, notReady, nExtraReg, ref zAff
3503
+ );
3504
+ addrNxt = pLevel.addrNxt;
3505
+
3506
+
3507
+ /* If we are doing a reverse order scan on an ascending index, or
3508
+ ** a forward order scan on a descending index, interchange the
3509
+ ** start and end terms (pRangeStart and pRangeEnd).
3510
+ */
3511
+ if (bRev == ((pIdx.aSortOrder[nEq] == SQLITE_SO_ASC) ? 1 : 0))
3512
+ {
3513
+ SWAP(ref pRangeEnd, ref pRangeStart);
3514
+ }
3515
+
3516
+ testcase(pRangeStart != null && (pRangeStart.eOperator & WO_LE) != 0);
3517
+ testcase(pRangeStart != null && (pRangeStart.eOperator & WO_GE) != 0);
3518
+ testcase(pRangeEnd != null && (pRangeEnd.eOperator & WO_LE) != 0);
3519
+ testcase(pRangeEnd != null && (pRangeEnd.eOperator & WO_GE) != 0);
3520
+ startEq = (null == pRangeStart || (pRangeStart.eOperator & (WO_LE | WO_GE)) != 0) ? 1 : 0;
3521
+ endEq = (null == pRangeEnd || (pRangeEnd.eOperator & (WO_LE | WO_GE)) != 0) ? 1 : 0;
3522
+ start_constraints = (pRangeStart != null || nEq > 0) ? 1 : 0;
3523
+
3524
+ /* Seek the index cursor to the start of the range. */
3525
+ nConstraint = nEq;
3526
+ if (pRangeStart != null)
3527
+ {
3528
+ Expr pRight = pRangeStart.pExpr.pRight;
3529
+ sqlite3ExprCode(pParse, pRight, regBase + nEq);
3530
+ sqlite3ExprCodeIsNullJump(v, pRight, regBase + nEq, addrNxt);
3531
+ if (zAff.Length == 0)
3532
+ {
3533
+ if (sqlite3CompareAffinity(pRight, zAff[nConstraint]) == SQLITE_AFF_NONE)
3534
+ {
3535
+ /* Since the comparison is to be performed with no conversions
3536
+ ** applied to the operands, set the affinity to apply to pRight to
3537
+ ** SQLITE_AFF_NONE. */
3538
+ zAff[nConstraint] = SQLITE_AFF_NONE;
3539
+ }
3540
+ if ((sqlite3ExprNeedsNoAffinityChange(pRight, zAff[nConstraint])) != 0)
3541
+ {
3542
+ zAff[nConstraint] = SQLITE_AFF_NONE;
3543
+ }
3544
+ }
3545
+ nConstraint++;
3546
+ }
3547
+ else if (isMinQuery != 0)
3548
+ {
3549
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase + nEq);
3550
+ nConstraint++;
3551
+ startEq = 0;
3552
+ start_constraints = 1;
3553
+ }
3554
+ codeApplyAffinity(pParse, regBase, nConstraint, zAff.ToString());
3555
+ op = aStartOp[(start_constraints << 2) + (startEq << 1) + bRev];
3556
+ Debug.Assert(op != 0);
3557
+ testcase(op == OP_Rewind);
3558
+ testcase(op == OP_Last);
3559
+ testcase(op == OP_SeekGt);
3560
+ testcase(op == OP_SeekGe);
3561
+ testcase(op == OP_SeekLe);
3562
+ testcase(op == OP_SeekLt);
3563
+ sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
3564
+
3565
+ /* Load the value for the inequality constraint at the end of the
3566
+ ** range (if any).
3567
+ */
3568
+ nConstraint = nEq;
3569
+ if (pRangeEnd != null)
3570
+ {
3571
+ Expr pRight = pRangeEnd.pExpr.pRight;
3572
+ sqlite3ExprCacheRemove(pParse, regBase + nEq, 1);
3573
+ sqlite3ExprCode(pParse, pRight, regBase + nEq);
3574
+ sqlite3ExprCodeIsNullJump(v, pRight, regBase + nEq, addrNxt);
3575
+ if (zAff.Length > 0)
3576
+ {
3577
+ if (sqlite3CompareAffinity(pRight, zAff[nConstraint]) == SQLITE_AFF_NONE)
3578
+ {
3579
+ /* Since the comparison is to be performed with no conversions
3580
+ ** applied to the operands, set the affinity to apply to pRight to
3581
+ ** SQLITE_AFF_NONE. */
3582
+ zAff[nConstraint] = SQLITE_AFF_NONE;
3583
+ }
3584
+ if ((sqlite3ExprNeedsNoAffinityChange(pRight, zAff[nConstraint])) != 0)
3585
+ {
3586
+ zAff[nConstraint] = SQLITE_AFF_NONE;
3587
+ }
3588
+ }
3589
+ codeApplyAffinity(pParse, regBase, nEq + 1, zAff.ToString());
3590
+ nConstraint++;
3591
+ }
3592
+ sqlite3DbFree(pParse.db, ref zAff);
3593
+
3594
+ /* Top of the loop body */
3595
+ pLevel.p2 = sqlite3VdbeCurrentAddr(v);
3596
+
3597
+ /* Check if the index cursor is past the end of the range. */
3598
+ op = aEndOp[((pRangeEnd != null || nEq != 0) ? 1 : 0) * (1 + bRev)];
3599
+ testcase(op == OP_Noop);
3600
+ testcase(op == OP_IdxGE);
3601
+ testcase(op == OP_IdxLT);
3602
+ if (op != OP_Noop)
3603
+ {
3604
+ sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
3605
+ sqlite3VdbeChangeP5(v, (u8)(endEq != bRev ? 1 : 0));
3606
+ }
3607
+
3608
+ /* If there are inequality constraints, check that the value
3609
+ ** of the table column that the inequality contrains is not NULL.
3610
+ ** If it is, jump to the next iteration of the loop.
3611
+ */
3612
+ r1 = sqlite3GetTempReg(pParse);
3613
+ testcase(pLevel.plan.wsFlags & WHERE_BTM_LIMIT);
3614
+ testcase(pLevel.plan.wsFlags & WHERE_TOP_LIMIT);
3615
+ if ((pLevel.plan.wsFlags & (WHERE_BTM_LIMIT | WHERE_TOP_LIMIT)) != 0)
3616
+ {
3617
+ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
3618
+ sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont);
3619
+ }
3620
+ sqlite3ReleaseTempReg(pParse, r1);
3621
+
3622
+ /* Seek the table cursor, if required */
3623
+ disableTerm(pLevel, pRangeStart);
3624
+ disableTerm(pLevel, pRangeEnd);
3625
+ if (0 == omitTable)
3626
+ {
3627
+ iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
3628
+ sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
3629
+ sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
3630
+ sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */
3631
+ }
3632
+
3633
+ /* Record the instruction used to terminate the loop. Disable
3634
+ ** WHERE clause terms made redundant by the index range scan.
3635
+ */
3636
+ pLevel.op = (u8)(bRev != 0 ? OP_Prev : OP_Next);
3637
+ pLevel.p1 = iIdxCur;
3638
+ }
3639
+ else
3640
+
3641
+ #if !SQLITE_OMIT_OR_OPTIMIZATION
3642
+ if ((pLevel.plan.wsFlags & WHERE_MULTI_OR) != 0)
3643
+ {
3644
+ /* Case 4: Two or more separately indexed terms connected by OR
3645
+ **
3646
+ ** Example:
3647
+ **
3648
+ ** CREATE TABLE t1(a,b,c,d);
3649
+ ** CREATE INDEX i1 ON t1(a);
3650
+ ** CREATE INDEX i2 ON t1(b);
3651
+ ** CREATE INDEX i3 ON t1(c);
3652
+ **
3653
+ ** SELECT * FROM t1 WHERE a=5 OR b=7 OR (c=11 AND d=13)
3654
+ **
3655
+ ** In the example, there are three indexed terms connected by OR.
3656
+ ** The top of the loop looks like this:
3657
+ **
3658
+ ** Null 1 # Zero the rowset in reg 1
3659
+ **
3660
+ ** Then, for each indexed term, the following. The arguments to
3661
+ ** RowSetTest are such that the rowid of the current row is inserted
3662
+ ** into the RowSet. If it is already present, control skips the
3663
+ ** Gosub opcode and jumps straight to the code generated by WhereEnd().
3664
+ **
3665
+ ** sqlite3WhereBegin(<term>)
3666
+ ** RowSetTest # Insert rowid into rowset
3667
+ ** Gosub 2 A
3668
+ ** sqlite3WhereEnd()
3669
+ **
3670
+ ** Following the above, code to terminate the loop. Label A, the target
3671
+ ** of the Gosub above, jumps to the instruction right after the Goto.
3672
+ **
3673
+ ** Null 1 # Zero the rowset in reg 1
3674
+ ** Goto B # The loop is finished.
3675
+ **
3676
+ ** A: <loop body> # Return data, whatever.
3677
+ **
3678
+ ** Return 2 # Jump back to the Gosub
3679
+ **
3680
+ ** B: <after the loop>
3681
+ **
3682
+ */
3683
+ WhereClause pOrWc; /* The OR-clause broken out into subterms */
3684
+ WhereTerm pFinal; /* Final subterm within the OR-clause. */
3685
+ SrcList pOrTab; /* Shortened table list or OR-clause generation */
3686
+
3687
+ int regReturn = ++pParse.nMem; /* Register used with OP_Gosub */
3688
+ int regRowset = 0; /* Register for RowSet object */
3689
+ int regRowid = 0; /* Register holding rowid */
3690
+ int iLoopBody = sqlite3VdbeMakeLabel(v);/* Start of loop body */
3691
+ int iRetInit; /* Address of regReturn init */
3692
+ int untestedTerms = 0; /* Some terms not completely tested */
3693
+ int ii;
3694
+ pTerm = pLevel.plan.u.pTerm;
3695
+ Debug.Assert(pTerm != null);
3696
+ Debug.Assert(pTerm.eOperator == WO_OR);
3697
+ Debug.Assert((pTerm.wtFlags & TERM_ORINFO) != 0);
3698
+ pOrWc = pTerm.u.pOrInfo.wc;
3699
+ pFinal = pOrWc.a[pOrWc.nTerm - 1];
3700
+ pLevel.op = OP_Return;
3701
+ pLevel.p1 = regReturn;
3702
+
3703
+ /* Set up a new SrcList in pOrTab containing the table being scanned
3704
+ ** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
3705
+ ** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
3706
+ */
3707
+ if (pWInfo.nLevel > 1)
3708
+ {
3709
+ int nNotReady; /* The number of notReady tables */
3710
+ SrcList_item[] origSrc; /* Original list of tables */
3711
+ nNotReady = pWInfo.nLevel - iLevel - 1;
3712
+ //sqlite3StackAllocRaw(pParse.db,
3713
+ //sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab.a[0]));
3714
+ pOrTab = new SrcList();
3715
+ pOrTab.a = new SrcList_item[nNotReady+1];
3716
+ //if( pOrTab==0 ) return notReady;
3717
+ pOrTab.nAlloc = (i16)(nNotReady + 1);
3718
+ pOrTab.nSrc = pOrTab.nAlloc;
3719
+ pOrTab.a[0] = pTabItem;//memcpy(pOrTab.a, pTabItem, sizeof(*pTabItem));
3720
+ origSrc = pWInfo.pTabList.a;
3721
+ for (k = 1; k <= nNotReady; k++)
3722
+ {
3723
+ pOrTab.a[k] = origSrc[pWInfo.a[iLevel + k].iFrom];// memcpy(&pOrTab.a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab.a[k]));
3724
+ }
3725
+ }
3726
+ else
3727
+ {
3728
+ pOrTab = pWInfo.pTabList;
3729
+ }
3730
+
3731
+ /* Initialize the rowset register to contain NULL. An SQL NULL is
3732
+ ** equivalent to an empty rowset.
3733
+ **
3734
+ ** Also initialize regReturn to contain the address of the instruction
3735
+ ** immediately following the OP_Return at the bottom of the loop. This
3736
+ ** is required in a few obscure LEFT JOIN cases where control jumps
3737
+ ** over the top of the loop into the body of it. In this case the
3738
+ ** correct response for the end-of-loop code (the OP_Return) is to
3739
+ ** fall through to the next instruction, just as an OP_Next does if
3740
+ ** called on an uninitialized cursor.
3741
+ */
3742
+ if ((wctrlFlags & WHERE_DUPLICATES_OK) == 0)
3743
+ {
3744
+ regRowset = ++pParse.nMem;
3745
+ regRowid = ++pParse.nMem;
3746
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
3747
+ }
3748
+ iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
3749
+
3750
+ for (ii = 0; ii < pOrWc.nTerm; ii++)
3751
+ {
3752
+ WhereTerm pOrTerm = pOrWc.a[ii];
3753
+ if (pOrTerm.leftCursor == iCur || pOrTerm.eOperator == WO_AND)
3754
+ {
3755
+ WhereInfo pSubWInfo; /* Info for single OR-term scan */
3756
+
3757
+ /* Loop through table entries that match term pOrTerm. */
3758
+ ExprList elDummy = null;
3759
+ pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrTerm.pExpr, ref elDummy,
3760
+ WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE |
3761
+ WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
3762
+ if (pSubWInfo != null)
3763
+ {
3764
+ if ((wctrlFlags & WHERE_DUPLICATES_OK) == 0)
3765
+ {
3766
+ int iSet = ((ii == pOrWc.nTerm - 1) ? -1 : ii);
3767
+ int r;
3768
+ r = sqlite3ExprCodeGetColumn(pParse, pTabItem.pTab, -1, iCur,
3769
+ regRowid);
3770
+ sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
3771
+ sqlite3VdbeCurrentAddr(v) + 2, r, iSet);
3772
+ }
3773
+ sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
3774
+
3775
+ /* The pSubWInfo->untestedTerms flag means that this OR term
3776
+ ** contained one or more AND term from a notReady table. The
3777
+ ** terms from the notReady table could not be tested and will
3778
+ ** need to be tested later.
3779
+ */
3780
+ if (pSubWInfo.untestedTerms != 0) untestedTerms = 1;
3781
+
3782
+ /* Finish the loop through table entries that match term pOrTerm. */
3783
+ sqlite3WhereEnd(pSubWInfo);
3784
+ }
3785
+ }
3786
+ }
3787
+ sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
3788
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel.addrBrk);
3789
+ sqlite3VdbeResolveLabel(v, iLoopBody);
3790
+
3791
+ if (pWInfo.nLevel > 1) sqlite3DbFree(pParse.db, ref pOrTab);//sqlite3DbFree(pParse.db, pOrTab)
3792
+ if (0 == untestedTerms) disableTerm(pLevel, pTerm);
3793
+ }
3794
+ else
3795
+ #endif //* SQLITE_OMIT_OR_OPTIMIZATION */
3796
+
3797
+ {
3798
+ /* Case 5: There is no usable index. We must do a complete
3799
+ ** scan of the entire table.
3800
+ */
3801
+ u8[] aStep = new u8[] { OP_Next, OP_Prev };
3802
+ u8[] aStart = new u8[] { OP_Rewind, OP_Last };
3803
+ Debug.Assert(bRev == 0 || bRev == 1);
3804
+ Debug.Assert(omitTable == 0);
3805
+ pLevel.op = aStep[bRev];
3806
+ pLevel.p1 = iCur;
3807
+ pLevel.p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
3808
+ pLevel.p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
3809
+ }
3810
+ notReady &= ~getMask(pWC.pMaskSet, iCur);
3811
+
3812
+ /* Insert code to test every subexpression that can be completely
3813
+ ** computed using the current set of tables.
3814
+ */
3815
+ k = 0;
3816
+ for (j = pWC.nTerm; j > 0; j--)//, pTerm++)
3817
+ {
3818
+ pTerm = pWC.a[pWC.nTerm - j];
3819
+ Expr pE;
3820
+ testcase(pTerm.wtFlags & TERM_VIRTUAL);
3821
+ testcase(pTerm.wtFlags & TERM_CODED);
3822
+ if ((pTerm.wtFlags & (TERM_VIRTUAL | TERM_CODED)) != 0) continue;
3823
+ if ((pTerm.prereqAll & notReady) != 0)
3824
+ {
3825
+ testcase(pWInfo.untestedTerms == 0
3826
+ && (pWInfo.wctrlFlags & WHERE_ONETABLE_ONLY) != 0);
3827
+ pWInfo.untestedTerms = 1;
3828
+ continue;
3829
+ }
3830
+ pE = pTerm.pExpr;
3831
+ Debug.Assert(pE != null);
3832
+ if (pLevel.iLeftJoin != 0 && !((pE.flags & EP_FromJoin) == EP_FromJoin))// !ExprHasProperty(pE, EP_FromJoin) ){
3833
+ {
3834
+ continue;
3835
+ }
3836
+ sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
3837
+ k = 1;
3838
+ pTerm.wtFlags |= TERM_CODED;
3839
+ }
3840
+
3841
+ /* For a LEFT OUTER JOIN, generate code that will record the fact that
3842
+ ** at least one row of the right table has matched the left table.
3843
+ */
3844
+ if (pLevel.iLeftJoin != 0)
3845
+ {
3846
+ pLevel.addrFirst = sqlite3VdbeCurrentAddr(v);
3847
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel.iLeftJoin);
3848
+ #if SQLITE_DEBUG
3849
+ VdbeComment(v, "record LEFT JOIN hit");
3850
+ #endif
3851
+ sqlite3ExprCacheClear(pParse);
3852
+ for (j = 0; j < pWC.nTerm; j++)//, pTerm++)
3853
+ {
3854
+ pTerm = pWC.a[j];
3855
+ testcase(pTerm.wtFlags & TERM_VIRTUAL);
3856
+ testcase(pTerm.wtFlags & TERM_CODED);
3857
+ if ((pTerm.wtFlags & (TERM_VIRTUAL | TERM_CODED)) != 0) continue;
3858
+ if ((pTerm.prereqAll & notReady) != 0)
3859
+ {
3860
+ Debug.Assert(pWInfo.untestedTerms != 0);
3861
+ continue;
3862
+ }
3863
+ Debug.Assert(pTerm.pExpr != null);
3864
+ sqlite3ExprIfFalse(pParse, pTerm.pExpr, addrCont, SQLITE_JUMPIFNULL);
3865
+ pTerm.wtFlags |= TERM_CODED;
3866
+ }
3867
+ }
3868
+
3869
+ sqlite3ReleaseTempReg(pParse, iReleaseReg);
3870
+ return notReady;
3871
+ }
3872
+
3873
+ #if (SQLITE_TEST)
3874
+ /*
3875
+ ** The following variable holds a text description of query plan generated
3876
+ ** by the most recent call to sqlite3WhereBegin(). Each call to WhereBegin
3877
+ ** overwrites the previous. This information is used for testing and
3878
+ ** analysis only.
3879
+ */
3880
+ //char sqlite3_query_plan[BMS*2*40]; /* Text of the join */
3881
+ static int nQPlan = 0; /* Next free slow in _query_plan[] */
3882
+
3883
+ #endif //* SQLITE_TEST */
3884
+
3885
+
3886
+ /*
3887
+ ** Free a WhereInfo structure
3888
+ */
3889
+ static void whereInfoFree(sqlite3 db, WhereInfo pWInfo)
3890
+ {
3891
+ if (pWInfo != null)
3892
+ {
3893
+ int i;
3894
+ for (i = 0; i < pWInfo.nLevel; i++)
3895
+ {
3896
+ sqlite3_index_info pInfo = pWInfo.a[i].pIdxInfo;
3897
+ if (pInfo != null)
3898
+ {
3899
+ /* Debug.Assert( pInfo.needToFreeIdxStr==0 || db.mallocFailed ); */
3900
+ if (pInfo.needToFreeIdxStr != 0)
3901
+ {
3902
+ //sqlite3_free( ref pInfo.idxStr );
3903
+ }
3904
+ sqlite3DbFree(db, ref pInfo);
3905
+ }
3906
+ }
3907
+ whereClauseClear(pWInfo.pWC);
3908
+ sqlite3DbFree(db, ref pWInfo);
3909
+ }
3910
+ }
3911
+
3912
+
3913
+ /*
3914
+ ** Generate the beginning of the loop used for WHERE clause processing.
3915
+ ** The return value is a pointer to an opaque structure that contains
3916
+ ** information needed to terminate the loop. Later, the calling routine
3917
+ ** should invoke sqlite3WhereEnd() with the return value of this function
3918
+ ** in order to complete the WHERE clause processing.
3919
+ **
3920
+ ** If an error occurs, this routine returns NULL.
3921
+ **
3922
+ ** The basic idea is to do a nested loop, one loop for each table in
3923
+ ** the FROM clause of a select. (INSERT and UPDATE statements are the
3924
+ ** same as a SELECT with only a single table in the FROM clause.) For
3925
+ ** example, if the SQL is this:
3926
+ **
3927
+ ** SELECT * FROM t1, t2, t3 WHERE ...;
3928
+ **
3929
+ ** Then the code generated is conceptually like the following:
3930
+ **
3931
+ ** foreach row1 in t1 do \ Code generated
3932
+ ** foreach row2 in t2 do |-- by sqlite3WhereBegin()
3933
+ ** foreach row3 in t3 do /
3934
+ ** ...
3935
+ ** end \ Code generated
3936
+ ** end |-- by sqlite3WhereEnd()
3937
+ ** end /
3938
+ **
3939
+ ** Note that the loops might not be nested in the order in which they
3940
+ ** appear in the FROM clause if a different order is better able to make
3941
+ ** use of indices. Note also that when the IN operator appears in
3942
+ ** the WHERE clause, it might result in additional nested loops for
3943
+ ** scanning through all values on the right-hand side of the IN.
3944
+ **
3945
+ ** There are Btree cursors Debug.Associated with each table. t1 uses cursor
3946
+ ** number pTabList.a[0].iCursor. t2 uses the cursor pTabList.a[1].iCursor.
3947
+ ** And so forth. This routine generates code to open those VDBE cursors
3948
+ ** and sqlite3WhereEnd() generates the code to close them.
3949
+ **
3950
+ ** The code that sqlite3WhereBegin() generates leaves the cursors named
3951
+ ** in pTabList pointing at their appropriate entries. The [...] code
3952
+ ** can use OP_Column and OP_Rowid opcodes on these cursors to extract
3953
+ ** data from the various tables of the loop.
3954
+ **
3955
+ ** If the WHERE clause is empty, the foreach loops must each scan their
3956
+ ** entire tables. Thus a three-way join is an O(N^3) operation. But if
3957
+ ** the tables have indices and there are terms in the WHERE clause that
3958
+ ** refer to those indices, a complete table scan can be avoided and the
3959
+ ** code will run much faster. Most of the work of this routine is checking
3960
+ ** to see if there are indices that can be used to speed up the loop.
3961
+ **
3962
+ ** Terms of the WHERE clause are also used to limit which rows actually
3963
+ ** make it to the "..." in the middle of the loop. After each "foreach",
3964
+ ** terms of the WHERE clause that use only terms in that loop and outer
3965
+ ** loops are evaluated and if false a jump is made around all subsequent
3966
+ ** inner loops (or around the "..." if the test occurs within the inner-
3967
+ ** most loop)
3968
+ **
3969
+ ** OUTER JOINS
3970
+ **
3971
+ ** An outer join of tables t1 and t2 is conceptally coded as follows:
3972
+ **
3973
+ ** foreach row1 in t1 do
3974
+ ** flag = 0
3975
+ ** foreach row2 in t2 do
3976
+ ** start:
3977
+ ** ...
3978
+ ** flag = 1
3979
+ ** end
3980
+ ** if flag==null then
3981
+ ** move the row2 cursor to a null row
3982
+ ** goto start
3983
+ ** fi
3984
+ ** end
3985
+ **
3986
+ ** ORDER BY CLAUSE PROCESSING
3987
+ **
3988
+ ** ppOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
3989
+ ** if there is one. If there is no ORDER BY clause or if this routine
3990
+ ** is called from an UPDATE or DELETE statement, then ppOrderBy is NULL.
3991
+ **
3992
+ ** If an index can be used so that the natural output order of the table
3993
+ ** scan is correct for the ORDER BY clause, then that index is used and
3994
+ ** ppOrderBy is set to NULL. This is an optimization that prevents an
3995
+ ** unnecessary sort of the result set if an index appropriate for the
3996
+ ** ORDER BY clause already exists.
3997
+ **
3998
+ ** If the where clause loops cannot be arranged to provide the correct
3999
+ ** output order, then the ppOrderBy is unchanged.
4000
+ */
4001
+ static WhereInfo sqlite3WhereBegin(
4002
+ Parse pParse, /* The parser context */
4003
+ SrcList pTabList, /* A list of all tables to be scanned */
4004
+ Expr pWhere, /* The WHERE clause */
4005
+ ref ExprList ppOrderBy, /* An ORDER BY clause, or NULL */
4006
+ u16 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */
4007
+ )
4008
+ {
4009
+ int i; /* Loop counter */
4010
+ int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
4011
+ int nTabList; /* Number of elements in pTabList */
4012
+ WhereInfo pWInfo; /* Will become the return value of this function */
4013
+ Vdbe v = pParse.pVdbe; /* The virtual data_base engine */
4014
+ Bitmask notReady; /* Cursors that are not yet positioned */
4015
+ WhereMaskSet pMaskSet; /* The expression mask set */
4016
+ WhereClause pWC = new WhereClause(); /* Decomposition of the WHERE clause */
4017
+ SrcList_item pTabItem; /* A single entry from pTabList */
4018
+ WhereLevel pLevel; /* A single level in the pWInfo list */
4019
+ int iFrom; /* First unused FROM clause element */
4020
+ int andFlags; /* AND-ed combination of all pWC.a[].wtFlags */
4021
+ sqlite3 db; /* Data_base connection */
4022
+
4023
+ /* The number of tables in the FROM clause is limited by the number of
4024
+ ** bits in a Bitmask
4025
+ */
4026
+ if (pTabList.nSrc > BMS)
4027
+ {
4028
+ sqlite3ErrorMsg(pParse, "at most %d tables in a join", BMS);
4029
+ return null;
4030
+ }
4031
+
4032
+ /* This function normally generates a nested loop for all tables in
4033
+ ** pTabList. But if the WHERE_ONETABLE_ONLY flag is set, then we should
4034
+ ** only generate code for the first table in pTabList and assume that
4035
+ ** any cursors associated with subsequent tables are uninitialized.
4036
+ */
4037
+ nTabList = ((wctrlFlags & WHERE_ONETABLE_ONLY) != 0) ? 1 : (int)pTabList.nSrc;
4038
+
4039
+ /* Allocate and initialize the WhereInfo structure that will become the
4040
+ ** return value. A single allocation is used to store the WhereInfo
4041
+ ** struct, the contents of WhereInfo.a[], the WhereClause structure
4042
+ ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte
4043
+ ** field (type Bitmask) it must be aligned on an 8-byte boundary on
4044
+ ** some architectures. Hence the ROUND8() below.
4045
+ */
4046
+ db = pParse.db;
4047
+ pWInfo = new WhereInfo();
4048
+ //nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
4049
+ //pWInfo = sqlite3DbMallocZero( db,
4050
+ // nByteWInfo +
4051
+ // sizeof( WhereClause ) +
4052
+ // sizeof( WhereMaskSet )
4053
+ //);
4054
+ pWInfo.a = new WhereLevel[pTabList.nSrc];
4055
+ //if ( db.mallocFailed != 0 )
4056
+ //{
4057
+ // goto whereBeginError;
4058
+ //}
4059
+ pWInfo.nLevel = nTabList;
4060
+ pWInfo.pParse = pParse;
4061
+ pWInfo.pTabList = pTabList;
4062
+ pWInfo.iBreak = sqlite3VdbeMakeLabel(v);
4063
+ pWInfo.pWC = pWC = new WhereClause();// (WhereClause )((u8 )pWInfo)[nByteWInfo];
4064
+ pWInfo.wctrlFlags = wctrlFlags;
4065
+ //pMaskSet = (WhereMaskSet)pWC[1];
4066
+
4067
+ /* Split the WHERE clause into separate subexpressions where each
4068
+ ** subexpression is separated by an AND operator.
4069
+ */
4070
+ pMaskSet = new WhereMaskSet();//initMaskSet(pMaskSet);
4071
+ whereClauseInit(pWC, pParse, pMaskSet);
4072
+ sqlite3ExprCodeConstants(pParse, pWhere);
4073
+ whereSplit(pWC, pWhere, TK_AND);
4074
+
4075
+ /* Special case: a WHERE clause that is constant. Evaluate the
4076
+ ** expression and either jump over all of the code or fall thru.
4077
+ */
4078
+ if (pWhere != null && (nTabList == 0 || sqlite3ExprIsConstantNotJoin(pWhere) != 0))
4079
+ {
4080
+ sqlite3ExprIfFalse(pParse, pWhere, pWInfo.iBreak, SQLITE_JUMPIFNULL);
4081
+ pWhere = null;
4082
+ }
4083
+
4084
+ /* Assign a bit from the bitmask to every term in the FROM clause.
4085
+ **
4086
+ ** When assigning bitmask values to FROM clause cursors, it must be
4087
+ ** the case that if X is the bitmask for the N-th FROM clause term then
4088
+ ** the bitmask for all FROM clause terms to the left of the N-th term
4089
+ ** is (X-1). An expression from the ON clause of a LEFT JOIN can use
4090
+ ** its Expr.iRightJoinTable value to find the bitmask of the right table
4091
+ ** of the join. Subtracting one from the right table bitmask gives a
4092
+ ** bitmask for all tables to the left of the join. Knowing the bitmask
4093
+ ** for all tables to the left of a left join is important. Ticket #3015.
4094
+ **
4095
+ ** Configure the WhereClause.vmask variable so that bits that correspond
4096
+ ** to virtual table cursors are set. This is used to selectively disable
4097
+ ** the OR-to-IN transformation in exprAnalyzeOrTerm(). It is not helpful
4098
+ ** with virtual tables.
4099
+ **
4100
+ ** Note that bitmasks are created for all pTabList->nSrc tables in
4101
+ ** pTabList, not just the first nTabList tables. nTabList is normally
4102
+ ** equal to pTabList->nSrc but might be shortened to 1 if the
4103
+ ** WHERE_ONETABLE_ONLY flag is set.
4104
+ */
4105
+ Debug.Assert(pWC.vmask == 0 && pMaskSet.n == 0);
4106
+ for (i = 0; i < pTabList.nSrc; i++)
4107
+ {
4108
+ createMask(pMaskSet, pTabList.a[i].iCursor);
4109
+ #if !SQLITE_OMIT_VIRTUALTABLE
4110
+ if ( ALWAYS( pTabList.a[i].pTab ) && IsVirtual( pTabList.a[i].pTab ) )
4111
+ {
4112
+ pWC.vmask |= ( (Bitmask)1 << i );
4113
+ }
4114
+ #endif
4115
+ }
4116
+ #if !NDEBUG
4117
+ {
4118
+ Bitmask toTheLeft = 0;
4119
+ for (i = 0; i < pTabList.nSrc; i++)
4120
+ {
4121
+ Bitmask m = getMask(pMaskSet, pTabList.a[i].iCursor);
4122
+ Debug.Assert((m - 1) == toTheLeft);
4123
+ toTheLeft |= m;
4124
+ }
4125
+ }
4126
+ #endif
4127
+
4128
+ /* Analyze all of the subexpressions. Note that exprAnalyze() might
4129
+ ** add new virtual terms onto the end of the WHERE clause. We do not
4130
+ ** want to analyze these virtual terms, so start analyzing at the end
4131
+ ** and work forward so that the added virtual terms are never processed.
4132
+ */
4133
+ exprAnalyzeAll(pTabList, pWC);
4134
+ //if ( db.mallocFailed != 0 )
4135
+ //{
4136
+ // goto whereBeginError;
4137
+ //}
4138
+
4139
+ /* Chose the best index to use for each table in the FROM clause.
4140
+ **
4141
+ ** This loop fills in the following fields:
4142
+ **
4143
+ ** pWInfo.a[].pIdx The index to use for this level of the loop.
4144
+ ** pWInfo.a[].wsFlags WHERE_xxx flags Debug.Associated with pIdx
4145
+ ** pWInfo.a[].nEq The number of == and IN constraints
4146
+ ** pWInfo.a[].iFrom Which term of the FROM clause is being coded
4147
+ ** pWInfo.a[].iTabCur The VDBE cursor for the data_base table
4148
+ ** pWInfo.a[].iIdxCur The VDBE cursor for the index
4149
+ ** pWInfo.a[].pTerm When wsFlags==WO_OR, the OR-clause term
4150
+ **
4151
+ ** This loop also figures out the nesting order of tables in the FROM
4152
+ ** clause.
4153
+ */
4154
+ notReady = ~(Bitmask)0;
4155
+ pTabItem = pTabList.a != null ? pTabList.a[0] : null; //pTabItem = pTabList.a;
4156
+ //pLevel = pWInfo.a;
4157
+ andFlags = ~0;
4158
+ #if (SQLITE_TEST) && (SQLITE_DEBUG)
4159
+ WHERETRACE("*** Optimizer Start ***\n");
4160
+ #endif
4161
+ for (i = iFrom = 0; i < nTabList; i++)//, pLevel++ )
4162
+ {
4163
+ pWInfo.a[i] = new WhereLevel();
4164
+ pLevel = pWInfo.a[i];
4165
+ WhereCost bestPlan; /* Most efficient plan seen so far */
4166
+ Index pIdx; /* Index for FROM table at pTabItem */
4167
+ int j; /* For looping over FROM tables */
4168
+ int bestJ = -1; /* The value of j */
4169
+ Bitmask m; /* Bitmask value for j or bestJ */
4170
+ int isOptimal; /* Iterator for optimal/non-optimal search */
4171
+
4172
+ bestPlan = new WhereCost();// memset( &bestPlan, 0, sizeof( bestPlan ) );
4173
+ bestPlan.rCost = SQLITE_BIG_DBL;
4174
+
4175
+ /* Loop through the remaining entries in the FROM clause to find the
4176
+ ** next nested loop. The FROM clause entries may be iterated through
4177
+ ** either once or twice.
4178
+ **
4179
+ ** The first iteration, which is always performed, searches for the
4180
+ ** FROM clause entry that permits the lowest-cost, "optimal" scan. In
4181
+ ** this context an optimal scan is one that uses the same strategy
4182
+ ** for the given FROM clause entry as would be selected if the entry
4183
+ ** were used as the innermost nested loop. In other words, a table
4184
+ ** is chosen such that the cost of running that table cannot be reduced
4185
+ ** by waiting for other tables to run first.
4186
+ **
4187
+ ** The second iteration is only performed if no optimal scan strategies
4188
+ ** were found by the first. This iteration is used to search for the
4189
+ ** lowest cost scan overall.
4190
+ **
4191
+ ** Previous versions of SQLite performed only the second iteration -
4192
+ ** the next outermost loop was always that with the lowest overall
4193
+ ** cost. However, this meant that SQLite could select the wrong plan
4194
+ ** for scripts such as the following:
4195
+ **
4196
+ ** CREATE TABLE t1(a, b);
4197
+ ** CREATE TABLE t2(c, d);
4198
+ ** SELECT * FROM t2, t1 WHERE t2.rowid = t1.a;
4199
+ **
4200
+ ** The best strategy is to iterate through table t1 first. However it
4201
+ ** is not possible to determine this with a simple greedy algorithm.
4202
+ ** However, since the cost of a linear scan through table t2 is the same
4203
+ ** as the cost of a linear scan through table t1, a simple greedy
4204
+ ** algorithm may choose to use t2 for the outer loop, which is a much
4205
+ ** costlier approach.
4206
+ */
4207
+ for (isOptimal = 1; isOptimal >= 0 && bestJ < 0; isOptimal--)
4208
+ {
4209
+ Bitmask mask = (isOptimal != 0 ? 0 : notReady);
4210
+ Debug.Assert((nTabList - iFrom) > 1 || isOptimal != 0);
4211
+ for (j = iFrom; j < nTabList; j++)//, pTabItem++)
4212
+ {
4213
+ pTabItem = pTabList.a[j];
4214
+ int doNotReorder; /* True if this table should not be reordered */
4215
+ WhereCost sCost = new WhereCost(); /* Cost information from best[Virtual]Index() */
4216
+ ExprList pOrderBy; /* ORDER BY clause for index to optimize */
4217
+
4218
+ doNotReorder = (pTabItem.jointype & (JT_LEFT | JT_CROSS)) != 0 ? 1 : 0;
4219
+ if ((j != iFrom && doNotReorder != 0)) break;
4220
+ m = getMask(pMaskSet, pTabItem.iCursor);
4221
+ if ((m & notReady) == 0)
4222
+ {
4223
+ if (j == iFrom) iFrom++;
4224
+ continue;
4225
+ }
4226
+ pOrderBy = ((i == 0 && ppOrderBy != null) ? ppOrderBy : null);
4227
+ Debug.Assert(pTabItem.pTab != null);
4228
+ #if !SQLITE_OMIT_VIRTUALTABLE
4229
+ if( IsVirtual(pTabItem.pTab) ){
4230
+ sqlite3_index_info **pp = &pWInfo.a[j].pIdxInfo;
4231
+ bestVirtualIndex(pParse, pWC, pTabItem, mask, pOrderBy, &sCost, pp);
4232
+ }else
4233
+ #endif
4234
+ {
4235
+ bestBtreeIndex(pParse, pWC, pTabItem, mask, pOrderBy, ref sCost);
4236
+ }
4237
+ Debug.Assert(isOptimal != 0 || (sCost.used & notReady) == 0);
4238
+
4239
+ if ((sCost.used & notReady) == 0
4240
+ && (j == iFrom || sCost.rCost < bestPlan.rCost)
4241
+ )
4242
+ {
4243
+ bestPlan = sCost;
4244
+ bestJ = j;
4245
+ }
4246
+ if (doNotReorder != 0) break;
4247
+ }
4248
+ }
4249
+ Debug.Assert(bestJ >= 0);
4250
+ Debug.Assert((notReady & getMask(pMaskSet, pTabList.a[bestJ].iCursor)) != 0);
4251
+ #if (SQLITE_TEST) && (SQLITE_DEBUG)
4252
+ WHERETRACE("*** Optimizer selects table %d for loop %d\n", bestJ,
4253
+ i);//pLevel - pWInfo.a );
4254
+ #endif
4255
+ if ((bestPlan.plan.wsFlags & WHERE_ORDERBY) != 0)
4256
+ {
4257
+ ppOrderBy = null;
4258
+ }
4259
+ andFlags = (int)(andFlags & bestPlan.plan.wsFlags);
4260
+ pLevel.plan = bestPlan.plan;
4261
+ if ((bestPlan.plan.wsFlags & WHERE_INDEXED) != 0)
4262
+ {
4263
+ pLevel.iIdxCur = pParse.nTab++;
4264
+ }
4265
+ else
4266
+ {
4267
+ pLevel.iIdxCur = -1;
4268
+ }
4269
+ notReady &= ~getMask(pMaskSet, pTabList.a[bestJ].iCursor);
4270
+ pLevel.iFrom = (u8)bestJ;
4271
+
4272
+ /* Check that if the table scanned by this loop iteration had an
4273
+ ** INDEXED BY clause attached to it, that the named index is being
4274
+ ** used for the scan. If not, then query compilation has failed.
4275
+ ** Return an error.
4276
+ */
4277
+ pIdx = pTabList.a[bestJ].pIndex;
4278
+ if (pIdx != null)
4279
+ {
4280
+ if ((bestPlan.plan.wsFlags & WHERE_INDEXED) == 0)
4281
+ {
4282
+ sqlite3ErrorMsg(pParse, "cannot use index: %s", pIdx.zName);
4283
+ goto whereBeginError;
4284
+ }
4285
+ else
4286
+ {
4287
+ /* If an INDEXED BY clause is used, the bestIndex() function is
4288
+ ** guaranteed to find the index specified in the INDEXED BY clause
4289
+ ** if it find an index at all. */
4290
+ Debug.Assert(bestPlan.plan.u.pIdx == pIdx);
4291
+ }
4292
+ }
4293
+ }
4294
+ #if (SQLITE_TEST) && (SQLITE_DEBUG)
4295
+ WHERETRACE("*** Optimizer Finished ***\n");
4296
+ #endif
4297
+ if (pParse.nErr != 0 /*|| db.mallocFailed != 0 */ )
4298
+ {
4299
+ goto whereBeginError;
4300
+ }
4301
+
4302
+ /* If the total query only selects a single row, then the ORDER BY
4303
+ ** clause is irrelevant.
4304
+ */
4305
+ if ((andFlags & WHERE_UNIQUE) != 0 && ppOrderBy != null)
4306
+ {
4307
+ ppOrderBy = null;
4308
+ }
4309
+
4310
+ /* If the caller is an UPDATE or DELETE statement that is requesting
4311
+ ** to use a one-pDebug.Ass algorithm, determine if this is appropriate.
4312
+ ** The one-pass algorithm only works if the WHERE clause constraints
4313
+ ** the statement to update a single row.
4314
+ */
4315
+ Debug.Assert((wctrlFlags & WHERE_ONEPASS_DESIRED) == 0 || pWInfo.nLevel == 1);
4316
+ if ((wctrlFlags & WHERE_ONEPASS_DESIRED) != 0 && (andFlags & WHERE_UNIQUE) != 0)
4317
+ {
4318
+ pWInfo.okOnePass = 1;
4319
+ pWInfo.a[0].plan.wsFlags = (u32)(pWInfo.a[0].plan.wsFlags & ~WHERE_IDX_ONLY);
4320
+ }
4321
+
4322
+ /* Open all tables in the pTabList and any indices selected for
4323
+ ** searching those tables.
4324
+ */
4325
+ sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
4326
+ for (i = 0; i < nTabList; i++)//, pLevel++ )
4327
+ {
4328
+ pLevel = pWInfo.a[i];
4329
+ Table pTab; /* Table to open */
4330
+ int iDb; /* Index of data_base containing table/index */
4331
+
4332
+ #if !SQLITE_OMIT_EXPLAIN
4333
+ if (pParse.explain == 2)
4334
+ {
4335
+ string zMsg;
4336
+ SrcList_item pItem = pTabList.a[pLevel.iFrom];
4337
+ zMsg = sqlite3MPrintf(db, "TABLE %s", pItem.zName);
4338
+ if (pItem.zAlias != null)
4339
+ {
4340
+ zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem.zAlias);
4341
+ }
4342
+ if ((pLevel.plan.wsFlags & WHERE_INDEXED) != 0)
4343
+ {
4344
+ zMsg = sqlite3MAppendf(db, zMsg, "%s WITH INDEX %s",
4345
+ zMsg, pLevel.plan.u.pIdx.zName);
4346
+ }
4347
+ else if ((pLevel.plan.wsFlags & WHERE_MULTI_OR) != 0)
4348
+ {
4349
+ zMsg = sqlite3MAppendf(db, zMsg, "%s VIA MULTI-INDEX UNION", zMsg);
4350
+ }
4351
+ else if ((pLevel.plan.wsFlags & (WHERE_ROWID_EQ | WHERE_ROWID_RANGE)) != 0)
4352
+ {
4353
+ zMsg = sqlite3MAppendf(db, zMsg, "%s USING PRIMARY KEY", zMsg);
4354
+ }
4355
+ #if !SQLITE_OMIT_VIRTUALTABLE
4356
+ else if( (pLevel.plan.wsFlags & WHERE_VIRTUALTABLE)!=null ){
4357
+ sqlite3_index_info pVtabIdx = pLevel.plan.u.pVtabIdx;
4358
+ zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
4359
+ pVtabIdx.idxNum, pVtabIdx.idxStr);
4360
+ }
4361
+ #endif
4362
+ if ((pLevel.plan.wsFlags & WHERE_ORDERBY) != 0)
4363
+ {
4364
+ zMsg = sqlite3MAppendf(db, zMsg, "%s ORDER BY", zMsg);
4365
+ }
4366
+ sqlite3VdbeAddOp4(v, OP_Explain, i, pLevel.iFrom, 0, zMsg, P4_DYNAMIC);
4367
+ }
4368
+ #endif //* SQLITE_OMIT_EXPLAIN */
4369
+ pTabItem = pTabList.a[pLevel.iFrom];
4370
+ pTab = pTabItem.pTab;
4371
+ iDb = sqlite3SchemaToIndex(db, pTab.pSchema);
4372
+ if ((pTab.tabFlags & TF_Ephemeral) != 0 || pTab.pSelect != null) continue;
4373
+ #if !SQLITE_OMIT_VIRTUALTABLE
4374
+ if( (pLevel.plan.wsFlags & WHERE_VIRTUALTABLE)!=null ){
4375
+ VTable pVTab = sqlite3GetVTable(db, pTab);
4376
+ int iCur = pTabItem.iCursor;
4377
+ sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0,
4378
+ pVTab, P4_VTAB);
4379
+ }else
4380
+ #endif
4381
+ if ((pLevel.plan.wsFlags & WHERE_IDX_ONLY) == 0
4382
+ && (wctrlFlags & WHERE_OMIT_OPEN) == 0)
4383
+ {
4384
+ int op = pWInfo.okOnePass != 0 ? OP_OpenWrite : OP_OpenRead;
4385
+ sqlite3OpenTable(pParse, pTabItem.iCursor, iDb, pTab, op);
4386
+ if (0 == pWInfo.okOnePass && pTab.nCol < BMS)
4387
+ {
4388
+ Bitmask b = pTabItem.colUsed;
4389
+ int n = 0;
4390
+ for (; b != 0; b = b >> 1, n++) { }
4391
+ sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v) - 1,
4392
+ n, P4_INT32);//SQLITE_INT_TO_PTR(n)
4393
+ Debug.Assert(n <= pTab.nCol);
4394
+ }
4395
+ }
4396
+ else
4397
+ {
4398
+ sqlite3TableLock(pParse, iDb, pTab.tnum, 0, pTab.zName);
4399
+ }
4400
+ pLevel.iTabCur = pTabItem.iCursor;
4401
+ if ((pLevel.plan.wsFlags & WHERE_INDEXED) != 0)
4402
+ {
4403
+ Index pIx = pLevel.plan.u.pIdx;
4404
+ KeyInfo pKey = sqlite3IndexKeyinfo(pParse, pIx);
4405
+ int iIdxCur = pLevel.iIdxCur;
4406
+ Debug.Assert(pIx.pSchema == pTab.pSchema);
4407
+ Debug.Assert(iIdxCur >= 0);
4408
+ sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIx.tnum, iDb,
4409
+ pKey, P4_KEYINFO_HANDOFF);
4410
+ #if SQLITE_DEBUG
4411
+ VdbeComment(v, "%s", pIx.zName);
4412
+ #endif
4413
+ }
4414
+ sqlite3CodeVerifySchema(pParse, iDb);
4415
+ }
4416
+ pWInfo.iTop = sqlite3VdbeCurrentAddr(v);
4417
+
4418
+ /* Generate the code to do the search. Each iteration of the for
4419
+ ** loop below generates code for a single nested loop of the VM
4420
+ ** program.
4421
+ */
4422
+ notReady = ~(Bitmask)0;
4423
+ for (i = 0; i < nTabList; i++)
4424
+ {
4425
+ notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady);
4426
+ pWInfo.iContinue = pWInfo.a[i].addrCont;
4427
+ }
4428
+
4429
+ #if SQLITE_TEST //* For testing and debugging use only */
4430
+ /* Record in the query plan information about the current table
4431
+ ** and the index used to access it (if any). If the table itself
4432
+ ** is not used, its name is just '{}'. If no index is used
4433
+ ** the index is listed as "{}". If the primary key is used the
4434
+ ** index name is '*'.
4435
+ */
4436
+ sqlite3_query_plan.sValue = "";
4437
+ for (i = 0; i < nTabList; i++)
4438
+ {
4439
+ string z;
4440
+ int n;
4441
+ pLevel = pWInfo.a[i];
4442
+ pTabItem = pTabList.a[pLevel.iFrom];
4443
+ z = pTabItem.zAlias;
4444
+ if (z == null) z = pTabItem.pTab.zName;
4445
+ n = sqlite3Strlen30(z);
4446
+ if (true) //n+nQPlan < sizeof(sqlite3_query_plan)-10 )
4447
+ {
4448
+ if ((pLevel.plan.wsFlags & WHERE_IDX_ONLY) != 0)
4449
+ {
4450
+ sqlite3_query_plan.Append("{}"); //memcpy( &sqlite3_query_plan[nQPlan], "{}", 2 );
4451
+ nQPlan += 2;
4452
+ }
4453
+ else
4454
+ {
4455
+ sqlite3_query_plan.Append(z); //memcpy( &sqlite3_query_plan[nQPlan], z, n );
4456
+ nQPlan += n;
4457
+ }
4458
+ sqlite3_query_plan.Append(" "); nQPlan++; //sqlite3_query_plan[nQPlan++] = ' ';
4459
+ }
4460
+ testcase(pLevel.plan.wsFlags & WHERE_ROWID_EQ);
4461
+ testcase(pLevel.plan.wsFlags & WHERE_ROWID_RANGE);
4462
+ if ((pLevel.plan.wsFlags & (WHERE_ROWID_EQ | WHERE_ROWID_RANGE)) != 0)
4463
+ {
4464
+ sqlite3_query_plan.Append("* "); //memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
4465
+ nQPlan += 2;
4466
+ }
4467
+ else if ((pLevel.plan.wsFlags & WHERE_INDEXED) != 0)
4468
+ {
4469
+ n = sqlite3Strlen30(pLevel.plan.u.pIdx.zName);
4470
+ if (true) //n+nQPlan < sizeof(sqlite3_query_plan)-2 )//if( n+nQPlan < sizeof(sqlite3_query_plan)-2 )
4471
+ {
4472
+ sqlite3_query_plan.Append(pLevel.plan.u.pIdx.zName); //memcpy(&sqlite3_query_plan[nQPlan], pLevel.plan.u.pIdx.zName, n);
4473
+ nQPlan += n;
4474
+ sqlite3_query_plan.Append(" "); //sqlite3_query_plan[nQPlan++] = ' ';
4475
+ }
4476
+ }
4477
+ else
4478
+ {
4479
+ sqlite3_query_plan.Append("{} "); //memcpy( &sqlite3_query_plan[nQPlan], "{} ", 3 );
4480
+ nQPlan += 3;
4481
+ }
4482
+ }
4483
+ //while( nQPlan>0 && sqlite3_query_plan[nQPlan-1]==' ' ){
4484
+ // sqlite3_query_plan[--nQPlan] = 0;
4485
+ //}
4486
+ //sqlite3_query_plan[nQPlan] = 0;
4487
+ sqlite3_query_plan.Trim();
4488
+ nQPlan = 0;
4489
+ #endif //* SQLITE_TEST // Testing and debugging use only */
4490
+
4491
+ /* Record the continuation address in the WhereInfo structure. Then
4492
+ ** clean up and return.
4493
+ */
4494
+ return pWInfo;
4495
+
4496
+ /* Jump here if malloc fails */
4497
+ whereBeginError:
4498
+ whereInfoFree(db, pWInfo);
4499
+ return null;
4500
+ }
4501
+
4502
+ /*
4503
+ ** Generate the end of the WHERE loop. See comments on
4504
+ ** sqlite3WhereBegin() for additional information.
4505
+ */
4506
+ static void sqlite3WhereEnd(WhereInfo pWInfo)
4507
+ {
4508
+ Parse pParse = pWInfo.pParse;
4509
+ Vdbe v = pParse.pVdbe;
4510
+ int i;
4511
+ WhereLevel pLevel;
4512
+ SrcList pTabList = pWInfo.pTabList;
4513
+ sqlite3 db = pParse.db;
4514
+
4515
+ /* Generate loop termination code.
4516
+ */
4517
+ sqlite3ExprCacheClear(pParse);
4518
+ for (i = pWInfo.nLevel - 1; i >= 0; i--)
4519
+ {
4520
+ pLevel = pWInfo.a[i];
4521
+ sqlite3VdbeResolveLabel(v, pLevel.addrCont);
4522
+ if (pLevel.op != OP_Noop)
4523
+ {
4524
+ sqlite3VdbeAddOp2(v, pLevel.op, pLevel.p1, pLevel.p2);
4525
+ sqlite3VdbeChangeP5(v, pLevel.p5);
4526
+ }
4527
+ if ((pLevel.plan.wsFlags & WHERE_IN_ABLE) != 0 && pLevel.u._in.nIn > 0)
4528
+ {
4529
+ InLoop pIn;
4530
+ int j;
4531
+ sqlite3VdbeResolveLabel(v, pLevel.addrNxt);
4532
+ for (j = pLevel.u._in.nIn; j > 0; j--)//, pIn--)
4533
+ {
4534
+ pIn = pLevel.u._in.aInLoop[j - 1];
4535
+ sqlite3VdbeJumpHere(v, pIn.addrInTop + 1);
4536
+ sqlite3VdbeAddOp2(v, OP_Next, pIn.iCur, pIn.addrInTop);
4537
+ sqlite3VdbeJumpHere(v, pIn.addrInTop - 1);
4538
+ }
4539
+ sqlite3DbFree(db, ref pLevel.u._in.aInLoop);
4540
+ }
4541
+ sqlite3VdbeResolveLabel(v, pLevel.addrBrk);
4542
+ if (pLevel.iLeftJoin != 0)
4543
+ {
4544
+ int addr;
4545
+ addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel.iLeftJoin);
4546
+ Debug.Assert((pLevel.plan.wsFlags & WHERE_IDX_ONLY) == 0
4547
+ || (pLevel.plan.wsFlags & WHERE_INDEXED) != 0);
4548
+ if ((pLevel.plan.wsFlags & WHERE_IDX_ONLY) == 0)
4549
+ {
4550
+ sqlite3VdbeAddOp1(v, OP_NullRow, pTabList.a[i].iCursor);
4551
+ }
4552
+ if (pLevel.iIdxCur >= 0)
4553
+ {
4554
+ sqlite3VdbeAddOp1(v, OP_NullRow, pLevel.iIdxCur);
4555
+ }
4556
+ if (pLevel.op == OP_Return)
4557
+ {
4558
+ sqlite3VdbeAddOp2(v, OP_Gosub, pLevel.p1, pLevel.addrFirst);
4559
+ }
4560
+ else
4561
+ {
4562
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel.addrFirst);
4563
+ }
4564
+ sqlite3VdbeJumpHere(v, addr);
4565
+ }
4566
+ }
4567
+
4568
+ /* The "break" point is here, just past the end of the outer loop.
4569
+ ** Set it.
4570
+ */
4571
+ sqlite3VdbeResolveLabel(v, pWInfo.iBreak);
4572
+
4573
+ /* Close all of the cursors that were opened by sqlite3WhereBegin.
4574
+ */
4575
+ Debug.Assert(pWInfo.nLevel == 1 || pWInfo.nLevel == pTabList.nSrc);
4576
+ for (i = 0; i < pWInfo.nLevel; i++)// for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
4577
+ {
4578
+ pLevel = pWInfo.a[i];
4579
+ SrcList_item pTabItem = pTabList.a[pLevel.iFrom];
4580
+ Table pTab = pTabItem.pTab;
4581
+ Debug.Assert(pTab != null);
4582
+ if ((pTab.tabFlags & TF_Ephemeral) != 0 || pTab.pSelect != null) continue;
4583
+ if ((pWInfo.wctrlFlags & WHERE_OMIT_CLOSE) == 0)
4584
+ {
4585
+ if (0 == pWInfo.okOnePass && (pLevel.plan.wsFlags & WHERE_IDX_ONLY) == 0)
4586
+ {
4587
+ sqlite3VdbeAddOp1(v, OP_Close, pTabItem.iCursor);
4588
+ }
4589
+ if ((pLevel.plan.wsFlags & WHERE_INDEXED) != 0)
4590
+ {
4591
+ sqlite3VdbeAddOp1(v, OP_Close, pLevel.iIdxCur);
4592
+ }
4593
+ }
4594
+
4595
+ /* If this scan uses an index, make code substitutions to read data
4596
+ ** from the index in preference to the table. Sometimes, this means
4597
+ ** the table need never be read from. This is a performance boost,
4598
+ ** as the vdbe level waits until the table is read before actually
4599
+ ** seeking the table cursor to the record corresponding to the current
4600
+ ** position in the index.
4601
+ **
4602
+ ** Calls to the code generator in between sqlite3WhereBegin and
4603
+ ** sqlite3WhereEnd will have created code that references the table
4604
+ ** directly. This loop scans all that code looking for opcodes
4605
+ ** that reference the table and converts them into opcodes that
4606
+ ** reference the index.
4607
+ */
4608
+ if ((pLevel.plan.wsFlags & WHERE_INDEXED) != 0)///* && 0 == db.mallocFailed */ )
4609
+ {
4610
+ int k, j, last;
4611
+ VdbeOp pOp;
4612
+ Index pIdx = pLevel.plan.u.pIdx;
4613
+
4614
+ Debug.Assert(pIdx != null);
4615
+ //pOp = sqlite3VdbeGetOp( v, pWInfo.iTop );
4616
+ last = sqlite3VdbeCurrentAddr(v);
4617
+ for (k = pWInfo.iTop; k < last; k++)//, pOp++ )
4618
+ {
4619
+ pOp = sqlite3VdbeGetOp(v, k);
4620
+ if (pOp.p1 != pLevel.iTabCur) continue;
4621
+ if (pOp.opcode == OP_Column)
4622
+ {
4623
+ for (j = 0; j < pIdx.nColumn; j++)
4624
+ {
4625
+ if (pOp.p2 == pIdx.aiColumn[j])
4626
+ {
4627
+ pOp.p2 = j;
4628
+ pOp.p1 = pLevel.iIdxCur;
4629
+ break;
4630
+ }
4631
+ }
4632
+ Debug.Assert((pLevel.plan.wsFlags & WHERE_IDX_ONLY) == 0
4633
+ || j < pIdx.nColumn);
4634
+
4635
+ }
4636
+ else if (pOp.opcode == OP_Rowid)
4637
+ {
4638
+ pOp.p1 = pLevel.iIdxCur;
4639
+ pOp.opcode = OP_IdxRowid;
4640
+ }
4641
+ }
4642
+ }
4643
+ }
4644
+
4645
+ /* Final cleanup
4646
+ */
4647
+ whereInfoFree(db, pWInfo);
4648
+ return;
4649
+ }
4650
+ }
4651
+ }