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,4406 @@
1
+ #define SQLITE_MAX_EXPR_DEPTH
2
+
3
+ using System;
4
+ using System.Diagnostics;
5
+ using System.Text;
6
+
7
+ using Bitmask = System.UInt64;
8
+ using i64 = System.Int64;
9
+ using u8 = System.Byte;
10
+ using u32 = System.UInt32;
11
+ using u16 = System.UInt16;
12
+
13
+ using Pgno = System.UInt32;
14
+
15
+ #if !SQLITE_MAX_VARIABLE_NUMBER
16
+ using ynVar = System.Int16;
17
+ #else
18
+ using ynVar = System.Int32;
19
+ #endif
20
+
21
+ namespace Community.CsharpSqlite
22
+ {
23
+ public partial class Sqlite3
24
+ {
25
+ /*
26
+ ** 2001 September 15
27
+ **
28
+ ** The author disclaims copyright to this source code. In place of
29
+ ** a legal notice, here is a blessing:
30
+ **
31
+ ** May you do good and not evil.
32
+ ** May you find forgiveness for yourself and forgive others.
33
+ ** May you share freely, never taking more than you give.
34
+ **
35
+ *************************************************************************
36
+ ** This file contains routines used for analyzing expressions and
37
+ ** for generating VDBE code that evaluates expressions in SQLite.
38
+ *************************************************************************
39
+ ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
40
+ ** C#-SQLite is an independent reimplementation of the SQLite software library
41
+ **
42
+ ** SQLITE_SOURCE_ID: 2010-03-09 19:31:43 4ae453ea7be69018d8c16eb8dabe05617397dc4d
43
+ **
44
+ ** $Header$
45
+ *************************************************************************
46
+ */
47
+ //#include "sqliteInt.h"
48
+
49
+ /*
50
+ ** Return the 'affinity' of the expression pExpr if any.
51
+ **
52
+ ** If pExpr is a column, a reference to a column via an 'AS' alias,
53
+ ** or a sub-select with a column as the return value, then the
54
+ ** affinity of that column is returned. Otherwise, 0x00 is returned,
55
+ ** indicating no affinity for the expression.
56
+ **
57
+ ** i.e. the WHERE clause expresssions in the following statements all
58
+ ** have an affinity:
59
+ **
60
+ ** CREATE TABLE t1(a);
61
+ ** SELECT * FROM t1 WHERE a;
62
+ ** SELECT a AS b FROM t1 WHERE b;
63
+ ** SELECT * FROM t1 WHERE (select a from t1);
64
+ */
65
+ static char sqlite3ExprAffinity( Expr pExpr )
66
+ {
67
+ int op = pExpr.op;
68
+ if ( op == TK_SELECT )
69
+ {
70
+ Debug.Assert( ( pExpr.flags & EP_xIsSelect ) != 0 );
71
+ return sqlite3ExprAffinity( pExpr.x.pSelect.pEList.a[0].pExpr );
72
+ }
73
+ #if !SQLITE_OMIT_CAST
74
+ if ( op == TK_CAST )
75
+ {
76
+ Debug.Assert( !ExprHasProperty( pExpr, EP_IntValue ) );
77
+ return sqlite3AffinityType( pExpr.u.zToken );
78
+ }
79
+ #endif
80
+ if ( ( op == TK_AGG_COLUMN || op == TK_COLUMN || op == TK_REGISTER )
81
+ && pExpr.pTab != null
82
+ )
83
+ {
84
+ /* op==TK_REGISTER && pExpr.pTab!=0 happens when pExpr was originally
85
+ ** a TK_COLUMN but was previously evaluated and cached in a register */
86
+ int j = pExpr.iColumn;
87
+ if ( j < 0 ) return SQLITE_AFF_INTEGER;
88
+ Debug.Assert( pExpr.pTab != null && j < pExpr.pTab.nCol );
89
+ return pExpr.pTab.aCol[j].affinity;
90
+ }
91
+ return pExpr.affinity;
92
+ }
93
+
94
+ /*
95
+ ** Set the collating sequence for expression pExpr to be the collating
96
+ ** sequence named by pToken. Return a pointer to the revised expression.
97
+ ** The collating sequence is marked as "explicit" using the EP_ExpCollate
98
+ ** flag. An explicit collating sequence will override implicit
99
+ ** collating sequences.
100
+ */
101
+ static Expr sqlite3ExprSetColl( Parse pParse, Expr pExpr, Token pCollName )
102
+ {
103
+ string zColl; /* Dequoted name of collation sequence */
104
+ CollSeq pColl;
105
+ sqlite3 db = pParse.db;
106
+ zColl = sqlite3NameFromToken( db, pCollName );
107
+ if ( pExpr != null && zColl != null )
108
+ {
109
+ pColl = sqlite3LocateCollSeq( pParse, zColl );
110
+ if ( pColl != null )
111
+ {
112
+ pExpr.pColl = pColl;
113
+ pExpr.flags |= EP_ExpCollate;
114
+ }
115
+ }
116
+ sqlite3DbFree( db, ref zColl );
117
+ return pExpr;
118
+ }
119
+
120
+ /*
121
+ ** Return the default collation sequence for the expression pExpr. If
122
+ ** there is no default collation type, return 0.
123
+ */
124
+ static CollSeq sqlite3ExprCollSeq( Parse pParse, Expr pExpr )
125
+ {
126
+ CollSeq pColl = null;
127
+ Expr p = pExpr;
128
+ while ( ALWAYS( p != null ) )
129
+ {
130
+ int op;
131
+ pColl = pExpr.pColl;
132
+ if ( pColl != null ) break;
133
+ op = p.op;
134
+ if ( p.pTab != null && (
135
+ op == TK_AGG_COLUMN || op == TK_COLUMN || op == TK_REGISTER || op == TK_TRIGGER
136
+ ) )
137
+ {
138
+ /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
139
+ ** a TK_COLUMN but was previously evaluated and cached in a register */
140
+ string zColl;
141
+ int j = p.iColumn;
142
+ if ( j >= 0 )
143
+ {
144
+ sqlite3 db = pParse.db;
145
+ zColl = p.pTab.aCol[j].zColl;
146
+ pColl = sqlite3FindCollSeq( db, ENC( db ), zColl, 0 );
147
+ pExpr.pColl = pColl;
148
+ }
149
+ break;
150
+ }
151
+ if ( op != TK_CAST && op != TK_UPLUS )
152
+ {
153
+ break;
154
+ }
155
+ p = p.pLeft;
156
+ }
157
+ if ( sqlite3CheckCollSeq( pParse, pColl ) != 0 )
158
+ {
159
+ pColl = null;
160
+ }
161
+ return pColl;
162
+ }
163
+
164
+ /*
165
+ ** pExpr is an operand of a comparison operator. aff2 is the
166
+ ** type affinity of the other operand. This routine returns the
167
+ ** type affinity that should be used for the comparison operator.
168
+ */
169
+ static char sqlite3CompareAffinity( Expr pExpr, char aff2 )
170
+ {
171
+ char aff1 = sqlite3ExprAffinity( pExpr );
172
+ if ( aff1 != '\0' && aff2 != '\0' )
173
+ {
174
+ /* Both sides of the comparison are columns. If one has numeric
175
+ ** affinity, use that. Otherwise use no affinity.
176
+ */
177
+ if ( aff1 >= SQLITE_AFF_NUMERIC || aff2 >= SQLITE_AFF_NUMERIC )
178
+ // if (sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2))
179
+ {
180
+ return SQLITE_AFF_NUMERIC;
181
+ }
182
+ else
183
+ {
184
+ return SQLITE_AFF_NONE;
185
+ }
186
+ }
187
+ else if ( aff1 == '\0' && aff2 == '\0' )
188
+ {
189
+ /* Neither side of the comparison is a column. Compare the
190
+ ** results directly.
191
+ */
192
+ return SQLITE_AFF_NONE;
193
+ }
194
+ else
195
+ {
196
+ /* One side is a column, the other is not. Use the columns affinity. */
197
+ Debug.Assert( aff1 == 0 || aff2 == 0 );
198
+ return ( aff1 != '\0' ? aff1 : aff2 );
199
+ }
200
+ }
201
+
202
+ /*
203
+ ** pExpr is a comparison operator. Return the type affinity that should
204
+ ** be applied to both operands prior to doing the comparison.
205
+ */
206
+ static char comparisonAffinity( Expr pExpr )
207
+ {
208
+ char aff;
209
+ Debug.Assert( pExpr.op == TK_EQ || pExpr.op == TK_IN || pExpr.op == TK_LT ||
210
+ pExpr.op == TK_GT || pExpr.op == TK_GE || pExpr.op == TK_LE ||
211
+ pExpr.op == TK_NE || pExpr.op == TK_IS || pExpr.op == TK_ISNOT );
212
+ Debug.Assert( pExpr.pLeft != null );
213
+ aff = sqlite3ExprAffinity( pExpr.pLeft );
214
+ if ( pExpr.pRight != null )
215
+ {
216
+ aff = sqlite3CompareAffinity( pExpr.pRight, aff );
217
+ }
218
+ else if ( ExprHasProperty( pExpr, EP_xIsSelect ) )
219
+ {
220
+ aff = sqlite3CompareAffinity( pExpr.x.pSelect.pEList.a[0].pExpr, aff );
221
+ }
222
+ else if ( aff == '\0' )
223
+ {
224
+ aff = SQLITE_AFF_NONE;
225
+ }
226
+ return aff;
227
+ }
228
+
229
+ /*
230
+ ** pExpr is a comparison expression, eg. '=', '<', IN(...) etc.
231
+ ** idx_affinity is the affinity of an indexed column. Return true
232
+ ** if the index with affinity idx_affinity may be used to implement
233
+ ** the comparison in pExpr.
234
+ */
235
+ static bool sqlite3IndexAffinityOk( Expr pExpr, char idx_affinity )
236
+ {
237
+ char aff = comparisonAffinity( pExpr );
238
+ switch ( aff )
239
+ {
240
+ case SQLITE_AFF_NONE:
241
+ return true;
242
+ case SQLITE_AFF_TEXT:
243
+ return idx_affinity == SQLITE_AFF_TEXT;
244
+ default:
245
+ return idx_affinity >= SQLITE_AFF_NUMERIC;// sqlite3IsNumericAffinity(idx_affinity);
246
+ }
247
+ }
248
+
249
+ /*
250
+ ** Return the P5 value that should be used for a binary comparison
251
+ ** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.
252
+ */
253
+ static u8 binaryCompareP5( Expr pExpr1, Expr pExpr2, int jumpIfNull )
254
+ {
255
+ u8 aff = (u8)sqlite3ExprAffinity( pExpr2 );
256
+ aff = (u8)( (u8)sqlite3CompareAffinity( pExpr1, (char)aff ) | (u8)jumpIfNull );
257
+ return aff;
258
+ }
259
+
260
+ /*
261
+ ** Return a pointer to the collation sequence that should be used by
262
+ ** a binary comparison operator comparing pLeft and pRight.
263
+ **
264
+ ** If the left hand expression has a collating sequence type, then it is
265
+ ** used. Otherwise the collation sequence for the right hand expression
266
+ ** is used, or the default (BINARY) if neither expression has a collating
267
+ ** type.
268
+ **
269
+ ** Argument pRight (but not pLeft) may be a null pointer. In this case,
270
+ ** it is not considered.
271
+ */
272
+ static CollSeq sqlite3BinaryCompareCollSeq(
273
+ Parse pParse,
274
+ Expr pLeft,
275
+ Expr pRight
276
+ )
277
+ {
278
+ CollSeq pColl;
279
+ Debug.Assert( pLeft != null );
280
+ if ( ( pLeft.flags & EP_ExpCollate ) != 0 )
281
+ {
282
+ Debug.Assert( pLeft.pColl != null );
283
+ pColl = pLeft.pColl;
284
+ }
285
+ else if ( pRight != null && ( ( pRight.flags & EP_ExpCollate ) != 0 ) )
286
+ {
287
+ Debug.Assert( pRight.pColl != null );
288
+ pColl = pRight.pColl;
289
+ }
290
+ else
291
+ {
292
+ pColl = sqlite3ExprCollSeq( pParse, pLeft );
293
+ if ( pColl == null )
294
+ {
295
+ pColl = sqlite3ExprCollSeq( pParse, pRight );
296
+ }
297
+ }
298
+ return pColl;
299
+ }
300
+
301
+ /*
302
+ ** Generate code for a comparison operator.
303
+ */
304
+ static int codeCompare(
305
+ Parse pParse, /* The parsing (and code generating) context */
306
+ Expr pLeft, /* The left operand */
307
+ Expr pRight, /* The right operand */
308
+ int opcode, /* The comparison opcode */
309
+ int in1, int in2, /* Register holding operands */
310
+ int dest, /* Jump here if true. */
311
+ int jumpIfNull /* If true, jump if either operand is NULL */
312
+ )
313
+ {
314
+ int p5;
315
+ int addr;
316
+ CollSeq p4;
317
+
318
+ p4 = sqlite3BinaryCompareCollSeq( pParse, pLeft, pRight );
319
+ p5 = binaryCompareP5( pLeft, pRight, jumpIfNull );
320
+ addr = sqlite3VdbeAddOp4( pParse.pVdbe, opcode, in2, dest, in1,
321
+ p4, P4_COLLSEQ );
322
+ sqlite3VdbeChangeP5( pParse.pVdbe, (u8)p5 );
323
+ return addr;
324
+ }
325
+
326
+ #if SQLITE_MAX_EXPR_DEPTH //>0
327
+ /*
328
+ ** Check that argument nHeight is less than or equal to the maximum
329
+ ** expression depth allowed. If it is not, leave an error message in
330
+ ** pParse.
331
+ */
332
+ static int sqlite3ExprCheckHeight( Parse pParse, int nHeight )
333
+ {
334
+ int rc = SQLITE_OK;
335
+ int mxHeight = pParse.db.aLimit[SQLITE_LIMIT_EXPR_DEPTH];
336
+ if ( nHeight > mxHeight )
337
+ {
338
+ sqlite3ErrorMsg( pParse,
339
+ "Expression tree is too large (maximum depth %d)", mxHeight
340
+ );
341
+ rc = SQLITE_ERROR;
342
+ }
343
+ return rc;
344
+ }
345
+
346
+ /* The following three functions, heightOfExpr(), heightOfExprList()
347
+ ** and heightOfSelect(), are used to determine the maximum height
348
+ ** of any expression tree referenced by the structure passed as the
349
+ ** first argument.
350
+ **
351
+ ** If this maximum height is greater than the current value pointed
352
+ ** to by pnHeight, the second parameter, then set pnHeight to that
353
+ ** value.
354
+ */
355
+ static void heightOfExpr( Expr p, ref int pnHeight )
356
+ {
357
+ if ( p != null )
358
+ {
359
+ if ( p.nHeight > pnHeight )
360
+ {
361
+ pnHeight = p.nHeight;
362
+ }
363
+ }
364
+ }
365
+ static void heightOfExprList( ExprList p, ref int pnHeight )
366
+ {
367
+ if ( p != null )
368
+ {
369
+ int i;
370
+ for ( i = 0; i < p.nExpr; i++ )
371
+ {
372
+ heightOfExpr( p.a[i].pExpr, ref pnHeight );
373
+ }
374
+ }
375
+ }
376
+ static void heightOfSelect( Select p, ref int pnHeight )
377
+ {
378
+ if ( p != null )
379
+ {
380
+ heightOfExpr( p.pWhere, ref pnHeight );
381
+ heightOfExpr( p.pHaving, ref pnHeight );
382
+ heightOfExpr( p.pLimit, ref pnHeight );
383
+ heightOfExpr( p.pOffset, ref pnHeight );
384
+ heightOfExprList( p.pEList, ref pnHeight );
385
+ heightOfExprList( p.pGroupBy, ref pnHeight );
386
+ heightOfExprList( p.pOrderBy, ref pnHeight );
387
+ heightOfSelect( p.pPrior, ref pnHeight );
388
+ }
389
+ }
390
+
391
+ /*
392
+ ** Set the Expr.nHeight variable in the structure passed as an
393
+ ** argument. An expression with no children, Expr.x.pList or
394
+ ** Expr.x.pSelect member has a height of 1. Any other expression
395
+ ** has a height equal to the maximum height of any other
396
+ ** referenced Expr plus one.
397
+ */
398
+ static void exprSetHeight( Expr p )
399
+ {
400
+ int nHeight = 0;
401
+ heightOfExpr( p.pLeft, ref nHeight );
402
+ heightOfExpr( p.pRight, ref nHeight );
403
+ if ( ExprHasProperty( p, EP_xIsSelect ) )
404
+ {
405
+ heightOfSelect( p.x.pSelect, ref nHeight );
406
+ }
407
+ else
408
+ {
409
+ heightOfExprList( p.x.pList, ref nHeight );
410
+ }
411
+ p.nHeight = nHeight + 1;
412
+ }
413
+
414
+ /*
415
+ ** Set the Expr.nHeight variable using the exprSetHeight() function. If
416
+ ** the height is greater than the maximum allowed expression depth,
417
+ ** leave an error in pParse.
418
+ */
419
+ static void sqlite3ExprSetHeight( Parse pParse, Expr p )
420
+ {
421
+ exprSetHeight( p );
422
+ sqlite3ExprCheckHeight( pParse, p.nHeight );
423
+ }
424
+
425
+ /*
426
+ ** Return the maximum height of any expression tree referenced
427
+ ** by the select statement passed as an argument.
428
+ */
429
+ static int sqlite3SelectExprHeight( Select p )
430
+ {
431
+ int nHeight = 0;
432
+ heightOfSelect( p, ref nHeight );
433
+ return nHeight;
434
+ }
435
+ #else
436
+ //#define exprSetHeight(y)
437
+ #endif //* SQLITE_MAX_EXPR_DEPTH>0 */
438
+
439
+ /*
440
+ ** This routine is the core allocator for Expr nodes.
441
+ **
442
+ ** Construct a new expression node and return a pointer to it. Memory
443
+ ** for this node and for the pToken argument is a single allocation
444
+ ** obtained from sqlite3DbMalloc(). The calling function
445
+ ** is responsible for making sure the node eventually gets freed.
446
+ **
447
+ ** If dequote is true, then the token (if it exists) is dequoted.
448
+ ** If dequote is false, no dequoting is performance. The deQuote
449
+ ** parameter is ignored if pToken is NULL or if the token does not
450
+ ** appear to be quoted. If the quotes were of the form "..." (double-quotes)
451
+ ** then the EP_DblQuoted flag is set on the expression node.
452
+ **
453
+ ** Special case: If op==TK_INTEGER and pToken points to a string that
454
+ ** can be translated into a 32-bit integer, then the token is not
455
+ ** stored in u.zToken. Instead, the integer values is written
456
+ ** into u.iValue and the EP_IntValue flag is set. No extra storage
457
+ ** is allocated to hold the integer text and the dequote flag is ignored.
458
+ */
459
+ static Expr sqlite3ExprAlloc(
460
+ sqlite3 db, /* Handle for sqlite3DbMallocZero() (may be null) */
461
+ int op, /* Expression opcode */
462
+ Token pToken, /* Token argument. Might be NULL */
463
+ int dequote /* True to dequote */
464
+ )
465
+ {
466
+ Expr pNew;
467
+ int nExtra = 0;
468
+ int iValue = 0;
469
+
470
+ if ( pToken != null )
471
+ {
472
+ if ( op != TK_INTEGER || pToken.z == null || pToken.z.Length == 0
473
+ || sqlite3GetInt32( pToken.z.ToString(), ref iValue ) == false )
474
+ {
475
+ nExtra = pToken.n + 1;
476
+ }
477
+ }
478
+ pNew = new Expr();//sqlite3DbMallocZero(db, sizeof(Expr)+nExtra);
479
+ if ( pNew != null )
480
+ {
481
+ pNew.op = (u8)op;
482
+ pNew.iAgg = -1;
483
+ if ( pToken != null )
484
+ {
485
+ if ( nExtra == 0 )
486
+ {
487
+ pNew.flags |= EP_IntValue;
488
+ pNew.u.iValue = iValue;
489
+ }
490
+ else
491
+ {
492
+ int c;
493
+ //pNew.u.zToken = (char*)&pNew[1];
494
+ if ( pToken.n > 0 ) pNew.u.zToken = pToken.z.Substring( 0, pToken.n );//memcpy(pNew.u.zToken, pToken.z, pToken.n);
495
+ else if ( pToken.n == 0 && pToken.z == "" ) pNew.u.zToken = "";
496
+ //pNew.u.zToken[pToken.n] = 0;
497
+ if ( dequote != 0 && nExtra >= 3
498
+ && ( ( c = pToken.z[0] ) == '\'' || c == '"' || c == '[' || c == '`' ) )
499
+ {
500
+ #if DEBUG_CLASS_EXPR || DEBUG_CLASS_ALL
501
+ sqlite3Dequote(ref pNew.u._zToken);
502
+ #else
503
+ sqlite3Dequote( ref pNew.u.zToken );
504
+ #endif
505
+ if ( c == '"' ) pNew.flags |= EP_DblQuoted;
506
+ }
507
+ }
508
+ }
509
+ #if SQLITE_MAX_EXPR_DEPTH//>0
510
+ pNew.nHeight = 1;
511
+ #endif
512
+ }
513
+ return pNew;
514
+ }
515
+
516
+ /*
517
+ ** Allocate a new expression node from a zero-terminated token that has
518
+ ** already been dequoted.
519
+ */
520
+ static Expr sqlite3Expr(
521
+ sqlite3 db, /* Handle for sqlite3DbMallocZero() (may be null) */
522
+ int op, /* Expression opcode */
523
+ string zToken /* Token argument. Might be NULL */
524
+ )
525
+ {
526
+ Token x = new Token();
527
+ x.z = zToken;
528
+ x.n = !String.IsNullOrEmpty( zToken ) ? sqlite3Strlen30( zToken ) : 0;
529
+ return sqlite3ExprAlloc( db, op, x, 0 );
530
+ }
531
+
532
+ /*
533
+ ** Attach subtrees pLeft and pRight to the Expr node pRoot.
534
+ **
535
+ ** If pRoot==NULL that means that a memory allocation error has occurred.
536
+ ** In that case, delete the subtrees pLeft and pRight.
537
+ */
538
+ static void sqlite3ExprAttachSubtrees(
539
+ sqlite3 db,
540
+ Expr pRoot,
541
+ Expr pLeft,
542
+ Expr pRight
543
+ )
544
+ {
545
+ if ( pRoot == null )
546
+ {
547
+ //Debug.Assert( db.mallocFailed != 0 );
548
+ sqlite3ExprDelete( db, ref pLeft );
549
+ sqlite3ExprDelete( db, ref pRight );
550
+ }
551
+ else
552
+ {
553
+ if ( pRight != null )
554
+ {
555
+ pRoot.pRight = pRight;
556
+ if ( ( pRight.flags & EP_ExpCollate ) != 0 )
557
+ {
558
+ pRoot.flags |= EP_ExpCollate;
559
+ pRoot.pColl = pRight.pColl;
560
+ }
561
+ }
562
+ if ( pLeft != null )
563
+ {
564
+ pRoot.pLeft = pLeft;
565
+ if ( ( pLeft.flags & EP_ExpCollate ) != 0 )
566
+ {
567
+ pRoot.flags |= EP_ExpCollate;
568
+ pRoot.pColl = pLeft.pColl;
569
+ }
570
+ }
571
+ exprSetHeight( pRoot );
572
+ }
573
+ }
574
+
575
+ /*
576
+ ** Allocate a Expr node which joins as many as two subtrees.
577
+ **
578
+ ** One or both of the subtrees can be NULL. Return a pointer to the new
579
+ ** Expr node. Or, if an OOM error occurs, set pParse->db->mallocFailed,
580
+ ** free the subtrees and return NULL.
581
+ */
582
+ // OVERLOADS, so I don't need to rewrite parse.c
583
+ static Expr sqlite3PExpr( Parse pParse, int op, int null_3, int null_4, int null_5 )
584
+ {
585
+ return sqlite3PExpr( pParse, op, null, null, null );
586
+ }
587
+ static Expr sqlite3PExpr( Parse pParse, int op, int null_3, int null_4, Token pToken )
588
+ {
589
+ return sqlite3PExpr( pParse, op, null, null, pToken );
590
+ }
591
+ static Expr sqlite3PExpr( Parse pParse, int op, Expr pLeft, int null_4, int null_5 )
592
+ {
593
+ return sqlite3PExpr( pParse, op, pLeft, null, null );
594
+ }
595
+ static Expr sqlite3PExpr( Parse pParse, int op, Expr pLeft, int null_4, Token pToken )
596
+ {
597
+ return sqlite3PExpr( pParse, op, pLeft, null, pToken );
598
+ }
599
+ static Expr sqlite3PExpr( Parse pParse, int op, Expr pLeft, Expr pRight, int null_5 )
600
+ {
601
+ return sqlite3PExpr( pParse, op, pLeft, pRight, null );
602
+ }
603
+ static Expr sqlite3PExpr(
604
+ Parse pParse, /* Parsing context */
605
+ int op, /* Expression opcode */
606
+ Expr pLeft, /* Left operand */
607
+ Expr pRight, /* Right operand */
608
+ Token pToken /* Argument Token */
609
+ )
610
+ {
611
+ Expr p = sqlite3ExprAlloc( pParse.db, op, pToken, 1 );
612
+ sqlite3ExprAttachSubtrees( pParse.db, p, pLeft, pRight );
613
+ return p;
614
+ }
615
+
616
+
617
+ /*
618
+ ** When doing a nested parse, you can include terms in an expression
619
+ ** that look like this: #1 #2 ... These terms refer to registers
620
+ ** in the virtual machine. #N is the N-th register.
621
+ **
622
+ ** This routine is called by the parser to deal with on of those terms.
623
+ ** It immediately generates code to store the value in a memory location.
624
+ ** The returns an expression that will code to extract the value from
625
+ ** that memory location as needed.
626
+ */
627
+ static Expr sqlite3RegisterExpr( Parse pParse, Token pToken )
628
+ {
629
+ Vdbe v = pParse.pVdbe;
630
+ Expr p;
631
+ if ( pParse.nested == 0 )
632
+ {
633
+ sqlite3ErrorMsg( pParse, "near \"%T\": syntax error", pToken );
634
+ return sqlite3PExpr( pParse, TK_NULL, null, null, null );
635
+ }
636
+ if ( v == null ) return null;
637
+ p = sqlite3PExpr( pParse, TK_REGISTER, null, null, pToken );
638
+ if ( p == null )
639
+ {
640
+ return null; /* Malloc failed */
641
+ }
642
+ p.u.iValue = atoi( pToken.z.Substring( 1 ) ); ;//atoi((char*)&pToken - z[1]);
643
+ return p;
644
+ }
645
+
646
+ /*
647
+ ** Join two expressions using an AND operator. If either expression is
648
+ ** NULL, then just return the other expression.
649
+ */
650
+ static Expr sqlite3ExprAnd( sqlite3 db, Expr pLeft, Expr pRight )
651
+ {
652
+ if ( pLeft == null )
653
+ {
654
+ return pRight;
655
+ }
656
+ else if ( pRight == null )
657
+ {
658
+ return pLeft;
659
+ }
660
+ else
661
+ {
662
+ Expr pNew = sqlite3ExprAlloc( db, TK_AND, null, 0 );
663
+ sqlite3ExprAttachSubtrees( db, pNew, pLeft, pRight );
664
+ return pNew;
665
+ }
666
+ }
667
+
668
+ /*
669
+ ** Construct a new expression node for a function with multiple
670
+ ** arguments.
671
+ */
672
+ // OVERLOADS, so I don't need to rewrite parse.c
673
+ static Expr sqlite3ExprFunction( Parse pParse, int null_2, Token pToken )
674
+ {
675
+ return sqlite3ExprFunction( pParse, null, pToken );
676
+ }
677
+ static Expr sqlite3ExprFunction( Parse pParse, ExprList pList, int null_3 )
678
+ {
679
+ return sqlite3ExprFunction( pParse, pList, null );
680
+ }
681
+ static Expr sqlite3ExprFunction( Parse pParse, ExprList pList, Token pToken )
682
+ {
683
+ Expr pNew;
684
+ sqlite3 db = pParse.db;
685
+ Debug.Assert( pToken != null );
686
+ pNew = sqlite3ExprAlloc( db, TK_FUNCTION, pToken, 1 );
687
+ if ( pNew == null )
688
+ {
689
+ sqlite3ExprListDelete( db, ref pList ); /* Avoid memory leak when malloc fails */
690
+ return null;
691
+ }
692
+ pNew.x.pList = pList;
693
+ Debug.Assert( !ExprHasProperty( pNew, EP_xIsSelect ) );
694
+
695
+ sqlite3ExprSetHeight( pParse, pNew );
696
+ return pNew;
697
+ }
698
+
699
+ /*
700
+ ** Assign a variable number to an expression that encodes a wildcard
701
+ ** in the original SQL statement.
702
+ **
703
+ ** Wildcards consisting of a single "?" are assigned the next sequential
704
+ ** variable number.
705
+ **
706
+ ** Wildcards of the form "?nnn" are assigned the number "nnn". We make
707
+ ** sure "nnn" is not too be to avoid a denial of service attack when
708
+ ** the SQL statement comes from an external source.
709
+ **
710
+ ** Wildcards of the form ":aaa", "@aaa" or "$aaa" are assigned the same number
711
+ ** as the previous instance of the same wildcard. Or if this is the first
712
+ ** instance of the wildcard, the next sequenial variable number is
713
+ ** assigned.
714
+ */
715
+ static void sqlite3ExprAssignVarNumber( Parse pParse, Expr pExpr )
716
+ {
717
+ sqlite3 db = pParse.db;
718
+ string z;
719
+
720
+ if ( pExpr == null ) return;
721
+ Debug.Assert( !ExprHasAnyProperty( pExpr, EP_IntValue | EP_Reduced | EP_TokenOnly ) );
722
+ z = pExpr.u.zToken;
723
+ Debug.Assert( z != null );
724
+ Debug.Assert( z.Length != 0 );
725
+ if ( z.Length == 1 )
726
+ {
727
+ /* Wildcard of the form "?". Assign the next variable number */
728
+ Debug.Assert( z[0] == '?' );
729
+ pExpr.iColumn = (ynVar)( ++pParse.nVar );
730
+ }
731
+ else if ( z[0] == '?' )
732
+ {
733
+ /* Wildcard of the form "?nnn". Convert "nnn" to an integer and
734
+ ** use it as the variable number */
735
+ int i = atoi( z.Substring( 1 ) );//atoi((char*)&z[1]);
736
+ pExpr.iColumn = (ynVar)i;
737
+ testcase( i == 0 );
738
+ testcase( i == 1 );
739
+ testcase( i == db.aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] - 1 );
740
+ testcase( i == db.aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
741
+ if ( i < 1 || i > db.aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] )
742
+ {
743
+ sqlite3ErrorMsg( pParse, "variable number must be between ?1 and ?%d",
744
+ db.aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
745
+ }
746
+ if ( i > pParse.nVar )
747
+ {
748
+ pParse.nVar = i;
749
+ }
750
+ }
751
+ else
752
+ {
753
+ /* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable
754
+ ** number as the prior appearance of the same name, or if the name
755
+ ** has never appeared before, reuse the same variable number
756
+ */
757
+ int i;
758
+ int n;
759
+ n = sqlite3Strlen30( z );
760
+ for ( i = 0; i < pParse.nVarExpr; i++ )
761
+ {
762
+ Expr pE = pParse.apVarExpr[i];
763
+ Debug.Assert( pE != null );
764
+ if ( memcmp( pE.u.zToken, z, n ) == 0 && pE.u.zToken.Length == n )
765
+ {
766
+ pExpr.iColumn = pE.iColumn;
767
+ break;
768
+ }
769
+ }
770
+ if ( i >= pParse.nVarExpr )
771
+ {
772
+ pExpr.iColumn = (ynVar)( ++pParse.nVar );
773
+ if ( pParse.nVarExpr >= pParse.nVarExprAlloc - 1 )
774
+ {
775
+ int oldLength = pParse.nVarExprAlloc;
776
+ pParse.nVarExprAlloc += pParse.nVarExprAlloc + 10;
777
+
778
+ Expr[] newXper = new Expr[pParse.nVarExprAlloc];
779
+ for (int iter = 0; iter < newXper.Length && iter < oldLength; iter++)
780
+ {
781
+ newXper[iter] = pParse.apVarExpr[iter];
782
+ }
783
+ pParse.apVarExpr = newXper;
784
+ //sqlite3DbReallocOrFree(
785
+ // db,
786
+ // pParse.apVarExpr,
787
+ // pParse.nVarExprAlloc*sizeof(pParse.apVarExpr[0])
788
+ //);
789
+ }
790
+ //if ( 0 == db.mallocFailed )
791
+ {
792
+ Debug.Assert( pParse.apVarExpr != null );
793
+ pParse.apVarExpr[pParse.nVarExpr++] = pExpr;
794
+ }
795
+ }
796
+ }
797
+ if ( pParse.nErr == 0 && pParse.nVar > db.aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] )
798
+ {
799
+ sqlite3ErrorMsg( pParse, "too many SQL variables" );
800
+ }
801
+ }
802
+
803
+ /*
804
+ ** Recursively delete an expression tree.
805
+ */
806
+ static void sqlite3ExprDelete( sqlite3 db, ref Expr p )
807
+ {
808
+ if ( p == null ) return;
809
+ if ( !ExprHasAnyProperty( p, EP_TokenOnly ) )
810
+ {
811
+ sqlite3ExprDelete( db, ref p.pLeft );
812
+ sqlite3ExprDelete( db, ref p.pRight );
813
+ if ( !ExprHasProperty( p, EP_Reduced ) && ( p.flags2 & EP2_MallocedToken ) != 0 )
814
+ {
815
+ #if DEBUG_CLASS_EXPR || DEBUG_CLASS_ALL
816
+ sqlite3DbFree( db, ref p.u._zToken );
817
+ #else
818
+ sqlite3DbFree( db, ref p.u.zToken );
819
+ #endif
820
+ }
821
+ if ( ExprHasProperty( p, EP_xIsSelect ) )
822
+ {
823
+ sqlite3SelectDelete( db, ref p.x.pSelect );
824
+ }
825
+ else
826
+ {
827
+ sqlite3ExprListDelete( db, ref p.x.pList );
828
+ }
829
+ }
830
+ if ( !ExprHasProperty( p, EP_Static ) )
831
+ {
832
+ sqlite3DbFree( db, ref p );
833
+ }
834
+ }
835
+
836
+ /*
837
+ ** Return the number of bytes allocated for the expression structure
838
+ ** passed as the first argument. This is always one of EXPR_FULLSIZE,
839
+ ** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE.
840
+ */
841
+ static int exprStructSize( Expr p )
842
+ {
843
+ if ( ExprHasProperty( p, EP_TokenOnly ) ) return EXPR_TOKENONLYSIZE;
844
+ if ( ExprHasProperty( p, EP_Reduced ) ) return EXPR_REDUCEDSIZE;
845
+ return EXPR_FULLSIZE;
846
+ }
847
+
848
+ /*
849
+ ** The dupedExpr*Size() routines each return the number of bytes required
850
+ ** to store a copy of an expression or expression tree. They differ in
851
+ ** how much of the tree is measured.
852
+ **
853
+ ** dupedExprStructSize() Size of only the Expr structure
854
+ ** dupedExprNodeSize() Size of Expr + space for token
855
+ ** dupedExprSize() Expr + token + subtree components
856
+ **
857
+ ***************************************************************************
858
+ **
859
+ ** The dupedExprStructSize() function returns two values OR-ed together:
860
+ ** (1) the space required for a copy of the Expr structure only and
861
+ ** (2) the EP_xxx flags that indicate what the structure size should be.
862
+ ** The return values is always one of:
863
+ **
864
+ ** EXPR_FULLSIZE
865
+ ** EXPR_REDUCEDSIZE | EP_Reduced
866
+ ** EXPR_TOKENONLYSIZE | EP_TokenOnly
867
+ **
868
+ ** The size of the structure can be found by masking the return value
869
+ ** of this routine with 0xfff. The flags can be found by masking the
870
+ ** return value with EP_Reduced|EP_TokenOnly.
871
+ **
872
+ ** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size
873
+ ** (unreduced) Expr objects as they or originally constructed by the parser.
874
+ ** During expression analysis, extra information is computed and moved into
875
+ ** later parts of teh Expr object and that extra information might get chopped
876
+ ** off if the expression is reduced. Note also that it does not work to
877
+ ** make a EXPRDUP_REDUCE copy of a reduced expression. It is only legal
878
+ ** to reduce a pristine expression tree from the parser. The implementation
879
+ ** of dupedExprStructSize() contain multiple Debug.Assert() statements that attempt
880
+ ** to enforce this constraint.
881
+ */
882
+ static int dupedExprStructSize( Expr p, int flags )
883
+ {
884
+ int nSize;
885
+ Debug.Assert( flags == EXPRDUP_REDUCE || flags == 0 ); /* Only one flag value allowed */
886
+ if ( 0 == ( flags & EXPRDUP_REDUCE ) )
887
+ {
888
+ nSize = EXPR_FULLSIZE;
889
+ }
890
+ else
891
+ {
892
+ Debug.Assert( !ExprHasAnyProperty( p, EP_TokenOnly | EP_Reduced ) );
893
+ Debug.Assert( !ExprHasProperty( p, EP_FromJoin ) );
894
+ Debug.Assert( ( p.flags2 & EP2_MallocedToken ) == 0 );
895
+ Debug.Assert( ( p.flags2 & EP2_Irreducible ) == 0 );
896
+ if ( p.pLeft != null || p.pRight != null || p.pColl != null || p.x.pList != null || p.x.pSelect != null )
897
+ {
898
+ nSize = EXPR_REDUCEDSIZE | EP_Reduced;
899
+ }
900
+ else
901
+ {
902
+ nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
903
+ }
904
+ }
905
+ return nSize;
906
+ }
907
+
908
+ /*
909
+ ** This function returns the space in bytes required to store the copy
910
+ ** of the Expr structure and a copy of the Expr.u.zToken string (if that
911
+ ** string is defined.)
912
+ */
913
+ static int dupedExprNodeSize( Expr p, int flags )
914
+ {
915
+ int nByte = dupedExprStructSize( p, flags ) & 0xfff;
916
+ if ( !ExprHasProperty( p, EP_IntValue ) && p.u.zToken != null )
917
+ {
918
+ nByte += sqlite3Strlen30( p.u.zToken ) + 1;
919
+ }
920
+ return ROUND8( nByte );
921
+ }
922
+
923
+ /*
924
+ ** Return the number of bytes required to create a duplicate of the
925
+ ** expression passed as the first argument. The second argument is a
926
+ ** mask containing EXPRDUP_XXX flags.
927
+ **
928
+ ** The value returned includes space to create a copy of the Expr struct
929
+ ** itself and the buffer referred to by Expr.u.zToken, if any.
930
+ **
931
+ ** If the EXPRDUP_REDUCE flag is set, then the return value includes
932
+ ** space to duplicate all Expr nodes in the tree formed by Expr.pLeft
933
+ ** and Expr.pRight variables (but not for any structures pointed to or
934
+ ** descended from the Expr.x.pList or Expr.x.pSelect variables).
935
+ */
936
+ static int dupedExprSize( Expr p, int flags )
937
+ {
938
+ int nByte = 0;
939
+ if ( p != null )
940
+ {
941
+ nByte = dupedExprNodeSize( p, flags );
942
+ if ( ( flags & EXPRDUP_REDUCE ) != 0 )
943
+ {
944
+ nByte += dupedExprSize( p.pLeft, flags ) + dupedExprSize( p.pRight, flags );
945
+ }
946
+ }
947
+ return nByte;
948
+ }
949
+
950
+ /*
951
+ ** This function is similar to sqlite3ExprDup(), except that if pzBuffer
952
+ ** is not NULL then *pzBuffer is assumed to point to a buffer large enough
953
+ ** to store the copy of expression p, the copies of p->u.zToken
954
+ ** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
955
+ ** if any. Before returning, *pzBuffer is set to the first byte passed the
956
+ ** portion of the buffer copied into by this function.
957
+ */
958
+ static Expr exprDup( sqlite3 db, Expr p, int flags, ref Expr pzBuffer )
959
+ {
960
+ Expr pNew = null; /* Value to return */
961
+ if ( p != null )
962
+ {
963
+ bool isReduced = ( flags & EXPRDUP_REDUCE ) != 0;
964
+ //Expr zAlloc = new Expr();
965
+ u32 staticFlag = 0;
966
+
967
+ Debug.Assert( pzBuffer == null || isReduced );
968
+
969
+ /* Figure out where to write the new Expr structure. */
970
+ //if ( pzBuffer !=null)
971
+ //{
972
+ // zAlloc = pzBuffer;
973
+ // staticFlag = EP_Static;
974
+ //}
975
+ //else
976
+ //{
977
+ // zAlloc = new Expr();//sqlite3DbMallocRaw( db, dupedExprSize( p, flags ) );
978
+ //}
979
+ // (Expr*)zAlloc;
980
+
981
+ //if ( pNew != null )
982
+ {
983
+ /* Set nNewSize to the size allocated for the structure pointed to
984
+ ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or
985
+ ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
986
+ ** by the copy of the p->u.zToken string (if any).
987
+ */
988
+ int nStructSize = dupedExprStructSize( p, flags );
989
+ int nNewSize = nStructSize & 0xfff;
990
+ int nToken;
991
+ if ( !ExprHasProperty( p, EP_IntValue ) && !String.IsNullOrEmpty( p.u.zToken ) )
992
+ {
993
+ nToken = sqlite3Strlen30( p.u.zToken );
994
+ }
995
+ else
996
+ {
997
+ nToken = 0;
998
+ }
999
+ if ( isReduced )
1000
+ {
1001
+ Debug.Assert( !ExprHasProperty( p, EP_Reduced ) );
1002
+ pNew = p.Copy( EXPR_TOKENONLYSIZE );//memcpy( zAlloc, p, nNewSize );
1003
+ }
1004
+ else
1005
+ {
1006
+ int nSize = exprStructSize( p );
1007
+ //memcpy( zAlloc, p, nSize );
1008
+ pNew = p.Copy();
1009
+ //memset( &zAlloc[nSize], 0, EXPR_FULLSIZE - nSize );
1010
+ }
1011
+
1012
+ /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
1013
+ unchecked { pNew.flags &= (ushort)( ~( EP_Reduced | EP_TokenOnly | EP_Static ) ); }
1014
+ pNew.flags |= (ushort)( nStructSize & ( EP_Reduced | EP_TokenOnly ) );
1015
+ pNew.flags |= (ushort)staticFlag;
1016
+
1017
+ /* Copy the p->u.zToken string, if any. */
1018
+ if ( nToken != 0 )
1019
+ {
1020
+ string zToken;// = pNew.u.zToken = (char*)&zAlloc[nNewSize];
1021
+ zToken = p.u.zToken.Substring( 0, nToken );// memcpy( zToken, p.u.zToken, nToken );
1022
+ }
1023
+
1024
+ if ( 0 == ( ( p.flags | pNew.flags ) & EP_TokenOnly ) )
1025
+ {
1026
+ /* Fill in the pNew.x.pSelect or pNew.x.pList member. */
1027
+ if ( ExprHasProperty( p, EP_xIsSelect ) )
1028
+ {
1029
+ pNew.x.pSelect = sqlite3SelectDup( db, p.x.pSelect, isReduced ? 1 : 0 );
1030
+ }
1031
+ else
1032
+ {
1033
+ pNew.x.pList = sqlite3ExprListDup( db, p.x.pList, isReduced ? 1 : 0 );
1034
+ }
1035
+ }
1036
+
1037
+ /* Fill in pNew.pLeft and pNew.pRight. */
1038
+ if ( ExprHasAnyProperty( pNew, EP_Reduced | EP_TokenOnly ) )
1039
+ {
1040
+ //zAlloc += dupedExprNodeSize( p, flags );
1041
+ if ( ExprHasProperty( pNew, EP_Reduced ) )
1042
+ {
1043
+ pNew.pLeft = exprDup( db, p.pLeft, EXPRDUP_REDUCE, ref pzBuffer );
1044
+ pNew.pRight = exprDup( db, p.pRight, EXPRDUP_REDUCE, ref pzBuffer );
1045
+ }
1046
+ //if ( pzBuffer != null )
1047
+ //{
1048
+ // pzBuffer = zAlloc;
1049
+ //}
1050
+ }
1051
+ else
1052
+ {
1053
+ pNew.flags2 = 0;
1054
+ if ( !ExprHasAnyProperty( p, EP_TokenOnly ) )
1055
+ {
1056
+ pNew.pLeft = sqlite3ExprDup( db, p.pLeft, 0 );
1057
+ pNew.pRight = sqlite3ExprDup( db, p.pRight, 0 );
1058
+ }
1059
+ }
1060
+ }
1061
+ }
1062
+ return pNew;
1063
+ }
1064
+
1065
+ /*
1066
+ ** The following group of routines make deep copies of expressions,
1067
+ ** expression lists, ID lists, and select statements. The copies can
1068
+ ** be deleted (by being passed to their respective ...Delete() routines)
1069
+ ** without effecting the originals.
1070
+ **
1071
+ ** The expression list, ID, and source lists return by sqlite3ExprListDup(),
1072
+ ** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded
1073
+ ** by subsequent calls to sqlite*ListAppend() routines.
1074
+ **
1075
+ ** Any tables that the SrcList might point to are not duplicated.
1076
+ **
1077
+ ** The flags parameter contains a combination of the EXPRDUP_XXX flags.
1078
+ ** If the EXPRDUP_REDUCE flag is set, then the structure returned is a
1079
+ ** truncated version of the usual Expr structure that will be stored as
1080
+ ** part of the in-memory representation of the database schema.
1081
+ */
1082
+ static Expr sqlite3ExprDup( sqlite3 db, Expr p, int flags )
1083
+ {
1084
+ Expr ExprDummy = null;
1085
+ return exprDup( db, p, flags, ref ExprDummy );
1086
+ }
1087
+
1088
+ static ExprList sqlite3ExprListDup( sqlite3 db, ExprList p, int flags )
1089
+ {
1090
+ ExprList pNew;
1091
+ ExprList_item pItem;
1092
+ ExprList_item pOldItem;
1093
+ int i;
1094
+ if ( p == null ) return null;
1095
+ pNew = new ExprList();//sqlite3DbMallocRaw(db, sizeof(*pNew) );
1096
+ //if ( pNew == null ) return null;
1097
+ pNew.iECursor = 0;
1098
+ pNew.nExpr = pNew.nAlloc = p.nExpr;
1099
+ pNew.a = new ExprList_item[p.nExpr];//sqlite3DbMallocRaw(db, p.nExpr*sizeof(p.a[0]) );
1100
+ //if( pItem==null ){
1101
+ // sqlite3DbFree(db,ref pNew);
1102
+ // return null;
1103
+ //}
1104
+ //pOldItem = p.a;
1105
+ for ( i = 0; i < p.nExpr; i++ )
1106
+ {//pItem++, pOldItem++){
1107
+ pItem = pNew.a[i] = new ExprList_item();
1108
+ pOldItem = p.a[i];
1109
+ Expr pOldExpr = pOldItem.pExpr;
1110
+ pItem.pExpr = sqlite3ExprDup( db, pOldExpr, flags );
1111
+ pItem.zName = pOldItem.zName;// sqlite3DbStrDup(db, pOldItem.zName);
1112
+ pItem.zSpan = pOldItem.zSpan;// sqlite3DbStrDup( db, pOldItem.zSpan );
1113
+ pItem.sortOrder = pOldItem.sortOrder;
1114
+ pItem.done = 0;
1115
+ pItem.iCol = pOldItem.iCol;
1116
+ pItem.iAlias = pOldItem.iAlias;
1117
+ }
1118
+ return pNew;
1119
+ }
1120
+
1121
+ /*
1122
+ ** If cursors, triggers, views and subqueries are all omitted from
1123
+ ** the build, then none of the following routines, except for
1124
+ ** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes
1125
+ ** called with a NULL argument.
1126
+ */
1127
+ #if !SQLITE_OMIT_VIEW || !SQLITE_OMIT_TRIGGER || !SQLITE_OMIT_SUBQUERY
1128
+ static SrcList sqlite3SrcListDup( sqlite3 db, SrcList p, int flags )
1129
+ {
1130
+ SrcList pNew;
1131
+ int i;
1132
+ int nByte;
1133
+ if ( p == null ) return null;
1134
+ //nByte = sizeof(*p) + (p.nSrc>0 ? sizeof(p.a[0]) * (p.nSrc-1) : 0);
1135
+ pNew = new SrcList();//sqlite3DbMallocRaw(db, nByte );
1136
+ if ( p.nSrc > 0 ) pNew.a = new SrcList_item[p.nSrc];
1137
+ if ( pNew == null ) return null;
1138
+ pNew.nSrc = pNew.nAlloc = p.nSrc;
1139
+ for ( i = 0; i < p.nSrc; i++ )
1140
+ {
1141
+ pNew.a[i] = new SrcList_item();
1142
+ SrcList_item pNewItem = pNew.a[i];
1143
+ SrcList_item pOldItem = p.a[i];
1144
+ Table pTab;
1145
+ pNewItem.zDatabase = pOldItem.zDatabase;// sqlite3DbStrDup(db, pOldItem.zDatabase);
1146
+ pNewItem.zName = pOldItem.zName;// sqlite3DbStrDup(db, pOldItem.zName);
1147
+ pNewItem.zAlias = pOldItem.zAlias;// sqlite3DbStrDup(db, pOldItem.zAlias);
1148
+ pNewItem.jointype = pOldItem.jointype;
1149
+ pNewItem.iCursor = pOldItem.iCursor;
1150
+ pNewItem.isPopulated = pOldItem.isPopulated;
1151
+ pNewItem.zIndex = pOldItem.zIndex;// sqlite3DbStrDup( db, pOldItem.zIndex );
1152
+ pNewItem.notIndexed = pOldItem.notIndexed;
1153
+ pNewItem.pIndex = pOldItem.pIndex;
1154
+ pTab = pNewItem.pTab = pOldItem.pTab;
1155
+ if ( pTab != null )
1156
+ {
1157
+ pTab.nRef++;
1158
+ }
1159
+ pNewItem.pSelect = sqlite3SelectDup( db, pOldItem.pSelect, flags );
1160
+ pNewItem.pOn = sqlite3ExprDup( db, pOldItem.pOn, flags );
1161
+ pNewItem.pUsing = sqlite3IdListDup( db, pOldItem.pUsing );
1162
+ pNewItem.colUsed = pOldItem.colUsed;
1163
+ }
1164
+ return pNew;
1165
+ }
1166
+
1167
+ static IdList sqlite3IdListDup( sqlite3 db, IdList p )
1168
+ {
1169
+ IdList pNew;
1170
+ int i;
1171
+ if ( p == null ) return null;
1172
+ pNew = new IdList();//sqlite3DbMallocRaw(db, sizeof(*pNew) );
1173
+ if ( pNew == null ) return null;
1174
+ pNew.nId = pNew.nAlloc = p.nId;
1175
+ pNew.a = new IdList_item[p.nId];//sqlite3DbMallocRaw(db, p.nId*sizeof(p.a[0]) );
1176
+ if ( pNew.a == null )
1177
+ {
1178
+ sqlite3DbFree( db, ref pNew );
1179
+ return null;
1180
+ }
1181
+ for ( i = 0; i < p.nId; i++ )
1182
+ {
1183
+ pNew.a[i] = new IdList_item();
1184
+ IdList_item pNewItem = pNew.a[i];
1185
+ IdList_item pOldItem = p.a[i];
1186
+ pNewItem.zName = pOldItem.zName;// sqlite3DbStrDup(db, pOldItem.zName);
1187
+ pNewItem.idx = pOldItem.idx;
1188
+ }
1189
+ return pNew;
1190
+ }
1191
+
1192
+ static Select sqlite3SelectDup( sqlite3 db, Select p, int flags )
1193
+ {
1194
+ Select pNew;
1195
+ if ( p == null ) return null;
1196
+ pNew = new Select();//sqlite3DbMallocRaw(db, sizeof(*p) );
1197
+ //if ( pNew == null ) return null;
1198
+ pNew.pEList = sqlite3ExprListDup( db, p.pEList, flags );
1199
+ pNew.pSrc = sqlite3SrcListDup( db, p.pSrc, flags );
1200
+ pNew.pWhere = sqlite3ExprDup( db, p.pWhere, flags );
1201
+ pNew.pGroupBy = sqlite3ExprListDup( db, p.pGroupBy, flags );
1202
+ pNew.pHaving = sqlite3ExprDup( db, p.pHaving, flags );
1203
+ pNew.pOrderBy = sqlite3ExprListDup( db, p.pOrderBy, flags );
1204
+ pNew.op = p.op;
1205
+ pNew.pPrior = sqlite3SelectDup( db, p.pPrior, flags );
1206
+ pNew.pLimit = sqlite3ExprDup( db, p.pLimit, flags );
1207
+ pNew.pOffset = sqlite3ExprDup( db, p.pOffset, flags );
1208
+ pNew.iLimit = 0;
1209
+ pNew.iOffset = 0;
1210
+ pNew.selFlags = (u16)( p.selFlags & ~SF_UsesEphemeral );
1211
+ pNew.pRightmost = null;
1212
+ pNew.addrOpenEphm[0] = -1;
1213
+ pNew.addrOpenEphm[1] = -1;
1214
+ pNew.addrOpenEphm[2] = -1;
1215
+ return pNew;
1216
+ }
1217
+ #else
1218
+ Select sqlite3SelectDup(sqlite3 db, Select p, int flags){
1219
+ Debug.Assert( p==null );
1220
+ return null;
1221
+ }
1222
+ #endif
1223
+
1224
+
1225
+ /*
1226
+ ** Add a new element to the end of an expression list. If pList is
1227
+ ** initially NULL, then create a new expression list.
1228
+ **
1229
+ ** If a memory allocation error occurs, the entire list is freed and
1230
+ ** NULL is returned. If non-NULL is returned, then it is guaranteed
1231
+ ** that the new entry was successfully appended.
1232
+ */
1233
+ // OVERLOADS, so I don't need to rewrite parse.c
1234
+ static ExprList sqlite3ExprListAppend( Parse pParse, int null_2, Expr pExpr )
1235
+ {
1236
+ return sqlite3ExprListAppend( pParse, null, pExpr );
1237
+ }
1238
+ static ExprList sqlite3ExprListAppend(
1239
+ Parse pParse, /* Parsing context */
1240
+ ExprList pList, /* List to which to append. Might be NULL */
1241
+ Expr pExpr /* Expression to be appended. Might be NULL */
1242
+ )
1243
+ {
1244
+ sqlite3 db = pParse.db;
1245
+ if ( pList == null )
1246
+ {
1247
+ pList = new ExprList(); //sqlite3DbMallocZero(db, ExprList).Length;
1248
+ //if ( pList == null )
1249
+ //{
1250
+ // goto no_mem;
1251
+ //}
1252
+ Debug.Assert( pList.nAlloc == 0 );
1253
+ }
1254
+ if ( pList.nAlloc <= pList.nExpr )
1255
+ {
1256
+ ExprList_item a;
1257
+ int n = pList.nAlloc * 2 + 4;
1258
+ //a = sqlite3DbRealloc(db, pList.a, n*sizeof(pList.a[0]));
1259
+ //if( a==0 ){
1260
+ // goto no_mem;
1261
+ //}
1262
+ Array.Resize( ref pList.a, n );// = a;
1263
+ pList.nAlloc = pList.a.Length;// sqlite3DbMallocSize(db, a)/sizeof(a[0]);
1264
+ }
1265
+ Debug.Assert( pList.a != null );
1266
+ if ( true )
1267
+ {
1268
+ pList.a[pList.nExpr] = new ExprList_item();
1269
+ //ExprList_item pItem = pList.a[pList.nExpr++];
1270
+ //pItem = new ExprList_item();//memset(pItem, 0, sizeof(*pItem));
1271
+ //pItem.pExpr = pExpr;
1272
+ pList.a[pList.nExpr++].pExpr = pExpr;
1273
+ }
1274
+ return pList;
1275
+
1276
+ //no_mem:
1277
+ // /* Avoid leaking memory if malloc has failed. */
1278
+ // sqlite3ExprDelete( db, ref pExpr );
1279
+ // sqlite3ExprListDelete( db, ref pList );
1280
+ // return null;
1281
+ }
1282
+
1283
+ /*
1284
+ ** Set the ExprList.a[].zName element of the most recently added item
1285
+ ** on the expression list.
1286
+ **
1287
+ ** pList might be NULL following an OOM error. But pName should never be
1288
+ ** NULL. If a memory allocation fails, the pParse.db.mallocFailed flag
1289
+ ** is set.
1290
+ */
1291
+ static void sqlite3ExprListSetName(
1292
+ Parse pParse, /* Parsing context */
1293
+ ExprList pList, /* List to which to add the span. */
1294
+ Token pName, /* Name to be added */
1295
+ int dequote /* True to cause the name to be dequoted */
1296
+ )
1297
+ {
1298
+ Debug.Assert( pList != null /* || pParse.db.mallocFailed != 0 */ );
1299
+ if ( pList != null )
1300
+ {
1301
+ ExprList_item pItem;
1302
+ Debug.Assert( pList.nExpr > 0 );
1303
+ pItem = pList.a[pList.nExpr - 1];
1304
+ Debug.Assert( pItem.zName == null );
1305
+ pItem.zName = pName.z.Substring( 0, pName.n );//sqlite3DbStrNDup(pParse.db, pName.z, pName.n);
1306
+ if ( dequote != 0 && !String.IsNullOrEmpty( pItem.zName ) ) sqlite3Dequote( ref pItem.zName );
1307
+ }
1308
+ }
1309
+
1310
+ /*
1311
+ ** Set the ExprList.a[].zSpan element of the most recently added item
1312
+ ** on the expression list.
1313
+ **
1314
+ ** pList might be NULL following an OOM error. But pSpan should never be
1315
+ ** NULL. If a memory allocation fails, the pParse.db.mallocFailed flag
1316
+ ** is set.
1317
+ */
1318
+ static void sqlite3ExprListSetSpan(
1319
+ Parse pParse, /* Parsing context */
1320
+ ExprList pList, /* List to which to add the span. */
1321
+ ExprSpan pSpan /* The span to be added */
1322
+ )
1323
+ {
1324
+ sqlite3 db = pParse.db;
1325
+ Debug.Assert( pList != null /*|| db.mallocFailed != 0 */ );
1326
+ if ( pList != null )
1327
+ {
1328
+ ExprList_item pItem = pList.a[pList.nExpr - 1];
1329
+ Debug.Assert( pList.nExpr > 0 );
1330
+ Debug.Assert( /* db.mallocFailed != 0 || */ pItem.pExpr == pSpan.pExpr );
1331
+ sqlite3DbFree( db, ref pItem.zSpan );
1332
+ pItem.zSpan = pSpan.zStart.Substring( 0, pSpan.zStart.Length <= pSpan.zEnd.Length ? pSpan.zStart.Length : pSpan.zStart.Length - pSpan.zEnd.Length );// sqlite3DbStrNDup( db, pSpan.zStart,
1333
+ //(int)( pSpan.zEnd- pSpan.zStart) );
1334
+ }
1335
+ }
1336
+
1337
+ /*
1338
+ ** If the expression list pEList contains more than iLimit elements,
1339
+ ** leave an error message in pParse.
1340
+ */
1341
+ static void sqlite3ExprListCheckLength(
1342
+ Parse pParse,
1343
+ ExprList pEList,
1344
+ string zObject
1345
+ )
1346
+ {
1347
+ int mx = pParse.db.aLimit[SQLITE_LIMIT_COLUMN];
1348
+ testcase( pEList != null && pEList.nExpr == mx );
1349
+ testcase( pEList != null && pEList.nExpr == mx + 1 );
1350
+ if ( pEList != null && pEList.nExpr > mx )
1351
+ {
1352
+ sqlite3ErrorMsg( pParse, "too many columns in %s", zObject );
1353
+ }
1354
+ }
1355
+
1356
+
1357
+ /*
1358
+ ** Delete an entire expression list.
1359
+ */
1360
+ static void sqlite3ExprListDelete( sqlite3 db, ref ExprList pList )
1361
+ {
1362
+ int i;
1363
+ ExprList_item pItem;
1364
+ if ( pList == null ) return;
1365
+ Debug.Assert( pList.a != null || ( pList.nExpr == 0 && pList.nAlloc == 0 ) );
1366
+ Debug.Assert( pList.nExpr <= pList.nAlloc );
1367
+ for ( i = 0; i < pList.nExpr; i++ )
1368
+ {
1369
+ if ( ( pItem = pList.a[i] ) != null )
1370
+ {
1371
+ sqlite3ExprDelete( db, ref pItem.pExpr );
1372
+ sqlite3DbFree( db, ref pItem.zName );
1373
+ sqlite3DbFree( db, ref pItem.zSpan );
1374
+ }
1375
+ }
1376
+ sqlite3DbFree( db, ref pList.a );
1377
+ sqlite3DbFree( db, ref pList );
1378
+ }
1379
+
1380
+ /*
1381
+ ** These routines are Walker callbacks. Walker.u.pi is a pointer
1382
+ ** to an integer. These routines are checking an expression to see
1383
+ ** if it is a constant. Set *Walker.u.pi to 0 if the expression is
1384
+ ** not constant.
1385
+ **
1386
+ ** These callback routines are used to implement the following:
1387
+ **
1388
+ ** sqlite3ExprIsConstant()
1389
+ ** sqlite3ExprIsConstantNotJoin()
1390
+ ** sqlite3ExprIsConstantOrFunction()
1391
+ **
1392
+ */
1393
+ static int exprNodeIsConstant( Walker pWalker, ref Expr pExpr )
1394
+ {
1395
+ /* If pWalker.u.i is 3 then any term of the expression that comes from
1396
+ ** the ON or USING clauses of a join disqualifies the expression
1397
+ ** from being considered constant. */
1398
+ if ( pWalker.u.i == 3 && ExprHasAnyProperty( pExpr, EP_FromJoin ) )
1399
+ {
1400
+ pWalker.u.i = 0;
1401
+ return WRC_Abort;
1402
+ }
1403
+
1404
+ switch ( pExpr.op )
1405
+ {
1406
+ /* Consider functions to be constant if all their arguments are constant
1407
+ ** and pWalker.u.i==2 */
1408
+ case TK_FUNCTION:
1409
+ if ( ( pWalker.u.i ) == 2 ) return 0;
1410
+ goto case TK_ID;
1411
+ /* Fall through */
1412
+ case TK_ID:
1413
+ case TK_COLUMN:
1414
+ case TK_AGG_FUNCTION:
1415
+ case TK_AGG_COLUMN:
1416
+ testcase( pExpr.op == TK_ID );
1417
+ testcase( pExpr.op == TK_COLUMN );
1418
+ testcase( pExpr.op == TK_AGG_FUNCTION );
1419
+ testcase( pExpr.op == TK_AGG_COLUMN );
1420
+ pWalker.u.i = 0;
1421
+ return WRC_Abort;
1422
+ default:
1423
+ testcase( pExpr.op == TK_SELECT ); /* selectNodeIsConstant will disallow */
1424
+ testcase( pExpr.op == TK_EXISTS ); /* selectNodeIsConstant will disallow */
1425
+ return WRC_Continue;
1426
+ }
1427
+ }
1428
+
1429
+ static int selectNodeIsConstant( Walker pWalker, Select NotUsed )
1430
+ {
1431
+ UNUSED_PARAMETER( NotUsed );
1432
+ pWalker.u.i = 0;
1433
+ return WRC_Abort;
1434
+ }
1435
+ static int exprIsConst( Expr p, int initFlag )
1436
+ {
1437
+ Walker w = new Walker();
1438
+ w.u.i = initFlag;
1439
+ w.xExprCallback = exprNodeIsConstant;
1440
+ w.xSelectCallback = selectNodeIsConstant;
1441
+ sqlite3WalkExpr( w, ref p );
1442
+ return w.u.i;
1443
+ }
1444
+
1445
+ /*
1446
+ ** Walk an expression tree. Return 1 if the expression is constant
1447
+ ** and 0 if it involves variables or function calls.
1448
+ **
1449
+ ** For the purposes of this function, a double-quoted string (ex: "abc")
1450
+ ** is considered a variable but a single-quoted string (ex: 'abc') is
1451
+ ** a constant.
1452
+ */
1453
+ static int sqlite3ExprIsConstant( Expr p )
1454
+ {
1455
+ return exprIsConst( p, 1 );
1456
+ }
1457
+
1458
+ /*
1459
+ ** Walk an expression tree. Return 1 if the expression is constant
1460
+ ** that does no originate from the ON or USING clauses of a join.
1461
+ ** Return 0 if it involves variables or function calls or terms from
1462
+ ** an ON or USING clause.
1463
+ */
1464
+ static int sqlite3ExprIsConstantNotJoin( Expr p )
1465
+ {
1466
+ return exprIsConst( p, 3 );
1467
+ }
1468
+
1469
+ /*
1470
+ ** Walk an expression tree. Return 1 if the expression is constant
1471
+ ** or a function call with constant arguments. Return and 0 if there
1472
+ ** are any variables.
1473
+ **
1474
+ ** For the purposes of this function, a double-quoted string (ex: "abc")
1475
+ ** is considered a variable but a single-quoted string (ex: 'abc') is
1476
+ ** a constant.
1477
+ */
1478
+ static int sqlite3ExprIsConstantOrFunction( Expr p )
1479
+ {
1480
+ return exprIsConst( p, 2 );
1481
+ }
1482
+
1483
+ /*
1484
+ ** If the expression p codes a constant integer that is small enough
1485
+ ** to fit in a 32-bit integer, return 1 and put the value of the integer
1486
+ ** in pValue. If the expression is not an integer or if it is too big
1487
+ ** to fit in a signed 32-bit integer, return 0 and leave pValue unchanged.
1488
+ */
1489
+ static int sqlite3ExprIsInteger( Expr p, ref int pValue )
1490
+ {
1491
+ int rc = 0;
1492
+ if ( ( p.flags & EP_IntValue ) != 0 )
1493
+ {
1494
+ pValue = (int)p.u.iValue;
1495
+ return 1;
1496
+ }
1497
+ switch ( p.op )
1498
+ {
1499
+ case TK_INTEGER:
1500
+ {
1501
+ rc = sqlite3GetInt32( p.u.zToken, ref pValue ) ? 1 : 0;
1502
+ Debug.Assert( rc == 0 );
1503
+ break;
1504
+ }
1505
+ case TK_UPLUS:
1506
+ {
1507
+ rc = sqlite3ExprIsInteger( p.pLeft, ref pValue );
1508
+ break;
1509
+ }
1510
+ case TK_UMINUS:
1511
+ {
1512
+ int v = 0;
1513
+ if ( sqlite3ExprIsInteger( p.pLeft, ref v ) != 0 )
1514
+ {
1515
+ pValue = -v;
1516
+ rc = 1;
1517
+ }
1518
+ break;
1519
+ }
1520
+ default: break;
1521
+ }
1522
+ if ( rc != 0 )
1523
+ {
1524
+ Debug.Assert( ExprHasAnyProperty( p, EP_Reduced | EP_TokenOnly )
1525
+ || ( p.flags2 & EP2_MallocedToken ) == 0 );
1526
+ p.op = TK_INTEGER;
1527
+ p.flags |= EP_IntValue;
1528
+ p.u.iValue = pValue;
1529
+ }
1530
+ return rc;
1531
+ }
1532
+
1533
+ /*
1534
+ ** Return FALSE if there is no chance that the expression can be NULL.
1535
+ **
1536
+ ** If the expression might be NULL or if the expression is too complex
1537
+ ** to tell return TRUE.
1538
+ **
1539
+ ** This routine is used as an optimization, to skip OP_IsNull opcodes
1540
+ ** when we know that a value cannot be NULL. Hence, a false positive
1541
+ ** (returning TRUE when in fact the expression can never be NULL) might
1542
+ ** be a small performance hit but is otherwise harmless. On the other
1543
+ ** hand, a false negative (returning FALSE when the result could be NULL)
1544
+ ** will likely result in an incorrect answer. So when in doubt, return
1545
+ ** TRUE.
1546
+ */
1547
+ static int sqlite3ExprCanBeNull( Expr p )
1548
+ {
1549
+ u8 op;
1550
+ while ( p.op == TK_UPLUS || p.op == TK_UMINUS ) { p = p.pLeft; }
1551
+ op = p.op;
1552
+ if ( op == TK_REGISTER ) op = p.op2;
1553
+ switch ( op )
1554
+ {
1555
+ case TK_INTEGER:
1556
+ case TK_STRING:
1557
+ case TK_FLOAT:
1558
+ case TK_BLOB:
1559
+ return 0;
1560
+ default:
1561
+ return 1;
1562
+ }
1563
+ }
1564
+
1565
+ /*
1566
+ ** Generate an OP_IsNull instruction that tests register iReg and jumps
1567
+ ** to location iDest if the value in iReg is NULL. The value in iReg
1568
+ ** was computed by pExpr. If we can look at pExpr at compile-time and
1569
+ ** determine that it can never generate a NULL, then the OP_IsNull operation
1570
+ ** can be omitted.
1571
+ */
1572
+ static void sqlite3ExprCodeIsNullJump(
1573
+ Vdbe v, /* The VDBE under construction */
1574
+ Expr pExpr, /* Only generate OP_IsNull if this expr can be NULL */
1575
+ int iReg, /* Test the value in this register for NULL */
1576
+ int iDest /* Jump here if the value is null */
1577
+ )
1578
+ {
1579
+ if ( sqlite3ExprCanBeNull( pExpr ) != 0 )
1580
+ {
1581
+ sqlite3VdbeAddOp2( v, OP_IsNull, iReg, iDest );
1582
+ }
1583
+ }
1584
+
1585
+ /*
1586
+ ** Return TRUE if the given expression is a constant which would be
1587
+ ** unchanged by OP_Affinity with the affinity given in the second
1588
+ ** argument.
1589
+ **
1590
+ ** This routine is used to determine if the OP_Affinity operation
1591
+ ** can be omitted. When in doubt return FALSE. A false negative
1592
+ ** is harmless. A false positive, however, can result in the wrong
1593
+ ** answer.
1594
+ */
1595
+ static int sqlite3ExprNeedsNoAffinityChange( Expr p, char aff )
1596
+ {
1597
+ u8 op;
1598
+ if ( aff == SQLITE_AFF_NONE ) return 1;
1599
+ while ( p.op == TK_UPLUS || p.op == TK_UMINUS ) { p = p.pLeft; }
1600
+ op = p.op;
1601
+ if ( op == TK_REGISTER ) op = p.op2;
1602
+ switch ( op )
1603
+ {
1604
+ case TK_INTEGER:
1605
+ {
1606
+ return ( aff == SQLITE_AFF_INTEGER || aff == SQLITE_AFF_NUMERIC ) ? 1 : 0;
1607
+ }
1608
+ case TK_FLOAT:
1609
+ {
1610
+ return ( aff == SQLITE_AFF_REAL || aff == SQLITE_AFF_NUMERIC ) ? 1 : 0;
1611
+ }
1612
+ case TK_STRING:
1613
+ {
1614
+ return ( aff == SQLITE_AFF_TEXT ) ? 1 : 0;
1615
+ }
1616
+ case TK_BLOB:
1617
+ {
1618
+ return 1;
1619
+ }
1620
+ case TK_COLUMN:
1621
+ {
1622
+ Debug.Assert( p.iTable >= 0 ); /* p cannot be part of a CHECK constraint */
1623
+ return ( p.iColumn < 0
1624
+ && ( aff == SQLITE_AFF_INTEGER || aff == SQLITE_AFF_NUMERIC ) ) ? 1 : 0;
1625
+ }
1626
+ default:
1627
+ {
1628
+ return 0;
1629
+ }
1630
+ }
1631
+ }
1632
+
1633
+ /*
1634
+ ** Return TRUE if the given string is a row-id column name.
1635
+ */
1636
+ static bool sqlite3IsRowid( string z )
1637
+ {
1638
+ if ( sqlite3StrICmp( z, "_ROWID_" ) == 0 ) return true;
1639
+ if ( sqlite3StrICmp( z, "ROWID" ) == 0 ) return true;
1640
+ if ( sqlite3StrICmp( z, "OID" ) == 0 ) return true;
1641
+ return false;
1642
+ }
1643
+
1644
+
1645
+ /*
1646
+ ** Return true if we are able to the IN operator optimization on a
1647
+ ** query of the form
1648
+ **
1649
+ ** x IN (SELECT ...)
1650
+ **
1651
+ ** Where the SELECT... clause is as specified by the parameter to this
1652
+ ** routine.
1653
+ **
1654
+ ** The Select object passed in has already been preprocessed and no
1655
+ ** errors have been found.
1656
+ */
1657
+ #if !SQLITE_OMIT_SUBQUERY
1658
+ static int isCandidateForInOpt( Select p )
1659
+ {
1660
+ SrcList pSrc;
1661
+ ExprList pEList;
1662
+ Table pTab;
1663
+ if ( p == null ) return 0; /* right-hand side of IN is SELECT */
1664
+ if ( p.pPrior != null ) return 0; /* Not a compound SELECT */
1665
+ if ( ( p.selFlags & ( SF_Distinct | SF_Aggregate ) ) != 0 )
1666
+ {
1667
+ testcase( ( p.selFlags & ( SF_Distinct | SF_Aggregate ) ) == SF_Distinct );
1668
+ testcase( ( p.selFlags & ( SF_Distinct | SF_Aggregate ) ) == SF_Aggregate );
1669
+ return 0; /* No DISTINCT keyword and no aggregate functions */
1670
+ }
1671
+ Debug.Assert( p.pGroupBy == null ); /* Has no GROUP BY clause */
1672
+ if ( p.pLimit != null ) return 0; /* Has no LIMIT clause */
1673
+ Debug.Assert( p.pOffset == null ); /* No LIMIT means no OFFSET */
1674
+
1675
+ if ( p.pWhere != null ) return 0; /* Has no WHERE clause */
1676
+ pSrc = p.pSrc;
1677
+ Debug.Assert( pSrc != null );
1678
+ if ( pSrc.nSrc != 1 ) return 0; /* Single term in FROM clause */
1679
+ if ( pSrc.a[0].pSelect != null ) return 0; /* FROM is not a subquery or view */
1680
+ pTab = pSrc.a[0].pTab;
1681
+ if ( NEVER( pTab == null ) ) return 0;
1682
+ Debug.Assert( pTab.pSelect == null ); /* FROM clause is not a view */
1683
+ if ( IsVirtual( pTab ) ) return 0; /* FROM clause not a virtual table */
1684
+ pEList = p.pEList;
1685
+ if ( pEList.nExpr != 1 ) return 0; /* One column in the result set */
1686
+ if ( pEList.a[0].pExpr.op != TK_COLUMN ) return 0; /* Result is a column */
1687
+ return 1;
1688
+ }
1689
+ #endif //* SQLITE_OMIT_SUBQUERY */
1690
+
1691
+ /*
1692
+ ** This function is used by the implementation of the IN (...) operator.
1693
+ ** It's job is to find or create a b-tree structure that may be used
1694
+ ** either to test for membership of the (...) set or to iterate through
1695
+ ** its members, skipping duplicates.
1696
+ **
1697
+ ** The index of the cursor opened on the b-tree (database table, database index
1698
+ ** or ephermal table) is stored in pX->iTable before this function returns.
1699
+ ** The returned value of this function indicates the b-tree type, as follows:
1700
+ **
1701
+ ** IN_INDEX_ROWID - The cursor was opened on a database table.
1702
+ ** IN_INDEX_INDEX - The cursor was opened on a database index.
1703
+ ** IN_INDEX_EPH - The cursor was opened on a specially created and
1704
+ ** populated epheremal table.
1705
+ **
1706
+ ** An existing b-tree may only be used if the SELECT is of the simple
1707
+ ** form:
1708
+ **
1709
+ ** SELECT <column> FROM <table>
1710
+ **
1711
+ ** If the prNotFound parameter is 0, then the b-tree will be used to iterate
1712
+ ** through the set members, skipping any duplicates. In this case an
1713
+ ** epheremal table must be used unless the selected <column> is guaranteed
1714
+ ** to be unique - either because it is an INTEGER PRIMARY KEY or it
1715
+ ** has a UNIQUE constraint or UNIQUE index.
1716
+ **
1717
+ ** If the prNotFound parameter is not 0, then the b-tree will be used
1718
+ ** for fast set membership tests. In this case an epheremal table must
1719
+ ** be used unless <column> is an INTEGER PRIMARY KEY or an index can
1720
+ ** be found with <column> as its left-most column.
1721
+ **
1722
+ ** When the b-tree is being used for membership tests, the calling function
1723
+ ** needs to know whether or not the structure contains an SQL NULL
1724
+ ** value in order to correctly evaluate expressions like "X IN (Y, Z)".
1725
+ ** If there is any chance that the (...) might contain a NULL value at
1726
+ ** runtime, then a register is allocated and the register number written
1727
+ ** to *prNotFound. If there is no chance that the (...) contains a
1728
+ ** NULL value, then *prNotFound is left unchanged.
1729
+ **
1730
+ ** If a register is allocated and its location stored in *prNotFound, then
1731
+ ** its initial value is NULL. If the (...) does not remain constant
1732
+ ** for the duration of the query (i.e. the SELECT within the (...)
1733
+ ** is a correlated subquery) then the value of the allocated register is
1734
+ ** reset to NULL each time the subquery is rerun. This allows the
1735
+ ** caller to use vdbe code equivalent to the following:
1736
+ **
1737
+ ** if( register==NULL ){
1738
+ ** has_null = <test if data structure contains null>
1739
+ ** register = 1
1740
+ ** }
1741
+ **
1742
+ ** in order to avoid running the <test if data structure contains null>
1743
+ ** test more often than is necessary.
1744
+ */
1745
+ #if !SQLITE_OMIT_SUBQUERY
1746
+ static int sqlite3FindInIndex( Parse pParse, Expr pX, ref int prNotFound )
1747
+ {
1748
+ Select p; /* SELECT to the right of IN operator */
1749
+ int eType = 0; /* Type of RHS table. IN_INDEX_* */
1750
+ int iTab = pParse.nTab++; /* Cursor of the RHS table */
1751
+ bool mustBeUnique = ( prNotFound != 0 ); /* True if RHS must be unique */
1752
+
1753
+ Debug.Assert( pX.op == TK_IN );
1754
+
1755
+ /* Check to see if an existing table or index can be used to
1756
+ ** satisfy the query. This is preferable to generating a new
1757
+ ** ephemeral table.
1758
+ */
1759
+ p = ( ExprHasProperty( pX, EP_xIsSelect ) ? pX.x.pSelect : null );
1760
+ if ( ALWAYS( pParse.nErr == 0 ) && isCandidateForInOpt( p ) != 0 )
1761
+ {
1762
+ sqlite3 db = pParse.db; /* Database connection */
1763
+ Expr pExpr = p.pEList.a[0].pExpr; /* Expression <column> */
1764
+ int iCol = pExpr.iColumn; /* Index of column <column> */
1765
+ Vdbe v = sqlite3GetVdbe( pParse ); /* Virtual machine being coded */
1766
+ Table pTab = p.pSrc.a[0].pTab; /* Table <table>. */
1767
+ int iDb; /* Database idx for pTab */
1768
+
1769
+ /* Code an OP_VerifyCookie and OP_TableLock for <table>. */
1770
+ iDb = sqlite3SchemaToIndex( db, pTab.pSchema );
1771
+ sqlite3CodeVerifySchema( pParse, iDb );
1772
+ sqlite3TableLock( pParse, iDb, pTab.tnum, 0, pTab.zName );
1773
+
1774
+ /* This function is only called from two places. In both cases the vdbe
1775
+ ** has already been allocated. So assume sqlite3GetVdbe() is always
1776
+ ** successful here.
1777
+ */
1778
+ Debug.Assert( v != null );
1779
+ if ( iCol < 0 )
1780
+ {
1781
+ int iMem = ++pParse.nMem;
1782
+ int iAddr;
1783
+
1784
+ iAddr = sqlite3VdbeAddOp1( v, OP_If, iMem );
1785
+ sqlite3VdbeAddOp2( v, OP_Integer, 1, iMem );
1786
+
1787
+ sqlite3OpenTable( pParse, iTab, iDb, pTab, OP_OpenRead );
1788
+ eType = IN_INDEX_ROWID;
1789
+
1790
+ sqlite3VdbeJumpHere( v, iAddr );
1791
+ }
1792
+ else
1793
+ {
1794
+ Index pIdx; /* Iterator variable */
1795
+ /* The collation sequence used by the comparison. If an index is to
1796
+ ** be used in place of a temp.table, it must be ordered according
1797
+ ** to this collation sequence. */
1798
+ CollSeq pReq = sqlite3BinaryCompareCollSeq( pParse, pX.pLeft, pExpr );
1799
+
1800
+ /* Check that the affinity that will be used to perform the
1801
+ ** comparison is the same as the affinity of the column. If
1802
+ ** it is not, it is not possible to use any index.
1803
+ */
1804
+ char aff = comparisonAffinity( pX );
1805
+ bool affinity_ok = ( pTab.aCol[iCol].affinity == aff || aff == SQLITE_AFF_NONE );
1806
+
1807
+ for ( pIdx = pTab.pIndex; pIdx != null && eType == 0 && affinity_ok; pIdx = pIdx.pNext )
1808
+ {
1809
+ if ( ( pIdx.aiColumn[0] == iCol )
1810
+ && ( sqlite3FindCollSeq( db, ENC( db ), pIdx.azColl[0], 0 ) == pReq )
1811
+ && ( mustBeUnique == false || ( pIdx.nColumn == 1 && pIdx.onError != OE_None ) )
1812
+ )
1813
+ {
1814
+ int iMem = ++pParse.nMem;
1815
+ int iAddr;
1816
+ KeyInfo pKey;
1817
+
1818
+ pKey = sqlite3IndexKeyinfo( pParse, pIdx );
1819
+
1820
+ iAddr = sqlite3VdbeAddOp1( v, OP_If, iMem );
1821
+ sqlite3VdbeAddOp2( v, OP_Integer, 1, iMem );
1822
+
1823
+ sqlite3VdbeAddOp4( v, OP_OpenRead, iTab, pIdx.tnum, iDb,
1824
+ pKey, P4_KEYINFO_HANDOFF );
1825
+ #if SQLITE_DEBUG
1826
+ VdbeComment( v, "%s", pIdx.zName );
1827
+ #endif
1828
+ eType = IN_INDEX_INDEX;
1829
+
1830
+ sqlite3VdbeJumpHere( v, iAddr );
1831
+ if ( //prNotFound != null && -- always exists under C#
1832
+ pTab.aCol[iCol].notNull == 0 )
1833
+ {
1834
+ prNotFound = ++pParse.nMem;
1835
+ }
1836
+ }
1837
+ }
1838
+ }
1839
+ }
1840
+
1841
+ if ( eType == 0 )
1842
+ {
1843
+ /* Could not found an existing table or index to use as the RHS b-tree.
1844
+ ** We will have to generate an ephemeral table to do the job.
1845
+ */
1846
+ int rMayHaveNull = 0;
1847
+ eType = IN_INDEX_EPH;
1848
+ if ( prNotFound != -1 ) // Klude to show prNotFound not available
1849
+ {
1850
+ prNotFound = rMayHaveNull = ++pParse.nMem;
1851
+ }
1852
+ else
1853
+ if ( pX.pLeft.iColumn < 0 && !ExprHasAnyProperty( pX, EP_xIsSelect ) )
1854
+ {
1855
+ eType = IN_INDEX_ROWID;
1856
+ }
1857
+ sqlite3CodeSubselect( pParse, pX, rMayHaveNull, eType == IN_INDEX_ROWID );
1858
+ }
1859
+ else
1860
+ {
1861
+ pX.iTable = iTab;
1862
+ }
1863
+ return eType;
1864
+ }
1865
+ #endif
1866
+
1867
+ /*
1868
+ ** Generate code for scalar subqueries used as an expression
1869
+ ** and IN operators. Examples:
1870
+ **
1871
+ ** (SELECT a FROM b) -- subquery
1872
+ ** EXISTS (SELECT a FROM b) -- EXISTS subquery
1873
+ ** x IN (4,5,11) -- IN operator with list on right-hand side
1874
+ ** x IN (SELECT a FROM b) -- IN operator with subquery on the right
1875
+ **
1876
+ ** The pExpr parameter describes the expression that contains the IN
1877
+ ** operator or subquery.
1878
+ **
1879
+ ** If parameter isRowid is non-zero, then expression pExpr is guaranteed
1880
+ ** to be of the form "<rowid> IN (?, ?, ?)", where <rowid> is a reference
1881
+ ** to some integer key column of a table B-Tree. In this case, use an
1882
+ ** intkey B-Tree to store the set of IN(...) values instead of the usual
1883
+ ** (slower) variable length keys B-Tree.
1884
+ **
1885
+ ** If rMayHaveNull is non-zero, that means that the operation is an IN
1886
+ ** (not a SELECT or EXISTS) and that the RHS might contains NULLs.
1887
+ ** Furthermore, the IN is in a WHERE clause and that we really want
1888
+ ** to iterate over the RHS of the IN operator in order to quickly locate
1889
+ ** all corresponding LHS elements. All this routine does is initialize
1890
+ ** the register given by rMayHaveNull to NULL. Calling routines will take
1891
+ ** care of changing this register value to non-NULL if the RHS is NULL-free.
1892
+ **
1893
+ ** If rMayHaveNull is zero, that means that the subquery is being used
1894
+ ** for membership testing only. There is no need to initialize any
1895
+ ** registers to indicate the presense or absence of NULLs on the RHS.
1896
+ **
1897
+ ** For a SELECT or EXISTS operator, return the register that holds the
1898
+ ** result. For IN operators or if an error occurs, the return value is 0.
1899
+ */
1900
+ #if !SQLITE_OMIT_SUBQUERY
1901
+ static int sqlite3CodeSubselect(
1902
+ Parse pParse, /* Parsing context */
1903
+ Expr pExpr, /* The IN, SELECT, or EXISTS operator */
1904
+ int rMayHaveNull, /* Register that records whether NULLs exist in RHS */
1905
+ bool isRowid /* If true, LHS of IN operator is a rowid */
1906
+ )
1907
+ {
1908
+ int testAddr = 0; /* One-time test address */
1909
+ int rReg = 0; /* Register storing resulting */
1910
+ Vdbe v = sqlite3GetVdbe( pParse );
1911
+ if ( NEVER( v == null ) ) return 0;
1912
+ sqlite3ExprCachePush( pParse );
1913
+
1914
+ /* This code must be run in its entirety every time it is encountered
1915
+ ** if any of the following is true:
1916
+ **
1917
+ ** * The right-hand side is a correlated subquery
1918
+ ** * The right-hand side is an expression list containing variables
1919
+ ** * We are inside a trigger
1920
+ **
1921
+ ** If all of the above are false, then we can run this code just once
1922
+ ** save the results, and reuse the same result on subsequent invocations.
1923
+ */
1924
+ if ( !ExprHasAnyProperty( pExpr, EP_VarSelect ) && null == pParse.pTriggerTab )
1925
+ {
1926
+ int mem = ++pParse.nMem;
1927
+ sqlite3VdbeAddOp1( v, OP_If, mem );
1928
+ testAddr = sqlite3VdbeAddOp2( v, OP_Integer, 1, mem );
1929
+ Debug.Assert( testAddr > 0 /* || pParse.db.mallocFailed != 0 */ );
1930
+ }
1931
+
1932
+ switch ( pExpr.op )
1933
+ {
1934
+ case TK_IN:
1935
+ {
1936
+ char affinity;
1937
+ KeyInfo keyInfo;
1938
+ int addr; /* Address of OP_OpenEphemeral instruction */
1939
+ Expr pLeft = pExpr.pLeft;
1940
+
1941
+ if ( rMayHaveNull != 0 )
1942
+ {
1943
+ sqlite3VdbeAddOp2( v, OP_Null, 0, rMayHaveNull );
1944
+ }
1945
+
1946
+ affinity = sqlite3ExprAffinity( pLeft );
1947
+
1948
+ /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
1949
+ ** expression it is handled the same way. An ephemeral table is
1950
+ ** filled with single-field index keys representing the results
1951
+ ** from the SELECT or the <exprlist>.
1952
+ **
1953
+ ** If the 'x' expression is a column value, or the SELECT...
1954
+ ** statement returns a column value, then the affinity of that
1955
+ ** column is used to build the index keys. If both 'x' and the
1956
+ ** SELECT... statement are columns, then numeric affinity is used
1957
+ ** if either column has NUMERIC or INTEGER affinity. If neither
1958
+ ** 'x' nor the SELECT... statement are columns, then numeric affinity
1959
+ ** is used.
1960
+ */
1961
+ pExpr.iTable = pParse.nTab++;
1962
+ addr = sqlite3VdbeAddOp2( v, OP_OpenEphemeral, (int)pExpr.iTable, !isRowid );
1963
+ keyInfo = new KeyInfo();// memset( &keyInfo, 0, sizeof(keyInfo ));
1964
+ keyInfo.nField = 1;
1965
+
1966
+ if ( ExprHasProperty( pExpr, EP_xIsSelect ) )
1967
+ {
1968
+ /* Case 1: expr IN (SELECT ...)
1969
+ **
1970
+ ** Generate code to write the results of the select into the temporary
1971
+ ** table allocated and opened above.
1972
+ */
1973
+ SelectDest dest = new SelectDest();
1974
+ ExprList pEList;
1975
+
1976
+ Debug.Assert( !isRowid );
1977
+ sqlite3SelectDestInit( dest, SRT_Set, pExpr.iTable );
1978
+ dest.affinity = (char)affinity;
1979
+ Debug.Assert( ( pExpr.iTable & 0x0000FFFF ) == pExpr.iTable );
1980
+ if ( sqlite3Select( pParse, pExpr.x.pSelect, ref dest ) != 0 )
1981
+ {
1982
+ return 0;
1983
+ }
1984
+ pEList = pExpr.x.pSelect.pEList;
1985
+ if ( ALWAYS( pEList != null ) && pEList.nExpr > 0 )
1986
+ {
1987
+ keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq( pParse, pExpr.pLeft,
1988
+ pEList.a[0].pExpr );
1989
+ }
1990
+ }
1991
+ else if ( pExpr.x.pList != null )
1992
+ {
1993
+ /* Case 2: expr IN (exprlist)
1994
+ **
1995
+ ** For each expression, build an index key from the evaluation and
1996
+ ** store it in the temporary table. If <expr> is a column, then use
1997
+ ** that columns affinity when building index keys. If <expr> is not
1998
+ ** a column, use numeric affinity.
1999
+ */
2000
+ int i;
2001
+ ExprList pList = pExpr.x.pList;
2002
+ ExprList_item pItem;
2003
+ int r1, r2, r3;
2004
+
2005
+ if ( affinity == '\0' )
2006
+ {
2007
+ affinity = SQLITE_AFF_NONE;
2008
+ }
2009
+ keyInfo.aColl[0] = sqlite3ExprCollSeq( pParse, pExpr.pLeft );
2010
+
2011
+ /* Loop through each expression in <exprlist>. */
2012
+ r1 = sqlite3GetTempReg( pParse );
2013
+ r2 = sqlite3GetTempReg( pParse );
2014
+ sqlite3VdbeAddOp2( v, OP_Null, 0, r2 );
2015
+ for ( i = 0; i < pList.nExpr; i++ )
2016
+ {//, pItem++){
2017
+ pItem = pList.a[i];
2018
+ Expr pE2 = pItem.pExpr;
2019
+ int iValToIns = 0;
2020
+
2021
+ /* If the expression is not constant then we will need to
2022
+ ** disable the test that was generated above that makes sure
2023
+ ** this code only executes once. Because for a non-constant
2024
+ ** expression we need to rerun this code each time.
2025
+ */
2026
+ if ( testAddr != 0 && sqlite3ExprIsConstant( pE2 ) == 0 )
2027
+ {
2028
+ sqlite3VdbeChangeToNoop( v, testAddr - 1, 2 );
2029
+ testAddr = 0;
2030
+ }
2031
+
2032
+ /* Evaluate the expression and insert it into the temp table */
2033
+ if ( isRowid && sqlite3ExprIsInteger( pE2, ref iValToIns ) != 0 )
2034
+ {
2035
+ sqlite3VdbeAddOp3( v, OP_InsertInt, pExpr.iTable, r2, iValToIns );
2036
+ }
2037
+ else
2038
+ {
2039
+ r3 = sqlite3ExprCodeTarget( pParse, pE2, r1 );
2040
+ if ( isRowid )
2041
+ {
2042
+ sqlite3VdbeAddOp2( v, OP_MustBeInt, r3,
2043
+ sqlite3VdbeCurrentAddr( v ) + 2 );
2044
+ sqlite3VdbeAddOp3( v, OP_Insert, pExpr.iTable, r2, r3 );
2045
+ }
2046
+ else
2047
+ {
2048
+ sqlite3VdbeAddOp4( v, OP_MakeRecord, r3, 1, r2, affinity, 1 );
2049
+ sqlite3ExprCacheAffinityChange( pParse, r3, 1 );
2050
+ sqlite3VdbeAddOp2( v, OP_IdxInsert, pExpr.iTable, r2 );
2051
+ }
2052
+ }
2053
+ }
2054
+ sqlite3ReleaseTempReg( pParse, r1 );
2055
+ sqlite3ReleaseTempReg( pParse, r2 );
2056
+ }
2057
+ if ( !isRowid )
2058
+ {
2059
+ sqlite3VdbeChangeP4( v, addr, keyInfo, P4_KEYINFO );
2060
+ }
2061
+ break;
2062
+ }
2063
+
2064
+ case TK_EXISTS:
2065
+ case TK_SELECT:
2066
+ default:
2067
+ {
2068
+ /* If this has to be a scalar SELECT. Generate code to put the
2069
+ ** value of this select in a memory cell and record the number
2070
+ ** of the memory cell in iColumn. If this is an EXISTS, write
2071
+ ** an integer 0 (not exists) or 1 (exists) into a memory cell
2072
+ ** and record that memory cell in iColumn.
2073
+ */
2074
+ Token one = new Token( "1", 1 ); /* Token for literal value 1 */
2075
+ Select pSel; /* SELECT statement to encode */
2076
+ SelectDest dest = new SelectDest(); /* How to deal with SELECt result */
2077
+
2078
+ testcase( pExpr.op == TK_EXISTS );
2079
+ testcase( pExpr.op == TK_SELECT );
2080
+ Debug.Assert( pExpr.op == TK_EXISTS || pExpr.op == TK_SELECT );
2081
+
2082
+ Debug.Assert( ExprHasProperty( pExpr, EP_xIsSelect ) );
2083
+ pSel = pExpr.x.pSelect;
2084
+ sqlite3SelectDestInit( dest, 0, ++pParse.nMem );
2085
+ if ( pExpr.op == TK_SELECT )
2086
+ {
2087
+ dest.eDest = SRT_Mem;
2088
+ sqlite3VdbeAddOp2( v, OP_Null, 0, dest.iParm );
2089
+ #if SQLITE_DEBUG
2090
+ VdbeComment( v, "Init subquery result" );
2091
+ #endif
2092
+ }
2093
+ else
2094
+ {
2095
+ dest.eDest = SRT_Exists;
2096
+ sqlite3VdbeAddOp2( v, OP_Integer, 0, dest.iParm );
2097
+ #if SQLITE_DEBUG
2098
+ VdbeComment( v, "Init EXISTS result" );
2099
+ #endif
2100
+ }
2101
+ sqlite3ExprDelete( pParse.db, ref pSel.pLimit );
2102
+ pSel.pLimit = sqlite3PExpr( pParse, TK_INTEGER, null, null, one );
2103
+ if ( sqlite3Select( pParse, pSel, ref dest ) != 0 )
2104
+ {
2105
+ return 0;
2106
+ }
2107
+ rReg = dest.iParm;
2108
+ ExprSetIrreducible( pExpr );
2109
+ break;
2110
+ }
2111
+ }
2112
+
2113
+ if ( testAddr != 0 )
2114
+ {
2115
+ sqlite3VdbeJumpHere( v, testAddr - 1 );
2116
+ }
2117
+ sqlite3ExprCachePop( pParse, 1 );
2118
+
2119
+ return rReg;
2120
+ }
2121
+ #endif // * SQLITE_OMIT_SUBQUERY */
2122
+
2123
+ #if !SQLITE_OMIT_SUBQUERY
2124
+ /*
2125
+ ** Generate code for an IN expression.
2126
+ **
2127
+ ** x IN (SELECT ...)
2128
+ ** x IN (value, value, ...)
2129
+ **
2130
+ ** The left-hand side (LHS) is a scalar expression. The right-hand side (RHS)
2131
+ ** is an array of zero or more values. The expression is true if the LHS is
2132
+ ** contained within the RHS. The value of the expression is unknown (NULL)
2133
+ ** if the LHS is NULL or if the LHS is not contained within the RHS and the
2134
+ ** RHS contains one or more NULL values.
2135
+ **
2136
+ ** This routine generates code will jump to destIfFalse if the LHS is not
2137
+ ** contained within the RHS. If due to NULLs we cannot determine if the LHS
2138
+ ** is contained in the RHS then jump to destIfNull. If the LHS is contained
2139
+ ** within the RHS then fall through.
2140
+ */
2141
+ static void sqlite3ExprCodeIN(
2142
+ Parse pParse, /* Parsing and code generating context */
2143
+ Expr pExpr, /* The IN expression */
2144
+ int destIfFalse, /* Jump here if LHS is not contained in the RHS */
2145
+ int destIfNull /* Jump here if the results are unknown due to NULLs */
2146
+ )
2147
+ {
2148
+ int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */
2149
+ char affinity; /* Comparison affinity to use */
2150
+ int eType; /* Type of the RHS */
2151
+ int r1; /* Temporary use register */
2152
+ Vdbe v; /* Statement under construction */
2153
+
2154
+ /* Compute the RHS. After this step, the table with cursor
2155
+ ** pExpr.iTable will contains the values that make up the RHS.
2156
+ */
2157
+ v = pParse.pVdbe;
2158
+ Debug.Assert( v != null ); /* OOM detected prior to this routine */
2159
+ VdbeNoopComment( v, "begin IN expr" );
2160
+ eType = sqlite3FindInIndex( pParse, pExpr, ref rRhsHasNull );
2161
+
2162
+ /* Figure out the affinity to use to create a key from the results
2163
+ ** of the expression. affinityStr stores a static string suitable for
2164
+ ** P4 of OP_MakeRecord.
2165
+ */
2166
+ affinity = comparisonAffinity( pExpr );
2167
+
2168
+ /* Code the LHS, the <expr> from "<expr> IN (...)".
2169
+ */
2170
+ sqlite3ExprCachePush( pParse );
2171
+ r1 = sqlite3GetTempReg( pParse );
2172
+ sqlite3ExprCode( pParse, pExpr.pLeft, r1 );
2173
+ sqlite3VdbeAddOp2( v, OP_IsNull, r1, destIfNull );
2174
+
2175
+
2176
+ if ( eType == IN_INDEX_ROWID )
2177
+ {
2178
+ /* In this case, the RHS is the ROWID of table b-tree
2179
+ */
2180
+ sqlite3VdbeAddOp2( v, OP_MustBeInt, r1, destIfFalse );
2181
+ sqlite3VdbeAddOp3( v, OP_NotExists, pExpr.iTable, destIfFalse, r1 );
2182
+ }
2183
+ else
2184
+ {
2185
+ /* In this case, the RHS is an index b-tree.
2186
+ */
2187
+ sqlite3VdbeAddOp4( v, OP_Affinity, r1, 1, 0, affinity, 1 );
2188
+
2189
+ /* If the set membership test fails, then the result of the
2190
+ ** "x IN (...)" expression must be either 0 or NULL. If the set
2191
+ ** contains no NULL values, then the result is 0. If the set
2192
+ ** contains one or more NULL values, then the result of the
2193
+ ** expression is also NULL.
2194
+ */
2195
+ if ( rRhsHasNull == 0 || destIfFalse == destIfNull )
2196
+ {
2197
+ /* This branch runs if it is known at compile time that the RHS
2198
+ ** cannot contain NULL values. This happens as the result
2199
+ ** of a "NOT NULL" constraint in the database schema.
2200
+ **
2201
+ ** Also run this branch if NULL is equivalent to FALSE
2202
+ ** for this particular IN operator.
2203
+ */
2204
+ sqlite3VdbeAddOp4Int( v, OP_NotFound, pExpr.iTable, destIfFalse, r1, 1 );
2205
+
2206
+ }
2207
+ else
2208
+ {
2209
+ /* In this branch, the RHS of the IN might contain a NULL and
2210
+ ** the presence of a NULL on the RHS makes a difference in the
2211
+ ** outcome.
2212
+ */
2213
+ int j1, j2, j3;
2214
+
2215
+ /* First check to see if the LHS is contained in the RHS. If so,
2216
+ ** then the presence of NULLs in the RHS does not matter, so jump
2217
+ ** over all of the code that follows.
2218
+ */
2219
+ j1 = sqlite3VdbeAddOp4Int( v, OP_Found, pExpr.iTable, 0, r1, 1 );
2220
+
2221
+ /* Here we begin generating code that runs if the LHS is not
2222
+ ** contained within the RHS. Generate additional code that
2223
+ ** tests the RHS for NULLs. If the RHS contains a NULL then
2224
+ ** jump to destIfNull. If there are no NULLs in the RHS then
2225
+ ** jump to destIfFalse.
2226
+ */
2227
+ j2 = sqlite3VdbeAddOp1( v, OP_NotNull, rRhsHasNull );
2228
+ j3 = sqlite3VdbeAddOp4Int( v, OP_Found, pExpr.iTable, 0, rRhsHasNull, 1 );
2229
+ sqlite3VdbeAddOp2( v, OP_Integer, -1, rRhsHasNull );
2230
+ sqlite3VdbeJumpHere( v, j3 );
2231
+ sqlite3VdbeAddOp2( v, OP_AddImm, rRhsHasNull, 1 );
2232
+ sqlite3VdbeJumpHere( v, j2 );
2233
+
2234
+ /* Jump to the appropriate target depending on whether or not
2235
+ ** the RHS contains a NULL
2236
+ */
2237
+ sqlite3VdbeAddOp2( v, OP_If, rRhsHasNull, destIfNull );
2238
+ sqlite3VdbeAddOp2( v, OP_Goto, 0, destIfFalse );
2239
+
2240
+ /* The OP_Found at the top of this branch jumps here when true,
2241
+ ** causing the overall IN expression evaluation to fall through.
2242
+ */
2243
+ sqlite3VdbeJumpHere( v, j1 );
2244
+ }
2245
+ }
2246
+ sqlite3ReleaseTempReg( pParse, r1 );
2247
+ sqlite3ExprCachePop( pParse, 1 );
2248
+ VdbeComment( v, "end IN expr" );
2249
+ }
2250
+ #endif //* SQLITE_OMIT_SUBQUERY */
2251
+
2252
+ /*
2253
+ ** Duplicate an 8-byte value
2254
+ */
2255
+ //static char *dup8bytes(Vdbe v, const char *in){
2256
+ // char *out = sqlite3DbMallocRaw(sqlite3VdbeDb(v), 8);
2257
+ // if( out ){
2258
+ // memcpy(out, in, 8);
2259
+ // }
2260
+ // return out;
2261
+ //}
2262
+
2263
+ #if !SQLITE_OMIT_FLOATING_POINT
2264
+ /*
2265
+ ** Generate an instruction that will put the floating point
2266
+ ** value described by z[0..n-1] into register iMem.
2267
+ **
2268
+ ** The z[] string will probably not be zero-terminated. But the
2269
+ ** z[n] character is guaranteed to be something that does not look
2270
+ ** like the continuation of the number.
2271
+ */
2272
+ static void codeReal( Vdbe v, string z, bool negateFlag, int iMem )
2273
+ {
2274
+ if ( ALWAYS( !String.IsNullOrEmpty( z ) ) )
2275
+ {
2276
+ double value = 0;
2277
+ //char *zV;
2278
+ sqlite3AtoF( z, ref value );
2279
+ Debug.Assert( !sqlite3IsNaN( value ) ); /* The new AtoF never returns NaN */
2280
+ if ( negateFlag ) value = -value;
2281
+ //zV = dup8bytes(v, value);
2282
+ sqlite3VdbeAddOp4( v, OP_Real, 0, iMem, 0, value, P4_REAL );
2283
+ }
2284
+ }
2285
+ #endif
2286
+
2287
+ /*
2288
+ ** Generate an instruction that will put the integer describe by
2289
+ ** text z[0..n-1] into register iMem.
2290
+ **
2291
+ ** The z[] string will probably not be zero-terminated. But the
2292
+ ** z[n] character is guaranteed to be something that does not look
2293
+ ** like the continuation of the number.
2294
+ */
2295
+ static void codeInteger( Parse pParse, Expr pExpr, bool negFlag, int iMem )
2296
+ {
2297
+ Vdbe v = pParse.pVdbe;
2298
+ if ( ( pExpr.flags & EP_IntValue ) != 0 )
2299
+ {
2300
+ int i = pExpr.u.iValue;
2301
+ if ( negFlag ) i = -i;
2302
+ sqlite3VdbeAddOp2( v, OP_Integer, i, iMem );
2303
+ }
2304
+ else
2305
+ {
2306
+ string z = pExpr.u.zToken;
2307
+ Debug.Assert( !String.IsNullOrEmpty( z ) );
2308
+ if ( sqlite3FitsIn64Bits( z, negFlag ) )
2309
+ {
2310
+ i64 value = 0;
2311
+ //string zV;
2312
+ sqlite3Atoi64( negFlag ? "-" + z : z, ref value );
2313
+ //if ( negFlag ) value = -value;
2314
+ //zV = dup8bytes( v, (char*)&value );
2315
+ //sqlite3VdbeAddOp4( v, OP_Int64, 0, iMem, 0, zV, P4_INT64 );
2316
+ sqlite3VdbeAddOp4( v, OP_Int64, 0, iMem, 0, value, P4_INT64 );
2317
+ }
2318
+ else
2319
+ {
2320
+ #if SQLITE_OMIT_FLOATING_POINT
2321
+ sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
2322
+ #else
2323
+ codeReal( v, z, negFlag, iMem );
2324
+ #endif
2325
+ }
2326
+ }
2327
+ }
2328
+
2329
+ /*
2330
+ ** Clear a cache entry.
2331
+ */
2332
+ static void cacheEntryClear( Parse pParse, yColCache p )
2333
+ {
2334
+ if ( p.tempReg != 0 )
2335
+ {
2336
+ if ( pParse.nTempReg < ArraySize( pParse.aTempReg ) )
2337
+ {
2338
+ pParse.aTempReg[pParse.nTempReg++] = p.iReg;
2339
+ }
2340
+ p.tempReg = 0;
2341
+ }
2342
+ }
2343
+
2344
+
2345
+ /*
2346
+ ** Record in the column cache that a particular column from a
2347
+ ** particular table is stored in a particular register.
2348
+ */
2349
+ static void sqlite3ExprCacheStore( Parse pParse, int iTab, int iCol, int iReg )
2350
+ {
2351
+ int i;
2352
+ int minLru;
2353
+ int idxLru;
2354
+ yColCache p = new yColCache();
2355
+
2356
+ Debug.Assert( iReg > 0 ); /* Register numbers are always positive */
2357
+ Debug.Assert( iCol >= -1 && iCol < 32768 ); /* Finite column numbers */
2358
+
2359
+ /* The SQLITE_ColumnCache flag disables the column cache. This is used
2360
+ ** for testing only - to verify that SQLite always gets the same answer
2361
+ ** with and without the column cache.
2362
+ */
2363
+ if ( ( pParse.db.flags & SQLITE_ColumnCache ) != 0 ) return;
2364
+
2365
+ /* First replace any existing entry.
2366
+ **
2367
+ ** Actually, the way the column cache is currently used, we are guaranteed
2368
+ ** that the object will never already be in cache. Verify this guarantee.
2369
+ */
2370
+ #if !NDEBUG
2371
+ for ( i = 0; i < SQLITE_N_COLCACHE; i++ )//p=pParse.aColCache... p++)
2372
+ {
2373
+ #if FALSE //* This code wold remove the entry from the cache if it existed */
2374
+ p = pParse.aColCache[i];
2375
+ if ( p.iReg != 0 && p.iTable == iTab && p.iColumn == iCol )
2376
+ {
2377
+ cacheEntryClear( pParse, p );
2378
+ p.iLevel = pParse.iCacheLevel;
2379
+ p.iReg = iReg;
2380
+ p.lru = pParse.iCacheCnt++;
2381
+ return;
2382
+ }
2383
+ #endif
2384
+ Debug.Assert( p.iReg == 0 || p.iTable != iTab || p.iColumn != iCol );
2385
+ }
2386
+ #endif
2387
+
2388
+ /* Find an empty slot and replace it */
2389
+ for ( i = 0; i < SQLITE_N_COLCACHE; i++ )//p=pParse.aColCache... p++)
2390
+ {
2391
+ p = pParse.aColCache[i];
2392
+ if ( p.iReg == 0 )
2393
+ {
2394
+ p.iLevel = pParse.iCacheLevel;
2395
+ p.iTable = iTab;
2396
+ p.iColumn = iCol;
2397
+ p.iReg = iReg;
2398
+ p.tempReg = 0;
2399
+ p.lru = pParse.iCacheCnt++;
2400
+ return;
2401
+ }
2402
+ }
2403
+
2404
+ /* Replace the last recently used */
2405
+ minLru = 0x7fffffff;
2406
+ idxLru = -1;
2407
+ for ( i = 0; i < SQLITE_N_COLCACHE; i++ )//p=pParse.aColCache..., p++)
2408
+ {
2409
+ p = pParse.aColCache[i];
2410
+ if ( p.lru < minLru )
2411
+ {
2412
+ idxLru = i;
2413
+ minLru = p.lru;
2414
+ }
2415
+ }
2416
+ if ( ALWAYS( idxLru >= 0 ) )
2417
+ {
2418
+ p = pParse.aColCache[idxLru];
2419
+ p.iLevel = pParse.iCacheLevel;
2420
+ p.iTable = iTab;
2421
+ p.iColumn = iCol;
2422
+ p.iReg = iReg;
2423
+ p.tempReg = 0;
2424
+ p.lru = pParse.iCacheCnt++;
2425
+ return;
2426
+ }
2427
+ }
2428
+
2429
+ /*
2430
+ ** Indicate that registers between iReg..iReg+nReg-1 are being overwritten.
2431
+ ** Purge the range of registers from the column cache.
2432
+ */
2433
+ static void sqlite3ExprCacheRemove( Parse pParse, int iReg, int nReg )
2434
+ {
2435
+ int i;
2436
+ int iLast = iReg + nReg - 1;
2437
+ yColCache p;
2438
+ for ( i = 0; i < SQLITE_N_COLCACHE; i++ )//p=pParse.aColCache... p++)
2439
+ {
2440
+ p = pParse.aColCache[i];
2441
+ int r = p.iReg;
2442
+ if ( r >= iReg && r <= iLast )
2443
+ {
2444
+ cacheEntryClear( pParse, p );
2445
+ p.iReg = 0;
2446
+ }
2447
+ }
2448
+ }
2449
+
2450
+ /*
2451
+ ** Remember the current column cache context. Any new entries added
2452
+ ** added to the column cache after this call are removed when the
2453
+ ** corresponding pop occurs.
2454
+ */
2455
+ static void sqlite3ExprCachePush( Parse pParse )
2456
+ {
2457
+ pParse.iCacheLevel++;
2458
+ }
2459
+
2460
+ /*
2461
+ ** Remove from the column cache any entries that were added since the
2462
+ ** the previous N Push operations. In other words, restore the cache
2463
+ ** to the state it was in N Pushes ago.
2464
+ */
2465
+ static void sqlite3ExprCachePop( Parse pParse, int N )
2466
+ {
2467
+ int i;
2468
+ yColCache p;
2469
+ Debug.Assert( N > 0 );
2470
+ Debug.Assert( pParse.iCacheLevel >= N );
2471
+ pParse.iCacheLevel -= N;
2472
+ for ( i = 0; i < SQLITE_N_COLCACHE; i++ )// p++)
2473
+ {
2474
+ p = pParse.aColCache[i];
2475
+ if ( p.iReg != 0 && p.iLevel > pParse.iCacheLevel )
2476
+ {
2477
+ cacheEntryClear( pParse, p );
2478
+ p.iReg = 0;
2479
+ }
2480
+ }
2481
+ }
2482
+
2483
+ /*
2484
+ ** When a cached column is reused, make sure that its register is
2485
+ ** no longer available as a temp register. ticket #3879: that same
2486
+ ** register might be in the cache in multiple places, so be sure to
2487
+ ** get them all.
2488
+ */
2489
+ static void sqlite3ExprCachePinRegister( Parse pParse, int iReg )
2490
+ {
2491
+ int i;
2492
+ yColCache p;
2493
+ for ( i = 0; i < SQLITE_N_COLCACHE; i++ )//p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++)
2494
+ {
2495
+ p = pParse.aColCache[i];
2496
+ if ( p.iReg == iReg )
2497
+ {
2498
+ p.tempReg = 0;
2499
+ }
2500
+ }
2501
+ }
2502
+
2503
+ /*
2504
+ ** Generate code that will extract the iColumn-th column from
2505
+ ** table pTab and store the column value in a register. An effort
2506
+ ** is made to store the column value in register iReg, but this is
2507
+ ** not guaranteed. The location of the column value is returned.
2508
+ **
2509
+ ** There must be an open cursor to pTab in iTable when this routine
2510
+ ** is called. If iColumn<0 then code is generated that extracts the rowid.
2511
+ */
2512
+ static int sqlite3ExprCodeGetColumn(
2513
+ Parse pParse, /* Parsing and code generating context */
2514
+ Table pTab, /* Description of the table we are reading from */
2515
+ int iColumn, /* Index of the table column */
2516
+ int iTable, /* The cursor pointing to the table */
2517
+ int iReg /* Store results here */
2518
+ )
2519
+ {
2520
+ Vdbe v = pParse.pVdbe;
2521
+ int i;
2522
+ yColCache p;
2523
+
2524
+ for ( i = 0; i < SQLITE_N_COLCACHE; i++ )
2525
+ {// p=pParse.aColCache, p++
2526
+ p = pParse.aColCache[i];
2527
+ if ( p.iReg > 0 && p.iTable == iTable && p.iColumn == iColumn )
2528
+ {
2529
+ p.lru = pParse.iCacheCnt++;
2530
+ sqlite3ExprCachePinRegister( pParse, p.iReg );
2531
+ return p.iReg;
2532
+ }
2533
+ }
2534
+ Debug.Assert( v != null );
2535
+ if ( iColumn < 0 )
2536
+ {
2537
+ sqlite3VdbeAddOp2( v, OP_Rowid, iTable, iReg );
2538
+ }
2539
+ else if ( ALWAYS( pTab != null ) )
2540
+ {
2541
+ int op = IsVirtual( pTab ) ? OP_VColumn : OP_Column;
2542
+ sqlite3VdbeAddOp3( v, op, iTable, iColumn, iReg );
2543
+ sqlite3ColumnDefault( v, pTab, iColumn, iReg );
2544
+ }
2545
+ sqlite3ExprCacheStore( pParse, iTable, iColumn, iReg );
2546
+ return iReg;
2547
+ }
2548
+
2549
+ /*
2550
+ ** Clear all column cache entries.
2551
+ */
2552
+ static void sqlite3ExprCacheClear( Parse pParse )
2553
+ {
2554
+ int i;
2555
+ yColCache p;
2556
+
2557
+ for ( i = 0; i < SQLITE_N_COLCACHE; i++ )// p=pParse.aColCache... p++)
2558
+ {
2559
+ p = pParse.aColCache[i];
2560
+ if ( p.iReg != 0 )
2561
+ {
2562
+ cacheEntryClear( pParse, p );
2563
+ p.iReg = 0;
2564
+ }
2565
+ }
2566
+ }
2567
+
2568
+ /*
2569
+ ** Record the fact that an affinity change has occurred on iCount
2570
+ ** registers starting with iStart.
2571
+ */
2572
+ static void sqlite3ExprCacheAffinityChange( Parse pParse, int iStart, int iCount )
2573
+ {
2574
+ sqlite3ExprCacheRemove( pParse, iStart, iCount );
2575
+ }
2576
+
2577
+ /*
2578
+ ** Generate code to move content from registers iFrom...iFrom+nReg-1
2579
+ ** over to iTo..iTo+nReg-1. Keep the column cache up-to-date.
2580
+ */
2581
+ static void sqlite3ExprCodeMove( Parse pParse, int iFrom, int iTo, int nReg )
2582
+ {
2583
+ int i;
2584
+ yColCache p;
2585
+ if ( NEVER( iFrom == iTo ) ) return;
2586
+ sqlite3VdbeAddOp3( pParse.pVdbe, OP_Move, iFrom, iTo, nReg );
2587
+ for ( i = 0; i < SQLITE_N_COLCACHE; i++ )// p=pParse.aColCache... p++)
2588
+ {
2589
+ p = pParse.aColCache[i];
2590
+ int x = p.iReg;
2591
+ if ( x >= iFrom && x < iFrom + nReg )
2592
+ {
2593
+ p.iReg += iTo - iFrom;
2594
+ }
2595
+ }
2596
+ }
2597
+
2598
+ /*
2599
+ ** Generate code to copy content from registers iFrom...iFrom+nReg-1
2600
+ ** over to iTo..iTo+nReg-1.
2601
+ */
2602
+ static void sqlite3ExprCodeCopy( Parse pParse, int iFrom, int iTo, int nReg )
2603
+ {
2604
+ int i;
2605
+ if ( NEVER( iFrom == iTo ) ) return;
2606
+ for ( i = 0; i < nReg; i++ )
2607
+ {
2608
+ sqlite3VdbeAddOp2( pParse.pVdbe, OP_Copy, iFrom + i, iTo + i );
2609
+ }
2610
+ }
2611
+
2612
+ #if (SQLITE_DEBUG) || (SQLITE_COVERAGE_TEST)
2613
+ /*
2614
+ ** Return true if any register in the range iFrom..iTo (inclusive)
2615
+ ** is used as part of the column cache.
2616
+ **
2617
+ ** This routine is used within assert() and testcase() macros only
2618
+ ** and does not appear in a normal build.
2619
+ */
2620
+ static int usedAsColumnCache( Parse pParse, int iFrom, int iTo )
2621
+ {
2622
+ int i;
2623
+ yColCache p;
2624
+ for ( i = 0; i < SQLITE_N_COLCACHE; i++ )//p=pParse.aColCache... p++)
2625
+ {
2626
+ p = pParse.aColCache[i];
2627
+ int r = p.iReg;
2628
+ if ( r >= iFrom && r <= iTo ) return 1; /*NO_TEST*/
2629
+ }
2630
+ return 0;
2631
+ }
2632
+ #else
2633
+ static int usedAsColumnCache( Parse pParse, int iFrom, int iTo ){return 1;}
2634
+ #endif //* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */
2635
+
2636
+
2637
+ /*
2638
+ ** If the last instruction coded is an ephemeral copy of any of
2639
+ ** the registers in the nReg registers beginning with iReg, then
2640
+ ** convert the last instruction from OP_SCopy to OP_Copy.
2641
+ */
2642
+ static void sqlite3ExprHardCopy( Parse pParse, int iReg, int nReg )
2643
+ {
2644
+ VdbeOp pOp;
2645
+ Vdbe v;
2646
+
2647
+ //Debug.Assert( pParse.db.mallocFailed == 0 );
2648
+ v = pParse.pVdbe;
2649
+ Debug.Assert( v != null );
2650
+ pOp = sqlite3VdbeGetOp( v, -1 );
2651
+ Debug.Assert( pOp != null );
2652
+ if ( pOp.opcode == OP_SCopy && pOp.p1 >= iReg && pOp.p1 < iReg + nReg )
2653
+ {
2654
+ pOp.opcode = OP_Copy;
2655
+ }
2656
+ }
2657
+
2658
+ /*
2659
+ ** Generate code to store the value of the iAlias-th alias in register
2660
+ ** target. The first time this is called, pExpr is evaluated to compute
2661
+ ** the value of the alias. The value is stored in an auxiliary register
2662
+ ** and the number of that register is returned. On subsequent calls,
2663
+ ** the register number is returned without generating any code.
2664
+ **
2665
+ ** Note that in order for this to work, code must be generated in the
2666
+ ** same order that it is executed.
2667
+ **
2668
+ ** Aliases are numbered starting with 1. So iAlias is in the range
2669
+ ** of 1 to pParse.nAlias inclusive.
2670
+ **
2671
+ ** pParse.aAlias[iAlias-1] records the register number where the value
2672
+ ** of the iAlias-th alias is stored. If zero, that means that the
2673
+ ** alias has not yet been computed.
2674
+ */
2675
+ static int codeAlias( Parse pParse, int iAlias, Expr pExpr, int target )
2676
+ {
2677
+ #if FALSE
2678
+ sqlite3 db = pParse.db;
2679
+ int iReg;
2680
+ if ( pParse.nAliasAlloc < pParse.nAlias )
2681
+ {
2682
+ pParse.aAlias = new int[pParse.nAlias]; //sqlite3DbReallocOrFree(db, pParse.aAlias,
2683
+ //sizeof(pParse.aAlias[0])*pParse.nAlias );
2684
+ testcase( db.mallocFailed != 0 && pParse.nAliasAlloc > 0 );
2685
+ if ( db.mallocFailed != 0 ) return 0;
2686
+ //memset(&pParse.aAlias[pParse.nAliasAlloc], 0,
2687
+ // (pParse.nAlias-pParse.nAliasAlloc)*sizeof(pParse.aAlias[0]));
2688
+ pParse.nAliasAlloc = pParse.nAlias;
2689
+ }
2690
+ Debug.Assert( iAlias > 0 && iAlias <= pParse.nAlias );
2691
+ iReg = pParse.aAlias[iAlias - 1];
2692
+ if ( iReg == 0 )
2693
+ {
2694
+ if ( pParse.iCacheLevel != 0 )
2695
+ {
2696
+ iReg = sqlite3ExprCodeTarget( pParse, pExpr, target );
2697
+ }
2698
+ else
2699
+ {
2700
+ iReg = ++pParse.nMem;
2701
+ sqlite3ExprCode( pParse, pExpr, iReg );
2702
+ pParse.aAlias[iAlias - 1] = iReg;
2703
+ }
2704
+ }
2705
+ return iReg;
2706
+ #else
2707
+ UNUSED_PARAMETER( iAlias );
2708
+ return sqlite3ExprCodeTarget( pParse, pExpr, target );
2709
+ #endif
2710
+ }
2711
+
2712
+ /*
2713
+ ** Generate code into the current Vdbe to evaluate the given
2714
+ ** expression. Attempt to store the results in register "target".
2715
+ ** Return the register where results are stored.
2716
+ **
2717
+ ** With this routine, there is no guarantee that results will
2718
+ ** be stored in target. The result might be stored in some other
2719
+ ** register if it is convenient to do so. The calling function
2720
+ ** must check the return code and move the results to the desired
2721
+ ** register.
2722
+ */
2723
+ static int sqlite3ExprCodeTarget( Parse pParse, Expr pExpr, int target )
2724
+ {
2725
+ Vdbe v = pParse.pVdbe; /* The VM under construction */
2726
+ int op; /* The opcode being coded */
2727
+ int inReg = target; /* Results stored in register inReg */
2728
+ int regFree1 = 0; /* If non-zero free this temporary register */
2729
+ int regFree2 = 0; /* If non-zero free this temporary register */
2730
+ int r1 = 0, r2 = 0, r3 = 0, r4 = 0; /* Various register numbers */
2731
+ sqlite3 db = pParse.db; /* The database connection */
2732
+
2733
+ Debug.Assert( target > 0 && target <= pParse.nMem );
2734
+ if ( v == null )
2735
+ {
2736
+ //Debug.Assert( pParse.db.mallocFailed != 0 );
2737
+ return 0;
2738
+ }
2739
+
2740
+ if ( pExpr == null )
2741
+ {
2742
+ op = TK_NULL;
2743
+ }
2744
+ else
2745
+ {
2746
+ op = pExpr.op;
2747
+ }
2748
+ switch ( op )
2749
+ {
2750
+ case TK_AGG_COLUMN:
2751
+ {
2752
+ AggInfo pAggInfo = pExpr.pAggInfo;
2753
+ AggInfo_col pCol = pAggInfo.aCol[pExpr.iAgg];
2754
+ if ( pAggInfo.directMode == 0 )
2755
+ {
2756
+ Debug.Assert( pCol.iMem > 0 );
2757
+ inReg = pCol.iMem;
2758
+ break;
2759
+ }
2760
+ else if ( pAggInfo.useSortingIdx != 0 )
2761
+ {
2762
+ sqlite3VdbeAddOp3( v, OP_Column, pAggInfo.sortingIdx,
2763
+ pCol.iSorterColumn, target );
2764
+ break;
2765
+ }
2766
+ /* Otherwise, fall thru into the TK_COLUMN case */
2767
+ }
2768
+ goto case TK_COLUMN;
2769
+ case TK_COLUMN:
2770
+ {
2771
+ if ( pExpr.iTable < 0 )
2772
+ {
2773
+ /* This only happens when coding check constraints */
2774
+ Debug.Assert( pParse.ckBase > 0 );
2775
+ inReg = pExpr.iColumn + pParse.ckBase;
2776
+ }
2777
+ else
2778
+ {
2779
+ inReg = sqlite3ExprCodeGetColumn( pParse, pExpr.pTab,
2780
+ pExpr.iColumn, pExpr.iTable, target );
2781
+ }
2782
+ break;
2783
+ }
2784
+ case TK_INTEGER:
2785
+ {
2786
+ codeInteger( pParse, pExpr, false, target );
2787
+ break;
2788
+ }
2789
+ #if !SQLITE_OMIT_FLOATING_POINT
2790
+ case TK_FLOAT:
2791
+ {
2792
+ Debug.Assert( !ExprHasProperty( pExpr, EP_IntValue ) );
2793
+ codeReal( v, pExpr.u.zToken, false, target );
2794
+ break;
2795
+ }
2796
+ #endif
2797
+ case TK_STRING:
2798
+ {
2799
+ Debug.Assert( !ExprHasProperty( pExpr, EP_IntValue ) );
2800
+ sqlite3VdbeAddOp4( v, OP_String8, 0, target, 0, pExpr.u.zToken, 0 );
2801
+ break;
2802
+ }
2803
+ case TK_NULL:
2804
+ {
2805
+ sqlite3VdbeAddOp2( v, OP_Null, 0, target );
2806
+ break;
2807
+ }
2808
+ #if !SQLITE_OMIT_BLOB_LITERAL
2809
+ case TK_BLOB:
2810
+ {
2811
+ int n;
2812
+ string z;
2813
+ byte[] zBlob;
2814
+ Debug.Assert( !ExprHasProperty( pExpr, EP_IntValue ) );
2815
+ Debug.Assert( pExpr.u.zToken[0] == 'x' || pExpr.u.zToken[0] == 'X' );
2816
+ Debug.Assert( pExpr.u.zToken[1] == '\'' );
2817
+ z = pExpr.u.zToken.Substring( 2 );
2818
+ n = sqlite3Strlen30( z ) - 1;
2819
+ Debug.Assert( z[n] == '\'' );
2820
+ zBlob = sqlite3HexToBlob( sqlite3VdbeDb( v ), z, n );
2821
+ sqlite3VdbeAddOp4( v, OP_Blob, n / 2, target, 0, zBlob, P4_DYNAMIC );
2822
+ break;
2823
+ }
2824
+ #endif
2825
+ case TK_VARIABLE:
2826
+ {
2827
+ VdbeOp pOp;
2828
+ Debug.Assert( !ExprHasProperty( pExpr, EP_IntValue ) );
2829
+ Debug.Assert( pExpr.u.zToken != null );
2830
+ Debug.Assert( pExpr.u.zToken.Length != 0 );
2831
+ if ( pExpr.u.zToken.Length == 1
2832
+ && ( pOp = sqlite3VdbeGetOp( v, -1 ) ).opcode == OP_Variable
2833
+ && pOp.p1 + pOp.p3 == pExpr.iColumn
2834
+ && pOp.p2 + pOp.p3 == target
2835
+ && pOp.p4.z == null
2836
+ )
2837
+ {
2838
+ /* If the previous instruction was a copy of the previous unnamed
2839
+ ** parameter into the previous register, then simply increment the
2840
+ ** repeat count on the prior instruction rather than making a new
2841
+ ** instruction.
2842
+ */
2843
+ pOp.p3++;
2844
+ }
2845
+ else
2846
+ {
2847
+ sqlite3VdbeAddOp3( v, OP_Variable, pExpr.iColumn, target, 1 );
2848
+ if ( pExpr.u.zToken.Length > 1 )
2849
+ {
2850
+ sqlite3VdbeChangeP4( v, -1, pExpr.u.zToken, 0 );
2851
+ }
2852
+ }
2853
+ break;
2854
+ }
2855
+ case TK_REGISTER:
2856
+ {
2857
+ inReg = pExpr.iTable;
2858
+ break;
2859
+ }
2860
+ case TK_AS:
2861
+ {
2862
+ inReg = codeAlias( pParse, pExpr.iTable, pExpr.pLeft, target );
2863
+ break;
2864
+ }
2865
+ #if !SQLITE_OMIT_CAST
2866
+ case TK_CAST:
2867
+ {
2868
+ /* Expressions of the form: CAST(pLeft AS token) */
2869
+ int aff, to_op;
2870
+ inReg = sqlite3ExprCodeTarget( pParse, pExpr.pLeft, target );
2871
+ Debug.Assert( !ExprHasProperty( pExpr, EP_IntValue ) );
2872
+ aff = sqlite3AffinityType( pExpr.u.zToken );
2873
+ to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
2874
+ Debug.Assert( to_op == OP_ToText || aff != SQLITE_AFF_TEXT );
2875
+ Debug.Assert( to_op == OP_ToBlob || aff != SQLITE_AFF_NONE );
2876
+ Debug.Assert( to_op == OP_ToNumeric || aff != SQLITE_AFF_NUMERIC );
2877
+ Debug.Assert( to_op == OP_ToInt || aff != SQLITE_AFF_INTEGER );
2878
+ Debug.Assert( to_op == OP_ToReal || aff != SQLITE_AFF_REAL );
2879
+ testcase( to_op == OP_ToText );
2880
+ testcase( to_op == OP_ToBlob );
2881
+ testcase( to_op == OP_ToNumeric );
2882
+ testcase( to_op == OP_ToInt );
2883
+ testcase( to_op == OP_ToReal );
2884
+ if ( inReg != target )
2885
+ {
2886
+ sqlite3VdbeAddOp2( v, OP_SCopy, inReg, target );
2887
+ inReg = target;
2888
+ }
2889
+ sqlite3VdbeAddOp1( v, to_op, inReg );
2890
+ testcase( usedAsColumnCache( pParse, inReg, inReg ) != 0 );
2891
+ sqlite3ExprCacheAffinityChange( pParse, inReg, 1 );
2892
+ break;
2893
+ }
2894
+ #endif // * SQLITE_OMIT_CAST */
2895
+ case TK_LT:
2896
+ case TK_LE:
2897
+ case TK_GT:
2898
+ case TK_GE:
2899
+ case TK_NE:
2900
+ case TK_EQ:
2901
+ {
2902
+ Debug.Assert( TK_LT == OP_Lt );
2903
+ Debug.Assert( TK_LE == OP_Le );
2904
+ Debug.Assert( TK_GT == OP_Gt );
2905
+ Debug.Assert( TK_GE == OP_Ge );
2906
+ Debug.Assert( TK_EQ == OP_Eq );
2907
+ Debug.Assert( TK_NE == OP_Ne );
2908
+ testcase( op == TK_LT );
2909
+ testcase( op == TK_LE );
2910
+ testcase( op == TK_GT );
2911
+ testcase( op == TK_GE );
2912
+ testcase( op == TK_EQ );
2913
+ testcase( op == TK_NE );
2914
+ r1 = sqlite3ExprCodeTemp( pParse, pExpr.pLeft, ref regFree1 );
2915
+ r2 = sqlite3ExprCodeTemp( pParse, pExpr.pRight, ref regFree2 );
2916
+ codeCompare( pParse, pExpr.pLeft, pExpr.pRight, op,
2917
+ r1, r2, inReg, SQLITE_STOREP2 );
2918
+ testcase( regFree1 == 0 );
2919
+ testcase( regFree2 == 0 );
2920
+ break;
2921
+ }
2922
+ case TK_IS:
2923
+ case TK_ISNOT:
2924
+ {
2925
+ testcase( op == TK_IS );
2926
+ testcase( op == TK_ISNOT );
2927
+ r1 = sqlite3ExprCodeTemp( pParse, pExpr.pLeft, ref regFree1 );
2928
+ r2 = sqlite3ExprCodeTemp( pParse, pExpr.pRight, ref regFree2 );
2929
+ op = ( op == TK_IS ) ? TK_EQ : TK_NE;
2930
+ codeCompare( pParse, pExpr.pLeft, pExpr.pRight, op,
2931
+ r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ );
2932
+ testcase( regFree1 == 0 );
2933
+ testcase( regFree2 == 0 );
2934
+ break;
2935
+ }
2936
+ case TK_AND:
2937
+ case TK_OR:
2938
+ case TK_PLUS:
2939
+ case TK_STAR:
2940
+ case TK_MINUS:
2941
+ case TK_REM:
2942
+ case TK_BITAND:
2943
+ case TK_BITOR:
2944
+ case TK_SLASH:
2945
+ case TK_LSHIFT:
2946
+ case TK_RSHIFT:
2947
+ case TK_CONCAT:
2948
+ {
2949
+ Debug.Assert( TK_AND == OP_And );
2950
+ Debug.Assert( TK_OR == OP_Or );
2951
+ Debug.Assert( TK_PLUS == OP_Add );
2952
+ Debug.Assert( TK_MINUS == OP_Subtract );
2953
+ Debug.Assert( TK_REM == OP_Remainder );
2954
+ Debug.Assert( TK_BITAND == OP_BitAnd );
2955
+ Debug.Assert( TK_BITOR == OP_BitOr );
2956
+ Debug.Assert( TK_SLASH == OP_Divide );
2957
+ Debug.Assert( TK_LSHIFT == OP_ShiftLeft );
2958
+ Debug.Assert( TK_RSHIFT == OP_ShiftRight );
2959
+ Debug.Assert( TK_CONCAT == OP_Concat );
2960
+ testcase( op == TK_AND );
2961
+ testcase( op == TK_OR );
2962
+ testcase( op == TK_PLUS );
2963
+ testcase( op == TK_MINUS );
2964
+ testcase( op == TK_REM );
2965
+ testcase( op == TK_BITAND );
2966
+ testcase( op == TK_BITOR );
2967
+ testcase( op == TK_SLASH );
2968
+ testcase( op == TK_LSHIFT );
2969
+ testcase( op == TK_RSHIFT );
2970
+ testcase( op == TK_CONCAT );
2971
+ r1 = sqlite3ExprCodeTemp( pParse, pExpr.pLeft, ref regFree1 );
2972
+ r2 = sqlite3ExprCodeTemp( pParse, pExpr.pRight, ref regFree2 );
2973
+ sqlite3VdbeAddOp3( v, op, r2, r1, target );
2974
+ testcase( regFree1 == 0 );
2975
+ testcase( regFree2 == 0 );
2976
+ break;
2977
+ }
2978
+ case TK_UMINUS:
2979
+ {
2980
+ Expr pLeft = pExpr.pLeft;
2981
+ Debug.Assert( pLeft != null );
2982
+ if ( pLeft.op == TK_INTEGER )
2983
+ {
2984
+ codeInteger( pParse, pLeft, true, target );
2985
+ #if !SQLITE_OMIT_FLOATING_POINT
2986
+ }
2987
+ else if ( pLeft.op == TK_FLOAT )
2988
+ {
2989
+ Debug.Assert( !ExprHasProperty( pExpr, EP_IntValue ) );
2990
+ codeReal( v, pLeft.u.zToken, true, target );
2991
+ #endif
2992
+ }
2993
+ else
2994
+ {
2995
+ regFree1 = r1 = sqlite3GetTempReg( pParse );
2996
+ sqlite3VdbeAddOp2( v, OP_Integer, 0, r1 );
2997
+ r2 = sqlite3ExprCodeTemp( pParse, pExpr.pLeft, ref regFree2 );
2998
+ sqlite3VdbeAddOp3( v, OP_Subtract, r2, r1, target );
2999
+ testcase( regFree2 == 0 );
3000
+ }
3001
+ inReg = target;
3002
+ break;
3003
+ }
3004
+ case TK_BITNOT:
3005
+ case TK_NOT:
3006
+ {
3007
+ Debug.Assert( TK_BITNOT == OP_BitNot );
3008
+ Debug.Assert( TK_NOT == OP_Not );
3009
+ testcase( op == TK_BITNOT );
3010
+ testcase( op == TK_NOT );
3011
+ r1 = sqlite3ExprCodeTemp( pParse, pExpr.pLeft, ref regFree1 );
3012
+ testcase( regFree1 == 0 );
3013
+ inReg = target;
3014
+ sqlite3VdbeAddOp2( v, op, r1, inReg );
3015
+ break;
3016
+ }
3017
+ case TK_ISNULL:
3018
+ case TK_NOTNULL:
3019
+ {
3020
+ int addr;
3021
+ Debug.Assert( TK_ISNULL == OP_IsNull );
3022
+ Debug.Assert( TK_NOTNULL == OP_NotNull );
3023
+ testcase( op == TK_ISNULL );
3024
+ testcase( op == TK_NOTNULL );
3025
+ sqlite3VdbeAddOp2( v, OP_Integer, 1, target );
3026
+ r1 = sqlite3ExprCodeTemp( pParse, pExpr.pLeft, ref regFree1 );
3027
+ testcase( regFree1 == 0 );
3028
+ addr = sqlite3VdbeAddOp1( v, op, r1 );
3029
+ sqlite3VdbeAddOp2( v, OP_AddImm, target, -1 );
3030
+ sqlite3VdbeJumpHere( v, addr );
3031
+ break;
3032
+ }
3033
+ case TK_AGG_FUNCTION:
3034
+ {
3035
+ AggInfo pInfo = pExpr.pAggInfo;
3036
+ if ( pInfo == null )
3037
+ {
3038
+ Debug.Assert( !ExprHasProperty( pExpr, EP_IntValue ) );
3039
+ sqlite3ErrorMsg( pParse, "misuse of aggregate: %s()", pExpr.u.zToken );
3040
+ }
3041
+ else
3042
+ {
3043
+ inReg = pInfo.aFunc[pExpr.iAgg].iMem;
3044
+ }
3045
+ break;
3046
+ }
3047
+ case TK_CONST_FUNC:
3048
+ case TK_FUNCTION:
3049
+ {
3050
+ ExprList pFarg; /* List of function arguments */
3051
+ int nFarg; /* Number of function arguments */
3052
+ FuncDef pDef; /* The function definition object */
3053
+ int nId; /* Length of the function name in bytes */
3054
+ string zId; /* The function name */
3055
+ int constMask = 0; /* Mask of function arguments that are constant */
3056
+ int i; /* Loop counter */
3057
+ u8 enc = ENC( db ); /* The text encoding used by this database */
3058
+ CollSeq pColl = null; /* A collating sequence */
3059
+
3060
+ Debug.Assert( !ExprHasProperty( pExpr, EP_xIsSelect ) );
3061
+ testcase( op == TK_CONST_FUNC );
3062
+ testcase( op == TK_FUNCTION );
3063
+ if ( ExprHasAnyProperty( pExpr, EP_TokenOnly ) )
3064
+ {
3065
+ pFarg = null;
3066
+ }
3067
+ else
3068
+ {
3069
+ pFarg = pExpr.x.pList;
3070
+ }
3071
+ nFarg = pFarg != null ? pFarg.nExpr : 0;
3072
+ Debug.Assert( !ExprHasProperty( pExpr, EP_IntValue ) );
3073
+ zId = pExpr.u.zToken;
3074
+ nId = sqlite3Strlen30( zId );
3075
+ pDef = sqlite3FindFunction( pParse.db, zId, nId, nFarg, enc, 0 );
3076
+ if ( pDef == null )
3077
+ {
3078
+ sqlite3ErrorMsg( pParse, "unknown function: %.*s()", nId, zId );
3079
+ break;
3080
+ }
3081
+
3082
+ /* Attempt a direct implementation of the built-in COALESCE() and
3083
+ ** IFNULL() functions. This avoids unnecessary evalation of
3084
+ ** arguments past the first non-NULL argument.
3085
+ */
3086
+ if ( ( pDef.flags & SQLITE_FUNC_COALESCE ) != 0 )
3087
+ {
3088
+ int endCoalesce = sqlite3VdbeMakeLabel( v );
3089
+ Debug.Assert( nFarg >= 2 );
3090
+ sqlite3ExprCode( pParse, pFarg.a[0].pExpr, target );
3091
+ for ( i = 1; i < nFarg; i++ )
3092
+ {
3093
+ sqlite3VdbeAddOp2( v, OP_NotNull, target, endCoalesce );
3094
+ sqlite3ExprCacheRemove( pParse, target, 1 );
3095
+ sqlite3ExprCachePush( pParse );
3096
+ sqlite3ExprCode( pParse, pFarg.a[i].pExpr, target );
3097
+ sqlite3ExprCachePop( pParse, 1 );
3098
+ }
3099
+ sqlite3VdbeResolveLabel( v, endCoalesce );
3100
+ break;
3101
+ }
3102
+
3103
+ if ( pFarg != null )
3104
+ {
3105
+ r1 = sqlite3GetTempRange( pParse, nFarg );
3106
+ sqlite3ExprCachePush( pParse ); /* Ticket 2ea2425d34be */
3107
+ sqlite3ExprCodeExprList( pParse, pFarg, r1, true );
3108
+ sqlite3ExprCachePop( pParse, 1 ); /* Ticket 2ea2425d34be */
3109
+ }
3110
+ else
3111
+ {
3112
+ r1 = 0;
3113
+ }
3114
+ #if !SQLITE_OMIT_VIRTUALTABLE
3115
+ /* Possibly overload the function if the first argument is
3116
+ ** a virtual table column.
3117
+ **
3118
+ ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the
3119
+ ** second argument, not the first, as the argument to test to
3120
+ ** see if it is a column in a virtual table. This is done because
3121
+ ** the left operand of infix functions (the operand we want to
3122
+ ** control overloading) ends up as the second argument to the
3123
+ ** function. The expression "A glob B" is equivalent to
3124
+ ** "glob(B,A). We want to use the A in "A glob B" to test
3125
+ ** for function overloading. But we use the B term in "glob(B,A)".
3126
+ */
3127
+ if ( nFarg >= 2 && ( pExpr.flags & EP_InfixFunc ) )
3128
+ {
3129
+ pDef = sqlite3VtabOverloadFunction( db, pDef, nFarg, pFarg.a[1].pExpr );
3130
+ }
3131
+ else if ( nFarg > 0 )
3132
+ {
3133
+ pDef = sqlite3VtabOverloadFunction( db, pDef, nFarg, pFarg.a[0].pExpr );
3134
+ }
3135
+ #endif
3136
+ for ( i = 0; i < nFarg; i++ )
3137
+ {
3138
+ if ( i < 32 && sqlite3ExprIsConstant( pFarg.a[i].pExpr ) != 0 )
3139
+ {
3140
+ constMask |= ( 1 << i );
3141
+ }
3142
+ if ( ( pDef.flags & SQLITE_FUNC_NEEDCOLL ) != 0 && null == pColl )
3143
+ {
3144
+ pColl = sqlite3ExprCollSeq( pParse, pFarg.a[i].pExpr );
3145
+ }
3146
+ }
3147
+ if ( ( pDef.flags & SQLITE_FUNC_NEEDCOLL ) != 0 )
3148
+ {
3149
+ if ( null == pColl ) pColl = db.pDfltColl;
3150
+ sqlite3VdbeAddOp4( v, OP_CollSeq, 0, 0, 0, pColl, P4_COLLSEQ );
3151
+ }
3152
+ sqlite3VdbeAddOp4( v, OP_Function, constMask, r1, target,
3153
+ pDef, P4_FUNCDEF );
3154
+ sqlite3VdbeChangeP5( v, (u8)nFarg );
3155
+ if ( nFarg != 0 )
3156
+ {
3157
+ sqlite3ReleaseTempRange( pParse, r1, nFarg );
3158
+ }
3159
+ break;
3160
+ }
3161
+ #if !SQLITE_OMIT_SUBQUERY
3162
+ case TK_EXISTS:
3163
+ case TK_SELECT:
3164
+ {
3165
+ testcase( op == TK_EXISTS );
3166
+ testcase( op == TK_SELECT );
3167
+ inReg = sqlite3CodeSubselect( pParse, pExpr, 0, false );
3168
+ break;
3169
+ }
3170
+ case TK_IN:
3171
+ {
3172
+ int destIfFalse = sqlite3VdbeMakeLabel( v );
3173
+ int destIfNull = sqlite3VdbeMakeLabel( v );
3174
+ sqlite3VdbeAddOp2( v, OP_Null, 0, target );
3175
+ sqlite3ExprCodeIN( pParse, pExpr, destIfFalse, destIfNull );
3176
+ sqlite3VdbeAddOp2( v, OP_Integer, 1, target );
3177
+ sqlite3VdbeResolveLabel( v, destIfFalse );
3178
+ sqlite3VdbeAddOp2( v, OP_AddImm, target, 0 );
3179
+ sqlite3VdbeResolveLabel( v, destIfNull );
3180
+ break;
3181
+ }
3182
+ #endif //* SQLITE_OMIT_SUBQUERY */
3183
+
3184
+ /*
3185
+ ** x BETWEEN y AND z
3186
+ **
3187
+ ** This is equivalent to
3188
+ **
3189
+ ** x>=y AND x<=z
3190
+ **
3191
+ ** X is stored in pExpr.pLeft.
3192
+ ** Y is stored in pExpr.x.pList.a[0].pExpr.
3193
+ ** Z is stored in pExpr.x.pList.a[1].pExpr.
3194
+ */
3195
+ case TK_BETWEEN:
3196
+ {
3197
+ Expr pLeft = pExpr.pLeft;
3198
+ ExprList_item pLItem = pExpr.x.pList.a[0];
3199
+ Expr pRight = pLItem.pExpr;
3200
+ r1 = sqlite3ExprCodeTemp( pParse, pLeft, ref regFree1 );
3201
+ r2 = sqlite3ExprCodeTemp( pParse, pRight, ref regFree2 );
3202
+ testcase( regFree1 == 0 );
3203
+ testcase( regFree2 == 0 );
3204
+ r3 = sqlite3GetTempReg( pParse );
3205
+ r4 = sqlite3GetTempReg( pParse );
3206
+ codeCompare( pParse, pLeft, pRight, OP_Ge,
3207
+ r1, r2, r3, SQLITE_STOREP2 );
3208
+ pLItem = pExpr.x.pList.a[1];// pLItem++;
3209
+ pRight = pLItem.pExpr;
3210
+ sqlite3ReleaseTempReg( pParse, regFree2 );
3211
+ r2 = sqlite3ExprCodeTemp( pParse, pRight, ref regFree2 );
3212
+ testcase( regFree2 == 0 );
3213
+ codeCompare( pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2 );
3214
+ sqlite3VdbeAddOp3( v, OP_And, r3, r4, target );
3215
+ sqlite3ReleaseTempReg( pParse, r3 );
3216
+ sqlite3ReleaseTempReg( pParse, r4 );
3217
+ break;
3218
+ }
3219
+ case TK_UPLUS:
3220
+ {
3221
+ inReg = sqlite3ExprCodeTarget( pParse, pExpr.pLeft, target );
3222
+ break;
3223
+ }
3224
+ case TK_TRIGGER:
3225
+ {
3226
+ /* If the opcode is TK_TRIGGER, then the expression is a reference
3227
+ ** to a column in the new.* or old.* pseudo-tables available to
3228
+ ** trigger programs. In this case Expr.iTable is set to 1 for the
3229
+ ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
3230
+ ** is set to the column of the pseudo-table to read, or to -1 to
3231
+ ** read the rowid field.
3232
+ **
3233
+ ** The expression is implemented using an OP_Param opcode. The p1
3234
+ ** parameter is set to 0 for an old.rowid reference, or to (i+1)
3235
+ ** to reference another column of the old.* pseudo-table, where
3236
+ ** i is the index of the column. For a new.rowid reference, p1 is
3237
+ ** set to (n+1), where n is the number of columns in each pseudo-table.
3238
+ ** For a reference to any other column in the new.* pseudo-table, p1
3239
+ ** is set to (n+2+i), where n and i are as defined previously. For
3240
+ ** example, if the table on which triggers are being fired is
3241
+ ** declared as:
3242
+ **
3243
+ ** CREATE TABLE t1(a, b);
3244
+ **
3245
+ ** Then p1 is interpreted as follows:
3246
+ **
3247
+ ** p1==0 . old.rowid p1==3 . new.rowid
3248
+ ** p1==1 . old.a p1==4 . new.a
3249
+ ** p1==2 . old.b p1==5 . new.b
3250
+ */
3251
+ Table pTab = pExpr.pTab;
3252
+ int p1 = pExpr.iTable * ( pTab.nCol + 1 ) + 1 + pExpr.iColumn;
3253
+
3254
+ Debug.Assert( pExpr.iTable == 0 || pExpr.iTable == 1 );
3255
+ Debug.Assert( pExpr.iColumn >= -1 && pExpr.iColumn < pTab.nCol );
3256
+ Debug.Assert( pTab.iPKey < 0 || pExpr.iColumn != pTab.iPKey );
3257
+ Debug.Assert( p1 >= 0 && p1 < ( pTab.nCol * 2 + 2 ) );
3258
+
3259
+ sqlite3VdbeAddOp2( v, OP_Param, p1, target );
3260
+ VdbeComment( v, "%s.%s -> $%d",
3261
+ ( pExpr.iTable != 0 ? "new" : "old" ),
3262
+ ( pExpr.iColumn < 0 ? "rowid" : pExpr.pTab.aCol[pExpr.iColumn].zName ),
3263
+ target
3264
+ );
3265
+
3266
+ /* If the column has REAL affinity, it may currently be stored as an
3267
+ ** integer. Use OP_RealAffinity to make sure it is really real. */
3268
+ if ( pExpr.iColumn >= 0
3269
+ && pTab.aCol[pExpr.iColumn].affinity == SQLITE_AFF_REAL
3270
+ )
3271
+ {
3272
+ sqlite3VdbeAddOp1( v, OP_RealAffinity, target );
3273
+ }
3274
+ break;
3275
+ }
3276
+
3277
+ /*
3278
+ ** Form A:
3279
+ ** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
3280
+ **
3281
+ ** Form B:
3282
+ ** CASE WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
3283
+ **
3284
+ ** Form A is can be transformed into the equivalent form B as follows:
3285
+ ** CASE WHEN x=e1 THEN r1 WHEN x=e2 THEN r2 ...
3286
+ ** WHEN x=eN THEN rN ELSE y END
3287
+ **
3288
+ ** X (if it exists) is in pExpr.pLeft.
3289
+ ** Y is in pExpr.pRight. The Y is also optional. If there is no
3290
+ ** ELSE clause and no other term matches, then the result of the
3291
+ ** exprssion is NULL.
3292
+ ** Ei is in pExpr.x.pList.a[i*2] and Ri is pExpr.x.pList.a[i*2+1].
3293
+ **
3294
+ ** The result of the expression is the Ri for the first matching Ei,
3295
+ ** or if there is no matching Ei, the ELSE term Y, or if there is
3296
+ ** no ELSE term, NULL.
3297
+ */
3298
+ default:
3299
+ {
3300
+ Debug.Assert( op == TK_CASE );
3301
+ int endLabel; /* GOTO label for end of CASE stmt */
3302
+ int nextCase; /* GOTO label for next WHEN clause */
3303
+ int nExpr; /* 2x number of WHEN terms */
3304
+ int i; /* Loop counter */
3305
+ ExprList pEList; /* List of WHEN terms */
3306
+ ExprList_item[] aListelem; /* Array of WHEN terms */
3307
+ Expr opCompare = new Expr(); /* The X==Ei expression */
3308
+ Expr cacheX; /* Cached expression X */
3309
+ Expr pX; /* The X expression */
3310
+ Expr pTest = null; /* X==Ei (form A) or just Ei (form B) */
3311
+ #if !NDEBUG
3312
+ int iCacheLevel = pParse.iCacheLevel;
3313
+ //VVA_ONLY( int iCacheLevel = pParse.iCacheLevel; )
3314
+ #endif
3315
+ Debug.Assert( !ExprHasProperty( pExpr, EP_xIsSelect ) && pExpr.x.pList != null );
3316
+ Debug.Assert( ( pExpr.x.pList.nExpr % 2 ) == 0 );
3317
+ Debug.Assert( pExpr.x.pList.nExpr > 0 );
3318
+ pEList = pExpr.x.pList;
3319
+ aListelem = pEList.a;
3320
+ nExpr = pEList.nExpr;
3321
+ endLabel = sqlite3VdbeMakeLabel( v );
3322
+ if ( ( pX = pExpr.pLeft ) != null )
3323
+ {
3324
+ cacheX = pX;
3325
+ testcase( pX.op == TK_COLUMN );
3326
+ testcase( pX.op == TK_REGISTER );
3327
+ cacheX.iTable = sqlite3ExprCodeTemp( pParse, pX, ref regFree1 );
3328
+ testcase( regFree1 == 0 );
3329
+ cacheX.op = TK_REGISTER;
3330
+ opCompare.op = TK_EQ;
3331
+ opCompare.pLeft = cacheX;
3332
+ pTest = opCompare;
3333
+ }
3334
+ for ( i = 0; i < nExpr; i = i + 2 )
3335
+ {
3336
+ sqlite3ExprCachePush( pParse );
3337
+ if ( pX != null )
3338
+ {
3339
+ Debug.Assert( pTest != null );
3340
+ opCompare.pRight = aListelem[i].pExpr;
3341
+ }
3342
+ else
3343
+ {
3344
+ pTest = aListelem[i].pExpr;
3345
+ }
3346
+ nextCase = sqlite3VdbeMakeLabel( v );
3347
+ testcase( pTest.op == TK_COLUMN );
3348
+ sqlite3ExprIfFalse( pParse, pTest, nextCase, SQLITE_JUMPIFNULL );
3349
+ testcase( aListelem[i + 1].pExpr.op == TK_COLUMN );
3350
+ testcase( aListelem[i + 1].pExpr.op == TK_REGISTER );
3351
+ sqlite3ExprCode( pParse, aListelem[i + 1].pExpr, target );
3352
+ sqlite3VdbeAddOp2( v, OP_Goto, 0, endLabel );
3353
+ sqlite3ExprCachePop( pParse, 1 );
3354
+ sqlite3VdbeResolveLabel( v, nextCase );
3355
+ }
3356
+ if ( pExpr.pRight != null )
3357
+ {
3358
+ sqlite3ExprCachePush( pParse );
3359
+ sqlite3ExprCode( pParse, pExpr.pRight, target );
3360
+ sqlite3ExprCachePop( pParse, 1 );
3361
+ }
3362
+ else
3363
+ {
3364
+ sqlite3VdbeAddOp2( v, OP_Null, 0, target );
3365
+ }
3366
+ #if !NDEBUG
3367
+ Debug.Assert( /* db.mallocFailed != 0 || */ pParse.nErr > 0
3368
+ || pParse.iCacheLevel == iCacheLevel );
3369
+ #endif
3370
+ sqlite3VdbeResolveLabel( v, endLabel );
3371
+ break;
3372
+ }
3373
+ #if !SQLITE_OMIT_TRIGGER
3374
+ case TK_RAISE:
3375
+ {
3376
+ Debug.Assert( pExpr.affinity == OE_Rollback
3377
+ || pExpr.affinity == OE_Abort
3378
+ || pExpr.affinity == OE_Fail
3379
+ || pExpr.affinity == OE_Ignore
3380
+ );
3381
+ if ( null == pParse.pTriggerTab )
3382
+ {
3383
+ sqlite3ErrorMsg( pParse,
3384
+ "RAISE() may only be used within a trigger-program" );
3385
+ return 0;
3386
+ }
3387
+ if ( pExpr.affinity == OE_Abort )
3388
+ {
3389
+ sqlite3MayAbort( pParse );
3390
+ }
3391
+ Debug.Assert( !ExprHasProperty( pExpr, EP_IntValue ) );
3392
+ if ( pExpr.affinity == OE_Ignore )
3393
+ {
3394
+ sqlite3VdbeAddOp4(
3395
+ v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr.u.zToken, 0 );
3396
+ }
3397
+ else
3398
+ {
3399
+ sqlite3HaltConstraint( pParse, pExpr.affinity, pExpr.u.zToken, 0 );
3400
+ }
3401
+
3402
+ break;
3403
+ }
3404
+ #endif
3405
+ }
3406
+ sqlite3ReleaseTempReg( pParse, regFree1 );
3407
+ sqlite3ReleaseTempReg( pParse, regFree2 );
3408
+ return inReg;
3409
+ }
3410
+
3411
+ /*
3412
+ ** Generate code to evaluate an expression and store the results
3413
+ ** into a register. Return the register number where the results
3414
+ ** are stored.
3415
+ **
3416
+ ** If the register is a temporary register that can be deallocated,
3417
+ ** then write its number into pReg. If the result register is not
3418
+ ** a temporary, then set pReg to zero.
3419
+ */
3420
+ static int sqlite3ExprCodeTemp( Parse pParse, Expr pExpr, ref int pReg )
3421
+ {
3422
+ int r1 = sqlite3GetTempReg( pParse );
3423
+ int r2 = sqlite3ExprCodeTarget( pParse, pExpr, r1 );
3424
+ if ( r2 == r1 )
3425
+ {
3426
+ pReg = r1;
3427
+ }
3428
+ else
3429
+ {
3430
+ sqlite3ReleaseTempReg( pParse, r1 );
3431
+ pReg = 0;
3432
+ }
3433
+ return r2;
3434
+ }
3435
+
3436
+ /*
3437
+ ** Generate code that will evaluate expression pExpr and store the
3438
+ ** results in register target. The results are guaranteed to appear
3439
+ ** in register target.
3440
+ */
3441
+ static int sqlite3ExprCode( Parse pParse, Expr pExpr, int target )
3442
+ {
3443
+ int inReg;
3444
+
3445
+ Debug.Assert( target > 0 && target <= pParse.nMem );
3446
+ inReg = sqlite3ExprCodeTarget( pParse, pExpr, target );
3447
+ Debug.Assert( pParse.pVdbe != null /* || pParse.db.mallocFailed != 0 */ );
3448
+ if ( inReg != target && pParse.pVdbe != null )
3449
+ {
3450
+ sqlite3VdbeAddOp2( pParse.pVdbe, OP_SCopy, inReg, target );
3451
+ }
3452
+ return target;
3453
+ }
3454
+
3455
+ /*
3456
+ ** Generate code that evalutes the given expression and puts the result
3457
+ ** in register target.
3458
+ **
3459
+ ** Also make a copy of the expression results into another "cache" register
3460
+ ** and modify the expression so that the next time it is evaluated,
3461
+ ** the result is a copy of the cache register.
3462
+ **
3463
+ ** This routine is used for expressions that are used multiple
3464
+ ** times. They are evaluated once and the results of the expression
3465
+ ** are reused.
3466
+ */
3467
+ static int sqlite3ExprCodeAndCache( Parse pParse, Expr pExpr, int target )
3468
+ {
3469
+ Vdbe v = pParse.pVdbe;
3470
+ int inReg;
3471
+ inReg = sqlite3ExprCode( pParse, pExpr, target );
3472
+ Debug.Assert( target > 0 );
3473
+ /* This routine is called for terms to INSERT or UPDATE. And the only
3474
+ ** other place where expressions can be converted into TK_REGISTER is
3475
+ ** in WHERE clause processing. So as currently implemented, there is
3476
+ ** no way for a TK_REGISTER to exist here. But it seems prudent to
3477
+ ** keep the ALWAYS() in case the conditions above change with future
3478
+ ** modifications or enhancements. */
3479
+ if ( ALWAYS( pExpr.op != TK_REGISTER ) )
3480
+ {
3481
+ int iMem;
3482
+ iMem = ++pParse.nMem;
3483
+ sqlite3VdbeAddOp2( v, OP_Copy, inReg, iMem );
3484
+ pExpr.iTable = iMem;
3485
+ pExpr.op2 = pExpr.op;
3486
+ pExpr.op = TK_REGISTER;
3487
+ }
3488
+ return inReg;
3489
+ }
3490
+
3491
+ /*
3492
+ ** Return TRUE if pExpr is an constant expression that is appropriate
3493
+ ** for factoring out of a loop. Appropriate expressions are:
3494
+ **
3495
+ ** * Any expression that evaluates to two or more opcodes.
3496
+ **
3497
+ ** * Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null,
3498
+ ** or OP_Variable that does not need to be placed in a
3499
+ ** specific register.
3500
+ **
3501
+ ** There is no point in factoring out single-instruction constant
3502
+ ** expressions that need to be placed in a particular register.
3503
+ ** We could factor them out, but then we would end up adding an
3504
+ ** OP_SCopy instruction to move the value into the correct register
3505
+ ** later. We might as well just use the original instruction and
3506
+ ** avoid the OP_SCopy.
3507
+ */
3508
+ static int isAppropriateForFactoring( Expr p )
3509
+ {
3510
+ if ( sqlite3ExprIsConstantNotJoin( p ) == 0 )
3511
+ {
3512
+ return 0; /* Only constant expressions are appropriate for factoring */
3513
+ }
3514
+ if ( ( p.flags & EP_FixedDest ) == 0 )
3515
+ {
3516
+ return 1; /* Any constant without a fixed destination is appropriate */
3517
+ }
3518
+ while ( p.op == TK_UPLUS ) p = p.pLeft;
3519
+ switch ( p.op )
3520
+ {
3521
+ #if !SQLITE_OMIT_BLOB_LITERAL
3522
+ case TK_BLOB:
3523
+ #endif
3524
+ case TK_VARIABLE:
3525
+ case TK_INTEGER:
3526
+ case TK_FLOAT:
3527
+ case TK_NULL:
3528
+ case TK_STRING:
3529
+ {
3530
+ testcase( p.op == TK_BLOB );
3531
+ testcase( p.op == TK_VARIABLE );
3532
+ testcase( p.op == TK_INTEGER );
3533
+ testcase( p.op == TK_FLOAT );
3534
+ testcase( p.op == TK_NULL );
3535
+ testcase( p.op == TK_STRING );
3536
+ /* Single-instruction constants with a fixed destination are
3537
+ ** better done in-line. If we factor them, they will just end
3538
+ ** up generating an OP_SCopy to move the value to the destination
3539
+ ** register. */
3540
+ return 0;
3541
+ }
3542
+ case TK_UMINUS:
3543
+ {
3544
+ if ( p.pLeft.op == TK_FLOAT || p.pLeft.op == TK_INTEGER )
3545
+ {
3546
+ return 0;
3547
+ }
3548
+ break;
3549
+ }
3550
+ default:
3551
+ {
3552
+ break;
3553
+ }
3554
+ }
3555
+ return 1;
3556
+ }
3557
+
3558
+ /*
3559
+ ** If pExpr is a constant expression that is appropriate for
3560
+ ** factoring out of a loop, then evaluate the expression
3561
+ ** into a register and convert the expression into a TK_REGISTER
3562
+ ** expression.
3563
+ */
3564
+ static int evalConstExpr( Walker pWalker, ref Expr pExpr )
3565
+ {
3566
+ Parse pParse = pWalker.pParse;
3567
+ switch ( pExpr.op )
3568
+ {
3569
+ case TK_IN:
3570
+ case TK_REGISTER:
3571
+ {
3572
+ return WRC_Prune;
3573
+ }
3574
+ case TK_FUNCTION:
3575
+ case TK_AGG_FUNCTION:
3576
+ case TK_CONST_FUNC:
3577
+ {
3578
+ /* The arguments to a function have a fixed destination.
3579
+ ** Mark them this way to avoid generated unneeded OP_SCopy
3580
+ ** instructions.
3581
+ */
3582
+ ExprList pList = pExpr.x.pList;
3583
+ Debug.Assert( !ExprHasProperty( pExpr, EP_xIsSelect ) );
3584
+ if ( pList != null )
3585
+ {
3586
+ int i = pList.nExpr;
3587
+ ExprList_item pItem;//= pList.a;
3588
+ for ( ; i > 0; i-- )
3589
+ {//, pItem++){
3590
+ pItem = pList.a[pList.nExpr - i];
3591
+ if ( ALWAYS( pItem.pExpr != null ) ) pItem.pExpr.flags |= EP_FixedDest;
3592
+ }
3593
+ }
3594
+ break;
3595
+ }
3596
+ }
3597
+ if ( isAppropriateForFactoring( pExpr ) != 0 )
3598
+ {
3599
+ int r1 = ++pParse.nMem;
3600
+ int r2;
3601
+ r2 = sqlite3ExprCodeTarget( pParse, pExpr, r1 );
3602
+ if ( NEVER( r1 != r2 ) ) sqlite3ReleaseTempReg( pParse, r1 );
3603
+ pExpr.op2 = pExpr.op;
3604
+ pExpr.op = TK_REGISTER;
3605
+ pExpr.iTable = r2;
3606
+ return WRC_Prune;
3607
+ }
3608
+ return WRC_Continue;
3609
+ }
3610
+
3611
+ /*
3612
+ ** Preevaluate constant subexpressions within pExpr and store the
3613
+ ** results in registers. Modify pExpr so that the constant subexpresions
3614
+ ** are TK_REGISTER opcodes that refer to the precomputed values.
3615
+ */
3616
+ static void sqlite3ExprCodeConstants( Parse pParse, Expr pExpr )
3617
+ {
3618
+ Walker w = new Walker();
3619
+ w.xExprCallback = (dxExprCallback)evalConstExpr;
3620
+ w.xSelectCallback = null;
3621
+ w.pParse = pParse;
3622
+ sqlite3WalkExpr( w, ref pExpr );
3623
+ }
3624
+
3625
+ /*
3626
+ ** Generate code that pushes the value of every element of the given
3627
+ ** expression list into a sequence of registers beginning at target.
3628
+ **
3629
+ ** Return the number of elements evaluated.
3630
+ */
3631
+ static int sqlite3ExprCodeExprList(
3632
+ Parse pParse, /* Parsing context */
3633
+ ExprList pList, /* The expression list to be coded */
3634
+ int target, /* Where to write results */
3635
+ bool doHardCopy /* Make a hard copy of every element */
3636
+ )
3637
+ {
3638
+ ExprList_item pItem;
3639
+ int i, n;
3640
+ Debug.Assert( pList != null );
3641
+ Debug.Assert( target > 0 );
3642
+ n = pList.nExpr;
3643
+ for ( i = 0; i < n; i++ )// pItem++)
3644
+ {
3645
+ pItem = pList.a[i];
3646
+ if ( pItem.iAlias != 0 )
3647
+ {
3648
+ int iReg = codeAlias( pParse, pItem.iAlias, pItem.pExpr, target + i );
3649
+ Vdbe v = sqlite3GetVdbe( pParse );
3650
+ if ( iReg != target + i )
3651
+ {
3652
+ sqlite3VdbeAddOp2( v, OP_SCopy, iReg, target + i );
3653
+ }
3654
+ }
3655
+ else
3656
+ {
3657
+ sqlite3ExprCode( pParse, pItem.pExpr, target + i );
3658
+ }
3659
+ if ( doHardCopy /* && 0 == pParse.db.mallocFailed */ )
3660
+ {
3661
+ sqlite3ExprHardCopy( pParse, target, n );
3662
+ }
3663
+ }
3664
+ return n;
3665
+ }
3666
+
3667
+
3668
+ /*
3669
+ ** Generate code for a BETWEEN operator.
3670
+ **
3671
+ ** x BETWEEN y AND z
3672
+ **
3673
+ ** The above is equivalent to
3674
+ **
3675
+ ** x>=y AND x<=z
3676
+ **
3677
+ ** Code it as such, taking care to do the common subexpression
3678
+ ** elementation of x.
3679
+ */
3680
+ static void exprCodeBetween(
3681
+ Parse pParse, /* Parsing and code generating context */
3682
+ Expr pExpr, /* The BETWEEN expression */
3683
+ int dest, /* Jump here if the jump is taken */
3684
+ int jumpIfTrue, /* Take the jump if the BETWEEN is true */
3685
+ int jumpIfNull /* Take the jump if the BETWEEN is NULL */
3686
+ )
3687
+ {
3688
+ Expr exprAnd = new Expr(); /* The AND operator in x>=y AND x<=z */
3689
+ Expr compLeft = new Expr(); /* The x>=y term */
3690
+ Expr compRight = new Expr(); /* The x<=z term */
3691
+ Expr exprX; /* The x subexpression */
3692
+ int regFree1 = 0; /* Temporary use register */
3693
+
3694
+ Debug.Assert( !ExprHasProperty( pExpr, EP_xIsSelect ) );
3695
+ exprX = pExpr.pLeft.Copy();
3696
+ exprAnd.op = TK_AND;
3697
+ exprAnd.pLeft = compLeft;
3698
+ exprAnd.pRight = compRight;
3699
+ compLeft.op = TK_GE;
3700
+ compLeft.pLeft = exprX;
3701
+ compLeft.pRight = pExpr.x.pList.a[0].pExpr;
3702
+ compRight.op = TK_LE;
3703
+ compRight.pLeft = exprX;
3704
+ compRight.pRight = pExpr.x.pList.a[1].pExpr;
3705
+ exprX.iTable = sqlite3ExprCodeTemp( pParse, exprX, ref regFree1 );
3706
+ exprX.op = TK_REGISTER;
3707
+ if ( jumpIfTrue != 0 )
3708
+ {
3709
+ sqlite3ExprIfTrue( pParse, exprAnd, dest, jumpIfNull );
3710
+ }
3711
+ else
3712
+ {
3713
+ sqlite3ExprIfFalse( pParse, exprAnd, dest, jumpIfNull );
3714
+ }
3715
+ sqlite3ReleaseTempReg( pParse, regFree1 );
3716
+
3717
+ /* Ensure adequate test coverage */
3718
+ testcase( jumpIfTrue == 0 && jumpIfNull == 0 && regFree1 == 0 );
3719
+ testcase( jumpIfTrue == 0 && jumpIfNull == 0 && regFree1 != 0 );
3720
+ testcase( jumpIfTrue == 0 && jumpIfNull != 0 && regFree1 == 0 );
3721
+ testcase( jumpIfTrue == 0 && jumpIfNull != 0 && regFree1 != 0 );
3722
+ testcase( jumpIfTrue != 0 && jumpIfNull == 0 && regFree1 == 0 );
3723
+ testcase( jumpIfTrue != 0 && jumpIfNull == 0 && regFree1 != 0 );
3724
+ testcase( jumpIfTrue != 0 && jumpIfNull != 0 && regFree1 == 0 );
3725
+ testcase( jumpIfTrue != 0 && jumpIfNull != 0 && regFree1 != 0 );
3726
+ }
3727
+ /*
3728
+ ** Generate code for a boolean expression such that a jump is made
3729
+ ** to the label "dest" if the expression is true but execution
3730
+ ** continues straight thru if the expression is false.
3731
+ **
3732
+ ** If the expression evaluates to NULL (neither true nor false), then
3733
+ ** take the jump if the jumpIfNull flag is SQLITE_JUMPIFNULL.
3734
+ **
3735
+ ** This code depends on the fact that certain token values (ex: TK_EQ)
3736
+ ** are the same as opcode values (ex: OP_Eq) that implement the corresponding
3737
+ ** operation. Special comments in vdbe.c and the mkopcodeh.awk script in
3738
+ ** the make process cause these values to align. Assert()s in the code
3739
+ ** below verify that the numbers are aligned correctly.
3740
+ */
3741
+ static void sqlite3ExprIfTrue( Parse pParse, Expr pExpr, int dest, int jumpIfNull )
3742
+ {
3743
+ Vdbe v = pParse.pVdbe;
3744
+ int op = 0;
3745
+ int regFree1 = 0;
3746
+ int regFree2 = 0;
3747
+ int r1 = 0, r2 = 0;
3748
+
3749
+ Debug.Assert( jumpIfNull == SQLITE_JUMPIFNULL || jumpIfNull == 0 );
3750
+ if ( NEVER( v == null ) ) return; /* Existance of VDBE checked by caller */
3751
+ if ( NEVER( pExpr == null ) ) return; /* No way this can happen */
3752
+ op = pExpr.op;
3753
+ switch ( op )
3754
+ {
3755
+ case TK_AND:
3756
+ {
3757
+ int d2 = sqlite3VdbeMakeLabel( v );
3758
+ testcase( jumpIfNull == 0 );
3759
+ sqlite3ExprCachePush( pParse );
3760
+ sqlite3ExprIfFalse( pParse, pExpr.pLeft, d2, jumpIfNull ^ SQLITE_JUMPIFNULL );
3761
+ sqlite3ExprIfTrue( pParse, pExpr.pRight, dest, jumpIfNull );
3762
+ sqlite3VdbeResolveLabel( v, d2 );
3763
+ sqlite3ExprCachePop( pParse, 1 );
3764
+ break;
3765
+ }
3766
+ case TK_OR:
3767
+ {
3768
+ testcase( jumpIfNull == 0 );
3769
+ sqlite3ExprIfTrue( pParse, pExpr.pLeft, dest, jumpIfNull );
3770
+ sqlite3ExprIfTrue( pParse, pExpr.pRight, dest, jumpIfNull );
3771
+ break;
3772
+ }
3773
+ case TK_NOT:
3774
+ {
3775
+ testcase( jumpIfNull == 0 );
3776
+ sqlite3ExprIfFalse( pParse, pExpr.pLeft, dest, jumpIfNull );
3777
+ break;
3778
+ }
3779
+ case TK_LT:
3780
+ case TK_LE:
3781
+ case TK_GT:
3782
+ case TK_GE:
3783
+ case TK_NE:
3784
+ case TK_EQ:
3785
+ {
3786
+ Debug.Assert( TK_LT == OP_Lt );
3787
+ Debug.Assert( TK_LE == OP_Le );
3788
+ Debug.Assert( TK_GT == OP_Gt );
3789
+ Debug.Assert( TK_GE == OP_Ge );
3790
+ Debug.Assert( TK_EQ == OP_Eq );
3791
+ Debug.Assert( TK_NE == OP_Ne );
3792
+ testcase( op == TK_LT );
3793
+ testcase( op == TK_LE );
3794
+ testcase( op == TK_GT );
3795
+ testcase( op == TK_GE );
3796
+ testcase( op == TK_EQ );
3797
+ testcase( op == TK_NE );
3798
+ testcase( jumpIfNull == 0 );
3799
+ r1 = sqlite3ExprCodeTemp( pParse, pExpr.pLeft, ref regFree1 );
3800
+ r2 = sqlite3ExprCodeTemp( pParse, pExpr.pRight, ref regFree2 );
3801
+ codeCompare( pParse, pExpr.pLeft, pExpr.pRight, op,
3802
+ r1, r2, dest, jumpIfNull );
3803
+ testcase( regFree1 == 0 );
3804
+ testcase( regFree2 == 0 );
3805
+ break;
3806
+ }
3807
+ case TK_IS:
3808
+ case TK_ISNOT:
3809
+ {
3810
+ testcase( op == TK_IS );
3811
+ testcase( op == TK_ISNOT );
3812
+ r1 = sqlite3ExprCodeTemp( pParse, pExpr.pLeft, ref regFree1 );
3813
+ r2 = sqlite3ExprCodeTemp( pParse, pExpr.pRight, ref regFree2 );
3814
+ op = ( op == TK_IS ) ? TK_EQ : TK_NE;
3815
+ codeCompare( pParse, pExpr.pLeft, pExpr.pRight, op,
3816
+ r1, r2, dest, SQLITE_NULLEQ );
3817
+ testcase( regFree1 == 0 );
3818
+ testcase( regFree2 == 0 );
3819
+ break;
3820
+ }
3821
+ case TK_ISNULL:
3822
+ case TK_NOTNULL:
3823
+ {
3824
+ Debug.Assert( TK_ISNULL == OP_IsNull );
3825
+ Debug.Assert( TK_NOTNULL == OP_NotNull );
3826
+ testcase( op == TK_ISNULL );
3827
+ testcase( op == TK_NOTNULL );
3828
+ r1 = sqlite3ExprCodeTemp( pParse, pExpr.pLeft, ref regFree1 );
3829
+ sqlite3VdbeAddOp2( v, op, r1, dest );
3830
+ testcase( regFree1 == 0 );
3831
+ break;
3832
+ }
3833
+ case TK_BETWEEN:
3834
+ {
3835
+ testcase( jumpIfNull == 0 );
3836
+ exprCodeBetween( pParse, pExpr, dest, 1, jumpIfNull );
3837
+ break;
3838
+ }
3839
+ case TK_IN:
3840
+ {
3841
+ int destIfFalse = sqlite3VdbeMakeLabel( v );
3842
+ int destIfNull = jumpIfNull != 0 ? dest : destIfFalse;
3843
+ sqlite3ExprCodeIN( pParse, pExpr, destIfFalse, destIfNull );
3844
+ sqlite3VdbeAddOp2( v, OP_Goto, 0, dest );
3845
+ sqlite3VdbeResolveLabel( v, destIfFalse );
3846
+ break;
3847
+ }
3848
+ default:
3849
+ {
3850
+ r1 = sqlite3ExprCodeTemp( pParse, pExpr, ref regFree1 );
3851
+ sqlite3VdbeAddOp3( v, OP_If, r1, dest, jumpIfNull != 0 ? 1 : 0 );
3852
+ testcase( regFree1 == 0 );
3853
+ testcase( jumpIfNull == 0 );
3854
+ break;
3855
+ }
3856
+ }
3857
+ sqlite3ReleaseTempReg( pParse, regFree1 );
3858
+ sqlite3ReleaseTempReg( pParse, regFree2 );
3859
+ }
3860
+
3861
+ /*
3862
+ ** Generate code for a boolean expression such that a jump is made
3863
+ ** to the label "dest" if the expression is false but execution
3864
+ ** continues straight thru if the expression is true.
3865
+ **
3866
+ ** If the expression evaluates to NULL (neither true nor false) then
3867
+ ** jump if jumpIfNull is SQLITE_JUMPIFNULL or fall through if jumpIfNull
3868
+ ** is 0.
3869
+ */
3870
+ static void sqlite3ExprIfFalse( Parse pParse, Expr pExpr, int dest, int jumpIfNull )
3871
+ {
3872
+ Vdbe v = pParse.pVdbe;
3873
+ int op = 0;
3874
+ int regFree1 = 0;
3875
+ int regFree2 = 0;
3876
+ int r1 = 0, r2 = 0;
3877
+
3878
+ Debug.Assert( jumpIfNull == SQLITE_JUMPIFNULL || jumpIfNull == 0 );
3879
+ if ( NEVER( v == null ) ) return; /* Existance of VDBE checked by caller */
3880
+ if ( pExpr == null ) return;
3881
+
3882
+ /* The value of pExpr.op and op are related as follows:
3883
+ **
3884
+ ** pExpr.op op
3885
+ ** --------- ----------
3886
+ ** TK_ISNULL OP_NotNull
3887
+ ** TK_NOTNULL OP_IsNull
3888
+ ** TK_NE OP_Eq
3889
+ ** TK_EQ OP_Ne
3890
+ ** TK_GT OP_Le
3891
+ ** TK_LE OP_Gt
3892
+ ** TK_GE OP_Lt
3893
+ ** TK_LT OP_Ge
3894
+ **
3895
+ ** For other values of pExpr.op, op is undefined and unused.
3896
+ ** The value of TK_ and OP_ constants are arranged such that we
3897
+ ** can compute the mapping above using the following expression.
3898
+ ** Assert()s verify that the computation is correct.
3899
+ */
3900
+ op = ( ( pExpr.op + ( TK_ISNULL & 1 ) ) ^ 1 ) - ( TK_ISNULL & 1 );
3901
+
3902
+ /* Verify correct alignment of TK_ and OP_ constants
3903
+ */
3904
+ Debug.Assert( pExpr.op != TK_ISNULL || op == OP_NotNull );
3905
+ Debug.Assert( pExpr.op != TK_NOTNULL || op == OP_IsNull );
3906
+ Debug.Assert( pExpr.op != TK_NE || op == OP_Eq );
3907
+ Debug.Assert( pExpr.op != TK_EQ || op == OP_Ne );
3908
+ Debug.Assert( pExpr.op != TK_LT || op == OP_Ge );
3909
+ Debug.Assert( pExpr.op != TK_LE || op == OP_Gt );
3910
+ Debug.Assert( pExpr.op != TK_GT || op == OP_Le );
3911
+ Debug.Assert( pExpr.op != TK_GE || op == OP_Lt );
3912
+
3913
+ switch ( pExpr.op )
3914
+ {
3915
+ case TK_AND:
3916
+ {
3917
+ testcase( jumpIfNull == 0 );
3918
+ sqlite3ExprIfFalse( pParse, pExpr.pLeft, dest, jumpIfNull );
3919
+ sqlite3ExprIfFalse( pParse, pExpr.pRight, dest, jumpIfNull );
3920
+ break;
3921
+ }
3922
+ case TK_OR:
3923
+ {
3924
+ int d2 = sqlite3VdbeMakeLabel( v );
3925
+ testcase( jumpIfNull == 0 );
3926
+ sqlite3ExprCachePush( pParse );
3927
+ sqlite3ExprIfTrue( pParse, pExpr.pLeft, d2, jumpIfNull ^ SQLITE_JUMPIFNULL );
3928
+ sqlite3ExprIfFalse( pParse, pExpr.pRight, dest, jumpIfNull );
3929
+ sqlite3VdbeResolveLabel( v, d2 );
3930
+ sqlite3ExprCachePop( pParse, 1 );
3931
+ break;
3932
+ }
3933
+ case TK_NOT:
3934
+ {
3935
+ testcase( jumpIfNull == 0 );
3936
+ sqlite3ExprIfTrue( pParse, pExpr.pLeft, dest, jumpIfNull );
3937
+ break;
3938
+ }
3939
+ case TK_LT:
3940
+ case TK_LE:
3941
+ case TK_GT:
3942
+ case TK_GE:
3943
+ case TK_NE:
3944
+ case TK_EQ:
3945
+ {
3946
+ testcase( op == TK_LT );
3947
+ testcase( op == TK_LE );
3948
+ testcase( op == TK_GT );
3949
+ testcase( op == TK_GE );
3950
+ testcase( op == TK_EQ );
3951
+ testcase( op == TK_NE );
3952
+ testcase( jumpIfNull == 0 );
3953
+ r1 = sqlite3ExprCodeTemp( pParse, pExpr.pLeft, ref regFree1 );
3954
+ r2 = sqlite3ExprCodeTemp( pParse, pExpr.pRight, ref regFree2 );
3955
+ codeCompare( pParse, pExpr.pLeft, pExpr.pRight, op,
3956
+ r1, r2, dest, jumpIfNull );
3957
+ testcase( regFree1 == 0 );
3958
+ testcase( regFree2 == 0 );
3959
+ break;
3960
+ }
3961
+ case TK_IS:
3962
+ case TK_ISNOT:
3963
+ {
3964
+ testcase( pExpr.op == TK_IS );
3965
+ testcase( pExpr.op == TK_ISNOT );
3966
+ r1 = sqlite3ExprCodeTemp( pParse, pExpr.pLeft, ref regFree1 );
3967
+ r2 = sqlite3ExprCodeTemp( pParse, pExpr.pRight, ref regFree2 );
3968
+ op = ( pExpr.op == TK_IS ) ? TK_NE : TK_EQ;
3969
+ codeCompare( pParse, pExpr.pLeft, pExpr.pRight, op,
3970
+ r1, r2, dest, SQLITE_NULLEQ );
3971
+ testcase( regFree1 == 0 );
3972
+ testcase( regFree2 == 0 );
3973
+ break;
3974
+ }
3975
+ case TK_ISNULL:
3976
+ case TK_NOTNULL:
3977
+ {
3978
+ testcase( op == TK_ISNULL );
3979
+ testcase( op == TK_NOTNULL );
3980
+ r1 = sqlite3ExprCodeTemp( pParse, pExpr.pLeft, ref regFree1 );
3981
+ sqlite3VdbeAddOp2( v, op, r1, dest );
3982
+ testcase( regFree1 == 0 );
3983
+ break;
3984
+ }
3985
+ case TK_BETWEEN:
3986
+ {
3987
+ testcase( jumpIfNull == 0 );
3988
+ exprCodeBetween( pParse, pExpr, dest, 0, jumpIfNull );
3989
+ break;
3990
+ }
3991
+ case TK_IN:
3992
+ {
3993
+ if ( jumpIfNull != 0 )
3994
+ {
3995
+ sqlite3ExprCodeIN( pParse, pExpr, dest, dest );
3996
+ }
3997
+ else
3998
+ {
3999
+ int destIfNull = sqlite3VdbeMakeLabel( v );
4000
+ sqlite3ExprCodeIN( pParse, pExpr, dest, destIfNull );
4001
+ sqlite3VdbeResolveLabel( v, destIfNull );
4002
+ }
4003
+ break;
4004
+ }
4005
+ default:
4006
+ {
4007
+ r1 = sqlite3ExprCodeTemp( pParse, pExpr, ref regFree1 );
4008
+ sqlite3VdbeAddOp3( v, OP_IfNot, r1, dest, jumpIfNull != 0 ? 1 : 0 );
4009
+ testcase( regFree1 == 0 );
4010
+ testcase( jumpIfNull == 0 );
4011
+ break;
4012
+ }
4013
+ }
4014
+ sqlite3ReleaseTempReg( pParse, regFree1 );
4015
+ sqlite3ReleaseTempReg( pParse, regFree2 );
4016
+ }
4017
+
4018
+ /*
4019
+ ** Do a deep comparison of two expression trees. Return 0 if the two
4020
+ ** expressions are completely identical. Return 1 if they differ only
4021
+ ** by a COLLATE operator at the top level. Return 2 if there are differences
4022
+ ** other than the top-level COLLATE operator.
4023
+ **
4024
+ ** Sometimes this routine will return 2 even if the two expressions
4025
+ ** really are equivalent. If we cannot prove that the expressions are
4026
+ ** identical, we return 2 just to be safe. So if this routine
4027
+ ** returns 2, then you do not really know for certain if the two
4028
+ ** expressions are the same. But if you get a 0 or 1 return, then you
4029
+ ** can be sure the expressions are the same. In the places where
4030
+ ** this routine is used, it does not hurt to get an extra 2 - that
4031
+ ** just might result in some slightly slower code. But returning
4032
+ ** an incorrect 0 or 1 could lead to a malfunction.
4033
+ */
4034
+ static int sqlite3ExprCompare(Expr pA, Expr pB)
4035
+ {
4036
+ int i;
4037
+ if ( pA == null || pB == null )
4038
+ {
4039
+ return pB == pA ? 0 : 2;
4040
+ }
4041
+ Debug.Assert( !ExprHasAnyProperty( pA, EP_TokenOnly | EP_Reduced ) );
4042
+ Debug.Assert( !ExprHasAnyProperty( pB, EP_TokenOnly | EP_Reduced ) );
4043
+ if ( ExprHasProperty( pA, EP_xIsSelect ) || ExprHasProperty( pB, EP_xIsSelect ) )
4044
+ {
4045
+ return 2;
4046
+ }
4047
+ if ( ( pA.flags & EP_Distinct ) != ( pB.flags & EP_Distinct ) ) return 2;
4048
+ if ( pA.op != pB.op ) return 2;
4049
+ if ( sqlite3ExprCompare( pA.pLeft, pB.pLeft ) != 0 ) return 2;
4050
+ if ( sqlite3ExprCompare( pA.pRight, pB.pRight ) != 0 ) return 2;
4051
+ if ( pA.x.pList != null && pB.x.pList != null )
4052
+ {
4053
+ if ( pA.x.pList.nExpr != pB.x.pList.nExpr ) return 2;
4054
+ for ( i = 0; i < pA.x.pList.nExpr; i++ )
4055
+ {
4056
+ Expr pExprA = pA.x.pList.a[i].pExpr;
4057
+ Expr pExprB = pB.x.pList.a[i].pExpr;
4058
+ if ( sqlite3ExprCompare( pExprA, pExprB ) != 0 ) return 2;
4059
+ }
4060
+ }
4061
+ else if ( pA.x.pList != null || pB.x.pList != null )
4062
+ {
4063
+ return 2;
4064
+ }
4065
+ if ( pA.iTable != pB.iTable || pA.iColumn != pB.iColumn ) return 2;
4066
+ if ( ExprHasProperty( pA, EP_IntValue ) )
4067
+ {
4068
+ if ( !ExprHasProperty( pB, EP_IntValue ) || pA.u.iValue != pB.u.iValue )
4069
+ {
4070
+ return 2;
4071
+ }
4072
+ }
4073
+ else if ( pA.op != TK_COLUMN && pA.u.zToken != null )
4074
+ {
4075
+ if ( ExprHasProperty( pB, EP_IntValue ) || NEVER( pB.u.zToken == null ) ) return 2;
4076
+ if ( sqlite3StrICmp( pA.u.zToken, pB.u.zToken ) != 0 )
4077
+ {
4078
+ return 2;
4079
+ }
4080
+ }
4081
+ if ( ( pA.flags & EP_ExpCollate ) != ( pB.flags & EP_ExpCollate ) ) return 1;
4082
+ if ( ( pA.flags & EP_ExpCollate ) != 0 && pA.pColl != pB.pColl ) return 2;
4083
+ return 0;
4084
+ }
4085
+
4086
+
4087
+ /*
4088
+ ** Add a new element to the pAggInfo.aCol[] array. Return the index of
4089
+ ** the new element. Return a negative number if malloc fails.
4090
+ */
4091
+ static int addAggInfoColumn( sqlite3 db, AggInfo pInfo )
4092
+ {
4093
+ int i = 0;
4094
+ pInfo.aCol = sqlite3ArrayAllocate(
4095
+ db,
4096
+ pInfo.aCol,
4097
+ -1,//sizeof(pInfo.aCol[0]),
4098
+ 3,
4099
+ ref pInfo.nColumn,
4100
+ ref pInfo.nColumnAlloc,
4101
+ ref i
4102
+ );
4103
+ return i;
4104
+ }
4105
+
4106
+ /*
4107
+ ** Add a new element to the pAggInfo.aFunc[] array. Return the index of
4108
+ ** the new element. Return a negative number if malloc fails.
4109
+ */
4110
+ static int addAggInfoFunc( sqlite3 db, AggInfo pInfo )
4111
+ {
4112
+ int i = 0;
4113
+ pInfo.aFunc = sqlite3ArrayAllocate(
4114
+ db,
4115
+ pInfo.aFunc,
4116
+ -1,//sizeof(pInfo.aFunc[0]),
4117
+ 3,
4118
+ ref pInfo.nFunc,
4119
+ ref pInfo.nFuncAlloc,
4120
+ ref i
4121
+ );
4122
+ return i;
4123
+ }
4124
+
4125
+ /*
4126
+ ** This is the xExprCallback for a tree walker. It is used to
4127
+ ** implement sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates
4128
+ ** for additional information.
4129
+ */
4130
+ static int analyzeAggregate( Walker pWalker, ref Expr pExpr )
4131
+ {
4132
+ int i;
4133
+ NameContext pNC = pWalker.u.pNC;
4134
+ Parse pParse = pNC.pParse;
4135
+ SrcList pSrcList = pNC.pSrcList;
4136
+ AggInfo pAggInfo = pNC.pAggInfo;
4137
+
4138
+ switch ( pExpr.op )
4139
+ {
4140
+ case TK_AGG_COLUMN:
4141
+ case TK_COLUMN:
4142
+ {
4143
+ testcase( pExpr.op == TK_AGG_COLUMN );
4144
+ testcase( pExpr.op == TK_COLUMN );
4145
+ /* Check to see if the column is in one of the tables in the FROM
4146
+ ** clause of the aggregate query */
4147
+ if ( ALWAYS( pSrcList != null ) )
4148
+ {
4149
+ SrcList_item pItem;// = pSrcList.a;
4150
+ for ( i = 0; i < pSrcList.nSrc; i++ )
4151
+ {//, pItem++){
4152
+ pItem = pSrcList.a[i];
4153
+ AggInfo_col pCol;
4154
+ Debug.Assert( !ExprHasAnyProperty( pExpr, EP_TokenOnly | EP_Reduced ) );
4155
+ if ( pExpr.iTable == pItem.iCursor )
4156
+ {
4157
+ /* If we reach this point, it means that pExpr refers to a table
4158
+ ** that is in the FROM clause of the aggregate query.
4159
+ **
4160
+ ** Make an entry for the column in pAggInfo.aCol[] if there
4161
+ ** is not an entry there already.
4162
+ */
4163
+ int k;
4164
+ //pCol = pAggInfo.aCol;
4165
+ for ( k = 0; k < pAggInfo.nColumn; k++ )
4166
+ {//, pCol++){
4167
+ pCol = pAggInfo.aCol[k];
4168
+ if ( pCol.iTable == pExpr.iTable &&
4169
+ pCol.iColumn == pExpr.iColumn )
4170
+ {
4171
+ break;
4172
+ }
4173
+ }
4174
+ if ( ( k >= pAggInfo.nColumn )
4175
+ && ( k = addAggInfoColumn( pParse.db, pAggInfo ) ) >= 0
4176
+ )
4177
+ {
4178
+ pCol = pAggInfo.aCol[k];
4179
+ pCol.pTab = pExpr.pTab;
4180
+ pCol.iTable = pExpr.iTable;
4181
+ pCol.iColumn = pExpr.iColumn;
4182
+ pCol.iMem = ++pParse.nMem;
4183
+ pCol.iSorterColumn = -1;
4184
+ pCol.pExpr = pExpr;
4185
+ if ( pAggInfo.pGroupBy != null )
4186
+ {
4187
+ int j, n;
4188
+ ExprList pGB = pAggInfo.pGroupBy;
4189
+ ExprList_item pTerm;// = pGB.a;
4190
+ n = pGB.nExpr;
4191
+ for ( j = 0; j < n; j++ )
4192
+ {//, pTerm++){
4193
+ pTerm = pGB.a[j];
4194
+ Expr pE = pTerm.pExpr;
4195
+ if ( pE.op == TK_COLUMN && pE.iTable == pExpr.iTable &&
4196
+ pE.iColumn == pExpr.iColumn )
4197
+ {
4198
+ pCol.iSorterColumn = j;
4199
+ break;
4200
+ }
4201
+ }
4202
+ }
4203
+ if ( pCol.iSorterColumn < 0 )
4204
+ {
4205
+ pCol.iSorterColumn = pAggInfo.nSortingColumn++;
4206
+ }
4207
+ }
4208
+ /* There is now an entry for pExpr in pAggInfo.aCol[] (either
4209
+ ** because it was there before or because we just created it).
4210
+ ** Convert the pExpr to be a TK_AGG_COLUMN referring to that
4211
+ ** pAggInfo.aCol[] entry.
4212
+ */
4213
+ ExprSetIrreducible( pExpr );
4214
+ pExpr.pAggInfo = pAggInfo;
4215
+ pExpr.op = TK_AGG_COLUMN;
4216
+ pExpr.iAgg = (short)k;
4217
+ break;
4218
+ } /* endif pExpr.iTable==pItem.iCursor */
4219
+ } /* end loop over pSrcList */
4220
+ }
4221
+ return WRC_Prune;
4222
+ }
4223
+ case TK_AGG_FUNCTION:
4224
+ {
4225
+ /* The pNC.nDepth==0 test causes aggregate functions in subqueries
4226
+ ** to be ignored */
4227
+ if ( pNC.nDepth == 0 )
4228
+ {
4229
+ /* Check to see if pExpr is a duplicate of another aggregate
4230
+ ** function that is already in the pAggInfo structure
4231
+ */
4232
+ AggInfo_func pItem;// = pAggInfo.aFunc;
4233
+ for ( i = 0; i < pAggInfo.nFunc; i++ )
4234
+ {//, pItem++){
4235
+ pItem = pAggInfo.aFunc[i];
4236
+ if ( sqlite3ExprCompare( pItem.pExpr, pExpr ) == 0 )
4237
+ {
4238
+ break;
4239
+ }
4240
+ }
4241
+ if ( i >= pAggInfo.nFunc )
4242
+ {
4243
+ /* pExpr is original. Make a new entry in pAggInfo.aFunc[]
4244
+ */
4245
+ u8 enc = pParse.db.aDbStatic[0].pSchema.enc;// ENC(pParse.db);
4246
+ i = addAggInfoFunc( pParse.db, pAggInfo );
4247
+ if ( i >= 0 )
4248
+ {
4249
+ Debug.Assert( !ExprHasProperty( pExpr, EP_xIsSelect ) );
4250
+ pItem = pAggInfo.aFunc[i];
4251
+ pItem.pExpr = pExpr;
4252
+ pItem.iMem = ++pParse.nMem;
4253
+ Debug.Assert( !ExprHasProperty( pExpr, EP_IntValue ) );
4254
+ pItem.pFunc = sqlite3FindFunction( pParse.db,
4255
+ pExpr.u.zToken, sqlite3Strlen30( pExpr.u.zToken ),
4256
+ pExpr.x.pList != null ? pExpr.x.pList.nExpr : 0, enc, 0 );
4257
+ if ( ( pExpr.flags & EP_Distinct ) != 0 )
4258
+ {
4259
+ pItem.iDistinct = pParse.nTab++;
4260
+ }
4261
+ else
4262
+ {
4263
+ pItem.iDistinct = -1;
4264
+ }
4265
+ }
4266
+ }
4267
+ /* Make pExpr point to the appropriate pAggInfo.aFunc[] entry
4268
+ */
4269
+ Debug.Assert( !ExprHasAnyProperty( pExpr, EP_TokenOnly | EP_Reduced ) );
4270
+ ExprSetIrreducible( pExpr );
4271
+ pExpr.iAgg = (short)i;
4272
+ pExpr.pAggInfo = pAggInfo;
4273
+ return WRC_Prune;
4274
+ }
4275
+ break;
4276
+ }
4277
+ }
4278
+ return WRC_Continue;
4279
+ }
4280
+
4281
+ static int analyzeAggregatesInSelect( Walker pWalker, Select pSelect )
4282
+ {
4283
+ NameContext pNC = pWalker.u.pNC;
4284
+ if ( pNC.nDepth == 0 )
4285
+ {
4286
+ pNC.nDepth++;
4287
+ sqlite3WalkSelect( pWalker, pSelect );
4288
+ pNC.nDepth--;
4289
+ return WRC_Prune;
4290
+ }
4291
+ else
4292
+ {
4293
+ return WRC_Continue;
4294
+ }
4295
+ }
4296
+
4297
+
4298
+ /*
4299
+ ** Analyze the given expression looking for aggregate functions and
4300
+ ** for variables that need to be added to the pParse.aAgg[] array.
4301
+ ** Make additional entries to the pParse.aAgg[] array as necessary.
4302
+ **
4303
+ ** This routine should only be called after the expression has been
4304
+ ** analyzed by sqlite3ResolveExprNames().
4305
+ */
4306
+ static void sqlite3ExprAnalyzeAggregates( NameContext pNC, ref Expr pExpr )
4307
+ {
4308
+ Walker w = new Walker();
4309
+ w.xExprCallback = (dxExprCallback)analyzeAggregate;
4310
+ w.xSelectCallback = (dxSelectCallback)analyzeAggregatesInSelect;
4311
+ w.u.pNC = pNC;
4312
+ Debug.Assert( pNC.pSrcList != null );
4313
+ sqlite3WalkExpr( w, ref pExpr );
4314
+ }
4315
+
4316
+ /*
4317
+ ** Call sqlite3ExprAnalyzeAggregates() for every expression in an
4318
+ ** expression list. Return the number of errors.
4319
+ **
4320
+ ** If an error is found, the analysis is cut short.
4321
+ */
4322
+ static void sqlite3ExprAnalyzeAggList( NameContext pNC, ExprList pList )
4323
+ {
4324
+ ExprList_item pItem;
4325
+ int i;
4326
+ if ( pList != null )
4327
+ {
4328
+ for ( i = 0; i < pList.nExpr; i++ )//, pItem++)
4329
+ {
4330
+ pItem = pList.a[i];
4331
+ sqlite3ExprAnalyzeAggregates( pNC, ref pItem.pExpr );
4332
+ }
4333
+ }
4334
+ }
4335
+
4336
+ /*
4337
+ ** Allocate a single new register for use to hold some intermediate result.
4338
+ */
4339
+ static int sqlite3GetTempReg( Parse pParse )
4340
+ {
4341
+ if ( pParse.nTempReg == 0 )
4342
+ {
4343
+ return ++pParse.nMem;
4344
+ }
4345
+ return pParse.aTempReg[--pParse.nTempReg];
4346
+ }
4347
+
4348
+ /*
4349
+ ** Deallocate a register, making available for reuse for some other
4350
+ ** purpose.
4351
+ **
4352
+ ** If a register is currently being used by the column cache, then
4353
+ ** the dallocation is deferred until the column cache line that uses
4354
+ ** the register becomes stale.
4355
+ */
4356
+ static void sqlite3ReleaseTempReg( Parse pParse, int iReg )
4357
+ {
4358
+ if ( iReg != 0 && pParse.nTempReg < ArraySize( pParse.aTempReg ) )
4359
+ {
4360
+ int i;
4361
+ yColCache p;
4362
+ for ( i = 0; i < SQLITE_N_COLCACHE; i++ )//p=pParse.aColCache... p++)
4363
+ {
4364
+ p = pParse.aColCache[i];
4365
+ if ( p.iReg == iReg )
4366
+ {
4367
+ p.tempReg = 1;
4368
+ return;
4369
+ }
4370
+ }
4371
+ pParse.aTempReg[pParse.nTempReg++] = iReg;
4372
+ }
4373
+ }
4374
+
4375
+ /*
4376
+ ** Allocate or deallocate a block of nReg consecutive registers
4377
+ */
4378
+ static int sqlite3GetTempRange( Parse pParse, int nReg )
4379
+ {
4380
+ int i, n;
4381
+ i = pParse.iRangeReg;
4382
+ n = pParse.nRangeReg;
4383
+ if ( nReg <= n )
4384
+ {
4385
+ //Debug.Assert( 0 == usedAsColumnCache( pParse, i, i + n - 1 ) );
4386
+ pParse.iRangeReg += nReg;
4387
+ pParse.nRangeReg -= nReg;
4388
+ }
4389
+ else
4390
+ {
4391
+ i = pParse.nMem + 1;
4392
+ pParse.nMem += nReg;
4393
+ }
4394
+ return i;
4395
+ }
4396
+ static void sqlite3ReleaseTempRange( Parse pParse, int iReg, int nReg )
4397
+ {
4398
+ sqlite3ExprCacheRemove( pParse, iReg, nReg );
4399
+ if ( nReg > pParse.nRangeReg )
4400
+ {
4401
+ pParse.nRangeReg = nReg;
4402
+ pParse.iRangeReg = iReg;
4403
+ }
4404
+ }
4405
+ }
4406
+ }