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,4878 @@
1
+ #define SQLITE_MAX_EXPR_DEPTH
2
+ using System;
3
+ using System.Diagnostics;
4
+ using System.Text;
5
+
6
+ using i16 = System.Int16;
7
+ using u8 = System.Byte;
8
+ using u16 = System.UInt16;
9
+ using u32 = System.UInt32;
10
+
11
+ using Pgno = System.UInt32;
12
+
13
+ namespace Community.CsharpSqlite
14
+ {
15
+ public partial class Sqlite3
16
+ {
17
+ /*
18
+ ** 2001 September 15
19
+ **
20
+ ** The author disclaims copyright to this source code. In place of
21
+ ** a legal notice, here is a blessing:
22
+ **
23
+ ** May you do good and not evil.
24
+ ** May you find forgiveness for yourself and forgive others.
25
+ ** May you share freely, never taking more than you give.
26
+ **
27
+ *************************************************************************
28
+ ** This file contains C code routines that are called by the parser
29
+ ** to handle SELECT statements in SQLite.
30
+ *************************************************************************
31
+ ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
32
+ ** C#-SQLite is an independent reimplementation of the SQLite software library
33
+ **
34
+ ** SQLITE_SOURCE_ID: 2010-03-09 19:31:43 4ae453ea7be69018d8c16eb8dabe05617397dc4d
35
+ **
36
+ ** $Header$
37
+ *************************************************************************
38
+ */
39
+ //#include "sqliteInt.h"
40
+
41
+
42
+ /*
43
+ ** Delete all the content of a Select structure but do not deallocate
44
+ ** the select structure itself.
45
+ */
46
+ static void clearSelect( sqlite3 db, Select p )
47
+ {
48
+ sqlite3ExprListDelete( db, ref p.pEList );
49
+ sqlite3SrcListDelete( db, ref p.pSrc );
50
+ sqlite3ExprDelete( db, ref p.pWhere );
51
+ sqlite3ExprListDelete( db, ref p.pGroupBy );
52
+ sqlite3ExprDelete( db, ref p.pHaving );
53
+ sqlite3ExprListDelete( db, ref p.pOrderBy );
54
+ sqlite3SelectDelete( db, ref p.pPrior );
55
+ sqlite3ExprDelete( db, ref p.pLimit );
56
+ sqlite3ExprDelete( db, ref p.pOffset );
57
+ }
58
+
59
+ /*
60
+ ** Initialize a SelectDest structure.
61
+ */
62
+ static void sqlite3SelectDestInit( SelectDest pDest, int eDest, int iParm )
63
+ {
64
+ pDest.eDest = (u8)eDest;
65
+ pDest.iParm = iParm;
66
+ pDest.affinity = '\0';
67
+ pDest.iMem = 0;
68
+ pDest.nMem = 0;
69
+ }
70
+
71
+
72
+ /*
73
+ ** Allocate a new Select structure and return a pointer to that
74
+ ** structure.
75
+ */
76
+ // OVERLOADS, so I don't need to rewrite parse.c
77
+ static Select sqlite3SelectNew( Parse pParse, int null_2, SrcList pSrc, int null_4, int null_5, int null_6, int null_7, int isDistinct, int null_9, int null_10 )
78
+ {
79
+ return sqlite3SelectNew( pParse, null, pSrc, null, null, null, null, isDistinct, null, null );
80
+ }
81
+ static Select sqlite3SelectNew(
82
+ Parse pParse, /* Parsing context */
83
+ ExprList pEList, /* which columns to include in the result */
84
+ SrcList pSrc, /* the FROM clause -- which tables to scan */
85
+ Expr pWhere, /* the WHERE clause */
86
+ ExprList pGroupBy, /* the GROUP BY clause */
87
+ Expr pHaving, /* the HAVING clause */
88
+ ExprList pOrderBy, /* the ORDER BY clause */
89
+ int isDistinct, /* true if the DISTINCT keyword is present */
90
+ Expr pLimit, /* LIMIT value. NULL means not used */
91
+ Expr pOffset /* OFFSET value. NULL means no offset */
92
+ )
93
+ {
94
+ Select pNew;
95
+ // Select standin;
96
+ sqlite3 db = pParse.db;
97
+ pNew = new Select();//sqlite3DbMallocZero(db, sizeof(*pNew) );
98
+ Debug.Assert( //db.mallocFailed != 0 ||
99
+ null == pOffset || pLimit != null ); /* OFFSET implies LIMIT */
100
+ //if( pNew==null ){
101
+ // pNew = standin;
102
+ // memset(pNew, 0, sizeof(*pNew));
103
+ //}
104
+ if ( pEList == null )
105
+ {
106
+ pEList = sqlite3ExprListAppend( pParse, null, sqlite3Expr( db, TK_ALL, null ) );
107
+ }
108
+ pNew.pEList = pEList;
109
+ pNew.pSrc = pSrc;
110
+ pNew.pWhere = pWhere;
111
+ pNew.pGroupBy = pGroupBy;
112
+ pNew.pHaving = pHaving;
113
+ pNew.pOrderBy = pOrderBy;
114
+ pNew.selFlags = (u16)( isDistinct != 0 ? SF_Distinct : 0 );
115
+ pNew.op = TK_SELECT;
116
+ pNew.pLimit = pLimit;
117
+ pNew.pOffset = pOffset;
118
+ Debug.Assert( pOffset == null || pLimit != null );
119
+ pNew.addrOpenEphm[0] = -1;
120
+ pNew.addrOpenEphm[1] = -1;
121
+ pNew.addrOpenEphm[2] = -1;
122
+ //if ( db.mallocFailed != 0 )
123
+ //{
124
+ // clearSelect( db, pNew );
125
+ // //if ( pNew != standin ) sqlite3DbFree( db, ref pNew );
126
+ // pNew = null;
127
+ //}
128
+ return pNew;
129
+ }
130
+
131
+ /*
132
+ ** Delete the given Select structure and all of its substructures.
133
+ */
134
+ static void sqlite3SelectDelete( sqlite3 db, ref Select p )
135
+ {
136
+ if ( p != null )
137
+ {
138
+ clearSelect( db, p );
139
+ sqlite3DbFree( db, ref p );
140
+ }
141
+ }
142
+
143
+ /*
144
+ ** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the
145
+ ** type of join. Return an integer constant that expresses that type
146
+ ** in terms of the following bit values:
147
+ **
148
+ ** JT_INNER
149
+ ** JT_CROSS
150
+ ** JT_OUTER
151
+ ** JT_NATURAL
152
+ ** JT_LEFT
153
+ ** JT_RIGHT
154
+ **
155
+ ** A full outer join is the combination of JT_LEFT and JT_RIGHT.
156
+ **
157
+ ** If an illegal or unsupported join type is seen, then still return
158
+ ** a join type, but put an error in the pParse structure.
159
+ */
160
+
161
+ class Keyword
162
+ {
163
+ public u8 i; /* Beginning of keyword text in zKeyText[] */
164
+ public u8 nChar; /* Length of the keyword in characters */
165
+ public u8 code; /* Join type mask */
166
+ public Keyword( u8 i, u8 nChar, u8 code )
167
+ {
168
+ this.i = i;
169
+ this.nChar = nChar;
170
+ this.code = code;
171
+ }
172
+ }
173
+
174
+ // OVERLOADS, so I don't need to rewrite parse.c
175
+ static int sqlite3JoinType( Parse pParse, Token pA, int null_3, int null_4 )
176
+ {
177
+ return sqlite3JoinType( pParse, pA, null, null );
178
+ }
179
+ static int sqlite3JoinType( Parse pParse, Token pA, Token pB, int null_4 )
180
+ {
181
+ return sqlite3JoinType( pParse, pA, pB, null );
182
+ }
183
+ static int sqlite3JoinType( Parse pParse, Token pA, Token pB, Token pC )
184
+ {
185
+ int jointype = 0;
186
+ Token[] apAll = new Token[3];
187
+ Token p;
188
+
189
+ /* 0123456789 123456789 123456789 123 */
190
+ string zKeyText = "naturaleftouterightfullinnercross";
191
+
192
+ Keyword[] aKeyword = new Keyword[]{
193
+ /* natural */ new Keyword( 0, 7, JT_NATURAL ),
194
+ /* left */ new Keyword( 6, 4, JT_LEFT|JT_OUTER ),
195
+ /* outer */ new Keyword( 10, 5, JT_OUTER ),
196
+ /* right */ new Keyword( 14, 5, JT_RIGHT|JT_OUTER ),
197
+ /* full */ new Keyword( 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER ),
198
+ /* inner */ new Keyword( 23, 5, JT_INNER ),
199
+ /* cross */ new Keyword( 28, 5, JT_INNER|JT_CROSS ),
200
+ };
201
+ int i, j;
202
+ apAll[0] = pA;
203
+ apAll[1] = pB;
204
+ apAll[2] = pC;
205
+ for ( i = 0; i < 3 && apAll[i] != null; i++ )
206
+ {
207
+ p = apAll[i];
208
+ for ( j = 0; j < ArraySize( aKeyword ); j++ )
209
+ {
210
+ if ( p.n == aKeyword[j].nChar
211
+ && sqlite3StrNICmp( p.z.ToString(), zKeyText.Substring( aKeyword[j].i ), p.n ) == 0 )
212
+ {
213
+ jointype |= aKeyword[j].code;
214
+ break;
215
+ }
216
+ }
217
+ testcase( j == 0 || j == 1 || j == 2 || j == 3 || j == 4 || j == 5 || j == 6 );
218
+ if ( j >= ArraySize( aKeyword ) )
219
+ {
220
+ jointype |= JT_ERROR;
221
+ break;
222
+ }
223
+ }
224
+ if (
225
+ ( jointype & ( JT_INNER | JT_OUTER ) ) == ( JT_INNER | JT_OUTER ) ||
226
+ ( jointype & JT_ERROR ) != 0
227
+ )
228
+ {
229
+ string zSp = " ";
230
+ Debug.Assert( pB != null );
231
+ if ( pC == null ) { zSp = ""; }
232
+ sqlite3ErrorMsg( pParse, "unknown or unsupported join type: " +
233
+ "%T %T%s%T", pA, pB, zSp, pC );
234
+ jointype = JT_INNER;
235
+ }
236
+ else if ( ( jointype & JT_OUTER ) != 0
237
+ && ( jointype & ( JT_LEFT | JT_RIGHT ) ) != JT_LEFT )
238
+ {
239
+ sqlite3ErrorMsg( pParse,
240
+ "RIGHT and FULL OUTER JOINs are not currently supported" );
241
+ jointype = JT_INNER;
242
+ }
243
+ return jointype;
244
+ }
245
+
246
+ /*
247
+ ** Return the index of a column in a table. Return -1 if the column
248
+ ** is not contained in the table.
249
+ */
250
+ static int columnIndex( Table pTab, string zCol )
251
+ {
252
+ int i;
253
+ for ( i = 0; i < pTab.nCol; i++ )
254
+ {
255
+ if ( sqlite3StrICmp( pTab.aCol[i].zName, zCol ) == 0 ) return i;
256
+ }
257
+ return -1;
258
+ }
259
+
260
+
261
+ /*
262
+ ** Search the first N tables in pSrc, from left to right, looking for a
263
+ ** table that has a column named zCol.
264
+ **
265
+ ** When found, set *piTab and *piCol to the table index and column index
266
+ ** of the matching column and return TRUE.
267
+ **
268
+ ** If not found, return FALSE.
269
+ */
270
+ static int tableAndColumnIndex(
271
+ SrcList pSrc, /* Array of tables to search */
272
+ int N, /* Number of tables in pSrc.a[] to search */
273
+ string zCol, /* Name of the column we are looking for */
274
+ ref int piTab, /* Write index of pSrc.a[] here */
275
+ ref int piCol /* Write index of pSrc.a[*piTab].pTab.aCol[] here */
276
+ )
277
+ {
278
+ int i; /* For looping over tables in pSrc */
279
+ int iCol; /* Index of column matching zCol */
280
+
281
+ Debug.Assert( ( piTab == 0 ) == ( piCol == 0 ) ); /* Both or neither are NULL */
282
+ for ( i = 0; i < N; i++ )
283
+ {
284
+ iCol = columnIndex( pSrc.a[i].pTab, zCol );
285
+ if ( iCol >= 0 )
286
+ {
287
+ //if( piTab )
288
+ {
289
+ piTab = i;
290
+ piCol = iCol;
291
+ }
292
+ return 1;
293
+ }
294
+ }
295
+ return 0;
296
+ }
297
+
298
+ /*
299
+ ** This function is used to add terms implied by JOIN syntax to the
300
+ ** WHERE clause expression of a SELECT statement. The new term, which
301
+ ** is ANDed with the existing WHERE clause, is of the form:
302
+ **
303
+ ** (tab1.col1 = tab2.col2)
304
+ **
305
+ ** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the
306
+ ** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is
307
+ ** column iColRight of tab2.
308
+ */
309
+ static void addWhereTerm(
310
+ Parse pParse, /* Parsing context */
311
+ SrcList pSrc, /* List of tables in FROM clause */
312
+ int iLeft, /* Index of first table to join in pSrc */
313
+ int iColLeft, /* Index of column in first table */
314
+ int iRight, /* Index of second table in pSrc */
315
+ int iColRight, /* Index of column in second table */
316
+ int isOuterJoin, /* True if this is an OUTER join */
317
+ ref Expr ppWhere /* IN/OUT: The WHERE clause to add to */
318
+ )
319
+ {
320
+ sqlite3 db = pParse.db;
321
+ Expr pE1;
322
+ Expr pE2;
323
+ Expr pEq;
324
+
325
+ Debug.Assert( iLeft < iRight );
326
+ Debug.Assert( pSrc.nSrc > iRight );
327
+ Debug.Assert( pSrc.a[iLeft].pTab != null );
328
+ Debug.Assert( pSrc.a[iRight].pTab != null );
329
+
330
+ pE1 = sqlite3CreateColumnExpr( db, pSrc, iLeft, iColLeft );
331
+ pE2 = sqlite3CreateColumnExpr( db, pSrc, iRight, iColRight );
332
+
333
+ pEq = sqlite3PExpr( pParse, TK_EQ, pE1, pE2, 0 );
334
+ if ( pEq != null && isOuterJoin != 0 )
335
+ {
336
+ ExprSetProperty( pEq, EP_FromJoin );
337
+ Debug.Assert( !ExprHasAnyProperty( pEq, EP_TokenOnly | EP_Reduced ) );
338
+ ExprSetIrreducible( pEq );
339
+ pEq.iRightJoinTable = (i16)pE2.iTable;
340
+ }
341
+ ppWhere = sqlite3ExprAnd( db, ppWhere, pEq );
342
+ }
343
+
344
+ /*
345
+ ** Set the EP_FromJoin property on all terms of the given expression.
346
+ ** And set the Expr.iRightJoinTable to iTable for every term in the
347
+ ** expression.
348
+ **
349
+ ** The EP_FromJoin property is used on terms of an expression to tell
350
+ ** the LEFT OUTER JOIN processing logic that this term is part of the
351
+ ** join restriction specified in the ON or USING clause and not a part
352
+ ** of the more general WHERE clause. These terms are moved over to the
353
+ ** WHERE clause during join processing but we need to remember that they
354
+ ** originated in the ON or USING clause.
355
+ **
356
+ ** The Expr.iRightJoinTable tells the WHERE clause processing that the
357
+ ** expression depends on table iRightJoinTable even if that table is not
358
+ ** explicitly mentioned in the expression. That information is needed
359
+ ** for cases like this:
360
+ **
361
+ ** SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5
362
+ **
363
+ ** The where clause needs to defer the handling of the t1.x=5
364
+ ** term until after the t2 loop of the join. In that way, a
365
+ ** NULL t2 row will be inserted whenever t1.x!=5. If we do not
366
+ ** defer the handling of t1.x=5, it will be processed immediately
367
+ ** after the t1 loop and rows with t1.x!=5 will never appear in
368
+ ** the output, which is incorrect.
369
+ */
370
+ static void setJoinExpr( Expr p, int iTable )
371
+ {
372
+ while ( p != null )
373
+ {
374
+ ExprSetProperty( p, EP_FromJoin );
375
+ Debug.Assert( !ExprHasAnyProperty( p, EP_TokenOnly | EP_Reduced ) );
376
+ ExprSetIrreducible( p );
377
+ p.iRightJoinTable = (i16)iTable;
378
+ setJoinExpr( p.pLeft, iTable );
379
+ p = p.pRight;
380
+ }
381
+ }
382
+
383
+ /*
384
+ ** This routine processes the join information for a SELECT statement.
385
+ ** ON and USING clauses are converted into extra terms of the WHERE clause.
386
+ ** NATURAL joins also create extra WHERE clause terms.
387
+ **
388
+ ** The terms of a FROM clause are contained in the Select.pSrc structure.
389
+ ** The left most table is the first entry in Select.pSrc. The right-most
390
+ ** table is the last entry. The join operator is held in the entry to
391
+ ** the left. Thus entry 0 contains the join operator for the join between
392
+ ** entries 0 and 1. Any ON or USING clauses associated with the join are
393
+ ** also attached to the left entry.
394
+ **
395
+ ** This routine returns the number of errors encountered.
396
+ */
397
+ static int sqliteProcessJoin( Parse pParse, Select p )
398
+ {
399
+ SrcList pSrc; /* All tables in the FROM clause */
400
+ int i; int j; /* Loop counters */
401
+ SrcList_item pLeft; /* Left table being joined */
402
+ SrcList_item pRight; /* Right table being joined */
403
+
404
+ pSrc = p.pSrc;
405
+ //pLeft = pSrc.a[0];
406
+ //pRight = pLeft[1];
407
+ for ( i = 0; i < pSrc.nSrc - 1; i++ )
408
+ {
409
+ pLeft = pSrc.a[i]; // pLeft ++
410
+ pRight = pSrc.a[i + 1];//Right++,
411
+ Table pLeftTab = pLeft.pTab;
412
+ Table pRightTab = pRight.pTab;
413
+ bool isOuter;
414
+
415
+ if ( NEVER( pLeftTab == null || pRightTab == null ) ) continue;
416
+ isOuter = ( pRight.jointype & JT_OUTER ) != 0;
417
+
418
+ /* When the NATURAL keyword is present, add WHERE clause terms for
419
+ ** every column that the two tables have in common.
420
+ */
421
+ if ( ( pRight.jointype & JT_NATURAL ) != 0 )
422
+ {
423
+ if ( pRight.pOn != null || pRight.pUsing != null )
424
+ {
425
+ sqlite3ErrorMsg( pParse, "a NATURAL join may not have " +
426
+ "an ON or USING clause", "" );
427
+ return 1;
428
+ }
429
+ for ( j = 0; j < pRightTab.nCol; j++ )
430
+ {
431
+ string zName; /* Name of column in the right table */
432
+ int iLeft = 0; /* Matching left table */
433
+ int iLeftCol = 0; /* Matching column in the left table */
434
+
435
+ zName = pRightTab.aCol[j].zName;
436
+ int iRightCol = columnIndex( pRightTab, zName );
437
+ if ( tableAndColumnIndex( pSrc, i + 1, zName, ref iLeft, ref iLeftCol ) != 0 )
438
+ {
439
+ addWhereTerm( pParse, pSrc, iLeft, iLeftCol, i + 1, j,
440
+ isOuter ? 1 : 0, ref p.pWhere );
441
+ }
442
+ }
443
+ }
444
+
445
+ /* Disallow both ON and USING clauses in the same join
446
+ */
447
+ if ( pRight.pOn != null && pRight.pUsing != null )
448
+ {
449
+ sqlite3ErrorMsg( pParse, "cannot have both ON and USING " +
450
+ "clauses in the same join" );
451
+ return 1;
452
+ }
453
+
454
+ /* Add the ON clause to the end of the WHERE clause, connected by
455
+ ** an AND operator.
456
+ */
457
+ if ( pRight.pOn != null )
458
+ {
459
+ if ( isOuter ) setJoinExpr( pRight.pOn, pRight.iCursor );
460
+ p.pWhere = sqlite3ExprAnd( pParse.db, p.pWhere, pRight.pOn );
461
+ pRight.pOn = null;
462
+ }
463
+
464
+ /* Create extra terms on the WHERE clause for each column named
465
+ ** in the USING clause. Example: If the two tables to be joined are
466
+ ** A and B and the USING clause names X, Y, and Z, then add this
467
+ ** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z
468
+ ** Report an error if any column mentioned in the USING clause is
469
+ ** not contained in both tables to be joined.
470
+ */
471
+ if ( pRight.pUsing != null )
472
+ {
473
+ IdList pList = pRight.pUsing;
474
+ for ( j = 0; j < pList.nId; j++ )
475
+ {
476
+ string zName; /* Name of the term in the USING clause */
477
+ int iLeft = 0; /* Table on the left with matching column name */
478
+ int iLeftCol = 0; /* Column number of matching column on the left */
479
+ int iRightCol; /* Column number of matching column on the right */
480
+
481
+ zName = pList.a[j].zName;
482
+ iRightCol = columnIndex( pRightTab, zName );
483
+ if ( iRightCol < 0
484
+ || 0 == tableAndColumnIndex( pSrc, i + 1, zName, ref iLeft, ref iLeftCol )
485
+ )
486
+ {
487
+ sqlite3ErrorMsg( pParse, "cannot join using column %s - column " +
488
+ "not present in both tables", zName );
489
+ return 1;
490
+ }
491
+ addWhereTerm( pParse, pSrc, iLeft, iLeftCol, i + 1, iRightCol,
492
+ isOuter ? 1 : 0, ref p.pWhere );
493
+ }
494
+ }
495
+ }
496
+ return 0;
497
+ }
498
+
499
+ /*
500
+ ** Insert code into "v" that will push the record on the top of the
501
+ ** stack into the sorter.
502
+ */
503
+ static void pushOntoSorter(
504
+ Parse pParse, /* Parser context */
505
+ ExprList pOrderBy, /* The ORDER BY clause */
506
+ Select pSelect, /* The whole SELECT statement */
507
+ int regData /* Register holding data to be sorted */
508
+ )
509
+ {
510
+ Vdbe v = pParse.pVdbe;
511
+ int nExpr = pOrderBy.nExpr;
512
+ int regBase = sqlite3GetTempRange( pParse, nExpr + 2 );
513
+ int regRecord = sqlite3GetTempReg( pParse );
514
+ sqlite3ExprCacheClear( pParse );
515
+ sqlite3ExprCodeExprList( pParse, pOrderBy, regBase, false );
516
+ sqlite3VdbeAddOp2( v, OP_Sequence, pOrderBy.iECursor, regBase + nExpr );
517
+ sqlite3ExprCodeMove( pParse, regData, regBase + nExpr + 1, 1 );
518
+ sqlite3VdbeAddOp3( v, OP_MakeRecord, regBase, nExpr + 2, regRecord );
519
+ sqlite3VdbeAddOp2( v, OP_IdxInsert, pOrderBy.iECursor, regRecord );
520
+ sqlite3ReleaseTempReg( pParse, regRecord );
521
+ sqlite3ReleaseTempRange( pParse, regBase, nExpr + 2 );
522
+ if ( pSelect.iLimit != 0 )
523
+ {
524
+ int addr1, addr2;
525
+ int iLimit;
526
+ if ( pSelect.iOffset != 0 )
527
+ {
528
+ iLimit = pSelect.iOffset + 1;
529
+ }
530
+ else
531
+ {
532
+ iLimit = pSelect.iLimit;
533
+ }
534
+ addr1 = sqlite3VdbeAddOp1( v, OP_IfZero, iLimit );
535
+ sqlite3VdbeAddOp2( v, OP_AddImm, iLimit, -1 );
536
+ addr2 = sqlite3VdbeAddOp0( v, OP_Goto );
537
+ sqlite3VdbeJumpHere( v, addr1 );
538
+ sqlite3VdbeAddOp1( v, OP_Last, pOrderBy.iECursor );
539
+ sqlite3VdbeAddOp1( v, OP_Delete, pOrderBy.iECursor );
540
+ sqlite3VdbeJumpHere( v, addr2 );
541
+ pSelect.iLimit = 0;
542
+ }
543
+ }
544
+
545
+ /*
546
+ ** Add code to implement the OFFSET
547
+ */
548
+ static void codeOffset(
549
+ Vdbe v, /* Generate code into this VM */
550
+ Select p, /* The SELECT statement being coded */
551
+ int iContinue /* Jump here to skip the current record */
552
+ )
553
+ {
554
+ if ( p.iOffset != 0 && iContinue != 0 )
555
+ {
556
+ int addr;
557
+ sqlite3VdbeAddOp2( v, OP_AddImm, p.iOffset, -1 );
558
+ addr = sqlite3VdbeAddOp1( v, OP_IfNeg, p.iOffset );
559
+ sqlite3VdbeAddOp2( v, OP_Goto, 0, iContinue );
560
+ #if SQLITE_DEBUG
561
+ VdbeComment( v, "skip OFFSET records" );
562
+ #endif
563
+ sqlite3VdbeJumpHere( v, addr );
564
+ }
565
+ }
566
+
567
+ /*
568
+ ** Add code that will check to make sure the N registers starting at iMem
569
+ ** form a distinct entry. iTab is a sorting index that holds previously
570
+ ** seen combinations of the N values. A new entry is made in iTab
571
+ ** if the current N values are new.
572
+ **
573
+ ** A jump to addrRepeat is made and the N+1 values are popped from the
574
+ ** stack if the top N elements are not distinct.
575
+ */
576
+ static void codeDistinct(
577
+ Parse pParse, /* Parsing and code generating context */
578
+ int iTab, /* A sorting index used to test for distinctness */
579
+ int addrRepeat, /* Jump to here if not distinct */
580
+ int N, /* Number of elements */
581
+ int iMem /* First element */
582
+ )
583
+ {
584
+ Vdbe v;
585
+ int r1;
586
+
587
+ v = pParse.pVdbe;
588
+ r1 = sqlite3GetTempReg( pParse );
589
+ sqlite3VdbeAddOp4Int( v, OP_Found, iTab, addrRepeat, iMem, N );
590
+ sqlite3VdbeAddOp3( v, OP_MakeRecord, iMem, N, r1 );
591
+ sqlite3VdbeAddOp2( v, OP_IdxInsert, iTab, r1 );
592
+ sqlite3ReleaseTempReg( pParse, r1 );
593
+ }
594
+
595
+ /*
596
+ ** Generate an error message when a SELECT is used within a subexpression
597
+ ** (example: "a IN (SELECT * FROM table)") but it has more than 1 result
598
+ ** column. We do this in a subroutine because the error occurs in multiple
599
+ ** places.
600
+ */
601
+ static bool checkForMultiColumnSelectError(
602
+ Parse pParse, /* Parse context. */
603
+ SelectDest pDest, /* Destination of SELECT results */
604
+ int nExpr /* Number of result columns returned by SELECT */
605
+ )
606
+ {
607
+ int eDest = pDest.eDest;
608
+ if ( nExpr > 1 && ( eDest == SRT_Mem || eDest == SRT_Set ) )
609
+ {
610
+ sqlite3ErrorMsg( pParse, "only a single result allowed for " +
611
+ "a SELECT that is part of an expression" );
612
+ return true;
613
+ }
614
+ else
615
+ {
616
+ return false;
617
+ }
618
+ }
619
+
620
+ /*
621
+ ** This routine generates the code for the inside of the inner loop
622
+ ** of a SELECT.
623
+ **
624
+ ** If srcTab and nColumn are both zero, then the pEList expressions
625
+ ** are evaluated in order to get the data for this row. If nColumn>0
626
+ ** then data is pulled from srcTab and pEList is used only to get the
627
+ ** datatypes for each column.
628
+ */
629
+ static void selectInnerLoop(
630
+ Parse pParse, /* The parser context */
631
+ Select p, /* The complete select statement being coded */
632
+ ExprList pEList, /* List of values being extracted */
633
+ int srcTab, /* Pull data from this table */
634
+ int nColumn, /* Number of columns in the source table */
635
+ ExprList pOrderBy, /* If not NULL, sort results using this key */
636
+ int distinct, /* If >=0, make sure results are distinct */
637
+ SelectDest pDest, /* How to dispose of the results */
638
+ int iContinue, /* Jump here to continue with next row */
639
+ int iBreak /* Jump here to break out of the inner loop */
640
+ )
641
+ {
642
+ Vdbe v = pParse.pVdbe;
643
+ int i;
644
+ bool hasDistinct; /* True if the DISTINCT keyword is present */
645
+ int regResult; /* Start of memory holding result set */
646
+ int eDest = pDest.eDest; /* How to dispose of results */
647
+ int iParm = pDest.iParm; /* First argument to disposal method */
648
+ int nResultCol; /* Number of result columns */
649
+
650
+ Debug.Assert( v != null );
651
+ if ( NEVER( v == null ) ) return;
652
+ Debug.Assert( pEList != null );
653
+ hasDistinct = distinct >= 0;
654
+ if ( pOrderBy == null && !hasDistinct )
655
+ {
656
+ codeOffset( v, p, iContinue );
657
+ }
658
+
659
+ /* Pull the requested columns.
660
+ */
661
+ if ( nColumn > 0 )
662
+ {
663
+ nResultCol = nColumn;
664
+ }
665
+ else
666
+ {
667
+ nResultCol = pEList.nExpr;
668
+ }
669
+ if ( pDest.iMem == 0 )
670
+ {
671
+ pDest.iMem = pParse.nMem + 1;
672
+ pDest.nMem = nResultCol;
673
+ pParse.nMem += nResultCol;
674
+ }
675
+ else
676
+ {
677
+ Debug.Assert( pDest.nMem == nResultCol );
678
+ }
679
+ regResult = pDest.iMem;
680
+ if ( nColumn > 0 )
681
+ {
682
+ for ( i = 0; i < nColumn; i++ )
683
+ {
684
+ sqlite3VdbeAddOp3( v, OP_Column, srcTab, i, regResult + i );
685
+ }
686
+ }
687
+ else if ( eDest != SRT_Exists )
688
+ {
689
+ /* If the destination is an EXISTS(...) expression, the actual
690
+ ** values returned by the SELECT are not required.
691
+ */
692
+ sqlite3ExprCacheClear( pParse );
693
+ sqlite3ExprCodeExprList( pParse, pEList, regResult, eDest == SRT_Output );
694
+ }
695
+ nColumn = nResultCol;
696
+
697
+ /* If the DISTINCT keyword was present on the SELECT statement
698
+ ** and this row has been seen before, then do not make this row
699
+ ** part of the result.
700
+ */
701
+ if ( hasDistinct )
702
+ {
703
+ Debug.Assert( pEList != null );
704
+ Debug.Assert( pEList.nExpr == nColumn );
705
+ codeDistinct( pParse, distinct, iContinue, nColumn, regResult );
706
+ if ( pOrderBy == null )
707
+ {
708
+ codeOffset( v, p, iContinue );
709
+ }
710
+ }
711
+
712
+ if ( checkForMultiColumnSelectError( pParse, pDest, pEList.nExpr ) )
713
+ {
714
+ return;
715
+ }
716
+
717
+ switch ( eDest )
718
+ {
719
+ /* In this mode, write each query result to the key of the temporary
720
+ ** table iParm.
721
+ */
722
+ #if !SQLITE_OMIT_COMPOUND_SELECT
723
+ case SRT_Union:
724
+ {
725
+ int r1;
726
+ r1 = sqlite3GetTempReg( pParse );
727
+ sqlite3VdbeAddOp3( v, OP_MakeRecord, regResult, nColumn, r1 );
728
+ sqlite3VdbeAddOp2( v, OP_IdxInsert, iParm, r1 );
729
+ sqlite3ReleaseTempReg( pParse, r1 );
730
+ break;
731
+ }
732
+
733
+ /* Construct a record from the query result, but instead of
734
+ ** saving that record, use it as a key to delete elements from
735
+ ** the temporary table iParm.
736
+ */
737
+ case SRT_Except:
738
+ {
739
+ sqlite3VdbeAddOp3( v, OP_IdxDelete, iParm, regResult, nColumn );
740
+ break;
741
+ }
742
+ #endif
743
+
744
+ /* Store the result as data using a unique key.
745
+ */
746
+ case SRT_Table:
747
+ case SRT_EphemTab:
748
+ {
749
+ int r1 = sqlite3GetTempReg( pParse );
750
+ testcase( eDest == SRT_Table );
751
+ testcase( eDest == SRT_EphemTab );
752
+ sqlite3VdbeAddOp3( v, OP_MakeRecord, regResult, nColumn, r1 );
753
+ if ( pOrderBy != null )
754
+ {
755
+ pushOntoSorter( pParse, pOrderBy, p, r1 );
756
+ }
757
+ else
758
+ {
759
+ int r2 = sqlite3GetTempReg( pParse );
760
+ sqlite3VdbeAddOp2( v, OP_NewRowid, iParm, r2 );
761
+ sqlite3VdbeAddOp3( v, OP_Insert, iParm, r1, r2 );
762
+ sqlite3VdbeChangeP5( v, OPFLAG_APPEND );
763
+ sqlite3ReleaseTempReg( pParse, r2 );
764
+ }
765
+ sqlite3ReleaseTempReg( pParse, r1 );
766
+ break;
767
+ }
768
+
769
+ #if !SQLITE_OMIT_SUBQUERY
770
+ /* If we are creating a set for an "expr IN (SELECT ...)" construct,
771
+ ** then there should be a single item on the stack. Write this
772
+ ** item into the set table with bogus data.
773
+ */
774
+ case SRT_Set:
775
+ {
776
+ Debug.Assert( nColumn == 1 );
777
+ p.affinity = sqlite3CompareAffinity( pEList.a[0].pExpr, pDest.affinity );
778
+ if ( pOrderBy != null )
779
+ {
780
+ /* At first glance you would think we could optimize out the
781
+ ** ORDER BY in this case since the order of entries in the set
782
+ ** does not matter. But there might be a LIMIT clause, in which
783
+ ** case the order does matter */
784
+ pushOntoSorter( pParse, pOrderBy, p, regResult );
785
+ }
786
+ else
787
+ {
788
+ int r1 = sqlite3GetTempReg( pParse );
789
+ sqlite3VdbeAddOp4( v, OP_MakeRecord, regResult, 1, r1, p.affinity, 1 );
790
+ sqlite3ExprCacheAffinityChange( pParse, regResult, 1 );
791
+ sqlite3VdbeAddOp2( v, OP_IdxInsert, iParm, r1 );
792
+ sqlite3ReleaseTempReg( pParse, r1 );
793
+ }
794
+ break;
795
+ }
796
+
797
+ /* If any row exist in the result set, record that fact and abort.
798
+ */
799
+ case SRT_Exists:
800
+ {
801
+ sqlite3VdbeAddOp2( v, OP_Integer, 1, iParm );
802
+ /* The LIMIT clause will terminate the loop for us */
803
+ break;
804
+ }
805
+
806
+ /* If this is a scalar select that is part of an expression, then
807
+ ** store the results in the appropriate memory cell and break out
808
+ ** of the scan loop.
809
+ */
810
+ case SRT_Mem:
811
+ {
812
+ Debug.Assert( nColumn == 1 );
813
+ if ( pOrderBy != null )
814
+ {
815
+ pushOntoSorter( pParse, pOrderBy, p, regResult );
816
+ }
817
+ else
818
+ {
819
+ sqlite3ExprCodeMove( pParse, regResult, iParm, 1 );
820
+ /* The LIMIT clause will jump out of the loop for us */
821
+ }
822
+ break;
823
+ }
824
+ #endif // * #if !SQLITE_OMIT_SUBQUERY */
825
+
826
+ /* Send the data to the callback function or to a subroutine. In the
827
+ ** case of a subroutine, the subroutine itself is responsible for
828
+ ** popping the data from the stack.
829
+ */
830
+ case SRT_Coroutine:
831
+ case SRT_Output:
832
+ {
833
+ testcase( eDest == SRT_Coroutine );
834
+ testcase( eDest == SRT_Output );
835
+ if ( pOrderBy != null )
836
+ {
837
+ int r1 = sqlite3GetTempReg( pParse );
838
+ sqlite3VdbeAddOp3( v, OP_MakeRecord, regResult, nColumn, r1 );
839
+ pushOntoSorter( pParse, pOrderBy, p, r1 );
840
+ sqlite3ReleaseTempReg( pParse, r1 );
841
+ }
842
+ else if ( eDest == SRT_Coroutine )
843
+ {
844
+ sqlite3VdbeAddOp1( v, OP_Yield, pDest.iParm );
845
+ }
846
+ else
847
+ {
848
+ sqlite3VdbeAddOp2( v, OP_ResultRow, regResult, nColumn );
849
+ sqlite3ExprCacheAffinityChange( pParse, regResult, nColumn );
850
+ }
851
+ break;
852
+ }
853
+
854
+ #if !SQLITE_OMIT_TRIGGER
855
+ /* Discard the results. This is used for SELECT statements inside
856
+ ** the body of a TRIGGER. The purpose of such selects is to call
857
+ ** user-defined functions that have side effects. We do not care
858
+ ** about the actual results of the select.
859
+ */
860
+ default:
861
+ {
862
+ Debug.Assert( eDest == SRT_Discard );
863
+ break;
864
+ }
865
+ #endif
866
+ }
867
+
868
+ /* Jump to the end of the loop if the LIMIT is reached.
869
+ */
870
+ if ( p.iLimit != 0 )
871
+ {
872
+ Debug.Assert( pOrderBy == null ); /* If there is an ORDER BY, the call to
873
+ ** pushOntoSorter() would have cleared p.iLimit */
874
+ sqlite3VdbeAddOp3( v, OP_IfZero, p.iLimit, iBreak, -1 );
875
+ }
876
+ }
877
+
878
+ /*
879
+ ** Given an expression list, generate a KeyInfo structure that records
880
+ ** the collating sequence for each expression in that expression list.
881
+ **
882
+ ** If the ExprList is an ORDER BY or GROUP BY clause then the resulting
883
+ ** KeyInfo structure is appropriate for initializing a virtual index to
884
+ ** implement that clause. If the ExprList is the result set of a SELECT
885
+ ** then the KeyInfo structure is appropriate for initializing a virtual
886
+ ** index to implement a DISTINCT test.
887
+ **
888
+ ** Space to hold the KeyInfo structure is obtain from malloc. The calling
889
+ ** function is responsible for seeing that this structure is eventually
890
+ ** freed. Add the KeyInfo structure to the P4 field of an opcode using
891
+ ** P4_KEYINFO_HANDOFF is the usual way of dealing with this.
892
+ */
893
+ static KeyInfo keyInfoFromExprList( Parse pParse, ExprList pList )
894
+ {
895
+ sqlite3 db = pParse.db;
896
+ int nExpr;
897
+ KeyInfo pInfo;
898
+ ExprList_item pItem;
899
+ int i;
900
+
901
+ nExpr = pList.nExpr;
902
+ pInfo = new KeyInfo();//sqlite3DbMallocZero(db, sizeof(*pInfo) + nExpr*(CollSeq*.Length+1) );
903
+ if ( pInfo != null )
904
+ {
905
+ pInfo.aSortOrder = new byte[nExpr];// pInfo.aColl[nExpr];
906
+ pInfo.aColl = new CollSeq[nExpr];
907
+ pInfo.nField = (u16)nExpr;
908
+ pInfo.enc = db.aDbStatic[0].pSchema.enc;// ENC(db);
909
+ pInfo.db = db;
910
+ for ( i = 0; i < nExpr; i++ )
911
+ {//, pItem++){
912
+ pItem = pList.a[i];
913
+ CollSeq pColl;
914
+ pColl = sqlite3ExprCollSeq( pParse, pItem.pExpr );
915
+ if ( pColl == null )
916
+ {
917
+ pColl = db.pDfltColl;
918
+ }
919
+ pInfo.aColl[i] = pColl;
920
+ pInfo.aSortOrder[i] = (byte)pItem.sortOrder;
921
+ }
922
+ }
923
+ return pInfo;
924
+ }
925
+
926
+
927
+ /*
928
+ ** If the inner loop was generated using a non-null pOrderBy argument,
929
+ ** then the results were placed in a sorter. After the loop is terminated
930
+ ** we need to run the sorter and output the results. The following
931
+ ** routine generates the code needed to do that.
932
+ */
933
+ static void generateSortTail(
934
+ Parse pParse, /* Parsing context */
935
+ Select p, /* The SELECT statement */
936
+ Vdbe v, /* Generate code into this VDBE */
937
+ int nColumn, /* Number of columns of data */
938
+ SelectDest pDest /* Write the sorted results here */
939
+ )
940
+ {
941
+ int addrBreak = sqlite3VdbeMakeLabel( v ); /* Jump here to exit loop */
942
+ int addrContinue = sqlite3VdbeMakeLabel( v ); /* Jump here for next cycle */
943
+ int addr;
944
+ int iTab;
945
+ int pseudoTab = 0;
946
+ ExprList pOrderBy = p.pOrderBy;
947
+
948
+ int eDest = pDest.eDest;
949
+ int iParm = pDest.iParm;
950
+
951
+ int regRow;
952
+ int regRowid;
953
+
954
+ iTab = pOrderBy.iECursor;
955
+ regRow = sqlite3GetTempReg( pParse );
956
+ if ( eDest == SRT_Output || eDest == SRT_Coroutine )
957
+ {
958
+ pseudoTab = pParse.nTab++;
959
+ sqlite3VdbeAddOp3( v, OP_OpenPseudo, pseudoTab, regRow, nColumn );
960
+ regRowid = 0;
961
+ }
962
+ else
963
+ {
964
+ regRowid = sqlite3GetTempReg( pParse );
965
+ }
966
+ addr = 1 + sqlite3VdbeAddOp2( v, OP_Sort, iTab, addrBreak );
967
+ codeOffset( v, p, addrContinue );
968
+ sqlite3VdbeAddOp3( v, OP_Column, iTab, pOrderBy.nExpr + 1, regRow );
969
+ switch ( eDest )
970
+ {
971
+ case SRT_Table:
972
+ case SRT_EphemTab:
973
+ {
974
+ testcase( eDest == SRT_Table );
975
+ testcase( eDest == SRT_EphemTab );
976
+ sqlite3VdbeAddOp2( v, OP_NewRowid, iParm, regRowid );
977
+ sqlite3VdbeAddOp3( v, OP_Insert, iParm, regRow, regRowid );
978
+ sqlite3VdbeChangeP5( v, OPFLAG_APPEND );
979
+ break;
980
+ }
981
+ #if !SQLITE_OMIT_SUBQUERY
982
+ case SRT_Set:
983
+ {
984
+ Debug.Assert( nColumn == 1 );
985
+ sqlite3VdbeAddOp4( v, OP_MakeRecord, regRow, 1, regRowid, p.affinity, 1 );
986
+ sqlite3ExprCacheAffinityChange( pParse, regRow, 1 );
987
+ sqlite3VdbeAddOp2( v, OP_IdxInsert, iParm, regRowid );
988
+ break;
989
+ }
990
+ case SRT_Mem:
991
+ {
992
+ Debug.Assert( nColumn == 1 );
993
+ sqlite3ExprCodeMove( pParse, regRow, iParm, 1 );
994
+ /* The LIMIT clause will terminate the loop for us */
995
+ break;
996
+ }
997
+ #endif
998
+ default:
999
+ {
1000
+ int i;
1001
+ Debug.Assert( eDest == SRT_Output || eDest == SRT_Coroutine );
1002
+ testcase( eDest == SRT_Output );
1003
+ testcase( eDest == SRT_Coroutine );
1004
+ for ( i = 0; i < nColumn; i++ )
1005
+ {
1006
+ Debug.Assert( regRow != pDest.iMem + i );
1007
+ sqlite3VdbeAddOp3( v, OP_Column, pseudoTab, i, pDest.iMem + i );
1008
+ if ( i == 0 )
1009
+ {
1010
+ sqlite3VdbeChangeP5( v, OPFLAG_CLEARCACHE );
1011
+ }
1012
+ }
1013
+ if ( eDest == SRT_Output )
1014
+ {
1015
+ sqlite3VdbeAddOp2( v, OP_ResultRow, pDest.iMem, nColumn );
1016
+ sqlite3ExprCacheAffinityChange( pParse, pDest.iMem, nColumn );
1017
+ }
1018
+ else
1019
+ {
1020
+ sqlite3VdbeAddOp1( v, OP_Yield, pDest.iParm );
1021
+ }
1022
+ break;
1023
+ }
1024
+ }
1025
+ sqlite3ReleaseTempReg( pParse, regRow );
1026
+ sqlite3ReleaseTempReg( pParse, regRowid );
1027
+
1028
+ /* LIMIT has been implemented by the pushOntoSorter() routine.
1029
+ */
1030
+ Debug.Assert( p.iLimit == 0 );
1031
+
1032
+ /* The bottom of the loop
1033
+ */
1034
+ sqlite3VdbeResolveLabel( v, addrContinue );
1035
+ sqlite3VdbeAddOp2( v, OP_Next, iTab, addr );
1036
+ sqlite3VdbeResolveLabel( v, addrBreak );
1037
+ if ( eDest == SRT_Output || eDest == SRT_Coroutine )
1038
+ {
1039
+ sqlite3VdbeAddOp2( v, OP_Close, pseudoTab, 0 );
1040
+ }
1041
+
1042
+ }
1043
+
1044
+ /*
1045
+ ** Return a pointer to a string containing the 'declaration type' of the
1046
+ ** expression pExpr. The string may be treated as static by the caller.
1047
+ **
1048
+ ** The declaration type is the exact datatype definition extracted from the
1049
+ ** original CREATE TABLE statement if the expression is a column. The
1050
+ ** declaration type for a ROWID field is INTEGER. Exactly when an expression
1051
+ ** is considered a column can be complex in the presence of subqueries. The
1052
+ ** result-set expression in all of the following SELECT statements is
1053
+ ** considered a column by this function.
1054
+ **
1055
+ ** SELECT col FROM tbl;
1056
+ ** SELECT (SELECT col FROM tbl;
1057
+ ** SELECT (SELECT col FROM tbl);
1058
+ ** SELECT abc FROM (SELECT col AS abc FROM tbl);
1059
+ **
1060
+ ** The declaration type for any expression other than a column is NULL.
1061
+ */
1062
+ static string columnType(
1063
+ NameContext pNC,
1064
+ Expr pExpr,
1065
+ ref string pzOriginDb,
1066
+ ref string pzOriginTab,
1067
+ ref string pzOriginCol
1068
+ )
1069
+ {
1070
+ string zType = null;
1071
+ string zOriginDb = null;
1072
+ string zOriginTab = null;
1073
+ string zOriginCol = null;
1074
+ int j;
1075
+ if ( NEVER( pExpr == null ) || pNC.pSrcList == null ) return null;
1076
+
1077
+ switch ( pExpr.op )
1078
+ {
1079
+ case TK_AGG_COLUMN:
1080
+ case TK_COLUMN:
1081
+ {
1082
+ /* The expression is a column. Locate the table the column is being
1083
+ ** extracted from in NameContext.pSrcList. This table may be real
1084
+ ** database table or a subquery.
1085
+ */
1086
+ Table pTab = null; /* Table structure column is extracted from */
1087
+ Select pS = null; /* Select the column is extracted from */
1088
+ int iCol = pExpr.iColumn; /* Index of column in pTab */
1089
+ testcase( pExpr.op == TK_AGG_COLUMN );
1090
+ testcase( pExpr.op == TK_COLUMN );
1091
+ while ( pNC != null && pTab == null )
1092
+ {
1093
+ SrcList pTabList = pNC.pSrcList;
1094
+ for ( j = 0; j < pTabList.nSrc && pTabList.a[j].iCursor != pExpr.iTable; j++ ) ;
1095
+ if ( j < pTabList.nSrc )
1096
+ {
1097
+ pTab = pTabList.a[j].pTab;
1098
+ pS = pTabList.a[j].pSelect;
1099
+ }
1100
+ else
1101
+ {
1102
+ pNC = pNC.pNext;
1103
+ }
1104
+ }
1105
+
1106
+ if ( pTab == null )
1107
+ {
1108
+ /* At one time, code such as "SELECT new.x" within a trigger would
1109
+ ** cause this condition to run. Since then, we have restructured how
1110
+ ** trigger code is generated and so this condition is no longer
1111
+ ** possible. However, it can still be true for statements like
1112
+ ** the following:
1113
+ **
1114
+ ** CREATE TABLE t1(col INTEGER);
1115
+ ** SELECT (SELECT t1.col) FROM FROM t1;
1116
+ **
1117
+ ** when columnType() is called on the expression "t1.col" in the
1118
+ ** sub-select. In this case, set the column type to NULL, even
1119
+ ** though it should really be "INTEGER".
1120
+ **
1121
+ ** This is not a problem, as the column type of "t1.col" is never
1122
+ ** used. When columnType() is called on the expression
1123
+ ** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT
1124
+ ** branch below. */
1125
+ break;
1126
+ }
1127
+
1128
+ //Debug.Assert( pTab != null && pExpr.pTab == pTab );
1129
+ if ( pS != null )
1130
+ {
1131
+ /* The "table" is actually a sub-select or a view in the FROM clause
1132
+ ** of the SELECT statement. Return the declaration type and origin
1133
+ ** data for the result-set column of the sub-select.
1134
+ */
1135
+ if ( iCol >= 0 && ALWAYS( iCol < pS.pEList.nExpr ) )
1136
+ {
1137
+ /* If iCol is less than zero, then the expression requests the
1138
+ ** rowid of the sub-select or view. This expression is legal (see
1139
+ ** test case misc2.2.2) - it always evaluates to NULL.
1140
+ */
1141
+ NameContext sNC = new NameContext();
1142
+ Expr p = pS.pEList.a[iCol].pExpr;
1143
+ sNC.pSrcList = pS.pSrc;
1144
+ sNC.pNext = pNC;
1145
+ sNC.pParse = pNC.pParse;
1146
+ zType = columnType( sNC, p, ref zOriginDb, ref zOriginTab, ref zOriginCol );
1147
+ }
1148
+ }
1149
+ else if ( ALWAYS( pTab.pSchema ) )
1150
+ {
1151
+ /* A real table */
1152
+ Debug.Assert( pS == null );
1153
+ if ( iCol < 0 ) iCol = pTab.iPKey;
1154
+ Debug.Assert( iCol == -1 || ( iCol >= 0 && iCol < pTab.nCol ) );
1155
+ if ( iCol < 0 )
1156
+ {
1157
+ zType = "INTEGER";
1158
+ zOriginCol = "rowid";
1159
+ }
1160
+ else
1161
+ {
1162
+ zType = pTab.aCol[iCol].zType;
1163
+ zOriginCol = pTab.aCol[iCol].zName;
1164
+ }
1165
+ zOriginTab = pTab.zName;
1166
+ if ( pNC.pParse != null )
1167
+ {
1168
+ int iDb = sqlite3SchemaToIndex( pNC.pParse.db, pTab.pSchema );
1169
+ zOriginDb = pNC.pParse.db.aDb[iDb].zName;
1170
+ }
1171
+ }
1172
+ break;
1173
+ }
1174
+ #if !SQLITE_OMIT_SUBQUERY
1175
+ case TK_SELECT:
1176
+ {
1177
+ /* The expression is a sub-select. Return the declaration type and
1178
+ ** origin info for the single column in the result set of the SELECT
1179
+ ** statement.
1180
+ */
1181
+ NameContext sNC = new NameContext();
1182
+ Select pS = pExpr.x.pSelect;
1183
+ Expr p = pS.pEList.a[0].pExpr;
1184
+ Debug.Assert( ExprHasProperty( pExpr, EP_xIsSelect ) );
1185
+ sNC.pSrcList = pS.pSrc;
1186
+ sNC.pNext = pNC;
1187
+ sNC.pParse = pNC.pParse;
1188
+ zType = columnType( sNC, p, ref zOriginDb, ref zOriginTab, ref zOriginCol );
1189
+ break;
1190
+ }
1191
+ #endif
1192
+ }
1193
+
1194
+ if ( pzOriginDb != null )
1195
+ {
1196
+ Debug.Assert( pzOriginTab != null && pzOriginCol != null );
1197
+ pzOriginDb = zOriginDb;
1198
+ pzOriginTab = zOriginTab;
1199
+ pzOriginCol = zOriginCol;
1200
+ }
1201
+ return zType;
1202
+ }
1203
+
1204
+ /*
1205
+ ** Generate code that will tell the VDBE the declaration types of columns
1206
+ ** in the result set.
1207
+ */
1208
+ static void generateColumnTypes(
1209
+ Parse pParse, /* Parser context */
1210
+ SrcList pTabList, /* List of tables */
1211
+ ExprList pEList /* Expressions defining the result set */
1212
+ )
1213
+ {
1214
+ #if !SQLITE_OMIT_DECLTYPE
1215
+ Vdbe v = pParse.pVdbe;
1216
+ int i;
1217
+ NameContext sNC = new NameContext();
1218
+ sNC.pSrcList = pTabList;
1219
+ sNC.pParse = pParse;
1220
+ for ( i = 0; i < pEList.nExpr; i++ )
1221
+ {
1222
+ Expr p = pEList.a[i].pExpr;
1223
+ string zType;
1224
+ #if SQLITE_ENABLE_COLUMN_METADATA
1225
+ const string zOrigDb = 0;
1226
+ const string zOrigTab = 0;
1227
+ const string zOrigCol = 0;
1228
+ zType = columnType(&sNC, p, zOrigDb, zOrigTab, zOrigCol);
1229
+
1230
+ /* The vdbe must make its own copy of the column-type and other
1231
+ ** column specific strings, in case the schema is reset before this
1232
+ ** virtual machine is deleted.
1233
+ */
1234
+ sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT);
1235
+ sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
1236
+ sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
1237
+ #else
1238
+ string sDummy = null;
1239
+ zType = columnType( sNC, p, ref sDummy, ref sDummy, ref sDummy );
1240
+ #endif
1241
+ sqlite3VdbeSetColName( v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT );
1242
+ }
1243
+ #endif //* SQLITE_OMIT_DECLTYPE */
1244
+ }
1245
+
1246
+ /*
1247
+ ** Generate code that will tell the VDBE the names of columns
1248
+ ** in the result set. This information is used to provide the
1249
+ ** azCol[] values in the callback.
1250
+ */
1251
+ static void generateColumnNames(
1252
+ Parse pParse, /* Parser context */
1253
+ SrcList pTabList, /* List of tables */
1254
+ ExprList pEList /* Expressions defining the result set */
1255
+ )
1256
+ {
1257
+ Vdbe v = pParse.pVdbe;
1258
+ int i, j;
1259
+ sqlite3 db = pParse.db;
1260
+ bool fullNames; bool shortNames;
1261
+
1262
+ #if !SQLITE_OMIT_EXPLAIN
1263
+ /* If this is an EXPLAIN, skip this step */
1264
+ if ( pParse.explain != 0 )
1265
+ {
1266
+ return;
1267
+ }
1268
+ #endif
1269
+
1270
+ if ( pParse.colNamesSet != 0 || NEVER( v == null ) /*|| db.mallocFailed != 0 */ ) return;
1271
+ pParse.colNamesSet = 1;
1272
+ fullNames = ( db.flags & SQLITE_FullColNames ) != 0;
1273
+ shortNames = ( db.flags & SQLITE_ShortColNames ) != 0;
1274
+ sqlite3VdbeSetNumCols( v, pEList.nExpr );
1275
+ for ( i = 0; i < pEList.nExpr; i++ )
1276
+ {
1277
+ Expr p;
1278
+ p = pEList.a[i].pExpr;
1279
+ if ( NEVER( p == null ) ) continue;
1280
+ if ( pEList.a[i].zName != null )
1281
+ {
1282
+ string zName = pEList.a[i].zName;
1283
+ sqlite3VdbeSetColName( v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT );
1284
+ }
1285
+ else if ( ( p.op == TK_COLUMN || p.op == TK_AGG_COLUMN ) && pTabList != null )
1286
+ {
1287
+ Table pTab;
1288
+ string zCol;
1289
+ int iCol = p.iColumn;
1290
+ for ( j = 0; ALWAYS( j < pTabList.nSrc ); j++ )
1291
+ {
1292
+ if ( pTabList.a[j].iCursor == p.iTable ) break;
1293
+ }
1294
+ Debug.Assert( j < pTabList.nSrc );
1295
+ pTab = pTabList.a[j].pTab;
1296
+ if ( iCol < 0 ) iCol = pTab.iPKey;
1297
+ Debug.Assert( iCol == -1 || ( iCol >= 0 && iCol < pTab.nCol ) );
1298
+ if ( iCol < 0 )
1299
+ {
1300
+ zCol = "rowid";
1301
+ }
1302
+ else
1303
+ {
1304
+ zCol = pTab.aCol[iCol].zName;
1305
+ }
1306
+ if ( !shortNames && !fullNames )
1307
+ {
1308
+ sqlite3VdbeSetColName( v, i, COLNAME_NAME,
1309
+ pEList.a[i].zSpan, SQLITE_DYNAMIC );//sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
1310
+ }
1311
+ else if ( fullNames )
1312
+ {
1313
+ string zName;
1314
+ zName = sqlite3MPrintf( db, "%s.%s", pTab.zName, zCol );
1315
+ sqlite3VdbeSetColName( v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC );
1316
+ }
1317
+ else
1318
+ {
1319
+ sqlite3VdbeSetColName( v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT );
1320
+ }
1321
+ }
1322
+ else
1323
+ {
1324
+ sqlite3VdbeSetColName( v, i, COLNAME_NAME,
1325
+ pEList.a[i].zSpan, SQLITE_DYNAMIC );//sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
1326
+ }
1327
+ }
1328
+ generateColumnTypes( pParse, pTabList, pEList );
1329
+ }
1330
+
1331
+ #if !SQLITE_OMIT_COMPOUND_SELECT
1332
+ /*
1333
+ ** Name of the connection operator, used for error messages.
1334
+ */
1335
+ static string selectOpName( int id )
1336
+ {
1337
+ string z;
1338
+ switch ( id )
1339
+ {
1340
+ case TK_ALL: z = "UNION ALL"; break;
1341
+ case TK_INTERSECT: z = "INTERSECT"; break;
1342
+ case TK_EXCEPT: z = "EXCEPT"; break;
1343
+ default: z = "UNION"; break;
1344
+ }
1345
+ return z;
1346
+ }
1347
+ #endif // * SQLITE_OMIT_COMPOUND_SELECT */
1348
+
1349
+ /*
1350
+ ** Given a an expression list (which is really the list of expressions
1351
+ ** that form the result set of a SELECT statement) compute appropriate
1352
+ ** column names for a table that would hold the expression list.
1353
+ **
1354
+ ** All column names will be unique.
1355
+ **
1356
+ ** Only the column names are computed. Column.zType, Column.zColl,
1357
+ ** and other fields of Column are zeroed.
1358
+ **
1359
+ ** Return SQLITE_OK on success. If a memory allocation error occurs,
1360
+ ** store NULL in paCol and 0 in pnCol and return SQLITE_NOMEM.
1361
+ */
1362
+ static int selectColumnsFromExprList(
1363
+ Parse pParse, /* Parsing context */
1364
+ ExprList pEList, /* Expr list from which to derive column names */
1365
+ ref int pnCol, /* Write the number of columns here */
1366
+ ref Column[] paCol /* Write the new column list here */
1367
+ )
1368
+ {
1369
+ sqlite3 db = pParse.db; /* Database connection */
1370
+ int i, j; /* Loop counters */
1371
+ int cnt; /* Index added to make the name unique */
1372
+ Column[] aCol; Column pCol; /* For looping over result columns */
1373
+ int nCol; /* Number of columns in the result set */
1374
+ Expr p; /* Expression for a single result column */
1375
+ string zName; /* Column name */
1376
+ int nName; /* Size of name in zName[] */
1377
+
1378
+
1379
+ pnCol = nCol = pEList.nExpr;
1380
+ aCol = paCol = new Column[nCol];//sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
1381
+ if ( aCol == null ) return SQLITE_NOMEM;
1382
+ for ( i = 0; i < nCol; i++ )//, pCol++)
1383
+ {
1384
+ if ( aCol[i] == null ) aCol[i] = new Column();
1385
+ pCol = aCol[i];
1386
+ /* Get an appropriate name for the column
1387
+ */
1388
+ p = pEList.a[i].pExpr;
1389
+ Debug.Assert( p.pRight == null || ExprHasProperty( p.pRight, EP_IntValue )
1390
+ || p.pRight.u.zToken == null || p.pRight.u.zToken.Length > 0 );
1391
+ if ( pEList.a[i].zName != null && ( zName = pEList.a[i].zName ) != "" )
1392
+ {
1393
+ /* If the column contains an "AS <name>" phrase, use <name> as the name */
1394
+ //zName = sqlite3DbStrDup(db, zName);
1395
+ }
1396
+ else
1397
+ {
1398
+ Expr pColExpr = p; /* The expression that is the result column name */
1399
+ Table pTab; /* Table associated with this expression */
1400
+ while ( pColExpr.op == TK_DOT ) pColExpr = pColExpr.pRight;
1401
+ if ( pColExpr.op == TK_COLUMN && ALWAYS( pColExpr.pTab != null ) )
1402
+ {
1403
+ /* For columns use the column name name */
1404
+ int iCol = pColExpr.iColumn;
1405
+ pTab = pColExpr.pTab;
1406
+ if ( iCol < 0 ) iCol = pTab.iPKey;
1407
+ zName = sqlite3MPrintf( db, "%s",
1408
+ iCol >= 0 ? pTab.aCol[iCol].zName : "rowid" );
1409
+ }
1410
+ else if ( pColExpr.op == TK_ID )
1411
+ {
1412
+ Debug.Assert( !ExprHasProperty( pColExpr, EP_IntValue ) );
1413
+ zName = sqlite3MPrintf( db, "%s", pColExpr.u.zToken );
1414
+ }
1415
+ else
1416
+ {
1417
+ /* Use the original text of the column expression as its name */
1418
+ zName = sqlite3MPrintf( db, "%s", pEList.a[i].zSpan );
1419
+ }
1420
+ }
1421
+ //if ( db.mallocFailed != 0 )
1422
+ //{
1423
+ // sqlite3DbFree( db, ref zName );
1424
+ // break;
1425
+ //}
1426
+
1427
+ /* Make sure the column name is unique. If the name is not unique,
1428
+ ** append a integer to the name so that it becomes unique.
1429
+ */
1430
+ nName = sqlite3Strlen30( zName );
1431
+ for ( j = cnt = 0; j < i; j++ )
1432
+ {
1433
+ if ( sqlite3StrICmp( aCol[j].zName, zName ) == 0 )
1434
+ {
1435
+ string zNewName;
1436
+ //zName[nName] = 0;
1437
+ zNewName = sqlite3MPrintf( db, "%s:%d", zName.Substring( 0, nName ), ++cnt );
1438
+ sqlite3DbFree( db, ref zName );
1439
+ zName = zNewName;
1440
+ j = -1;
1441
+ if ( zName == "" ) break;
1442
+ }
1443
+ }
1444
+ pCol.zName = zName;
1445
+ }
1446
+ //if ( db.mallocFailed != 0 )
1447
+ //{
1448
+ // for ( j = 0 ; j < i ; j++ )
1449
+ // {
1450
+ // sqlite3DbFree( db, aCol[j].zName );
1451
+ // }
1452
+ // sqlite3DbFree( db, aCol );
1453
+ // paCol = null;
1454
+ // pnCol = 0;
1455
+ // return SQLITE_NOMEM;
1456
+ //}
1457
+ return SQLITE_OK;
1458
+ }
1459
+
1460
+ /*
1461
+ ** Add type and collation information to a column list based on
1462
+ ** a SELECT statement.
1463
+ **
1464
+ ** The column list presumably came from selectColumnNamesFromExprList().
1465
+ ** The column list has only names, not types or collations. This
1466
+ ** routine goes through and adds the types and collations.
1467
+ **
1468
+ ** This routine requires that all identifiers in the SELECT
1469
+ ** statement be resolved.
1470
+ */
1471
+ static void selectAddColumnTypeAndCollation(
1472
+ Parse pParse, /* Parsing contexts */
1473
+ int nCol, /* Number of columns */
1474
+ Column[] aCol, /* List of columns */
1475
+ Select pSelect /* SELECT used to determine types and collations */
1476
+ )
1477
+ {
1478
+ sqlite3 db = pParse.db;
1479
+ NameContext sNC;
1480
+ Column pCol;
1481
+ CollSeq pColl;
1482
+ int i;
1483
+ Expr p;
1484
+ ExprList_item[] a;
1485
+
1486
+ Debug.Assert( pSelect != null );
1487
+ Debug.Assert( ( pSelect.selFlags & SF_Resolved ) != 0 );
1488
+ Debug.Assert( nCol == pSelect.pEList.nExpr /*|| db.mallocFailed != 0 */ );
1489
+ // if ( db.mallocFailed != 0 ) return;
1490
+ sNC = new NameContext();// memset( &sNC, 0, sizeof( sNC ) );
1491
+ sNC.pSrcList = pSelect.pSrc;
1492
+ a = pSelect.pEList.a;
1493
+ for ( i = 0; i < nCol; i++ )//, pCol++ )
1494
+ {
1495
+ pCol = aCol[i];
1496
+ p = a[i].pExpr;
1497
+ string bDummy = null; pCol.zType = columnType( sNC, p, ref bDummy, ref bDummy, ref bDummy );// sqlite3DbStrDup( db, columnType( sNC, p, 0, 0, 0 ) );
1498
+ pCol.affinity = sqlite3ExprAffinity( p );
1499
+ if ( pCol.affinity == 0 ) pCol.affinity = SQLITE_AFF_NONE;
1500
+ pColl = sqlite3ExprCollSeq( pParse, p );
1501
+ if ( pColl != null )
1502
+ {
1503
+ pCol.zColl = pColl.zName;// sqlite3DbStrDup( db, pColl.zName );
1504
+ }
1505
+ }
1506
+ }
1507
+
1508
+ /*
1509
+ ** Given a SELECT statement, generate a Table structure that describes
1510
+ ** the result set of that SELECT.
1511
+ */
1512
+ static Table sqlite3ResultSetOfSelect( Parse pParse, Select pSelect )
1513
+ {
1514
+ Table pTab;
1515
+ sqlite3 db = pParse.db;
1516
+ int savedFlags;
1517
+
1518
+ savedFlags = db.flags;
1519
+ db.flags &= ~SQLITE_FullColNames;
1520
+ db.flags |= SQLITE_ShortColNames;
1521
+ sqlite3SelectPrep( pParse, pSelect, null );
1522
+ if ( pParse.nErr != 0 ) return null;
1523
+ while ( pSelect.pPrior != null ) pSelect = pSelect.pPrior;
1524
+ db.flags = savedFlags;
1525
+ pTab = new Table();// sqlite3DbMallocZero( db, sizeof( Table ) );
1526
+ if ( pTab == null )
1527
+ {
1528
+ return null;
1529
+ }
1530
+ /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
1531
+ ** is disabled, so we might as well hard-code pTab->dbMem to NULL. */
1532
+ Debug.Assert( db.lookaside.bEnabled == 0 );
1533
+ pTab.dbMem = null;
1534
+ pTab.nRef = 1;
1535
+ pTab.zName = null;
1536
+ selectColumnsFromExprList( pParse, pSelect.pEList, ref pTab.nCol, ref pTab.aCol );
1537
+ selectAddColumnTypeAndCollation( pParse, pTab.nCol, pTab.aCol, pSelect );
1538
+ pTab.iPKey = -1;
1539
+ //if ( db.mallocFailed != 0 )
1540
+ //{
1541
+ // sqlite3DeleteTable( ref pTab );
1542
+ // return null;
1543
+ //}
1544
+ return pTab;
1545
+ }
1546
+
1547
+ /*
1548
+ ** Get a VDBE for the given parser context. Create a new one if necessary.
1549
+ ** If an error occurs, return NULL and leave a message in pParse.
1550
+ */
1551
+ static Vdbe sqlite3GetVdbe( Parse pParse )
1552
+ {
1553
+ Vdbe v = pParse.pVdbe;
1554
+ if ( v == null )
1555
+ {
1556
+ v = pParse.pVdbe = sqlite3VdbeCreate( pParse.db );
1557
+ #if !SQLITE_OMIT_TRACE
1558
+ if ( v != null )
1559
+ {
1560
+ sqlite3VdbeAddOp0( v, OP_Trace );
1561
+ }
1562
+ #endif
1563
+ }
1564
+ return v;
1565
+ }
1566
+
1567
+
1568
+ /*
1569
+ ** Compute the iLimit and iOffset fields of the SELECT based on the
1570
+ ** pLimit and pOffset expressions. pLimit and pOffset hold the expressions
1571
+ ** that appear in the original SQL statement after the LIMIT and OFFSET
1572
+ ** keywords. Or NULL if those keywords are omitted. iLimit and iOffset
1573
+ ** are the integer memory register numbers for counters used to compute
1574
+ ** the limit and offset. If there is no limit and/or offset, then
1575
+ ** iLimit and iOffset are negative.
1576
+ **
1577
+ ** This routine changes the values of iLimit and iOffset only if
1578
+ ** a limit or offset is defined by pLimit and pOffset. iLimit and
1579
+ ** iOffset should have been preset to appropriate default values
1580
+ ** (usually but not always -1) prior to calling this routine.
1581
+ ** Only if pLimit!=0 or pOffset!=0 do the limit registers get
1582
+ ** redefined. The UNION ALL operator uses this property to force
1583
+ ** the reuse of the same limit and offset registers across multiple
1584
+ ** SELECT statements.
1585
+ */
1586
+ static void computeLimitRegisters( Parse pParse, Select p, int iBreak )
1587
+ {
1588
+ Vdbe v = null;
1589
+ int iLimit = 0;
1590
+ int iOffset;
1591
+ int addr1, n = 0;
1592
+ if ( p.iLimit != 0 ) return;
1593
+
1594
+ /*
1595
+ ** "LIMIT -1" always shows all rows. There is some
1596
+ ** contraversy about what the correct behavior should be.
1597
+ ** The current implementation interprets "LIMIT 0" to mean
1598
+ ** no rows.
1599
+ */
1600
+ sqlite3ExprCacheClear( pParse );
1601
+ Debug.Assert( p.pOffset == null || p.pLimit != null );
1602
+ if ( p.pLimit != null )
1603
+ {
1604
+ p.iLimit = iLimit = ++pParse.nMem;
1605
+ v = sqlite3GetVdbe( pParse );
1606
+ if ( NEVER( v == null ) ) return; /* VDBE should have already been allocated */
1607
+ if ( sqlite3ExprIsInteger( p.pLimit, ref n ) != 0 )
1608
+ {
1609
+ sqlite3VdbeAddOp2( v, OP_Integer, n, iLimit );
1610
+ VdbeComment( v, "LIMIT counter" );
1611
+ if ( n == 0 )
1612
+ {
1613
+ sqlite3VdbeAddOp2( v, OP_Goto, 0, iBreak );
1614
+ }
1615
+ }
1616
+ else
1617
+ {
1618
+ sqlite3ExprCode( pParse, p.pLimit, iLimit );
1619
+ sqlite3VdbeAddOp1( v, OP_MustBeInt, iLimit );
1620
+ #if SQLITE_DEBUG
1621
+ VdbeComment( v, "LIMIT counter" );
1622
+ #endif
1623
+ sqlite3VdbeAddOp2( v, OP_IfZero, iLimit, iBreak );
1624
+ }
1625
+ if ( p.pOffset != null )
1626
+ {
1627
+ p.iOffset = iOffset = ++pParse.nMem;
1628
+ pParse.nMem++; /* Allocate an extra register for limit+offset */
1629
+ sqlite3ExprCode( pParse, p.pOffset, iOffset );
1630
+ sqlite3VdbeAddOp1( v, OP_MustBeInt, iOffset );
1631
+ #if SQLITE_DEBUG
1632
+ VdbeComment( v, "OFFSET counter" );
1633
+ #endif
1634
+ addr1 = sqlite3VdbeAddOp1( v, OP_IfPos, iOffset );
1635
+ sqlite3VdbeAddOp2( v, OP_Integer, 0, iOffset );
1636
+ sqlite3VdbeJumpHere( v, addr1 );
1637
+ sqlite3VdbeAddOp3( v, OP_Add, iLimit, iOffset, iOffset + 1 );
1638
+ #if SQLITE_DEBUG
1639
+ VdbeComment( v, "LIMIT+OFFSET" );
1640
+ #endif
1641
+ addr1 = sqlite3VdbeAddOp1( v, OP_IfPos, iLimit );
1642
+ sqlite3VdbeAddOp2( v, OP_Integer, -1, iOffset + 1 );
1643
+ sqlite3VdbeJumpHere( v, addr1 );
1644
+ }
1645
+ }
1646
+ }
1647
+
1648
+ #if !SQLITE_OMIT_COMPOUND_SELECT
1649
+ /*
1650
+ ** Return the appropriate collating sequence for the iCol-th column of
1651
+ ** the result set for the compound-select statement "p". Return NULL if
1652
+ ** the column has no default collating sequence.
1653
+ **
1654
+ ** The collating sequence for the compound select is taken from the
1655
+ ** left-most term of the select that has a collating sequence.
1656
+ */
1657
+ static CollSeq multiSelectCollSeq( Parse pParse, Select p, int iCol )
1658
+ {
1659
+ CollSeq pRet;
1660
+ if ( p.pPrior != null )
1661
+ {
1662
+ pRet = multiSelectCollSeq( pParse, p.pPrior, iCol );
1663
+ }
1664
+ else
1665
+ {
1666
+ pRet = null;
1667
+ }
1668
+ Debug.Assert( iCol >= 0 );
1669
+ if ( pRet == null && iCol < p.pEList.nExpr )
1670
+ {
1671
+ pRet = sqlite3ExprCollSeq( pParse, p.pEList.a[iCol].pExpr );
1672
+ }
1673
+ return pRet;
1674
+ }
1675
+ #endif // * SQLITE_OMIT_COMPOUND_SELECT */
1676
+
1677
+ /* Forward reference */
1678
+ //static int multiSelectOrderBy(
1679
+ // Parse* pParse, /* Parsing context */
1680
+ // Select* p, /* The right-most of SELECTs to be coded */
1681
+ // SelectDest* pDest /* What to do with query results */
1682
+ //);
1683
+
1684
+ #if !SQLITE_OMIT_COMPOUND_SELECT
1685
+ /*
1686
+ ** This routine is called to process a compound query form from
1687
+ ** two or more separate queries using UNION, UNION ALL, EXCEPT, or
1688
+ ** INTERSECT
1689
+ **
1690
+ ** "p" points to the right-most of the two queries. the query on the
1691
+ ** left is p.pPrior. The left query could also be a compound query
1692
+ ** in which case this routine will be called recursively.
1693
+ **
1694
+ ** The results of the total query are to be written into a destination
1695
+ ** of type eDest with parameter iParm.
1696
+ **
1697
+ ** Example 1: Consider a three-way compound SQL statement.
1698
+ **
1699
+ ** SELECT a FROM t1 UNION SELECT b FROM t2 UNION SELECT c FROM t3
1700
+ **
1701
+ ** This statement is parsed up as follows:
1702
+ **
1703
+ ** SELECT c FROM t3
1704
+ ** |
1705
+ ** `----. SELECT b FROM t2
1706
+ ** |
1707
+ ** `-----. SELECT a FROM t1
1708
+ **
1709
+ ** The arrows in the diagram above represent the Select.pPrior pointer.
1710
+ ** So if this routine is called with p equal to the t3 query, then
1711
+ ** pPrior will be the t2 query. p.op will be TK_UNION in this case.
1712
+ **
1713
+ ** Notice that because of the way SQLite parses compound SELECTs, the
1714
+ ** individual selects always group from left to right.
1715
+ */
1716
+ static int multiSelect(
1717
+ Parse pParse, /* Parsing context */
1718
+ Select p, /* The right-most of SELECTs to be coded */
1719
+ SelectDest pDest /* What to do with query results */
1720
+ )
1721
+ {
1722
+ int rc = SQLITE_OK; /* Success code from a subroutine */
1723
+ Select pPrior; /* Another SELECT immediately to our left */
1724
+ Vdbe v; /* Generate code to this VDBE */
1725
+ SelectDest dest = new SelectDest(); /* Alternative data destination */
1726
+ Select pDelete = null; /* Chain of simple selects to delete */
1727
+ sqlite3 db; /* Database connection */
1728
+
1729
+ /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only
1730
+ ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
1731
+ */
1732
+ Debug.Assert( p != null && p.pPrior != null ); /* Calling function guarantees this much */
1733
+ db = pParse.db;
1734
+ pPrior = p.pPrior;
1735
+ Debug.Assert( pPrior.pRightmost != pPrior );
1736
+ Debug.Assert( pPrior.pRightmost == p.pRightmost );
1737
+ dest = pDest;
1738
+ if ( pPrior.pOrderBy != null )
1739
+ {
1740
+ sqlite3ErrorMsg( pParse, "ORDER BY clause should come after %s not before",
1741
+ selectOpName( p.op ) );
1742
+ rc = 1;
1743
+ goto multi_select_end;
1744
+ }
1745
+ if ( pPrior.pLimit != null )
1746
+ {
1747
+ sqlite3ErrorMsg( pParse, "LIMIT clause should come after %s not before",
1748
+ selectOpName( p.op ) );
1749
+ rc = 1;
1750
+ goto multi_select_end;
1751
+ }
1752
+
1753
+ v = sqlite3GetVdbe( pParse );
1754
+ Debug.Assert( v != null ); /* The VDBE already created by calling function */
1755
+
1756
+ /* Create the destination temporary table if necessary
1757
+ */
1758
+ if ( dest.eDest == SRT_EphemTab )
1759
+ {
1760
+ Debug.Assert( p.pEList != null );
1761
+ sqlite3VdbeAddOp2( v, OP_OpenEphemeral, dest.iParm, p.pEList.nExpr );
1762
+ dest.eDest = SRT_Table;
1763
+ }
1764
+
1765
+ /* Make sure all SELECTs in the statement have the same number of elements
1766
+ ** in their result sets.
1767
+ */
1768
+ Debug.Assert( p.pEList != null && pPrior.pEList != null );
1769
+ if ( p.pEList.nExpr != pPrior.pEList.nExpr )
1770
+ {
1771
+ sqlite3ErrorMsg( pParse, "SELECTs to the left and right of %s" +
1772
+ " do not have the same number of result columns", selectOpName( p.op ) );
1773
+ rc = 1;
1774
+ goto multi_select_end;
1775
+ }
1776
+
1777
+ /* Compound SELECTs that have an ORDER BY clause are handled separately.
1778
+ */
1779
+ if ( p.pOrderBy != null )
1780
+ {
1781
+ return multiSelectOrderBy( pParse, p, pDest );
1782
+ }
1783
+
1784
+ /* Generate code for the left and right SELECT statements.
1785
+ */
1786
+ switch ( p.op )
1787
+ {
1788
+ case TK_ALL:
1789
+ {
1790
+ int addr = 0;
1791
+ Debug.Assert( pPrior.pLimit == null );
1792
+ pPrior.pLimit = p.pLimit;
1793
+ pPrior.pOffset = p.pOffset;
1794
+ rc = sqlite3Select( pParse, pPrior, ref dest );
1795
+ p.pLimit = null;
1796
+ p.pOffset = null;
1797
+ if ( rc != 0 )
1798
+ {
1799
+ goto multi_select_end;
1800
+ }
1801
+ p.pPrior = null;
1802
+ p.iLimit = pPrior.iLimit;
1803
+ p.iOffset = pPrior.iOffset;
1804
+ if ( p.iLimit != 0 )
1805
+ {
1806
+ addr = sqlite3VdbeAddOp1( v, OP_IfZero, p.iLimit );
1807
+ #if SQLITE_DEBUG
1808
+ VdbeComment( v, "Jump ahead if LIMIT reached" );
1809
+ #endif
1810
+ }
1811
+ rc = sqlite3Select( pParse, p, ref dest );
1812
+ testcase( rc != SQLITE_OK );
1813
+ pDelete = p.pPrior;
1814
+ p.pPrior = pPrior;
1815
+ if ( addr != 0 )
1816
+ {
1817
+ sqlite3VdbeJumpHere( v, addr );
1818
+ }
1819
+ break;
1820
+ }
1821
+ case TK_EXCEPT:
1822
+ case TK_UNION:
1823
+ {
1824
+ int unionTab; /* VdbeCursor number of the temporary table holding result */
1825
+ u8 op = 0; /* One of the SRT_ operations to apply to self */
1826
+ int priorOp; /* The SRT_ operation to apply to prior selects */
1827
+ Expr pLimit, pOffset; /* Saved values of p.nLimit and p.nOffset */
1828
+ int addr;
1829
+ SelectDest uniondest = new SelectDest();
1830
+
1831
+ testcase( p.op == TK_EXCEPT );
1832
+ testcase( p.op == TK_UNION );
1833
+ priorOp = SRT_Union;
1834
+ if ( dest.eDest == priorOp && ALWAYS( null == p.pLimit && null == p.pOffset ) )
1835
+ {
1836
+ /* We can reuse a temporary table generated by a SELECT to our
1837
+ ** right.
1838
+ */
1839
+ Debug.Assert( p.pRightmost != p ); /* Can only happen for leftward elements
1840
+ ** of a 3-way or more compound */
1841
+ Debug.Assert( p.pLimit == null ); /* Not allowed on leftward elements */
1842
+ Debug.Assert( p.pOffset == null ); /* Not allowed on leftward elements */
1843
+ unionTab = dest.iParm;
1844
+ }
1845
+ else
1846
+ {
1847
+ /* We will need to create our own temporary table to hold the
1848
+ ** intermediate results.
1849
+ */
1850
+ unionTab = pParse.nTab++;
1851
+ Debug.Assert( p.pOrderBy == null );
1852
+ addr = sqlite3VdbeAddOp2( v, OP_OpenEphemeral, unionTab, 0 );
1853
+ Debug.Assert( p.addrOpenEphm[0] == -1 );
1854
+ p.addrOpenEphm[0] = addr;
1855
+ p.pRightmost.selFlags |= SF_UsesEphemeral;
1856
+ Debug.Assert( p.pEList != null );
1857
+ }
1858
+
1859
+ /* Code the SELECT statements to our left
1860
+ */
1861
+ Debug.Assert( pPrior.pOrderBy == null );
1862
+ sqlite3SelectDestInit( uniondest, priorOp, unionTab );
1863
+ rc = sqlite3Select( pParse, pPrior, ref uniondest );
1864
+ if ( rc != 0 )
1865
+ {
1866
+ goto multi_select_end;
1867
+ }
1868
+
1869
+ /* Code the current SELECT statement
1870
+ */
1871
+ if ( p.op == TK_EXCEPT )
1872
+ {
1873
+ op = SRT_Except;
1874
+ }
1875
+ else
1876
+ {
1877
+ Debug.Assert( p.op == TK_UNION );
1878
+ op = SRT_Union;
1879
+ }
1880
+ p.pPrior = null;
1881
+ pLimit = p.pLimit;
1882
+ p.pLimit = null;
1883
+ pOffset = p.pOffset;
1884
+ p.pOffset = null;
1885
+ uniondest.eDest = op;
1886
+ rc = sqlite3Select( pParse, p, ref uniondest );
1887
+ testcase( rc != SQLITE_OK );
1888
+ /* Query flattening in sqlite3Select() might refill p.pOrderBy.
1889
+ ** Be sure to delete p.pOrderBy, therefore, to avoid a memory leak. */
1890
+ sqlite3ExprListDelete( db, ref p.pOrderBy );
1891
+ pDelete = p.pPrior;
1892
+ p.pPrior = pPrior;
1893
+ p.pOrderBy = null;
1894
+ sqlite3ExprDelete( db, ref p.pLimit );
1895
+ p.pLimit = pLimit;
1896
+ p.pOffset = pOffset;
1897
+ p.iLimit = 0;
1898
+ p.iOffset = 0;
1899
+
1900
+ /* Convert the data in the temporary table into whatever form
1901
+ ** it is that we currently need.
1902
+ */
1903
+ Debug.Assert( unionTab == dest.iParm || dest.eDest != priorOp );
1904
+ if ( dest.eDest != priorOp )
1905
+ {
1906
+ int iCont, iBreak, iStart;
1907
+ Debug.Assert( p.pEList != null );
1908
+ if ( dest.eDest == SRT_Output )
1909
+ {
1910
+ Select pFirst = p;
1911
+ while ( pFirst.pPrior != null ) pFirst = pFirst.pPrior;
1912
+ generateColumnNames( pParse, null, pFirst.pEList );
1913
+ }
1914
+ iBreak = sqlite3VdbeMakeLabel( v );
1915
+ iCont = sqlite3VdbeMakeLabel( v );
1916
+ computeLimitRegisters( pParse, p, iBreak );
1917
+ sqlite3VdbeAddOp2( v, OP_Rewind, unionTab, iBreak );
1918
+ iStart = sqlite3VdbeCurrentAddr( v );
1919
+ selectInnerLoop( pParse, p, p.pEList, unionTab, p.pEList.nExpr,
1920
+ null, -1, dest, iCont, iBreak );
1921
+ sqlite3VdbeResolveLabel( v, iCont );
1922
+ sqlite3VdbeAddOp2( v, OP_Next, unionTab, iStart );
1923
+ sqlite3VdbeResolveLabel( v, iBreak );
1924
+ sqlite3VdbeAddOp2( v, OP_Close, unionTab, 0 );
1925
+ }
1926
+ break;
1927
+ }
1928
+ default: Debug.Assert( p.op == TK_INTERSECT );
1929
+ {
1930
+ int tab1, tab2;
1931
+ int iCont, iBreak, iStart;
1932
+ Expr pLimit, pOffset;
1933
+ int addr;
1934
+ SelectDest intersectdest = new SelectDest();
1935
+ int r1;
1936
+
1937
+ /* INTERSECT is different from the others since it requires
1938
+ ** two temporary tables. Hence it has its own case. Begin
1939
+ ** by allocating the tables we will need.
1940
+ */
1941
+ tab1 = pParse.nTab++;
1942
+ tab2 = pParse.nTab++;
1943
+ Debug.Assert( p.pOrderBy == null );
1944
+
1945
+ addr = sqlite3VdbeAddOp2( v, OP_OpenEphemeral, tab1, 0 );
1946
+ Debug.Assert( p.addrOpenEphm[0] == -1 );
1947
+ p.addrOpenEphm[0] = addr;
1948
+ p.pRightmost.selFlags |= SF_UsesEphemeral;
1949
+ Debug.Assert( p.pEList != null );
1950
+
1951
+ /* Code the SELECTs to our left into temporary table "tab1".
1952
+ */
1953
+ sqlite3SelectDestInit( intersectdest, SRT_Union, tab1 );
1954
+ rc = sqlite3Select( pParse, pPrior, ref intersectdest );
1955
+ if ( rc != 0 )
1956
+ {
1957
+ goto multi_select_end;
1958
+ }
1959
+
1960
+ /* Code the current SELECT into temporary table "tab2"
1961
+ */
1962
+ addr = sqlite3VdbeAddOp2( v, OP_OpenEphemeral, tab2, 0 );
1963
+ Debug.Assert( p.addrOpenEphm[1] == -1 );
1964
+ p.addrOpenEphm[1] = addr;
1965
+ p.pPrior = null;
1966
+ pLimit = p.pLimit;
1967
+ p.pLimit = null;
1968
+ pOffset = p.pOffset;
1969
+ p.pOffset = null;
1970
+ intersectdest.iParm = tab2;
1971
+ rc = sqlite3Select( pParse, p, ref intersectdest );
1972
+ testcase( rc != SQLITE_OK );
1973
+ p.pPrior = pPrior;
1974
+ sqlite3ExprDelete( db, ref p.pLimit );
1975
+ p.pLimit = pLimit;
1976
+ p.pOffset = pOffset;
1977
+
1978
+ /* Generate code to take the intersection of the two temporary
1979
+ ** tables.
1980
+ */
1981
+ Debug.Assert( p.pEList != null );
1982
+ if ( dest.eDest == SRT_Output )
1983
+ {
1984
+ Select pFirst = p;
1985
+ while ( pFirst.pPrior != null ) pFirst = pFirst.pPrior;
1986
+ generateColumnNames( pParse, null, pFirst.pEList );
1987
+ }
1988
+ iBreak = sqlite3VdbeMakeLabel( v );
1989
+ iCont = sqlite3VdbeMakeLabel( v );
1990
+ computeLimitRegisters( pParse, p, iBreak );
1991
+ sqlite3VdbeAddOp2( v, OP_Rewind, tab1, iBreak );
1992
+ r1 = sqlite3GetTempReg( pParse );
1993
+ iStart = sqlite3VdbeAddOp2( v, OP_RowKey, tab1, r1 );
1994
+ sqlite3VdbeAddOp4Int( v, OP_NotFound, tab2, iCont, r1, 0 );
1995
+ sqlite3ReleaseTempReg( pParse, r1 );
1996
+ selectInnerLoop( pParse, p, p.pEList, tab1, p.pEList.nExpr,
1997
+ null, -1, dest, iCont, iBreak );
1998
+ sqlite3VdbeResolveLabel( v, iCont );
1999
+ sqlite3VdbeAddOp2( v, OP_Next, tab1, iStart );
2000
+ sqlite3VdbeResolveLabel( v, iBreak );
2001
+ sqlite3VdbeAddOp2( v, OP_Close, tab2, 0 );
2002
+ sqlite3VdbeAddOp2( v, OP_Close, tab1, 0 );
2003
+ break;
2004
+ }
2005
+ }
2006
+
2007
+
2008
+ /* Compute collating sequences used by
2009
+ ** temporary tables needed to implement the compound select.
2010
+ ** Attach the KeyInfo structure to all temporary tables.
2011
+ **
2012
+ ** This section is run by the right-most SELECT statement only.
2013
+ ** SELECT statements to the left always skip this part. The right-most
2014
+ ** SELECT might also skip this part if it has no ORDER BY clause and
2015
+ ** no temp tables are required.
2016
+ */
2017
+ if ( ( p.selFlags & SF_UsesEphemeral ) != 0 )
2018
+ {
2019
+ int i; /* Loop counter */
2020
+ KeyInfo pKeyInfo; /* Collating sequence for the result set */
2021
+ Select pLoop; /* For looping through SELECT statements */
2022
+ CollSeq apColl; /* For looping through pKeyInfo.aColl[] */
2023
+ int nCol; /* Number of columns in result set */
2024
+
2025
+ Debug.Assert( p.pRightmost == p );
2026
+ nCol = p.pEList.nExpr;
2027
+ pKeyInfo = new KeyInfo(); //sqlite3DbMallocZero(db,
2028
+ pKeyInfo.aColl = new CollSeq[nCol]; //sizeof(*pKeyInfo)+nCol*(CollSeq*.Length + 1));
2029
+ if ( pKeyInfo == null )
2030
+ {
2031
+ rc = SQLITE_NOMEM;
2032
+ goto multi_select_end;
2033
+ }
2034
+
2035
+ pKeyInfo.enc = db.aDbStatic[0].pSchema.enc;// ENC( pParse.db );
2036
+ pKeyInfo.nField = (u16)nCol;
2037
+
2038
+ for ( i = 0; i < nCol; i++ )
2039
+ {//, apColl++){
2040
+ apColl = multiSelectCollSeq( pParse, p, i );
2041
+ if ( null == apColl )
2042
+ {
2043
+ apColl = db.pDfltColl;
2044
+ }
2045
+ pKeyInfo.aColl[i] = apColl;
2046
+ }
2047
+
2048
+ for ( pLoop = p; pLoop != null; pLoop = pLoop.pPrior )
2049
+ {
2050
+ for ( i = 0; i < 2; i++ )
2051
+ {
2052
+ int addr = pLoop.addrOpenEphm[i];
2053
+ if ( addr < 0 )
2054
+ {
2055
+ /* If [0] is unused then [1] is also unused. So we can
2056
+ ** always safely abort as soon as the first unused slot is found */
2057
+ Debug.Assert( pLoop.addrOpenEphm[1] < 0 );
2058
+ break;
2059
+ }
2060
+ sqlite3VdbeChangeP2( v, addr, nCol );
2061
+ sqlite3VdbeChangeP4( v, addr, pKeyInfo, P4_KEYINFO );
2062
+ pLoop.addrOpenEphm[i] = -1;
2063
+ }
2064
+ }
2065
+ sqlite3DbFree( db, ref pKeyInfo );
2066
+ }
2067
+
2068
+ multi_select_end:
2069
+ pDest.iMem = dest.iMem;
2070
+ pDest.nMem = dest.nMem;
2071
+ sqlite3SelectDelete( db, ref pDelete );
2072
+ return rc;
2073
+ }
2074
+ #endif // * SQLITE_OMIT_COMPOUND_SELECT */
2075
+
2076
+ /*
2077
+ ** Code an output subroutine for a coroutine implementation of a
2078
+ ** SELECT statment.
2079
+ **
2080
+ ** The data to be output is contained in pIn.iMem. There are
2081
+ ** pIn.nMem columns to be output. pDest is where the output should
2082
+ ** be sent.
2083
+ **
2084
+ ** regReturn is the number of the register holding the subroutine
2085
+ ** return address.
2086
+ **
2087
+ ** If regPrev>0 then it is a the first register in a vector that
2088
+ ** records the previous output. mem[regPrev] is a flag that is false
2089
+ ** if there has been no previous output. If regPrev>0 then code is
2090
+ ** generated to suppress duplicates. pKeyInfo is used for comparing
2091
+ ** keys.
2092
+ **
2093
+ ** If the LIMIT found in p.iLimit is reached, jump immediately to
2094
+ ** iBreak.
2095
+ */
2096
+ static int generateOutputSubroutine(
2097
+ Parse pParse, /* Parsing context */
2098
+ Select p, /* The SELECT statement */
2099
+ SelectDest pIn, /* Coroutine supplying data */
2100
+ SelectDest pDest, /* Where to send the data */
2101
+ int regReturn, /* The return address register */
2102
+ int regPrev, /* Previous result register. No uniqueness if 0 */
2103
+ KeyInfo pKeyInfo, /* For comparing with previous entry */
2104
+ int p4type, /* The p4 type for pKeyInfo */
2105
+ int iBreak /* Jump here if we hit the LIMIT */
2106
+ )
2107
+ {
2108
+ Vdbe v = pParse.pVdbe;
2109
+ int iContinue;
2110
+ int addr;
2111
+
2112
+ addr = sqlite3VdbeCurrentAddr( v );
2113
+ iContinue = sqlite3VdbeMakeLabel( v );
2114
+
2115
+ /* Suppress duplicates for UNION, EXCEPT, and INTERSECT
2116
+ */
2117
+ if ( regPrev != 0 )
2118
+ {
2119
+ int j1, j2;
2120
+ j1 = sqlite3VdbeAddOp1( v, OP_IfNot, regPrev );
2121
+ j2 = sqlite3VdbeAddOp4( v, OP_Compare, pIn.iMem, regPrev + 1, pIn.nMem,
2122
+ pKeyInfo, p4type );
2123
+ sqlite3VdbeAddOp3( v, OP_Jump, j2 + 2, iContinue, j2 + 2 );
2124
+ sqlite3VdbeJumpHere( v, j1 );
2125
+ sqlite3ExprCodeCopy( pParse, pIn.iMem, regPrev + 1, pIn.nMem );
2126
+ sqlite3VdbeAddOp2( v, OP_Integer, 1, regPrev );
2127
+ }
2128
+ //if ( pParse.db.mallocFailed != 0 ) return 0;
2129
+
2130
+ /* Suppress the the first OFFSET entries if there is an OFFSET clause
2131
+ */
2132
+ codeOffset( v, p, iContinue );
2133
+
2134
+ switch ( pDest.eDest )
2135
+ {
2136
+ /* Store the result as data using a unique key.
2137
+ */
2138
+ case SRT_Table:
2139
+ case SRT_EphemTab:
2140
+ {
2141
+ int r1 = sqlite3GetTempReg( pParse );
2142
+ int r2 = sqlite3GetTempReg( pParse );
2143
+ testcase( pDest.eDest == SRT_Table );
2144
+ testcase( pDest.eDest == SRT_EphemTab );
2145
+ sqlite3VdbeAddOp3( v, OP_MakeRecord, pIn.iMem, pIn.nMem, r1 );
2146
+ sqlite3VdbeAddOp2( v, OP_NewRowid, pDest.iParm, r2 );
2147
+ sqlite3VdbeAddOp3( v, OP_Insert, pDest.iParm, r1, r2 );
2148
+ sqlite3VdbeChangeP5( v, OPFLAG_APPEND );
2149
+ sqlite3ReleaseTempReg( pParse, r2 );
2150
+ sqlite3ReleaseTempReg( pParse, r1 );
2151
+ break;
2152
+ }
2153
+
2154
+ #if !SQLITE_OMIT_SUBQUERY
2155
+ /* If we are creating a set for an "expr IN (SELECT ...)" construct,
2156
+ ** then there should be a single item on the stack. Write this
2157
+ ** item into the set table with bogus data.
2158
+ */
2159
+ case SRT_Set:
2160
+ {
2161
+ int r1;
2162
+ Debug.Assert( pIn.nMem == 1 );
2163
+ p.affinity =
2164
+ sqlite3CompareAffinity( p.pEList.a[0].pExpr, pDest.affinity );
2165
+ r1 = sqlite3GetTempReg( pParse );
2166
+ sqlite3VdbeAddOp4( v, OP_MakeRecord, pIn.iMem, 1, r1, p.affinity, 1 );
2167
+ sqlite3ExprCacheAffinityChange( pParse, pIn.iMem, 1 );
2168
+ sqlite3VdbeAddOp2( v, OP_IdxInsert, pDest.iParm, r1 );
2169
+ sqlite3ReleaseTempReg( pParse, r1 );
2170
+ break;
2171
+ }
2172
+
2173
+ #if FALSE //* Never occurs on an ORDER BY query */
2174
+ /* If any row exist in the result set, record that fact and abort.
2175
+ */
2176
+ case SRT_Exists: {
2177
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest.iParm);
2178
+ /* The LIMIT clause will terminate the loop for us */
2179
+ break;
2180
+ }
2181
+ #endif
2182
+
2183
+ /* If this is a scalar select that is part of an expression, then
2184
+ ** store the results in the appropriate memory cell and break out
2185
+ ** of the scan loop.
2186
+ */
2187
+ case SRT_Mem:
2188
+ {
2189
+ Debug.Assert( pIn.nMem == 1 );
2190
+ sqlite3ExprCodeMove( pParse, pIn.iMem, pDest.iParm, 1 );
2191
+ /* The LIMIT clause will jump out of the loop for us */
2192
+ break;
2193
+ }
2194
+ #endif //* #if !SQLITE_OMIT_SUBQUERY */
2195
+
2196
+ /* The results are stored in a sequence of registers
2197
+ ** starting at pDest.iMem. Then the co-routine yields.
2198
+ */
2199
+ case SRT_Coroutine:
2200
+ {
2201
+ if ( pDest.iMem == 0 )
2202
+ {
2203
+ pDest.iMem = sqlite3GetTempRange( pParse, pIn.nMem );
2204
+ pDest.nMem = pIn.nMem;
2205
+ }
2206
+ sqlite3ExprCodeMove( pParse, pIn.iMem, pDest.iMem, pDest.nMem );
2207
+ sqlite3VdbeAddOp1( v, OP_Yield, pDest.iParm );
2208
+ break;
2209
+ }
2210
+
2211
+ /* If none of the above, then the result destination must be
2212
+ ** SRT_Output. This routine is never called with any other
2213
+ ** destination other than the ones handled above or SRT_Output.
2214
+ **
2215
+ ** For SRT_Output, results are stored in a sequence of registers.
2216
+ ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to
2217
+ ** return the next row of result.
2218
+ */
2219
+ default:
2220
+ {
2221
+ Debug.Assert( pDest.eDest == SRT_Output );
2222
+ sqlite3VdbeAddOp2( v, OP_ResultRow, pIn.iMem, pIn.nMem );
2223
+ sqlite3ExprCacheAffinityChange( pParse, pIn.iMem, pIn.nMem );
2224
+ break;
2225
+ }
2226
+ }
2227
+
2228
+ /* Jump to the end of the loop if the LIMIT is reached.
2229
+ */
2230
+ if ( p.iLimit != 0 )
2231
+ {
2232
+ sqlite3VdbeAddOp3( v, OP_IfZero, p.iLimit, iBreak, -1 );
2233
+ }
2234
+
2235
+ /* Generate the subroutine return
2236
+ */
2237
+ sqlite3VdbeResolveLabel( v, iContinue );
2238
+ sqlite3VdbeAddOp1( v, OP_Return, regReturn );
2239
+
2240
+ return addr;
2241
+ }
2242
+
2243
+ /*
2244
+ ** Alternative compound select code generator for cases when there
2245
+ ** is an ORDER BY clause.
2246
+ **
2247
+ ** We assume a query of the following form:
2248
+ **
2249
+ ** <selectA> <operator> <selectB> ORDER BY <orderbylist>
2250
+ **
2251
+ ** <operator> is one of UNION ALL, UNION, EXCEPT, or INTERSECT. The idea
2252
+ ** is to code both <selectA> and <selectB> with the ORDER BY clause as
2253
+ ** co-routines. Then run the co-routines in parallel and merge the results
2254
+ ** into the output. In addition to the two coroutines (called selectA and
2255
+ ** selectB) there are 7 subroutines:
2256
+ **
2257
+ ** outA: Move the output of the selectA coroutine into the output
2258
+ ** of the compound query.
2259
+ **
2260
+ ** outB: Move the output of the selectB coroutine into the output
2261
+ ** of the compound query. (Only generated for UNION and
2262
+ ** UNION ALL. EXCEPT and INSERTSECT never output a row that
2263
+ ** appears only in B.)
2264
+ **
2265
+ ** AltB: Called when there is data from both coroutines and A<B.
2266
+ **
2267
+ ** AeqB: Called when there is data from both coroutines and A==B.
2268
+ **
2269
+ ** AgtB: Called when there is data from both coroutines and A>B.
2270
+ **
2271
+ ** EofA: Called when data is exhausted from selectA.
2272
+ **
2273
+ ** EofB: Called when data is exhausted from selectB.
2274
+ **
2275
+ ** The implementation of the latter five subroutines depend on which
2276
+ ** <operator> is used:
2277
+ **
2278
+ **
2279
+ ** UNION ALL UNION EXCEPT INTERSECT
2280
+ ** ------------- ----------------- -------------- -----------------
2281
+ ** AltB: outA, nextA outA, nextA outA, nextA nextA
2282
+ **
2283
+ ** AeqB: outA, nextA nextA nextA outA, nextA
2284
+ **
2285
+ ** AgtB: outB, nextB outB, nextB nextB nextB
2286
+ **
2287
+ ** EofA: outB, nextB outB, nextB halt halt
2288
+ **
2289
+ ** EofB: outA, nextA outA, nextA outA, nextA halt
2290
+ **
2291
+ ** In the AltB, AeqB, and AgtB subroutines, an EOF on A following nextA
2292
+ ** causes an immediate jump to EofA and an EOF on B following nextB causes
2293
+ ** an immediate jump to EofB. Within EofA and EofB, and EOF on entry or
2294
+ ** following nextX causes a jump to the end of the select processing.
2295
+ **
2296
+ ** Duplicate removal in the UNION, EXCEPT, and INTERSECT cases is handled
2297
+ ** within the output subroutine. The regPrev register set holds the previously
2298
+ ** output value. A comparison is made against this value and the output
2299
+ ** is skipped if the next results would be the same as the previous.
2300
+ **
2301
+ ** The implementation plan is to implement the two coroutines and seven
2302
+ ** subroutines first, then put the control logic at the bottom. Like this:
2303
+ **
2304
+ ** goto Init
2305
+ ** coA: coroutine for left query (A)
2306
+ ** coB: coroutine for right query (B)
2307
+ ** outA: output one row of A
2308
+ ** outB: output one row of B (UNION and UNION ALL only)
2309
+ ** EofA: ...
2310
+ ** EofB: ...
2311
+ ** AltB: ...
2312
+ ** AeqB: ...
2313
+ ** AgtB: ...
2314
+ ** Init: initialize coroutine registers
2315
+ ** yield coA
2316
+ ** if eof(A) goto EofA
2317
+ ** yield coB
2318
+ ** if eof(B) goto EofB
2319
+ ** Cmpr: Compare A, B
2320
+ ** Jump AltB, AeqB, AgtB
2321
+ ** End: ...
2322
+ **
2323
+ ** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not
2324
+ ** actually called using Gosub and they do not Return. EofA and EofB loop
2325
+ ** until all data is exhausted then jump to the "end" labe. AltB, AeqB,
2326
+ ** and AgtB jump to either L2 or to one of EofA or EofB.
2327
+ */
2328
+ #if !SQLITE_OMIT_COMPOUND_SELECT
2329
+ static int multiSelectOrderBy(
2330
+ Parse pParse, /* Parsing context */
2331
+ Select p, /* The right-most of SELECTs to be coded */
2332
+ SelectDest pDest /* What to do with query results */
2333
+ )
2334
+ {
2335
+ int i, j; /* Loop counters */
2336
+ Select pPrior; /* Another SELECT immediately to our left */
2337
+ Vdbe v; /* Generate code to this VDBE */
2338
+ SelectDest destA = new SelectDest(); /* Destination for coroutine A */
2339
+ SelectDest destB = new SelectDest(); /* Destination for coroutine B */
2340
+ int regAddrA; /* Address register for select-A coroutine */
2341
+ int regEofA; /* Flag to indicate when select-A is complete */
2342
+ int regAddrB; /* Address register for select-B coroutine */
2343
+ int regEofB; /* Flag to indicate when select-B is complete */
2344
+ int addrSelectA; /* Address of the select-A coroutine */
2345
+ int addrSelectB; /* Address of the select-B coroutine */
2346
+ int regOutA; /* Address register for the output-A subroutine */
2347
+ int regOutB; /* Address register for the output-B subroutine */
2348
+ int addrOutA; /* Address of the output-A subroutine */
2349
+ int addrOutB = 0; /* Address of the output-B subroutine */
2350
+ int addrEofA; /* Address of the select-A-exhausted subroutine */
2351
+ int addrEofB; /* Address of the select-B-exhausted subroutine */
2352
+ int addrAltB; /* Address of the A<B subroutine */
2353
+ int addrAeqB; /* Address of the A==B subroutine */
2354
+ int addrAgtB; /* Address of the A>B subroutine */
2355
+ int regLimitA; /* Limit register for select-A */
2356
+ int regLimitB; /* Limit register for select-A */
2357
+ int regPrev; /* A range of registers to hold previous output */
2358
+ int savedLimit; /* Saved value of p.iLimit */
2359
+ int savedOffset; /* Saved value of p.iOffset */
2360
+ int labelCmpr; /* Label for the start of the merge algorithm */
2361
+ int labelEnd; /* Label for the end of the overall SELECT stmt */
2362
+ int j1; /* Jump instructions that get retargetted */
2363
+ int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */
2364
+ KeyInfo pKeyDup = null; /* Comparison information for duplicate removal */
2365
+ KeyInfo pKeyMerge; /* Comparison information for merging rows */
2366
+ sqlite3 db; /* Database connection */
2367
+ ExprList pOrderBy; /* The ORDER BY clause */
2368
+ int nOrderBy; /* Number of terms in the ORDER BY clause */
2369
+ int[] aPermute; /* Mapping from ORDER BY terms to result set columns */
2370
+
2371
+ Debug.Assert( p.pOrderBy != null );
2372
+ Debug.Assert( pKeyDup == null ); /* "Managed" code needs this. Ticket #3382. */
2373
+ db = pParse.db;
2374
+ v = pParse.pVdbe;
2375
+ Debug.Assert( v != null ); /* Already thrown the error if VDBE alloc failed */
2376
+ labelEnd = sqlite3VdbeMakeLabel( v );
2377
+ labelCmpr = sqlite3VdbeMakeLabel( v );
2378
+
2379
+
2380
+ /* Patch up the ORDER BY clause
2381
+ */
2382
+ op = p.op;
2383
+ pPrior = p.pPrior;
2384
+ Debug.Assert( pPrior.pOrderBy == null );
2385
+ pOrderBy = p.pOrderBy;
2386
+ Debug.Assert( pOrderBy != null );
2387
+ nOrderBy = pOrderBy.nExpr;
2388
+
2389
+ /* For operators other than UNION ALL we have to make sure that
2390
+ ** the ORDER BY clause covers every term of the result set. Add
2391
+ ** terms to the ORDER BY clause as necessary.
2392
+ */
2393
+ if ( op != TK_ALL )
2394
+ {
2395
+ for ( i = 1; /* db.mallocFailed == 0 && */ i <= p.pEList.nExpr; i++ )
2396
+ {
2397
+ ExprList_item pItem;
2398
+ for ( j = 0; j < nOrderBy; j++ )//, pItem++)
2399
+ {
2400
+ pItem = pOrderBy.a[j];
2401
+ Debug.Assert( pItem.iCol > 0 );
2402
+ if ( pItem.iCol == i ) break;
2403
+ }
2404
+ if ( j == nOrderBy )
2405
+ {
2406
+ Expr pNew = sqlite3Expr( db, TK_INTEGER, null );
2407
+ if ( pNew == null ) return SQLITE_NOMEM;
2408
+ pNew.flags |= EP_IntValue;
2409
+ pNew.u.iValue = i;
2410
+ pOrderBy = sqlite3ExprListAppend( pParse, pOrderBy, pNew );
2411
+ pOrderBy.a[nOrderBy++].iCol = (u16)i;
2412
+ }
2413
+ }
2414
+ }
2415
+
2416
+ /* Compute the comparison permutation and keyinfo that is used with
2417
+ ** the permutation used to determine if the next
2418
+ ** row of results comes from selectA or selectB. Also add explicit
2419
+ ** collations to the ORDER BY clause terms so that when the subqueries
2420
+ ** to the right and the left are evaluated, they use the correct
2421
+ ** collation.
2422
+ */
2423
+ aPermute = new int[nOrderBy];// sqlite3DbMallocRaw( db, sizeof( int ) * nOrderBy );
2424
+ if ( aPermute != null )
2425
+ {
2426
+ ExprList_item pItem;
2427
+ for ( i = 0; i < nOrderBy; i++ )//, pItem++)
2428
+ {
2429
+ pItem = pOrderBy.a[i];
2430
+ Debug.Assert( pItem.iCol > 0 && pItem.iCol <= p.pEList.nExpr );
2431
+ aPermute[i] = pItem.iCol - 1;
2432
+ }
2433
+ pKeyMerge = new KeyInfo();// sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1));
2434
+ if ( pKeyMerge != null )
2435
+ {
2436
+ pKeyMerge.aColl = new CollSeq[nOrderBy];
2437
+ pKeyMerge.aSortOrder = new byte[nOrderBy];//(u8*)&pKeyMerge.aColl[nOrderBy];
2438
+ pKeyMerge.nField = (u16)nOrderBy;
2439
+ pKeyMerge.enc = ENC( db );
2440
+ for ( i = 0; i < nOrderBy; i++ )
2441
+ {
2442
+ CollSeq pColl;
2443
+ Expr pTerm = pOrderBy.a[i].pExpr;
2444
+ if ( ( pTerm.flags & EP_ExpCollate ) != 0 )
2445
+ {
2446
+ pColl = pTerm.pColl;
2447
+ }
2448
+ else
2449
+ {
2450
+ pColl = multiSelectCollSeq( pParse, p, aPermute[i] );
2451
+ pTerm.flags |= EP_ExpCollate;
2452
+ pTerm.pColl = pColl;
2453
+ }
2454
+ pKeyMerge.aColl[i] = pColl;
2455
+ pKeyMerge.aSortOrder[i] = (byte)pOrderBy.a[i].sortOrder;
2456
+ }
2457
+ }
2458
+ }
2459
+ else
2460
+ {
2461
+ pKeyMerge = null;
2462
+ }
2463
+
2464
+ /* Reattach the ORDER BY clause to the query.
2465
+ */
2466
+ p.pOrderBy = pOrderBy;
2467
+ pPrior.pOrderBy = sqlite3ExprListDup( pParse.db, pOrderBy, 0 );
2468
+
2469
+ /* Allocate a range of temporary registers and the KeyInfo needed
2470
+ ** for the logic that removes duplicate result rows when the
2471
+ ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL).
2472
+ */
2473
+ if ( op == TK_ALL )
2474
+ {
2475
+ regPrev = 0;
2476
+ }
2477
+ else
2478
+ {
2479
+ int nExpr = p.pEList.nExpr;
2480
+ Debug.Assert( nOrderBy >= nExpr /*|| db.mallocFailed != 0 */ );
2481
+ regPrev = sqlite3GetTempRange( pParse, nExpr + 1 );
2482
+ sqlite3VdbeAddOp2( v, OP_Integer, 0, regPrev );
2483
+ pKeyDup = new KeyInfo();//sqlite3DbMallocZero(db,
2484
+ //sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) );
2485
+ if ( pKeyDup != null )
2486
+ {
2487
+ pKeyDup.aColl = new CollSeq[nExpr];
2488
+ pKeyDup.aSortOrder = new byte[nExpr];//(u8*)&pKeyDup.aColl[nExpr];
2489
+ pKeyDup.nField = (u16)nExpr;
2490
+ pKeyDup.enc = ENC( db );
2491
+ for ( i = 0; i < nExpr; i++ )
2492
+ {
2493
+ pKeyDup.aColl[i] = multiSelectCollSeq( pParse, p, i );
2494
+ pKeyDup.aSortOrder[i] = 0;
2495
+ }
2496
+ }
2497
+ }
2498
+
2499
+ /* Separate the left and the right query from one another
2500
+ */
2501
+ p.pPrior = null;
2502
+ pPrior.pRightmost = null;
2503
+ sqlite3ResolveOrderGroupBy( pParse, p, p.pOrderBy, "ORDER" );
2504
+ if ( pPrior.pPrior == null )
2505
+ {
2506
+ sqlite3ResolveOrderGroupBy( pParse, pPrior, pPrior.pOrderBy, "ORDER" );
2507
+ }
2508
+
2509
+ /* Compute the limit registers */
2510
+ computeLimitRegisters( pParse, p, labelEnd );
2511
+ if ( p.iLimit != 0 && op == TK_ALL )
2512
+ {
2513
+ regLimitA = ++pParse.nMem;
2514
+ regLimitB = ++pParse.nMem;
2515
+ sqlite3VdbeAddOp2( v, OP_Copy, ( p.iOffset != 0 ) ? p.iOffset + 1 : p.iLimit,
2516
+ regLimitA );
2517
+ sqlite3VdbeAddOp2( v, OP_Copy, regLimitA, regLimitB );
2518
+ }
2519
+ else
2520
+ {
2521
+ regLimitA = regLimitB = 0;
2522
+ }
2523
+ sqlite3ExprDelete( db, ref p.pLimit );
2524
+ p.pLimit = null;
2525
+ sqlite3ExprDelete( db, ref p.pOffset );
2526
+ p.pOffset = null;
2527
+
2528
+ regAddrA = ++pParse.nMem;
2529
+ regEofA = ++pParse.nMem;
2530
+ regAddrB = ++pParse.nMem;
2531
+ regEofB = ++pParse.nMem;
2532
+ regOutA = ++pParse.nMem;
2533
+ regOutB = ++pParse.nMem;
2534
+ sqlite3SelectDestInit( destA, SRT_Coroutine, regAddrA );
2535
+ sqlite3SelectDestInit( destB, SRT_Coroutine, regAddrB );
2536
+
2537
+ /* Jump past the various subroutines and coroutines to the main
2538
+ ** merge loop
2539
+ */
2540
+ j1 = sqlite3VdbeAddOp0( v, OP_Goto );
2541
+ addrSelectA = sqlite3VdbeCurrentAddr( v );
2542
+
2543
+
2544
+ /* Generate a coroutine to evaluate the SELECT statement to the
2545
+ ** left of the compound operator - the "A" select.
2546
+ */
2547
+ VdbeNoopComment( v, "Begin coroutine for left SELECT" );
2548
+ pPrior.iLimit = regLimitA;
2549
+ sqlite3Select( pParse, pPrior, ref destA );
2550
+ sqlite3VdbeAddOp2( v, OP_Integer, 1, regEofA );
2551
+ sqlite3VdbeAddOp1( v, OP_Yield, regAddrA );
2552
+ VdbeNoopComment( v, "End coroutine for left SELECT" );
2553
+
2554
+ /* Generate a coroutine to evaluate the SELECT statement on
2555
+ ** the right - the "B" select
2556
+ */
2557
+ addrSelectB = sqlite3VdbeCurrentAddr( v );
2558
+ VdbeNoopComment( v, "Begin coroutine for right SELECT" );
2559
+ savedLimit = p.iLimit;
2560
+ savedOffset = p.iOffset;
2561
+ p.iLimit = regLimitB;
2562
+ p.iOffset = 0;
2563
+ sqlite3Select( pParse, p, ref destB );
2564
+ p.iLimit = savedLimit;
2565
+ p.iOffset = savedOffset;
2566
+ sqlite3VdbeAddOp2( v, OP_Integer, 1, regEofB );
2567
+ sqlite3VdbeAddOp1( v, OP_Yield, regAddrB );
2568
+ VdbeNoopComment( v, "End coroutine for right SELECT" );
2569
+
2570
+ /* Generate a subroutine that outputs the current row of the A
2571
+ ** select as the next output row of the compound select.
2572
+ */
2573
+ VdbeNoopComment( v, "Output routine for A" );
2574
+ addrOutA = generateOutputSubroutine( pParse,
2575
+ p, destA, pDest, regOutA,
2576
+ regPrev, pKeyDup, P4_KEYINFO_HANDOFF, labelEnd );
2577
+
2578
+ /* Generate a subroutine that outputs the current row of the B
2579
+ ** select as the next output row of the compound select.
2580
+ */
2581
+ if ( op == TK_ALL || op == TK_UNION )
2582
+ {
2583
+ VdbeNoopComment( v, "Output routine for B" );
2584
+ addrOutB = generateOutputSubroutine( pParse,
2585
+ p, destB, pDest, regOutB,
2586
+ regPrev, pKeyDup, P4_KEYINFO_STATIC, labelEnd );
2587
+ }
2588
+
2589
+ /* Generate a subroutine to run when the results from select A
2590
+ ** are exhausted and only data in select B remains.
2591
+ */
2592
+ VdbeNoopComment( v, "eof-A subroutine" );
2593
+ if ( op == TK_EXCEPT || op == TK_INTERSECT )
2594
+ {
2595
+ addrEofA = sqlite3VdbeAddOp2( v, OP_Goto, 0, labelEnd );
2596
+ }
2597
+ else
2598
+ {
2599
+ addrEofA = sqlite3VdbeAddOp2( v, OP_If, regEofB, labelEnd );
2600
+ sqlite3VdbeAddOp2( v, OP_Gosub, regOutB, addrOutB );
2601
+ sqlite3VdbeAddOp1( v, OP_Yield, regAddrB );
2602
+ sqlite3VdbeAddOp2( v, OP_Goto, 0, addrEofA );
2603
+ }
2604
+
2605
+ /* Generate a subroutine to run when the results from select B
2606
+ ** are exhausted and only data in select A remains.
2607
+ */
2608
+ if ( op == TK_INTERSECT )
2609
+ {
2610
+ addrEofB = addrEofA;
2611
+ }
2612
+ else
2613
+ {
2614
+ VdbeNoopComment( v, "eof-B subroutine" );
2615
+ addrEofB = sqlite3VdbeAddOp2( v, OP_If, regEofA, labelEnd );
2616
+ sqlite3VdbeAddOp2( v, OP_Gosub, regOutA, addrOutA );
2617
+ sqlite3VdbeAddOp1( v, OP_Yield, regAddrA );
2618
+ sqlite3VdbeAddOp2( v, OP_Goto, 0, addrEofB );
2619
+ }
2620
+
2621
+ /* Generate code to handle the case of A<B
2622
+ */
2623
+ VdbeNoopComment( v, "A-lt-B subroutine" );
2624
+ addrAltB = sqlite3VdbeAddOp2( v, OP_Gosub, regOutA, addrOutA );
2625
+ sqlite3VdbeAddOp1( v, OP_Yield, regAddrA );
2626
+ sqlite3VdbeAddOp2( v, OP_If, regEofA, addrEofA );
2627
+ sqlite3VdbeAddOp2( v, OP_Goto, 0, labelCmpr );
2628
+
2629
+ /* Generate code to handle the case of A==B
2630
+ */
2631
+ if ( op == TK_ALL )
2632
+ {
2633
+ addrAeqB = addrAltB;
2634
+ }
2635
+ else if ( op == TK_INTERSECT )
2636
+ {
2637
+ addrAeqB = addrAltB;
2638
+ addrAltB++;
2639
+ }
2640
+ else
2641
+ {
2642
+ VdbeNoopComment( v, "A-eq-B subroutine" );
2643
+ addrAeqB =
2644
+ sqlite3VdbeAddOp1( v, OP_Yield, regAddrA );
2645
+ sqlite3VdbeAddOp2( v, OP_If, regEofA, addrEofA );
2646
+ sqlite3VdbeAddOp2( v, OP_Goto, 0, labelCmpr );
2647
+ }
2648
+
2649
+ /* Generate code to handle the case of A>B
2650
+ */
2651
+ VdbeNoopComment( v, "A-gt-B subroutine" );
2652
+ addrAgtB = sqlite3VdbeCurrentAddr( v );
2653
+ if ( op == TK_ALL || op == TK_UNION )
2654
+ {
2655
+ sqlite3VdbeAddOp2( v, OP_Gosub, regOutB, addrOutB );
2656
+ }
2657
+ sqlite3VdbeAddOp1( v, OP_Yield, regAddrB );
2658
+ sqlite3VdbeAddOp2( v, OP_If, regEofB, addrEofB );
2659
+ sqlite3VdbeAddOp2( v, OP_Goto, 0, labelCmpr );
2660
+
2661
+ /* This code runs once to initialize everything.
2662
+ */
2663
+ sqlite3VdbeJumpHere( v, j1 );
2664
+ sqlite3VdbeAddOp2( v, OP_Integer, 0, regEofA );
2665
+ sqlite3VdbeAddOp2( v, OP_Integer, 0, regEofB );
2666
+ sqlite3VdbeAddOp2( v, OP_Gosub, regAddrA, addrSelectA );
2667
+ sqlite3VdbeAddOp2( v, OP_Gosub, regAddrB, addrSelectB );
2668
+ sqlite3VdbeAddOp2( v, OP_If, regEofA, addrEofA );
2669
+ sqlite3VdbeAddOp2( v, OP_If, regEofB, addrEofB );
2670
+
2671
+ /* Implement the main merge loop
2672
+ */
2673
+ sqlite3VdbeResolveLabel( v, labelCmpr );
2674
+ sqlite3VdbeAddOp4( v, OP_Permutation, 0, 0, 0, aPermute, P4_INTARRAY );
2675
+ sqlite3VdbeAddOp4( v, OP_Compare, destA.iMem, destB.iMem, nOrderBy,
2676
+ pKeyMerge, P4_KEYINFO_HANDOFF );
2677
+ sqlite3VdbeAddOp3( v, OP_Jump, addrAltB, addrAeqB, addrAgtB );
2678
+
2679
+ /* Release temporary registers
2680
+ */
2681
+ if ( regPrev != 0 )
2682
+ {
2683
+ sqlite3ReleaseTempRange( pParse, regPrev, nOrderBy + 1 );
2684
+ }
2685
+
2686
+ /* Jump to the this point in order to terminate the query.
2687
+ */
2688
+ sqlite3VdbeResolveLabel( v, labelEnd );
2689
+
2690
+ /* Set the number of output columns
2691
+ */
2692
+ if ( pDest.eDest == SRT_Output )
2693
+ {
2694
+ Select pFirst = pPrior;
2695
+ while ( pFirst.pPrior != null ) pFirst = pFirst.pPrior;
2696
+ generateColumnNames( pParse, null, pFirst.pEList );
2697
+ }
2698
+
2699
+ /* Reassembly the compound query so that it will be freed correctly
2700
+ ** by the calling function */
2701
+ if ( p.pPrior != null )
2702
+ {
2703
+ sqlite3SelectDelete( db, ref p.pPrior );
2704
+ }
2705
+ p.pPrior = pPrior;
2706
+
2707
+ /*** TBD: Insert subroutine calls to close cursors on incomplete
2708
+ **** subqueries ****/
2709
+ return SQLITE_OK;
2710
+ }
2711
+ #endif
2712
+ #if !(SQLITE_OMIT_SUBQUERY) || !(SQLITE_OMIT_VIEW)
2713
+ /* Forward Declarations */
2714
+ //static void substExprList(sqlite3*, ExprList*, int, ExprList*);
2715
+ //static void substSelect(sqlite3*, Select *, int, ExprList *);
2716
+
2717
+ /*
2718
+ ** Scan through the expression pExpr. Replace every reference to
2719
+ ** a column in table number iTable with a copy of the iColumn-th
2720
+ ** entry in pEList. (But leave references to the ROWID column
2721
+ ** unchanged.)
2722
+ **
2723
+ ** This routine is part of the flattening procedure. A subquery
2724
+ ** whose result set is defined by pEList appears as entry in the
2725
+ ** FROM clause of a SELECT such that the VDBE cursor assigned to that
2726
+ ** FORM clause entry is iTable. This routine make the necessary
2727
+ ** changes to pExpr so that it refers directly to the source table
2728
+ ** of the subquery rather the result set of the subquery.
2729
+ */
2730
+ static Expr substExpr(
2731
+ sqlite3 db, /* Report malloc errors to this connection */
2732
+ Expr pExpr, /* Expr in which substitution occurs */
2733
+ int iTable, /* Table to be substituted */
2734
+ ExprList pEList /* Substitute expressions */
2735
+ )
2736
+ {
2737
+ if ( pExpr == null ) return null;
2738
+ if ( pExpr.op == TK_COLUMN && pExpr.iTable == iTable )
2739
+ {
2740
+ if ( pExpr.iColumn < 0 )
2741
+ {
2742
+ pExpr.op = TK_NULL;
2743
+ }
2744
+ else
2745
+ {
2746
+ Expr pNew;
2747
+ Debug.Assert( pEList != null && pExpr.iColumn < pEList.nExpr );
2748
+ Debug.Assert( pExpr.pLeft == null && pExpr.pRight == null );
2749
+ pNew = sqlite3ExprDup( db, pEList.a[pExpr.iColumn].pExpr, 0 );
2750
+ if ( pExpr.pColl != null )
2751
+ {
2752
+ pNew.pColl = pExpr.pColl;
2753
+ }
2754
+ sqlite3ExprDelete( db, ref pExpr );
2755
+ pExpr = pNew;
2756
+ }
2757
+ }
2758
+ else
2759
+ {
2760
+ pExpr.pLeft = substExpr( db, pExpr.pLeft, iTable, pEList );
2761
+ pExpr.pRight = substExpr( db, pExpr.pRight, iTable, pEList );
2762
+ if ( ExprHasProperty( pExpr, EP_xIsSelect ) )
2763
+ {
2764
+ substSelect( db, pExpr.x.pSelect, iTable, pEList );
2765
+ }
2766
+ else
2767
+ {
2768
+ substExprList( db, pExpr.x.pList, iTable, pEList );
2769
+ }
2770
+ }
2771
+ return pExpr;
2772
+ }
2773
+
2774
+ static void substExprList(
2775
+ sqlite3 db, /* Report malloc errors here */
2776
+ ExprList pList, /* List to scan and in which to make substitutes */
2777
+ int iTable, /* Table to be substituted */
2778
+ ExprList pEList /* Substitute values */
2779
+ )
2780
+ {
2781
+ int i;
2782
+ if ( pList == null ) return;
2783
+ for ( i = 0; i < pList.nExpr; i++ )
2784
+ {
2785
+ pList.a[i].pExpr = substExpr( db, pList.a[i].pExpr, iTable, pEList );
2786
+ }
2787
+ }
2788
+
2789
+ static void substSelect(
2790
+ sqlite3 db, /* Report malloc errors here */
2791
+ Select p, /* SELECT statement in which to make substitutions */
2792
+ int iTable, /* Table to be replaced */
2793
+ ExprList pEList /* Substitute values */
2794
+ )
2795
+ {
2796
+ SrcList pSrc;
2797
+ SrcList_item pItem;
2798
+ int i;
2799
+ if ( p == null ) return;
2800
+ substExprList( db, p.pEList, iTable, pEList );
2801
+ substExprList( db, p.pGroupBy, iTable, pEList );
2802
+ substExprList( db, p.pOrderBy, iTable, pEList );
2803
+ p.pHaving = substExpr( db, p.pHaving, iTable, pEList );
2804
+ p.pWhere = substExpr( db, p.pWhere, iTable, pEList );
2805
+ substSelect( db, p.pPrior, iTable, pEList );
2806
+ pSrc = p.pSrc;
2807
+ Debug.Assert( pSrc != null ); /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */
2808
+ if ( ALWAYS( pSrc ) )
2809
+ {
2810
+ for ( i = pSrc.nSrc; i > 0; i-- )//, pItem++ )
2811
+ {
2812
+ pItem = pSrc.a[pSrc.nSrc - i];
2813
+ substSelect( db, pItem.pSelect, iTable, pEList );
2814
+ }
2815
+ }
2816
+ }
2817
+ #endif //* !SQLITE_OMIT_SUBQUERY) || !SQLITE_OMIT_VIEW) */
2818
+
2819
+ #if !(SQLITE_OMIT_SUBQUERY) || !(SQLITE_OMIT_VIEW)
2820
+ /*
2821
+ ** This routine attempts to flatten subqueries in order to speed
2822
+ ** execution. It returns 1 if it makes changes and 0 if no flattening
2823
+ ** occurs.
2824
+ **
2825
+ ** To understand the concept of flattening, consider the following
2826
+ ** query:
2827
+ **
2828
+ ** SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5
2829
+ **
2830
+ ** The default way of implementing this query is to execute the
2831
+ ** subquery first and store the results in a temporary table, then
2832
+ ** run the outer query on that temporary table. This requires two
2833
+ ** passes over the data. Furthermore, because the temporary table
2834
+ ** has no indices, the WHERE clause on the outer query cannot be
2835
+ ** optimized.
2836
+ **
2837
+ ** This routine attempts to rewrite queries such as the above into
2838
+ ** a single flat select, like this:
2839
+ **
2840
+ ** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5
2841
+ **
2842
+ ** The code generated for this simpification gives the same result
2843
+ ** but only has to scan the data once. And because indices might
2844
+ ** exist on the table t1, a complete scan of the data might be
2845
+ ** avoided.
2846
+ **
2847
+ ** Flattening is only attempted if all of the following are true:
2848
+ **
2849
+ ** (1) The subquery and the outer query do not both use aggregates.
2850
+ **
2851
+ ** (2) The subquery is not an aggregate or the outer query is not a join.
2852
+ **
2853
+ ** (3) The subquery is not the right operand of a left outer join
2854
+ ** (Originally ticket #306. Strenghtened by ticket #3300)
2855
+ **
2856
+ ** (4) The subquery is not DISTINCT or the outer query is not a join.
2857
+ **
2858
+ ** (5) The subquery is not DISTINCT or the outer query does not use
2859
+ ** aggregates.
2860
+ **
2861
+ ** (6) The subquery does not use aggregates or the outer query is not
2862
+ ** DISTINCT.
2863
+ **
2864
+ ** (7) The subquery has a FROM clause.
2865
+ **
2866
+ ** (8) The subquery does not use LIMIT or the outer query is not a join.
2867
+ **
2868
+ ** (9) The subquery does not use LIMIT or the outer query does not use
2869
+ ** aggregates.
2870
+ **
2871
+ ** (10) The subquery does not use aggregates or the outer query does not
2872
+ ** use LIMIT.
2873
+ **
2874
+ ** (11) The subquery and the outer query do not both have ORDER BY clauses.
2875
+ **
2876
+ ** (**) Not implemented. Subsumed into restriction (3). Was previously
2877
+ ** a separate restriction deriving from ticket #350.
2878
+ **
2879
+ ** (13) The subquery and outer query do not both use LIMIT
2880
+ **
2881
+ ** (14) The subquery does not use OFFSET
2882
+ **
2883
+ ** (15) The outer query is not part of a compound select or the
2884
+ ** subquery does not have both an ORDER BY and a LIMIT clause.
2885
+ ** (See ticket #2339)
2886
+ **
2887
+ ** (16) The outer query is not an aggregate or the subquery does
2888
+ ** not contain ORDER BY. (Ticket #2942) This used to not matter
2889
+ ** until we introduced the group_concat() function.
2890
+ **
2891
+ ** (17) The sub-query is not a compound select, or it is a UNION ALL
2892
+ ** compound clause made up entirely of non-aggregate queries, and
2893
+ ** the parent query:
2894
+ **
2895
+ ** * is not itself part of a compound select,
2896
+ ** * is not an aggregate or DISTINCT query, and
2897
+ ** * has no other tables or sub-selects in the FROM clause.
2898
+ **
2899
+ ** The parent and sub-query may contain WHERE clauses. Subject to
2900
+ ** rules (11), (13) and (14), they may also contain ORDER BY,
2901
+ ** LIMIT and OFFSET clauses.
2902
+ **
2903
+ ** (18) If the sub-query is a compound select, then all terms of the
2904
+ ** ORDER by clause of the parent must be simple references to
2905
+ ** columns of the sub-query.
2906
+ **
2907
+ ** (19) The subquery does not use LIMIT or the outer query does not
2908
+ ** have a WHERE clause.
2909
+ **
2910
+ ** (20) If the sub-query is a compound select, then it must not use
2911
+ ** an ORDER BY clause. Ticket #3773. We could relax this constraint
2912
+ ** somewhat by saying that the terms of the ORDER BY clause must
2913
+ ** appear as unmodified result columns in the outer query. But
2914
+ ** have other optimizations in mind to deal with that case.
2915
+ **
2916
+ ** In this routine, the "p" parameter is a pointer to the outer query.
2917
+ ** The subquery is p.pSrc.a[iFrom]. isAgg is true if the outer query
2918
+ ** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
2919
+ **
2920
+ ** If flattening is not attempted, this routine is a no-op and returns 0.
2921
+ ** If flattening is attempted this routine returns 1.
2922
+ **
2923
+ ** All of the expression analysis must occur on both the outer query and
2924
+ ** the subquery before this routine runs.
2925
+ */
2926
+ static int flattenSubquery(
2927
+ Parse pParse, /* Parsing context */
2928
+ Select p, /* The parent or outer SELECT statement */
2929
+ int iFrom, /* Index in p.pSrc.a[] of the inner subquery */
2930
+ bool isAgg, /* True if outer SELECT uses aggregate functions */
2931
+ bool subqueryIsAgg /* True if the subquery uses aggregate functions */
2932
+ )
2933
+ {
2934
+ string zSavedAuthContext = pParse.zAuthContext;
2935
+ Select pParent;
2936
+ Select pSub; /* The inner query or "subquery" */
2937
+ Select pSub1; /* Pointer to the rightmost select in sub-query */
2938
+ SrcList pSrc; /* The FROM clause of the outer query */
2939
+ SrcList pSubSrc; /* The FROM clause of the subquery */
2940
+ ExprList pList; /* The result set of the outer query */
2941
+ int iParent; /* VDBE cursor number of the pSub result set temp table */
2942
+ int i; /* Loop counter */
2943
+ Expr pWhere; /* The WHERE clause */
2944
+ SrcList_item pSubitem;/* The subquery */
2945
+ sqlite3 db = pParse.db;
2946
+
2947
+ /* Check to see if flattening is permitted. Return 0 if not.
2948
+ */
2949
+ Debug.Assert( p != null );
2950
+ Debug.Assert( p.pPrior == null ); /* Unable to flatten compound queries */
2951
+ if ( ( db.flags & SQLITE_QueryFlattener ) != 0 ) return 0;
2952
+ pSrc = p.pSrc;
2953
+ Debug.Assert( pSrc != null && iFrom >= 0 && iFrom < pSrc.nSrc );
2954
+ pSubitem = pSrc.a[iFrom];
2955
+ iParent = pSubitem.iCursor;
2956
+ pSub = pSubitem.pSelect;
2957
+ Debug.Assert( pSub != null );
2958
+ if ( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */
2959
+ if ( subqueryIsAgg && pSrc.nSrc > 1 ) return 0; /* Restriction (2) */
2960
+ pSubSrc = pSub.pSrc;
2961
+ Debug.Assert( pSubSrc != null );
2962
+ /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
2963
+ ** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET
2964
+ ** because they could be computed at compile-time. But when LIMIT and OFFSET
2965
+ ** became arbitrary expressions, we were forced to add restrictions (13)
2966
+ ** and (14). */
2967
+ if ( pSub.pLimit != null && p.pLimit != null ) return 0; /* Restriction (13) */
2968
+ if ( pSub.pOffset != null ) return 0; /* Restriction (14) */
2969
+ if ( p.pRightmost != null && pSub.pLimit != null && pSub.pOrderBy != null )
2970
+ {
2971
+ return 0; /* Restriction (15) */
2972
+ }
2973
+ if ( pSubSrc.nSrc == 0 ) return 0; /* Restriction (7) */
2974
+ if ( ( pSub.selFlags & SF_Distinct ) != 0 || pSub.pLimit != null
2975
+ && ( pSrc.nSrc > 1 || isAgg ) )
2976
+ { /* Restrictions (4)(5)(8)(9) */
2977
+ return 0;
2978
+ }
2979
+ if ( ( p.selFlags & SF_Distinct ) != 0 && subqueryIsAgg )
2980
+ {
2981
+ return 0; /* Restriction (6) */
2982
+ }
2983
+ if ( p.pOrderBy != null && pSub.pOrderBy != null )
2984
+ {
2985
+ return 0; /* Restriction (11) */
2986
+ }
2987
+ if ( isAgg && pSub.pOrderBy != null ) return 0; /* Restriction (16) */
2988
+ if ( pSub.pLimit != null && p.pWhere != null ) return 0; /* Restriction (19) */
2989
+
2990
+ /* OBSOLETE COMMENT 1:
2991
+ ** Restriction 3: If the subquery is a join, make sure the subquery is
2992
+ ** not used as the right operand of an outer join. Examples of why this
2993
+ ** is not allowed:
2994
+ **
2995
+ ** t1 LEFT OUTER JOIN (t2 JOIN t3)
2996
+ **
2997
+ ** If we flatten the above, we would get
2998
+ **
2999
+ ** (t1 LEFT OUTER JOIN t2) JOIN t3
3000
+ **
3001
+ ** which is not at all the same thing.
3002
+ **
3003
+ ** OBSOLETE COMMENT 2:
3004
+ ** Restriction 12: If the subquery is the right operand of a left outer
3005
+
3006
+ /* Restriction 12: If the subquery is the right operand of a left outer
3007
+ ** join, make sure the subquery has no WHERE clause.
3008
+ ** An examples of why this is not allowed:
3009
+ **
3010
+ ** t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0)
3011
+ **
3012
+ ** If we flatten the above, we would get
3013
+ **
3014
+ ** (t1 LEFT OUTER JOIN t2) WHERE t2.x>0
3015
+ **
3016
+ ** But the t2.x>0 test will always fail on a NULL row of t2, which
3017
+ ** effectively converts the OUTER JOIN into an INNER JOIN.
3018
+ **
3019
+ ** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE:
3020
+ ** Ticket #3300 shows that flattening the right term of a LEFT JOIN
3021
+ ** is fraught with danger. Best to avoid the whole thing. If the
3022
+ ** subquery is the right term of a LEFT JOIN, then do not flatten.
3023
+ */
3024
+ if ( ( pSubitem.jointype & JT_OUTER ) != 0 )
3025
+ {
3026
+ return 0;
3027
+ }
3028
+
3029
+ /* Restriction 17: If the sub-query is a compound SELECT, then it must
3030
+ ** use only the UNION ALL operator. And none of the simple select queries
3031
+ ** that make up the compound SELECT are allowed to be aggregate or distinct
3032
+ ** queries.
3033
+ */
3034
+ if ( pSub.pPrior != null )
3035
+ {
3036
+ if ( pSub.pOrderBy != null )
3037
+ {
3038
+ return 0; /* Restriction 20 */
3039
+ }
3040
+ if ( isAgg || ( p.selFlags & SF_Distinct ) != 0 || pSrc.nSrc != 1 )
3041
+ {
3042
+ return 0;
3043
+ }
3044
+ for ( pSub1 = pSub; pSub1 != null; pSub1 = pSub1.pPrior )
3045
+ {
3046
+ testcase( ( pSub1.selFlags & ( SF_Distinct | SF_Aggregate ) ) == SF_Distinct );
3047
+ testcase( ( pSub1.selFlags & ( SF_Distinct | SF_Aggregate ) ) == SF_Aggregate );
3048
+ if ( ( pSub1.selFlags & ( SF_Distinct | SF_Aggregate ) ) != 0
3049
+ || ( pSub1.pPrior != null && pSub1.op != TK_ALL )
3050
+ || NEVER( pSub1.pSrc == null ) || pSub1.pSrc.nSrc != 1
3051
+ )
3052
+ {
3053
+ return 0;
3054
+ }
3055
+ }
3056
+
3057
+ /* Restriction 18. */
3058
+ if ( p.pOrderBy != null )
3059
+ {
3060
+ int ii;
3061
+ for ( ii = 0; ii < p.pOrderBy.nExpr; ii++ )
3062
+ {
3063
+ if ( p.pOrderBy.a[ii].iCol == 0 ) return 0;
3064
+ }
3065
+ }
3066
+ }
3067
+
3068
+ /***** If we reach this point, flattening is permitted. *****/
3069
+
3070
+ /* Authorize the subquery */
3071
+ pParse.zAuthContext = pSubitem.zName;
3072
+ sqlite3AuthCheck( pParse, SQLITE_SELECT, null, null, null );
3073
+ pParse.zAuthContext = zSavedAuthContext;
3074
+
3075
+ /* If the sub-query is a compound SELECT statement, then (by restrictions
3076
+ ** 17 and 18 above) it must be a UNION ALL and the parent query must
3077
+ ** be of the form:
3078
+ **
3079
+ ** SELECT <expr-list> FROM (<sub-query>) <where-clause>
3080
+ **
3081
+ ** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block
3082
+ ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or
3083
+ ** OFFSET clauses and joins them to the left-hand-side of the original
3084
+ ** using UNION ALL operators. In this case N is the number of simple
3085
+ ** select statements in the compound sub-query.
3086
+ **
3087
+ ** Example:
3088
+ **
3089
+ ** SELECT a+1 FROM (
3090
+ ** SELECT x FROM tab
3091
+ ** UNION ALL
3092
+ ** SELECT y FROM tab
3093
+ ** UNION ALL
3094
+ ** SELECT abs(z*2) FROM tab2
3095
+ ** ) WHERE a!=5 ORDER BY 1
3096
+ **
3097
+ ** Transformed into:
3098
+ **
3099
+ ** SELECT x+1 FROM tab WHERE x+1!=5
3100
+ ** UNION ALL
3101
+ ** SELECT y+1 FROM tab WHERE y+1!=5
3102
+ ** UNION ALL
3103
+ ** SELECT abs(z*2)+1 FROM tab2 WHERE abs(z*2)+1!=5
3104
+ ** ORDER BY 1
3105
+ **
3106
+ ** We call this the "compound-subquery flattening".
3107
+ */
3108
+ for ( pSub = pSub.pPrior; pSub != null; pSub = pSub.pPrior )
3109
+ {
3110
+ Select pNew;
3111
+ ExprList pOrderBy = p.pOrderBy;
3112
+ Expr pLimit = p.pLimit;
3113
+ Select pPrior = p.pPrior;
3114
+ p.pOrderBy = null;
3115
+ p.pSrc = null;
3116
+ p.pPrior = null;
3117
+ p.pLimit = null;
3118
+ pNew = sqlite3SelectDup( db, p, 0 );
3119
+ p.pLimit = pLimit;
3120
+ p.pOrderBy = pOrderBy;
3121
+ p.pSrc = pSrc;
3122
+ p.op = TK_ALL;
3123
+ p.pRightmost = null;
3124
+ if ( pNew == null )
3125
+ {
3126
+ pNew = pPrior;
3127
+ }
3128
+ else
3129
+ {
3130
+ pNew.pPrior = pPrior;
3131
+ pNew.pRightmost = null;
3132
+ }
3133
+ p.pPrior = pNew;
3134
+ // if ( db.mallocFailed != 0 ) return 1;
3135
+ }
3136
+
3137
+ /* Begin flattening the iFrom-th entry of the FROM clause
3138
+ ** in the outer query.
3139
+ */
3140
+ pSub = pSub1 = pSubitem.pSelect;
3141
+ /* Delete the transient table structure associated with the
3142
+ ** subquery
3143
+ */
3144
+
3145
+ sqlite3DbFree( db, ref pSubitem.zDatabase );
3146
+ sqlite3DbFree( db, ref pSubitem.zName );
3147
+ sqlite3DbFree( db, ref pSubitem.zAlias );
3148
+ pSubitem.zDatabase = null;
3149
+ pSubitem.zName = null;
3150
+ pSubitem.zAlias = null;
3151
+ pSubitem.pSelect = null;
3152
+ /* Defer deleting the Table object associated with the
3153
+ ** subquery until code generation is
3154
+ ** complete, since there may still exist Expr.pTab entries that
3155
+ ** refer to the subquery even after flattening. Ticket #3346.
3156
+ **
3157
+ ** pSubitem->pTab is always non-NULL by test restrictions and tests above.
3158
+ */
3159
+ if ( ALWAYS( pSubitem.pTab != null ) )
3160
+ {
3161
+ Table pTabToDel = pSubitem.pTab;
3162
+ if ( pTabToDel.nRef == 1 )
3163
+ {
3164
+ Parse pToplevel = sqlite3ParseToplevel( pParse );
3165
+ pTabToDel.pNextZombie = pToplevel.pZombieTab;
3166
+ pToplevel.pZombieTab = pTabToDel;
3167
+ }
3168
+ else
3169
+ {
3170
+ pTabToDel.nRef--;
3171
+ }
3172
+ pSubitem.pTab = null;
3173
+ }
3174
+
3175
+ /* The following loop runs once for each term in a compound-subquery
3176
+ ** flattening (as described above). If we are doing a different kind
3177
+ ** of flattening - a flattening other than a compound-subquery flattening -
3178
+ ** then this loop only runs once.
3179
+ **
3180
+ ** This loop moves all of the FROM elements of the subquery into the
3181
+ ** the FROM clause of the outer query. Before doing this, remember
3182
+ ** the cursor number for the original outer query FROM element in
3183
+ ** iParent. The iParent cursor will never be used. Subsequent code
3184
+ ** will scan expressions looking for iParent references and replace
3185
+ ** those references with expressions that resolve to the subquery FROM
3186
+ ** elements we are now copying in.
3187
+ */
3188
+ for ( pParent = p; pParent != null; pParent = pParent.pPrior, pSub = pSub.pPrior )
3189
+ {
3190
+ int nSubSrc;
3191
+ u8 jointype = 0;
3192
+ pSubSrc = pSub.pSrc; /* FROM clause of subquery */
3193
+ nSubSrc = pSubSrc.nSrc; /* Number of terms in subquery FROM clause */
3194
+ pSrc = pParent.pSrc; /* FROM clause of the outer query */
3195
+
3196
+ if ( pSrc != null )
3197
+ {
3198
+ Debug.Assert( pParent == p ); /* First time through the loop */
3199
+ jointype = pSubitem.jointype;
3200
+ }
3201
+ else
3202
+ {
3203
+ Debug.Assert( pParent != p ); /* 2nd and subsequent times through the loop */
3204
+ pSrc = pParent.pSrc = sqlite3SrcListAppend( db, null, null, null );
3205
+ //if ( pSrc == null )
3206
+ //{
3207
+ // //Debug.Assert( db.mallocFailed != 0 );
3208
+ // break;
3209
+ //}
3210
+ }
3211
+
3212
+ /* The subquery uses a single slot of the FROM clause of the outer
3213
+ ** query. If the subquery has more than one element in its FROM clause,
3214
+ ** then expand the outer query to make space for it to hold all elements
3215
+ ** of the subquery.
3216
+ **
3217
+ ** Example:
3218
+ **
3219
+ ** SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB;
3220
+ **
3221
+ ** The outer query has 3 slots in its FROM clause. One slot of the
3222
+ ** outer query (the middle slot) is used by the subquery. The next
3223
+ ** block of code will expand the out query to 4 slots. The middle
3224
+ ** slot is expanded to two slots in order to make space for the
3225
+ ** two elements in the FROM clause of the subquery.
3226
+ */
3227
+ if ( nSubSrc > 1 )
3228
+ {
3229
+ pParent.pSrc = pSrc = sqlite3SrcListEnlarge( db, pSrc, nSubSrc - 1, iFrom + 1 );
3230
+ //if ( db.mallocFailed != 0 )
3231
+ //{
3232
+ // break;
3233
+ //}
3234
+ }
3235
+
3236
+ /* Transfer the FROM clause terms from the subquery into the
3237
+ ** outer query.
3238
+ */
3239
+ for ( i = 0; i < nSubSrc; i++ )
3240
+ {
3241
+ sqlite3IdListDelete( db, ref pSrc.a[i + iFrom].pUsing );
3242
+ pSrc.a[i + iFrom] = pSubSrc.a[i];
3243
+ pSubSrc.a[i] = new SrcList_item();//memset(pSubSrc.a[i], 0, sizeof(pSubSrc.a[i]));
3244
+ }
3245
+ pSubitem = pSrc.a[iFrom]; // Reset for C#
3246
+ pSrc.a[iFrom].jointype = jointype;
3247
+
3248
+ /* Now begin substituting subquery result set expressions for
3249
+ ** references to the iParent in the outer query.
3250
+ **
3251
+ ** Example:
3252
+ **
3253
+ ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
3254
+ ** \ \_____________ subquery __________/ /
3255
+ ** \_____________________ outer query ______________________________/
3256
+ **
3257
+ ** We look at every expression in the outer query and every place we see
3258
+ ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
3259
+ */
3260
+ pList = pParent.pEList;
3261
+ for ( i = 0; i < pList.nExpr; i++ )
3262
+ {
3263
+ if ( pList.a[i].zName == null )
3264
+ {
3265
+ string zSpan = pList.a[i].zSpan;
3266
+ if ( ALWAYS( zSpan ) )
3267
+ {
3268
+ pList.a[i].zName = zSpan;// sqlite3DbStrDup( db, zSpan );
3269
+ }
3270
+ }
3271
+ }
3272
+ substExprList( db, pParent.pEList, iParent, pSub.pEList );
3273
+ if ( isAgg )
3274
+ {
3275
+ substExprList( db, pParent.pGroupBy, iParent, pSub.pEList );
3276
+ pParent.pHaving = substExpr( db, pParent.pHaving, iParent, pSub.pEList );
3277
+ }
3278
+ if ( pSub.pOrderBy != null )
3279
+ {
3280
+ Debug.Assert( pParent.pOrderBy == null );
3281
+ pParent.pOrderBy = pSub.pOrderBy;
3282
+ pSub.pOrderBy = null;
3283
+ }
3284
+ else if ( pParent.pOrderBy != null )
3285
+ {
3286
+ substExprList( db, pParent.pOrderBy, iParent, pSub.pEList );
3287
+ }
3288
+ if ( pSub.pWhere != null )
3289
+ {
3290
+ pWhere = sqlite3ExprDup( db, pSub.pWhere, 0 );
3291
+ }
3292
+ else
3293
+ {
3294
+ pWhere = null;
3295
+ }
3296
+ if ( subqueryIsAgg )
3297
+ {
3298
+ Debug.Assert( pParent.pHaving == null );
3299
+ pParent.pHaving = pParent.pWhere;
3300
+ pParent.pWhere = pWhere;
3301
+ pParent.pHaving = substExpr( db, pParent.pHaving, iParent, pSub.pEList );
3302
+ pParent.pHaving = sqlite3ExprAnd( db, pParent.pHaving,
3303
+ sqlite3ExprDup( db, pSub.pHaving, 0 ) );
3304
+ Debug.Assert( pParent.pGroupBy == null );
3305
+ pParent.pGroupBy = sqlite3ExprListDup( db, pSub.pGroupBy, 0 );
3306
+ }
3307
+ else
3308
+ {
3309
+ pParent.pWhere = substExpr( db, pParent.pWhere, iParent, pSub.pEList );
3310
+ pParent.pWhere = sqlite3ExprAnd( db, pParent.pWhere, pWhere );
3311
+ }
3312
+
3313
+ /* The flattened query is distinct if either the inner or the
3314
+ ** outer query is distinct.
3315
+ */
3316
+ pParent.selFlags = (u16)( pParent.selFlags | pSub.selFlags & SF_Distinct );
3317
+
3318
+ /*
3319
+ ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
3320
+ **
3321
+ ** One is tempted to try to add a and b to combine the limits. But this
3322
+ ** does not work if either limit is negative.
3323
+ */
3324
+ if ( pSub.pLimit != null )
3325
+ {
3326
+ pParent.pLimit = pSub.pLimit;
3327
+ pSub.pLimit = null;
3328
+ }
3329
+ }
3330
+
3331
+ /* Finially, delete what is left of the subquery and return
3332
+ ** success.
3333
+ */
3334
+ sqlite3SelectDelete( db, ref pSub );
3335
+ sqlite3SelectDelete( db, ref pSub1 );
3336
+ return 1;
3337
+ }
3338
+ #endif //* !SQLITE_OMIT_SUBQUERY) || !SQLITE_OMIT_VIEW) */
3339
+
3340
+ /*
3341
+ ** Analyze the SELECT statement passed as an argument to see if it
3342
+ ** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if
3343
+ ** it is, or 0 otherwise. At present, a query is considered to be
3344
+ ** a min()/max() query if:
3345
+ **
3346
+ ** 1. There is a single object in the FROM clause.
3347
+ **
3348
+ ** 2. There is a single expression in the result set, and it is
3349
+ ** either min(x) or max(x), where x is a column reference.
3350
+ */
3351
+ static u8 minMaxQuery( Select p )
3352
+ {
3353
+ Expr pExpr;
3354
+ ExprList pEList = p.pEList;
3355
+
3356
+ if ( pEList.nExpr != 1 ) return WHERE_ORDERBY_NORMAL;
3357
+ pExpr = pEList.a[0].pExpr;
3358
+ if ( pExpr.op != TK_AGG_FUNCTION ) return 0;
3359
+ if ( NEVER( ExprHasProperty( pExpr, EP_xIsSelect ) ) ) return 0;
3360
+ pEList = pExpr.x.pList;
3361
+ if ( pEList == null || pEList.nExpr != 1 ) return 0;
3362
+ if ( pEList.a[0].pExpr.op != TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
3363
+ Debug.Assert( !ExprHasProperty( pExpr, EP_IntValue ) );
3364
+ if (String.Compare(pExpr.u.zToken, "min", StringComparison.InvariantCultureIgnoreCase) == 0)//sqlite3StrICmp(pExpr->u.zToken,"min")==0 )
3365
+ {
3366
+ return WHERE_ORDERBY_MIN;
3367
+ }
3368
+ else if (String.Compare(pExpr.u.zToken, "max", StringComparison.InvariantCultureIgnoreCase) == 0)//sqlite3StrICmp(pExpr->u.zToken,"max")==0 )
3369
+ {
3370
+ return WHERE_ORDERBY_MAX;
3371
+ }
3372
+ return WHERE_ORDERBY_NORMAL;
3373
+ }
3374
+
3375
+ /*
3376
+ ** The select statement passed as the first argument is an aggregate query.
3377
+ ** The second argment is the associated aggregate-info object. This
3378
+ ** function tests if the SELECT is of the form:
3379
+ **
3380
+ ** SELECT count(*) FROM <tbl>
3381
+ **
3382
+ ** where table is a database table, not a sub-select or view. If the query
3383
+ ** does match this pattern, then a pointer to the Table object representing
3384
+ ** <tbl> is returned. Otherwise, 0 is returned.
3385
+ */
3386
+ static Table isSimpleCount( Select p, AggInfo pAggInfo )
3387
+ {
3388
+ Table pTab;
3389
+ Expr pExpr;
3390
+
3391
+ Debug.Assert( null == p.pGroupBy );
3392
+
3393
+ if ( p.pWhere != null || p.pEList.nExpr != 1
3394
+ || p.pSrc.nSrc != 1 || p.pSrc.a[0].pSelect != null
3395
+ )
3396
+ {
3397
+ return null;
3398
+ }
3399
+ pTab = p.pSrc.a[0].pTab;
3400
+ pExpr = p.pEList.a[0].pExpr;
3401
+ Debug.Assert( pTab != null && null == pTab.pSelect && pExpr != null );
3402
+
3403
+ if ( IsVirtual( pTab ) ) return null;
3404
+ if ( pExpr.op != TK_AGG_FUNCTION ) return null;
3405
+ if ( ( pAggInfo.aFunc[0].pFunc.flags & SQLITE_FUNC_COUNT ) == 0 ) return null;
3406
+ if ( ( pExpr.flags & EP_Distinct ) != 0 ) return null;
3407
+
3408
+ return pTab;
3409
+ }
3410
+
3411
+ /*
3412
+ ** If the source-list item passed as an argument was augmented with an
3413
+ ** INDEXED BY clause, then try to locate the specified index. If there
3414
+ ** was such a clause and the named index cannot be found, return
3415
+ ** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
3416
+ ** pFrom.pIndex and return SQLITE_OK.
3417
+ */
3418
+ static int sqlite3IndexedByLookup( Parse pParse, SrcList_item pFrom )
3419
+ {
3420
+ if ( pFrom.pTab != null && pFrom.zIndex != null && pFrom.zIndex.Length != 0 )
3421
+ {
3422
+ Table pTab = pFrom.pTab;
3423
+ string zIndex = pFrom.zIndex;
3424
+ Index pIdx;
3425
+ for ( pIdx = pTab.pIndex;
3426
+ pIdx != null && sqlite3StrICmp( pIdx.zName, zIndex ) != 0;
3427
+ pIdx = pIdx.pNext
3428
+ ) ;
3429
+ if ( null == pIdx )
3430
+ {
3431
+ sqlite3ErrorMsg( pParse, "no such index: %s", zIndex );
3432
+ return SQLITE_ERROR;
3433
+ }
3434
+ pFrom.pIndex = pIdx;
3435
+ }
3436
+ return SQLITE_OK;
3437
+ }
3438
+
3439
+ /*
3440
+ ** This routine is a Walker callback for "expanding" a SELECT statement.
3441
+ ** "Expanding" means to do the following:
3442
+ **
3443
+ ** (1) Make sure VDBE cursor numbers have been assigned to every
3444
+ ** element of the FROM clause.
3445
+ **
3446
+ ** (2) Fill in the pTabList.a[].pTab fields in the SrcList that
3447
+ ** defines FROM clause. When views appear in the FROM clause,
3448
+ ** fill pTabList.a[].x.pSelect with a copy of the SELECT statement
3449
+ ** that implements the view. A copy is made of the view's SELECT
3450
+ ** statement so that we can freely modify or delete that statement
3451
+ ** without worrying about messing up the presistent representation
3452
+ ** of the view.
3453
+ **
3454
+ ** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword
3455
+ ** on joins and the ON and USING clause of joins.
3456
+ **
3457
+ ** (4) Scan the list of columns in the result set (pEList) looking
3458
+ ** for instances of the "*" operator or the TABLE.* operator.
3459
+ ** If found, expand each "*" to be every column in every table
3460
+ ** and TABLE.* to be every column in TABLE.
3461
+ **
3462
+ */
3463
+ static int selectExpander( Walker pWalker, Select p )
3464
+ {
3465
+ Parse pParse = pWalker.pParse;
3466
+ int i, j, k;
3467
+ SrcList pTabList;
3468
+ ExprList pEList;
3469
+ SrcList_item pFrom;
3470
+ sqlite3 db = pParse.db;
3471
+
3472
+ //if ( db.mallocFailed != 0 )
3473
+ //{
3474
+ // return WRC_Abort;
3475
+ //}
3476
+ if ( NEVER( p.pSrc == null ) || ( p.selFlags & SF_Expanded ) != 0 )
3477
+ {
3478
+ return WRC_Prune;
3479
+ }
3480
+ p.selFlags |= SF_Expanded;
3481
+ pTabList = p.pSrc;
3482
+ pEList = p.pEList;
3483
+
3484
+ /* Make sure cursor numbers have been assigned to all entries in
3485
+ ** the FROM clause of the SELECT statement.
3486
+ */
3487
+ sqlite3SrcListAssignCursors( pParse, pTabList );
3488
+
3489
+ /* Look up every table named in the FROM clause of the select. If
3490
+ ** an entry of the FROM clause is a subquery instead of a table or view,
3491
+ ** then create a transient table ure to describe the subquery.
3492
+ */
3493
+ for ( i = 0; i < pTabList.nSrc; i++ )// pFrom++ )
3494
+ {
3495
+ pFrom = pTabList.a[i];
3496
+ Table pTab;
3497
+ if ( pFrom.pTab != null )
3498
+ {
3499
+ /* This statement has already been prepared. There is no need
3500
+ ** to go further. */
3501
+ Debug.Assert( i == 0 );
3502
+ return WRC_Prune;
3503
+ }
3504
+ if ( pFrom.zName == null )
3505
+ {
3506
+ #if !SQLITE_OMIT_SUBQUERY
3507
+ Select pSel = pFrom.pSelect;
3508
+ /* A sub-query in the FROM clause of a SELECT */
3509
+ Debug.Assert( pSel != null );
3510
+ Debug.Assert( pFrom.pTab == null );
3511
+ sqlite3WalkSelect( pWalker, pSel );
3512
+ pFrom.pTab = pTab = new Table();// sqlite3DbMallocZero( db, sizeof( Table ) );
3513
+ if ( pTab == null ) return WRC_Abort;
3514
+ pTab.dbMem = db.lookaside.bEnabled != 0 ? db : null;
3515
+ pTab.nRef = 1;
3516
+ pTab.zName = sqlite3MPrintf( db, "sqlite_subquery_%p_", pTab );
3517
+ while ( pSel.pPrior != null ) { pSel = pSel.pPrior; }
3518
+ selectColumnsFromExprList( pParse, pSel.pEList, ref pTab.nCol, ref pTab.aCol );
3519
+ pTab.iPKey = -1;
3520
+ pTab.tabFlags |= TF_Ephemeral;
3521
+ #endif
3522
+ }
3523
+ else
3524
+ {
3525
+ /* An ordinary table or view name in the FROM clause */
3526
+ Debug.Assert( pFrom.pTab == null );
3527
+ pFrom.pTab = pTab =
3528
+ sqlite3LocateTable( pParse, 0, pFrom.zName, pFrom.zDatabase );
3529
+ if ( pTab == null ) return WRC_Abort;
3530
+ pTab.nRef++;
3531
+ #if !(SQLITE_OMIT_VIEW) || !(SQLITE_OMIT_VIRTUALTABLE)
3532
+ if ( pTab.pSelect != null || IsVirtual( pTab ) )
3533
+ {
3534
+ /* We reach here if the named table is a really a view */
3535
+ if ( sqlite3ViewGetColumnNames( pParse, pTab ) != 0 ) return WRC_Abort;
3536
+
3537
+ pFrom.pSelect = sqlite3SelectDup( db, pTab.pSelect, 0 );
3538
+ sqlite3WalkSelect( pWalker, pFrom.pSelect );
3539
+ }
3540
+ #endif
3541
+ }
3542
+ /* Locate the index named by the INDEXED BY clause, if any. */
3543
+ if ( sqlite3IndexedByLookup( pParse, pFrom ) != 0 )
3544
+ {
3545
+ return WRC_Abort;
3546
+ }
3547
+ }
3548
+
3549
+ /* Process NATURAL keywords, and ON and USING clauses of joins.
3550
+ */
3551
+ if ( /* db.mallocFailed != 0 || */ sqliteProcessJoin( pParse, p ) != 0 )
3552
+ {
3553
+ return WRC_Abort;
3554
+ }
3555
+
3556
+ /* For every "*" that occurs in the column list, insert the names of
3557
+ ** all columns in all tables. And for every TABLE.* insert the names
3558
+ ** of all columns in TABLE. The parser inserted a special expression
3559
+ ** with the TK_ALL operator for each "*" that it found in the column list.
3560
+ ** The following code just has to locate the TK_ALL expressions and expand
3561
+ ** each one to the list of all columns in all tables.
3562
+ **
3563
+ ** The first loop just checks to see if there are any "*" operators
3564
+ ** that need expanding.
3565
+ */
3566
+ for ( k = 0; k < pEList.nExpr; k++ )
3567
+ {
3568
+ Expr pE = pEList.a[k].pExpr;
3569
+ if ( pE.op == TK_ALL ) break;
3570
+ Debug.Assert( pE.op != TK_DOT || pE.pRight != null );
3571
+ Debug.Assert( pE.op != TK_DOT || ( pE.pLeft != null && pE.pLeft.op == TK_ID ) );
3572
+ if ( pE.op == TK_DOT && pE.pRight.op == TK_ALL ) break;
3573
+ }
3574
+ if ( k < pEList.nExpr )
3575
+ {
3576
+ /*
3577
+ ** If we get here it means the result set contains one or more "*"
3578
+ ** operators that need to be expanded. Loop through each expression
3579
+ ** in the result set and expand them one by one.
3580
+ */
3581
+ ExprList_item[] a = pEList.a;
3582
+ ExprList pNew = null;
3583
+ int flags = pParse.db.flags;
3584
+ bool longNames = ( flags & SQLITE_FullColNames ) != 0
3585
+ && ( flags & SQLITE_ShortColNames ) == 0;
3586
+
3587
+ for ( k = 0; k < pEList.nExpr; k++ )
3588
+ {
3589
+ Expr pE = a[k].pExpr;
3590
+ Debug.Assert( pE.op != TK_DOT || pE.pRight != null );
3591
+ if ( pE.op != TK_ALL && ( pE.op != TK_DOT || pE.pRight.op != TK_ALL ) )
3592
+ {
3593
+ /* This particular expression does not need to be expanded.
3594
+ */
3595
+ pNew = sqlite3ExprListAppend( pParse, pNew, a[k].pExpr );
3596
+ if ( pNew != null )
3597
+ {
3598
+ pNew.a[pNew.nExpr - 1].zName = a[k].zName;
3599
+ pNew.a[pNew.nExpr - 1].zSpan = a[k].zSpan;
3600
+ a[k].zName = null;
3601
+ a[k].zSpan = null;
3602
+ }
3603
+ a[k].pExpr = null;
3604
+ }
3605
+ else
3606
+ {
3607
+ /* This expression is a "*" or a "TABLE.*" and needs to be
3608
+ ** expanded. */
3609
+ int tableSeen = 0; /* Set to 1 when TABLE matches */
3610
+ string zTName; /* text of name of TABLE */
3611
+ if ( pE.op == TK_DOT )
3612
+ {
3613
+ Debug.Assert( pE.pLeft != null );
3614
+ Debug.Assert( !ExprHasProperty( pE.pLeft, EP_IntValue ) );
3615
+ zTName = pE.pLeft.u.zToken;
3616
+ }
3617
+ else
3618
+ {
3619
+ zTName = null;
3620
+ }
3621
+ for ( i = 0; i < pTabList.nSrc; i++ )//, pFrom++ )
3622
+ {
3623
+ pFrom = pTabList.a[i];
3624
+ Table pTab = pFrom.pTab;
3625
+ string zTabName = pFrom.zAlias;
3626
+ if ( zTabName == null )
3627
+ {
3628
+ zTabName = pTab.zName;
3629
+ }
3630
+ ///if ( db.mallocFailed != 0 ) break;
3631
+ if ( zTName != null && sqlite3StrICmp( zTName, zTabName ) != 0 )
3632
+ {
3633
+ continue;
3634
+ }
3635
+ tableSeen = 1;
3636
+ for ( j = 0; j < pTab.nCol; j++ )
3637
+ {
3638
+ Expr pExpr, pRight;
3639
+ string zName = pTab.aCol[j].zName;
3640
+ string zColname; /* The computed column name */
3641
+ string zToFree; /* Malloced string that needs to be freed */
3642
+ Token sColname = new Token(); /* Computed column name as a token */
3643
+
3644
+ /* If a column is marked as 'hidden' (currently only possible
3645
+ ** for virtual tables), do not include it in the expanded
3646
+ ** result-set list.
3647
+ */
3648
+ if ( IsHiddenColumn( pTab.aCol[j] ) )
3649
+ {
3650
+ Debug.Assert( IsVirtual( pTab ) );
3651
+ continue;
3652
+ }
3653
+
3654
+ if ( i > 0 && ( zTName == null || zTName.Length == 0 ) )
3655
+ {
3656
+ int iDummy = 0;
3657
+ if ( ( pFrom.jointype & JT_NATURAL ) != 0
3658
+ && tableAndColumnIndex( pTabList, i, zName, ref iDummy, ref iDummy ) != 0
3659
+ )
3660
+ {
3661
+ /* In a NATURAL join, omit the join columns from the
3662
+ ** table to the right of the join */
3663
+ continue;
3664
+ }
3665
+ if ( sqlite3IdListIndex( pFrom.pUsing, zName ) >= 0 )
3666
+ {
3667
+ /* In a join with a USING clause, omit columns in the
3668
+ ** using clause from the table on the right. */
3669
+ continue;
3670
+ }
3671
+ }
3672
+ pRight = sqlite3Expr( db, TK_ID, zName );
3673
+ zColname = zName;
3674
+ zToFree = "";
3675
+ if ( longNames || pTabList.nSrc > 1 )
3676
+ {
3677
+ Expr pLeft;
3678
+ pLeft = sqlite3Expr( db, TK_ID, zTabName );
3679
+ pExpr = sqlite3PExpr( pParse, TK_DOT, pLeft, pRight, 0 );
3680
+ if ( longNames )
3681
+ {
3682
+ zColname = sqlite3MPrintf( db, "%s.%s", zTabName, zName );
3683
+ zToFree = zColname;
3684
+ }
3685
+ }
3686
+ else
3687
+ {
3688
+ pExpr = pRight;
3689
+ }
3690
+ pNew = sqlite3ExprListAppend( pParse, pNew, pExpr );
3691
+ sColname.z = zColname;
3692
+ sColname.n = sqlite3Strlen30( zColname );
3693
+ sqlite3ExprListSetName( pParse, pNew, sColname, 0 );
3694
+ sqlite3DbFree( db, ref zToFree );
3695
+ }
3696
+ }
3697
+ if ( tableSeen == 0 )
3698
+ {
3699
+ if ( zTName != null )
3700
+ {
3701
+ sqlite3ErrorMsg( pParse, "no such table: %s", zTName );
3702
+ }
3703
+ else
3704
+ {
3705
+ sqlite3ErrorMsg( pParse, "no tables specified" );
3706
+ }
3707
+ }
3708
+ }
3709
+ }
3710
+ sqlite3ExprListDelete( db, ref pEList );
3711
+ p.pEList = pNew;
3712
+ }
3713
+ #if SQLITE_MAX_COLUMN
3714
+ if( p.pEList && p.pEList.nExpr>db.aLimit[SQLITE_LIMIT_COLUMN] ){
3715
+ sqlite3ErrorMsg(pParse, "too many columns in result set");
3716
+ }
3717
+ #endif
3718
+ return WRC_Continue;
3719
+ }
3720
+
3721
+ /*
3722
+ ** No-op routine for the parse-tree walker.
3723
+ **
3724
+ ** When this routine is the Walker.xExprCallback then expression trees
3725
+ ** are walked without any actions being taken at each node. Presumably,
3726
+ ** when this routine is used for Walker.xExprCallback then
3727
+ ** Walker.xSelectCallback is set to do something useful for every
3728
+ ** subquery in the parser tree.
3729
+ */
3730
+ static int exprWalkNoop( Walker NotUsed, ref Expr NotUsed2 )
3731
+ {
3732
+ UNUSED_PARAMETER2( NotUsed, NotUsed2 );
3733
+ return WRC_Continue;
3734
+ }
3735
+
3736
+ /*
3737
+ ** This routine "expands" a SELECT statement and all of its subqueries.
3738
+ ** For additional information on what it means to "expand" a SELECT
3739
+ ** statement, see the comment on the selectExpand worker callback above.
3740
+ **
3741
+ ** Expanding a SELECT statement is the first step in processing a
3742
+ ** SELECT statement. The SELECT statement must be expanded before
3743
+ ** name resolution is performed.
3744
+ **
3745
+ ** If anything goes wrong, an error message is written into pParse.
3746
+ ** The calling function can detect the problem by looking at pParse.nErr
3747
+ ** and/or pParse.db.mallocFailed.
3748
+ */
3749
+ static void sqlite3SelectExpand( Parse pParse, Select pSelect )
3750
+ {
3751
+ Walker w = new Walker();
3752
+ w.xSelectCallback = selectExpander;
3753
+ w.xExprCallback = exprWalkNoop;
3754
+ w.pParse = pParse;
3755
+ sqlite3WalkSelect( w, pSelect );
3756
+ }
3757
+
3758
+
3759
+ #if !SQLITE_OMIT_SUBQUERY
3760
+ /*
3761
+ ** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo()
3762
+ ** interface.
3763
+ **
3764
+ ** For each FROM-clause subquery, add Column.zType and Column.zColl
3765
+ ** information to the Table ure that represents the result set
3766
+ ** of that subquery.
3767
+ **
3768
+ ** The Table ure that represents the result set was coned
3769
+ ** by selectExpander() but the type and collation information was omitted
3770
+ ** at that point because identifiers had not yet been resolved. This
3771
+ ** routine is called after identifier resolution.
3772
+ */
3773
+ static int selectAddSubqueryTypeInfo( Walker pWalker, Select p )
3774
+ {
3775
+ Parse pParse;
3776
+ int i;
3777
+ SrcList pTabList;
3778
+ SrcList_item pFrom;
3779
+
3780
+ Debug.Assert( ( p.selFlags & SF_Resolved ) != 0 );
3781
+ if ((p.selFlags & SF_HasTypeInfo) == 0)
3782
+ {
3783
+ p.selFlags |= SF_HasTypeInfo;
3784
+ pParse = pWalker.pParse;
3785
+ pTabList = p.pSrc;
3786
+ for (i = 0; i < pTabList.nSrc; i++)//, pFrom++ )
3787
+ {
3788
+ pFrom = pTabList.a[i];
3789
+ Table pTab = pFrom.pTab;
3790
+ if (ALWAYS(pTab != null) && (pTab.tabFlags & TF_Ephemeral) != 0)
3791
+ {
3792
+ /* A sub-query in the FROM clause of a SELECT */
3793
+ Select pSel = pFrom.pSelect;
3794
+ Debug.Assert(pSel != null);
3795
+ while (pSel.pPrior != null) pSel = pSel.pPrior;
3796
+ selectAddColumnTypeAndCollation(pParse, pTab.nCol, pTab.aCol, pSel);
3797
+ }
3798
+ }
3799
+ }
3800
+ return WRC_Continue;
3801
+ }
3802
+ #endif
3803
+
3804
+
3805
+ /*
3806
+ ** This routine adds datatype and collating sequence information to
3807
+ ** the Table ures of all FROM-clause subqueries in a
3808
+ ** SELECT statement.
3809
+ **
3810
+ ** Use this routine after name resolution.
3811
+ */
3812
+ static void sqlite3SelectAddTypeInfo( Parse pParse, Select pSelect )
3813
+ {
3814
+ #if !SQLITE_OMIT_SUBQUERY
3815
+ Walker w = new Walker();
3816
+ w.xSelectCallback = selectAddSubqueryTypeInfo;
3817
+ w.xExprCallback = exprWalkNoop;
3818
+ w.pParse = pParse;
3819
+ sqlite3WalkSelect( w, pSelect );
3820
+ #endif
3821
+ }
3822
+
3823
+
3824
+ /*
3825
+ ** This routine sets of a SELECT statement for processing. The
3826
+ ** following is accomplished:
3827
+ **
3828
+ ** * VDBE VdbeCursor numbers are assigned to all FROM-clause terms.
3829
+ ** * Ephemeral Table objects are created for all FROM-clause subqueries.
3830
+ ** * ON and USING clauses are shifted into WHERE statements
3831
+ ** * Wildcards "*" and "TABLE.*" in result sets are expanded.
3832
+ ** * Identifiers in expression are matched to tables.
3833
+ **
3834
+ ** This routine acts recursively on all subqueries within the SELECT.
3835
+ */
3836
+ static void sqlite3SelectPrep(
3837
+ Parse pParse, /* The parser context */
3838
+ Select p, /* The SELECT statement being coded. */
3839
+ NameContext pOuterNC /* Name context for container */
3840
+ )
3841
+ {
3842
+ sqlite3 db;
3843
+ if ( NEVER( p == null ) ) return;
3844
+ db = pParse.db;
3845
+ if ( ( p.selFlags & SF_HasTypeInfo ) != 0 ) return;
3846
+ sqlite3SelectExpand( pParse, p );
3847
+ if ( pParse.nErr != 0 /*|| db.mallocFailed != 0 */ ) return;
3848
+ sqlite3ResolveSelectNames( pParse, p, pOuterNC );
3849
+ if ( pParse.nErr != 0 /*|| db.mallocFailed != 0 */ ) return;
3850
+ sqlite3SelectAddTypeInfo( pParse, p );
3851
+ }
3852
+
3853
+ /*
3854
+ ** Reset the aggregate accumulator.
3855
+ **
3856
+ ** The aggregate accumulator is a set of memory cells that hold
3857
+ ** intermediate results while calculating an aggregate. This
3858
+ ** routine simply stores NULLs in all of those memory cells.
3859
+ */
3860
+ static void resetAccumulator( Parse pParse, AggInfo pAggInfo )
3861
+ {
3862
+ Vdbe v = pParse.pVdbe;
3863
+ int i;
3864
+ AggInfo_func pFunc;
3865
+ if ( pAggInfo.nFunc + pAggInfo.nColumn == 0 )
3866
+ {
3867
+ return;
3868
+ }
3869
+ for ( i = 0; i < pAggInfo.nColumn; i++ )
3870
+ {
3871
+ sqlite3VdbeAddOp2( v, OP_Null, 0, pAggInfo.aCol[i].iMem );
3872
+ }
3873
+ for ( i = 0; i < pAggInfo.nFunc; i++ )
3874
+ {//, pFunc++){
3875
+ pFunc = pAggInfo.aFunc[i];
3876
+ sqlite3VdbeAddOp2( v, OP_Null, 0, pFunc.iMem );
3877
+ if ( pFunc.iDistinct >= 0 )
3878
+ {
3879
+ Expr pE = pFunc.pExpr;
3880
+ Debug.Assert( !ExprHasProperty( pE, EP_xIsSelect ) );
3881
+ if ( pE.x.pList == null || pE.x.pList.nExpr != 1 )
3882
+ {
3883
+ sqlite3ErrorMsg( pParse, "DISTINCT aggregates must have exactly one " +
3884
+ "argument" );
3885
+ pFunc.iDistinct = -1;
3886
+ }
3887
+ else
3888
+ {
3889
+ KeyInfo pKeyInfo = keyInfoFromExprList( pParse, pE.x.pList );
3890
+ sqlite3VdbeAddOp4( v, OP_OpenEphemeral, pFunc.iDistinct, 0, 0,
3891
+ pKeyInfo, P4_KEYINFO_HANDOFF );
3892
+ }
3893
+ }
3894
+ }
3895
+ }
3896
+
3897
+ /*
3898
+ ** Invoke the OP_AggFinalize opcode for every aggregate function
3899
+ ** in the AggInfo structure.
3900
+ */
3901
+ static void finalizeAggFunctions( Parse pParse, AggInfo pAggInfo )
3902
+ {
3903
+ Vdbe v = pParse.pVdbe;
3904
+ int i;
3905
+ AggInfo_func pF;
3906
+ for ( i = 0; i < pAggInfo.nFunc; i++ )
3907
+ {//, pF++){
3908
+ pF = pAggInfo.aFunc[i];
3909
+ ExprList pList = pF.pExpr.x.pList;
3910
+ Debug.Assert( !ExprHasProperty( pF.pExpr, EP_xIsSelect ) );
3911
+ sqlite3VdbeAddOp4( v, OP_AggFinal, pF.iMem, pList != null ? pList.nExpr : 0, 0,
3912
+ pF.pFunc, P4_FUNCDEF );
3913
+ }
3914
+ }
3915
+
3916
+ /*
3917
+ ** Update the accumulator memory cells for an aggregate based on
3918
+ ** the current cursor position.
3919
+ */
3920
+ static void updateAccumulator( Parse pParse, AggInfo pAggInfo )
3921
+ {
3922
+ Vdbe v = pParse.pVdbe;
3923
+ int i;
3924
+ AggInfo_func pF;
3925
+ AggInfo_col pC;
3926
+
3927
+ pAggInfo.directMode = 1;
3928
+ sqlite3ExprCacheClear( pParse );
3929
+ for ( i = 0; i < pAggInfo.nFunc; i++ )
3930
+ {//, pF++){
3931
+ pF = pAggInfo.aFunc[i];
3932
+ int nArg;
3933
+ int addrNext = 0;
3934
+ int regAgg;
3935
+ Debug.Assert( !ExprHasProperty( pF.pExpr, EP_xIsSelect ) );
3936
+ ExprList pList = pF.pExpr.x.pList;
3937
+ if ( pList != null )
3938
+ {
3939
+ nArg = pList.nExpr;
3940
+ regAgg = sqlite3GetTempRange( pParse, nArg );
3941
+ sqlite3ExprCodeExprList( pParse, pList, regAgg, false );
3942
+ }
3943
+ else
3944
+ {
3945
+ nArg = 0;
3946
+ regAgg = 0;
3947
+ }
3948
+ if ( pF.iDistinct >= 0 )
3949
+ {
3950
+ addrNext = sqlite3VdbeMakeLabel( v );
3951
+ Debug.Assert( nArg == 1 );
3952
+ codeDistinct( pParse, pF.iDistinct, addrNext, 1, regAgg );
3953
+ }
3954
+ if ( ( pF.pFunc.flags & SQLITE_FUNC_NEEDCOLL ) != 0 )
3955
+ {
3956
+ CollSeq pColl = null;
3957
+ ExprList_item pItem;
3958
+ int j;
3959
+ Debug.Assert( pList != null ); /* pList!=0 if pF->pFunc has NEEDCOLL */
3960
+ for ( j = 0; pColl == null && j < nArg; j++ )
3961
+ {//, pItem++){
3962
+ pItem = pList.a[j];
3963
+ pColl = sqlite3ExprCollSeq( pParse, pItem.pExpr );
3964
+ }
3965
+ if ( pColl == null )
3966
+ {
3967
+ pColl = pParse.db.pDfltColl;
3968
+ }
3969
+ sqlite3VdbeAddOp4( v, OP_CollSeq, 0, 0, 0, pColl, P4_COLLSEQ );
3970
+ }
3971
+ sqlite3VdbeAddOp4( v, OP_AggStep, 0, regAgg, pF.iMem,
3972
+ pF.pFunc, P4_FUNCDEF );
3973
+ sqlite3VdbeChangeP5( v, (u8)nArg );
3974
+ sqlite3ExprCacheAffinityChange( pParse, regAgg, nArg );
3975
+ sqlite3ReleaseTempRange( pParse, regAgg, nArg );
3976
+ if ( addrNext != 0 )
3977
+ {
3978
+ sqlite3VdbeResolveLabel( v, addrNext );
3979
+ sqlite3ExprCacheClear( pParse );
3980
+ }
3981
+ }
3982
+ for ( i = 0; i < pAggInfo.nAccumulator; i++ )//, pC++)
3983
+ {
3984
+ pC = pAggInfo.aCol[i];
3985
+ sqlite3ExprCode( pParse, pC.pExpr, pC.iMem );
3986
+ }
3987
+ pAggInfo.directMode = 0;
3988
+ sqlite3ExprCacheClear( pParse );
3989
+ }
3990
+
3991
+ /*
3992
+ ** Generate code for the SELECT statement given in the p argument.
3993
+ **
3994
+ ** The results are distributed in various ways depending on the
3995
+ ** contents of the SelectDest structure pointed to by argument pDest
3996
+ ** as follows:
3997
+ **
3998
+ ** pDest.eDest Result
3999
+ ** ------------ -------------------------------------------
4000
+ ** SRT_Output Generate a row of output (using the OP_ResultRow
4001
+ ** opcode) for each row in the result set.
4002
+ **
4003
+ ** SRT_Mem Only valid if the result is a single column.
4004
+ ** Store the first column of the first result row
4005
+ ** in register pDest.iParm then abandon the rest
4006
+ ** of the query. This destination implies "LIMIT 1".
4007
+ **
4008
+ ** SRT_Set The result must be a single column. Store each
4009
+ ** row of result as the key in table pDest.iParm.
4010
+ ** Apply the affinity pDest.affinity before storing
4011
+ ** results. Used to implement "IN (SELECT ...)".
4012
+ **
4013
+ ** SRT_Union Store results as a key in a temporary table pDest.iParm.
4014
+ **
4015
+ ** SRT_Except Remove results from the temporary table pDest.iParm.
4016
+ **
4017
+ ** SRT_Table Store results in temporary table pDest.iParm.
4018
+ ** This is like SRT_EphemTab except that the table
4019
+ ** is assumed to already be open.
4020
+ **
4021
+ ** SRT_EphemTab Create an temporary table pDest.iParm and store
4022
+ ** the result there. The cursor is left open after
4023
+ ** returning. This is like SRT_Table except that
4024
+ ** this destination uses OP_OpenEphemeral to create
4025
+ ** the table first.
4026
+ **
4027
+ ** SRT_Coroutine Generate a co-routine that returns a new row of
4028
+ ** results each time it is invoked. The entry point
4029
+ ** of the co-routine is stored in register pDest.iParm.
4030
+ **
4031
+ ** SRT_Exists Store a 1 in memory cell pDest.iParm if the result
4032
+ ** set is not empty.
4033
+ **
4034
+ ** SRT_Discard Throw the results away. This is used by SELECT
4035
+ ** statements within triggers whose only purpose is
4036
+ ** the side-effects of functions.
4037
+ **
4038
+ ** This routine returns the number of errors. If any errors are
4039
+ ** encountered, then an appropriate error message is left in
4040
+ ** pParse.zErrMsg.
4041
+ **
4042
+ ** This routine does NOT free the Select structure passed in. The
4043
+ ** calling function needs to do that.
4044
+ */
4045
+ static SelectDest sdDummy = null;
4046
+ static bool bDummy = false;
4047
+
4048
+ static int sqlite3Select(
4049
+ Parse pParse, /* The parser context */
4050
+ Select p, /* The SELECT statement being coded. */
4051
+ ref SelectDest pDest /* What to do with the query results */
4052
+ )
4053
+ {
4054
+ int i, j; /* Loop counters */
4055
+ WhereInfo pWInfo; /* Return from sqlite3WhereBegin() */
4056
+ Vdbe v; /* The virtual machine under construction */
4057
+ bool isAgg; /* True for select lists like "count(*)" */
4058
+ ExprList pEList = new ExprList(); /* List of columns to extract. */
4059
+ SrcList pTabList = new SrcList(); /* List of tables to select from */
4060
+ Expr pWhere; /* The WHERE clause. May be NULL */
4061
+ ExprList pOrderBy; /* The ORDER BY clause. May be NULL */
4062
+ ExprList pGroupBy; /* The GROUP BY clause. May be NULL */
4063
+ Expr pHaving; /* The HAVING clause. May be NULL */
4064
+ bool isDistinct; /* True if the DISTINCT keyword is present */
4065
+ int distinct; /* Table to use for the distinct set */
4066
+ int rc = 1; /* Value to return from this function */
4067
+ int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
4068
+ AggInfo sAggInfo; /* Information used by aggregate queries */
4069
+ int iEnd; /* Address of the end of the query */
4070
+ sqlite3 db; /* The database connection */
4071
+
4072
+ db = pParse.db;
4073
+ if ( p == null /*|| db.mallocFailed != 0 */ || pParse.nErr != 0 )
4074
+ {
4075
+ return 1;
4076
+ }
4077
+ #if !SQLITE_OMIT_AUTHORIZATION
4078
+ if (sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0)) return 1;
4079
+ #endif
4080
+ sAggInfo = new AggInfo();// memset(sAggInfo, 0, sAggInfo).Length;
4081
+
4082
+ if ( pDest.eDest <= SRT_Discard ) //IgnorableOrderby(pDest))
4083
+ {
4084
+ Debug.Assert( pDest.eDest == SRT_Exists || pDest.eDest == SRT_Union ||
4085
+ pDest.eDest == SRT_Except || pDest.eDest == SRT_Discard );
4086
+ /* If ORDER BY makes no difference in the output then neither does
4087
+ ** DISTINCT so it can be removed too. */
4088
+ sqlite3ExprListDelete( db, ref p.pOrderBy );
4089
+ p.pOrderBy = null;
4090
+ p.selFlags = (u16)( p.selFlags & ~SF_Distinct );
4091
+ }
4092
+ sqlite3SelectPrep( pParse, p, null );
4093
+ pOrderBy = p.pOrderBy;
4094
+ pTabList = p.pSrc;
4095
+ pEList = p.pEList;
4096
+ if ( pParse.nErr != 0 /*|| db.mallocFailed != 0 */ )
4097
+ {
4098
+ goto select_end;
4099
+ }
4100
+ isAgg = ( p.selFlags & SF_Aggregate ) != 0;
4101
+ Debug.Assert( pEList != null );
4102
+
4103
+ /* Begin generating code.
4104
+ */
4105
+ v = sqlite3GetVdbe( pParse );
4106
+ if ( v == null ) goto select_end;
4107
+
4108
+ /* Generate code for all sub-queries in the FROM clause
4109
+ */
4110
+ #if !SQLITE_OMIT_SUBQUERY || !SQLITE_OMIT_VIEW
4111
+ for ( i = 0; p.pPrior == null && i < pTabList.nSrc; i++ )
4112
+ {
4113
+ SrcList_item pItem = pTabList.a[i];
4114
+ SelectDest dest = new SelectDest();
4115
+ Select pSub = pItem.pSelect;
4116
+ bool isAggSub;
4117
+
4118
+ if ( pSub == null || pItem.isPopulated != 0 ) continue;
4119
+
4120
+ /* Increment Parse.nHeight by the height of the largest expression
4121
+ ** tree refered to by this, the parent select. The child select
4122
+ ** may contain expression trees of at most
4123
+ ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
4124
+ ** more conservative than necessary, but much easier than enforcing
4125
+ ** an exact limit.
4126
+ */
4127
+ pParse.nHeight += sqlite3SelectExprHeight( p );
4128
+
4129
+ /* Check to see if the subquery can be absorbed into the parent. */
4130
+ isAggSub = ( pSub.selFlags & SF_Aggregate ) != 0;
4131
+ if ( flattenSubquery( pParse, p, i, isAgg, isAggSub ) != 0 )
4132
+ {
4133
+ if ( isAggSub )
4134
+ {
4135
+ isAgg = true;
4136
+ p.selFlags |= SF_Aggregate;
4137
+ }
4138
+ i = -1;
4139
+ }
4140
+ else
4141
+ {
4142
+ sqlite3SelectDestInit( dest, SRT_EphemTab, pItem.iCursor );
4143
+ Debug.Assert( 0 == pItem.isPopulated );
4144
+ sqlite3Select( pParse, pSub, ref dest );
4145
+ pItem.isPopulated = 1;
4146
+ }
4147
+ //if ( /* pParse.nErr != 0 || */ db.mallocFailed != 0 )
4148
+ //{
4149
+ // goto select_end;
4150
+ //}
4151
+ pParse.nHeight -= sqlite3SelectExprHeight( p );
4152
+ pTabList = p.pSrc;
4153
+ if ( !( pDest.eDest <= SRT_Discard ) )// if( !IgnorableOrderby(pDest) )
4154
+ {
4155
+ pOrderBy = p.pOrderBy;
4156
+ }
4157
+ }
4158
+ pEList = p.pEList;
4159
+ #endif
4160
+ pWhere = p.pWhere;
4161
+ pGroupBy = p.pGroupBy;
4162
+ pHaving = p.pHaving;
4163
+ isDistinct = ( p.selFlags & SF_Distinct ) != 0;
4164
+
4165
+ #if !SQLITE_OMIT_COMPOUND_SELECT
4166
+ /* If there is are a sequence of queries, do the earlier ones first.
4167
+ */
4168
+ if ( p.pPrior != null )
4169
+ {
4170
+ if ( p.pRightmost == null )
4171
+ {
4172
+ Select pLoop, pRight = null;
4173
+ int cnt = 0;
4174
+ int mxSelect;
4175
+ for ( pLoop = p; pLoop != null; pLoop = pLoop.pPrior, cnt++ )
4176
+ {
4177
+ pLoop.pRightmost = p;
4178
+ pLoop.pNext = pRight;
4179
+ pRight = pLoop;
4180
+ }
4181
+ mxSelect = db.aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
4182
+ if ( mxSelect != 0 && cnt > mxSelect )
4183
+ {
4184
+ sqlite3ErrorMsg( pParse, "too many terms in compound SELECT" );
4185
+ return 1;
4186
+ }
4187
+ }
4188
+ return multiSelect( pParse, p, pDest );
4189
+ }
4190
+ #endif
4191
+
4192
+ /* If writing to memory or generating a set
4193
+ ** only a single column may be output.
4194
+ */
4195
+ #if !SQLITE_OMIT_SUBQUERY
4196
+ if ( checkForMultiColumnSelectError( pParse, pDest, pEList.nExpr ) )
4197
+ {
4198
+ goto select_end;
4199
+ }
4200
+ #endif
4201
+ /* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
4202
+ ** GROUP BY might use an index, DISTINCT never does.
4203
+ */
4204
+ Debug.Assert( p.pGroupBy == null || ( p.selFlags & SF_Aggregate ) != 0 );
4205
+ if ( ( p.selFlags & ( SF_Distinct | SF_Aggregate ) ) == SF_Distinct )
4206
+ {
4207
+ p.pGroupBy = sqlite3ExprListDup( db, p.pEList, 0 );
4208
+ pGroupBy = p.pGroupBy;
4209
+ p.selFlags = (u16)( p.selFlags & ~SF_Distinct );
4210
+ isDistinct = false;
4211
+ }
4212
+
4213
+ /* If there is an ORDER BY clause, then this sorting
4214
+ ** index might end up being unused if the data can be
4215
+ ** extracted in pre-sorted order. If that is the case, then the
4216
+ ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
4217
+ ** we figure out that the sorting index is not needed. The addrSortIndex
4218
+ ** variable is used to facilitate that change.
4219
+ */
4220
+ if ( pOrderBy != null )
4221
+ {
4222
+ KeyInfo pKeyInfo;
4223
+ pKeyInfo = keyInfoFromExprList( pParse, pOrderBy );
4224
+ pOrderBy.iECursor = pParse.nTab++;
4225
+ p.addrOpenEphm[2] = addrSortIndex =
4226
+ sqlite3VdbeAddOp4( v, OP_OpenEphemeral,
4227
+ pOrderBy.iECursor, pOrderBy.nExpr + 2, 0,
4228
+ pKeyInfo, P4_KEYINFO_HANDOFF );
4229
+ }
4230
+ else
4231
+ {
4232
+ addrSortIndex = -1;
4233
+ }
4234
+
4235
+ /* If the output is destined for a temporary table, open that table.
4236
+ */
4237
+ if ( pDest.eDest == SRT_EphemTab )
4238
+ {
4239
+ sqlite3VdbeAddOp2( v, OP_OpenEphemeral, pDest.iParm, pEList.nExpr );
4240
+ }
4241
+
4242
+ /* Set the limiter.
4243
+ */
4244
+ iEnd = sqlite3VdbeMakeLabel( v );
4245
+ computeLimitRegisters( pParse, p, iEnd );
4246
+
4247
+ /* Open a virtual index to use for the distinct set.
4248
+ */
4249
+ if ( isDistinct )
4250
+ {
4251
+ KeyInfo pKeyInfo;
4252
+ Debug.Assert( isAgg || pGroupBy != null );
4253
+ distinct = pParse.nTab++;
4254
+ pKeyInfo = keyInfoFromExprList( pParse, p.pEList );
4255
+ sqlite3VdbeAddOp4( v, OP_OpenEphemeral, distinct, 0, 0,
4256
+ pKeyInfo, P4_KEYINFO_HANDOFF );
4257
+ }
4258
+ else
4259
+ {
4260
+ distinct = -1;
4261
+ }
4262
+
4263
+ /* Aggregate and non-aggregate queries are handled differently */
4264
+ if ( !isAgg && pGroupBy == null )
4265
+ {
4266
+ /* This case is for non-aggregate queries
4267
+ ** Begin the database scan
4268
+ */
4269
+ pWInfo = sqlite3WhereBegin( pParse, pTabList, pWhere, ref pOrderBy, 0 );
4270
+ if ( pWInfo == null ) goto select_end;
4271
+
4272
+ /* If sorting index that was created by a prior OP_OpenEphemeral
4273
+ ** instruction ended up not being needed, then change the OP_OpenEphemeral
4274
+ ** into an OP_Noop.
4275
+ */
4276
+ if ( addrSortIndex >= 0 && pOrderBy == null )
4277
+ {
4278
+ sqlite3VdbeChangeToNoop( v, addrSortIndex, 1 );
4279
+ p.addrOpenEphm[2] = -1;
4280
+ }
4281
+
4282
+ /* Use the standard inner loop
4283
+ */
4284
+ Debug.Assert( !isDistinct );
4285
+ selectInnerLoop( pParse, p, pEList, 0, 0, pOrderBy, -1, pDest,
4286
+ pWInfo.iContinue, pWInfo.iBreak );
4287
+
4288
+ /* End the database scan loop.
4289
+ */
4290
+ sqlite3WhereEnd( pWInfo );
4291
+ }
4292
+ else
4293
+ {
4294
+ /* This is the processing for aggregate queries */
4295
+ NameContext sNC; /* Name context for processing aggregate information */
4296
+ int iAMem; /* First Mem address for storing current GROUP BY */
4297
+ int iBMem; /* First Mem address for previous GROUP BY */
4298
+ int iUseFlag; /* Mem address holding flag indicating that at least
4299
+ ** one row of the input to the aggregator has been
4300
+ ** processed */
4301
+ int iAbortFlag; /* Mem address which causes query abort if positive */
4302
+ int groupBySort; /* Rows come from source in GR BY' clause thanROUP BY order */
4303
+
4304
+ int addrEnd; /* End of processing for this SELECT */
4305
+
4306
+ /* Remove any and all aliases between the result set and the
4307
+ ** GROUP BY clause.
4308
+ */
4309
+ if ( pGroupBy != null )
4310
+ {
4311
+ int k; /* Loop counter */
4312
+ ExprList_item pItem; /* For looping over expression in a list */
4313
+
4314
+ for ( k = p.pEList.nExpr; k > 0; k-- )//, pItem++)
4315
+ {
4316
+ pItem = p.pEList.a[p.pEList.nExpr - k];
4317
+ pItem.iAlias = 0;
4318
+ }
4319
+ for ( k = pGroupBy.nExpr; k > 0; k-- )//, pItem++ )
4320
+ {
4321
+ pItem = pGroupBy.a[pGroupBy.nExpr - k];
4322
+ pItem.iAlias = 0;
4323
+ }
4324
+ }
4325
+
4326
+ /* Create a label to jump to when we want to abort the query */
4327
+ addrEnd = sqlite3VdbeMakeLabel( v );
4328
+
4329
+ /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
4330
+ ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
4331
+ ** SELECT statement.
4332
+ */
4333
+ sNC = new NameContext(); // memset(sNC, 0, sNC).Length;
4334
+ sNC.pParse = pParse;
4335
+ sNC.pSrcList = pTabList;
4336
+ sNC.pAggInfo = sAggInfo;
4337
+ sAggInfo.nSortingColumn = pGroupBy != null ? pGroupBy.nExpr + 1 : 0;
4338
+ sAggInfo.pGroupBy = pGroupBy;
4339
+ sqlite3ExprAnalyzeAggList( sNC, pEList );
4340
+ sqlite3ExprAnalyzeAggList( sNC, pOrderBy );
4341
+ if ( pHaving != null )
4342
+ {
4343
+ sqlite3ExprAnalyzeAggregates( sNC, ref pHaving );
4344
+ }
4345
+ sAggInfo.nAccumulator = sAggInfo.nColumn;
4346
+ for ( i = 0; i < sAggInfo.nFunc; i++ )
4347
+ {
4348
+ Debug.Assert( !ExprHasProperty( sAggInfo.aFunc[i].pExpr, EP_xIsSelect ) );
4349
+ sqlite3ExprAnalyzeAggList( sNC, sAggInfo.aFunc[i].pExpr.x.pList );
4350
+ }
4351
+ // if ( db.mallocFailed != 0 ) goto select_end;
4352
+
4353
+ /* Processing for aggregates with GROUP BY is very different and
4354
+ ** much more complex than aggregates without a GROUP BY.
4355
+ */
4356
+ if ( pGroupBy != null )
4357
+ {
4358
+ KeyInfo pKeyInfo; /* Keying information for the group by clause */
4359
+ int j1; /* A-vs-B comparision jump */
4360
+ int addrOutputRow; /* Start of subroutine that outputs a result row */
4361
+ int regOutputRow; /* Return address register for output subroutine */
4362
+ int addrSetAbort; /* Set the abort flag and return */
4363
+ int addrTopOfLoop; /* Top of the input loop */
4364
+ int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
4365
+ int addrReset; /* Subroutine for resetting the accumulator */
4366
+ int regReset; /* Return address register for reset subroutine */
4367
+
4368
+ /* If there is a GROUP BY clause we might need a sorting index to
4369
+ ** implement it. Allocate that sorting index now. If it turns out
4370
+ ** that we do not need it after all, the OpenEphemeral instruction
4371
+ ** will be converted into a Noop.
4372
+ */
4373
+ sAggInfo.sortingIdx = pParse.nTab++;
4374
+ pKeyInfo = keyInfoFromExprList( pParse, pGroupBy );
4375
+ addrSortingIdx = sqlite3VdbeAddOp4( v, OP_OpenEphemeral,
4376
+ sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
4377
+ 0, pKeyInfo, P4_KEYINFO_HANDOFF );
4378
+
4379
+ /* Initialize memory locations used by GROUP BY aggregate processing
4380
+ */
4381
+ iUseFlag = ++pParse.nMem;
4382
+ iAbortFlag = ++pParse.nMem;
4383
+ regOutputRow = ++pParse.nMem;
4384
+ addrOutputRow = sqlite3VdbeMakeLabel( v );
4385
+ regReset = ++pParse.nMem;
4386
+ addrReset = sqlite3VdbeMakeLabel( v );
4387
+ iAMem = pParse.nMem + 1;
4388
+ pParse.nMem += pGroupBy.nExpr;
4389
+ iBMem = pParse.nMem + 1;
4390
+ pParse.nMem += pGroupBy.nExpr;
4391
+ sqlite3VdbeAddOp2( v, OP_Integer, 0, iAbortFlag );
4392
+ #if SQLITE_DEBUG
4393
+ VdbeComment( v, "clear abort flag" );
4394
+ #endif
4395
+ sqlite3VdbeAddOp2( v, OP_Integer, 0, iUseFlag );
4396
+ #if SQLITE_DEBUG
4397
+ VdbeComment( v, "indicate accumulator empty" );
4398
+ #endif
4399
+
4400
+ /* Begin a loop that will extract all source rows in GROUP BY order.
4401
+ ** This might involve two separate loops with an OP_Sort in between, or
4402
+ ** it might be a single loop that uses an index to extract information
4403
+ ** in the right order to begin with.
4404
+ */
4405
+ sqlite3VdbeAddOp2( v, OP_Gosub, regReset, addrReset );
4406
+ pWInfo = sqlite3WhereBegin( pParse, pTabList, pWhere, ref pGroupBy, 0 );
4407
+ if ( pWInfo == null ) goto select_end;
4408
+ if ( pGroupBy == null )
4409
+ {
4410
+ /* The optimizer is able to deliver rows in group by order so
4411
+ ** we do not have to sort. The OP_OpenEphemeral table will be
4412
+ ** cancelled later because we still need to use the pKeyInfo
4413
+ */
4414
+ pGroupBy = p.pGroupBy;
4415
+ groupBySort = 0;
4416
+ }
4417
+ else
4418
+ {
4419
+ /* Rows are coming out in undetermined order. We have to push
4420
+ ** each row into a sorting index, terminate the first loop,
4421
+ ** then loop over the sorting index in order to get the output
4422
+ ** in sorted order
4423
+ */
4424
+ int regBase;
4425
+ int regRecord;
4426
+ int nCol;
4427
+ int nGroupBy;
4428
+
4429
+ groupBySort = 1;
4430
+ nGroupBy = pGroupBy.nExpr;
4431
+ nCol = nGroupBy + 1;
4432
+ j = nGroupBy + 1;
4433
+ for ( i = 0; i < sAggInfo.nColumn; i++ )
4434
+ {
4435
+ if ( sAggInfo.aCol[i].iSorterColumn >= j )
4436
+ {
4437
+ nCol++;
4438
+ j++;
4439
+ }
4440
+ }
4441
+ regBase = sqlite3GetTempRange( pParse, nCol );
4442
+ sqlite3ExprCacheClear( pParse );
4443
+ sqlite3ExprCodeExprList( pParse, pGroupBy, regBase, false );
4444
+ sqlite3VdbeAddOp2( v, OP_Sequence, sAggInfo.sortingIdx, regBase + nGroupBy );
4445
+ j = nGroupBy + 1;
4446
+ for ( i = 0; i < sAggInfo.nColumn; i++ )
4447
+ {
4448
+ AggInfo_col pCol = sAggInfo.aCol[i];
4449
+ if ( pCol.iSorterColumn >= j )
4450
+ {
4451
+ int r1 = j + regBase;
4452
+ int r2;
4453
+ r2 = sqlite3ExprCodeGetColumn( pParse,
4454
+ pCol.pTab, pCol.iColumn, pCol.iTable, r1 );
4455
+ if ( r1 != r2 )
4456
+ {
4457
+ sqlite3VdbeAddOp2( v, OP_SCopy, r2, r1 );
4458
+ }
4459
+ j++;
4460
+ }
4461
+ }
4462
+ regRecord = sqlite3GetTempReg( pParse );
4463
+ sqlite3VdbeAddOp3( v, OP_MakeRecord, regBase, nCol, regRecord );
4464
+ sqlite3VdbeAddOp2( v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord );
4465
+ sqlite3ReleaseTempReg( pParse, regRecord );
4466
+ sqlite3ReleaseTempRange( pParse, regBase, nCol );
4467
+ sqlite3WhereEnd( pWInfo );
4468
+ sqlite3VdbeAddOp2( v, OP_Sort, sAggInfo.sortingIdx, addrEnd );
4469
+ #if SQLITE_DEBUG
4470
+ VdbeComment( v, "GROUP BY sort" );
4471
+ #endif
4472
+ sAggInfo.useSortingIdx = 1;
4473
+ sqlite3ExprCacheClear( pParse );
4474
+ }
4475
+
4476
+ /* Evaluate the current GROUP BY terms and store in b0, b1, b2...
4477
+ ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth)
4478
+ ** Then compare the current GROUP BY terms against the GROUP BY terms
4479
+ ** from the previous row currently stored in a0, a1, a2...
4480
+ */
4481
+ addrTopOfLoop = sqlite3VdbeCurrentAddr( v );
4482
+ sqlite3ExprCacheClear( pParse );
4483
+ for ( j = 0; j < pGroupBy.nExpr; j++ )
4484
+ {
4485
+ if ( groupBySort != 0 )
4486
+ {
4487
+ sqlite3VdbeAddOp3( v, OP_Column, sAggInfo.sortingIdx, j, iBMem + j );
4488
+ }
4489
+ else
4490
+ {
4491
+ sAggInfo.directMode = 1;
4492
+ sqlite3ExprCode( pParse, pGroupBy.a[j].pExpr, iBMem + j );
4493
+ }
4494
+ }
4495
+ sqlite3VdbeAddOp4( v, OP_Compare, iAMem, iBMem, pGroupBy.nExpr,
4496
+ pKeyInfo, P4_KEYINFO );
4497
+ j1 = sqlite3VdbeCurrentAddr( v );
4498
+ sqlite3VdbeAddOp3( v, OP_Jump, j1 + 1, 0, j1 + 1 );
4499
+
4500
+ /* Generate code that runs whenever the GROUP BY changes.
4501
+ ** Changes in the GROUP BY are detected by the previous code
4502
+ ** block. If there were no changes, this block is skipped.
4503
+ **
4504
+ ** This code copies current group by terms in b0,b1,b2,...
4505
+ ** over to a0,a1,a2. It then calls the output subroutine
4506
+ ** and resets the aggregate accumulator registers in preparation
4507
+ ** for the next GROUP BY batch.
4508
+ */
4509
+ sqlite3ExprCodeMove( pParse, iBMem, iAMem, pGroupBy.nExpr );
4510
+ sqlite3VdbeAddOp2( v, OP_Gosub, regOutputRow, addrOutputRow );
4511
+ #if SQLITE_DEBUG
4512
+ VdbeComment( v, "output one row" );
4513
+ #endif
4514
+ sqlite3VdbeAddOp2( v, OP_IfPos, iAbortFlag, addrEnd );
4515
+ #if SQLITE_DEBUG
4516
+ VdbeComment( v, "check abort flag" );
4517
+ #endif
4518
+ sqlite3VdbeAddOp2( v, OP_Gosub, regReset, addrReset );
4519
+ #if SQLITE_DEBUG
4520
+ VdbeComment( v, "reset accumulator" );
4521
+ #endif
4522
+
4523
+ /* Update the aggregate accumulators based on the content of
4524
+ ** the current row
4525
+ */
4526
+ sqlite3VdbeJumpHere( v, j1 );
4527
+ updateAccumulator( pParse, sAggInfo );
4528
+ sqlite3VdbeAddOp2( v, OP_Integer, 1, iUseFlag );
4529
+ #if SQLITE_DEBUG
4530
+ VdbeComment( v, "indicate data in accumulator" );
4531
+ #endif
4532
+ /* End of the loop
4533
+ */
4534
+ if ( groupBySort != 0 )
4535
+ {
4536
+ sqlite3VdbeAddOp2( v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop );
4537
+ }
4538
+ else
4539
+ {
4540
+ sqlite3WhereEnd( pWInfo );
4541
+ sqlite3VdbeChangeToNoop( v, addrSortingIdx, 1 );
4542
+ }
4543
+
4544
+ /* Output the final row of result
4545
+ */
4546
+ sqlite3VdbeAddOp2( v, OP_Gosub, regOutputRow, addrOutputRow );
4547
+ #if SQLITE_DEBUG
4548
+ VdbeComment( v, "output final row" );
4549
+ #endif
4550
+ /* Jump over the subroutines
4551
+ */
4552
+ sqlite3VdbeAddOp2( v, OP_Goto, 0, addrEnd );
4553
+
4554
+ /* Generate a subroutine that outputs a single row of the result
4555
+ ** set. This subroutine first looks at the iUseFlag. If iUseFlag
4556
+ ** is less than or equal to zero, the subroutine is a no-op. If
4557
+ ** the processing calls for the query to abort, this subroutine
4558
+ ** increments the iAbortFlag memory location before returning in
4559
+ ** order to signal the caller to abort.
4560
+ */
4561
+ addrSetAbort = sqlite3VdbeCurrentAddr( v );
4562
+ sqlite3VdbeAddOp2( v, OP_Integer, 1, iAbortFlag );
4563
+ VdbeComment( v, "set abort flag" );
4564
+ sqlite3VdbeAddOp1( v, OP_Return, regOutputRow );
4565
+ sqlite3VdbeResolveLabel( v, addrOutputRow );
4566
+ addrOutputRow = sqlite3VdbeCurrentAddr( v );
4567
+ sqlite3VdbeAddOp2( v, OP_IfPos, iUseFlag, addrOutputRow + 2 );
4568
+ VdbeComment( v, "Groupby result generator entry point" );
4569
+ sqlite3VdbeAddOp1( v, OP_Return, regOutputRow );
4570
+ finalizeAggFunctions( pParse, sAggInfo );
4571
+ sqlite3ExprIfFalse( pParse, pHaving, addrOutputRow + 1, SQLITE_JUMPIFNULL );
4572
+ selectInnerLoop( pParse, p, p.pEList, 0, 0, pOrderBy,
4573
+ distinct, pDest,
4574
+ addrOutputRow + 1, addrSetAbort );
4575
+ sqlite3VdbeAddOp1( v, OP_Return, regOutputRow );
4576
+ VdbeComment( v, "end groupby result generator" );
4577
+
4578
+ /* Generate a subroutine that will reset the group-by accumulator
4579
+ */
4580
+ sqlite3VdbeResolveLabel( v, addrReset );
4581
+ resetAccumulator( pParse, sAggInfo );
4582
+ sqlite3VdbeAddOp1( v, OP_Return, regReset );
4583
+
4584
+ } /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
4585
+ else
4586
+ {
4587
+ ExprList pDel = null;
4588
+ #if !SQLITE_OMIT_BTREECOUNT
4589
+ Table pTab;
4590
+ if ( ( pTab = isSimpleCount( p, sAggInfo ) ) != null )
4591
+ {
4592
+ /* If isSimpleCount() returns a pointer to a Table structure, then
4593
+ ** the SQL statement is of the form:
4594
+ **
4595
+ ** SELECT count(*) FROM <tbl>
4596
+ **
4597
+ ** where the Table structure returned represents table <tbl>.
4598
+ **
4599
+ ** This statement is so common that it is optimized specially. The
4600
+ ** OP_Count instruction is executed either on the intkey table that
4601
+ ** contains the data for table <tbl> or on one of its indexes. It
4602
+ ** is better to execute the op on an index, as indexes are almost
4603
+ ** always spread across less pages than their corresponding tables.
4604
+ */
4605
+ int iDb = sqlite3SchemaToIndex( pParse.db, pTab.pSchema );
4606
+ int iCsr = pParse.nTab++; /* Cursor to scan b-tree */
4607
+ Index pIdx; /* Iterator variable */
4608
+ KeyInfo pKeyInfo = null; /* Keyinfo for scanned index */
4609
+ Index pBest = null; /* Best index found so far */
4610
+ int iRoot = pTab.tnum; /* Root page of scanned b-tree */
4611
+
4612
+ sqlite3CodeVerifySchema( pParse, iDb );
4613
+ sqlite3TableLock( pParse, iDb, pTab.tnum, 0, pTab.zName );
4614
+
4615
+ /* Search for the index that has the least amount of columns. If
4616
+ ** there is such an index, and it has less columns than the table
4617
+ ** does, then we can assume that it consumes less space on disk and
4618
+ ** will therefore be cheaper to scan to determine the query result.
4619
+ ** In this case set iRoot to the root page number of the index b-tree
4620
+ ** and pKeyInfo to the KeyInfo structure required to navigate the
4621
+ ** index.
4622
+ **
4623
+ ** In practice the KeyInfo structure will not be used. It is only
4624
+ ** passed to keep OP_OpenRead happy.
4625
+ */
4626
+ for ( pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext )
4627
+ {
4628
+ if ( null == pBest || pIdx.nColumn < pBest.nColumn )
4629
+ {
4630
+ pBest = pIdx;
4631
+ }
4632
+ }
4633
+ if ( pBest != null && pBest.nColumn < pTab.nCol )
4634
+ {
4635
+ iRoot = pBest.tnum;
4636
+ pKeyInfo = sqlite3IndexKeyinfo( pParse, pBest );
4637
+ }
4638
+
4639
+ /* Open a read-only cursor, execute the OP_Count, close the cursor. */
4640
+ sqlite3VdbeAddOp3( v, OP_OpenRead, iCsr, iRoot, iDb );
4641
+ if ( pKeyInfo != null )
4642
+ {
4643
+ sqlite3VdbeChangeP4( v, -1, pKeyInfo, P4_KEYINFO_HANDOFF );
4644
+ }
4645
+ sqlite3VdbeAddOp2( v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem );
4646
+ sqlite3VdbeAddOp1( v, OP_Close, iCsr );
4647
+ }
4648
+ else
4649
+ #endif //* SQLITE_OMIT_BTREECOUNT */
4650
+ {
4651
+
4652
+ /* Check if the query is of one of the following forms:
4653
+ **
4654
+ ** SELECT min(x) FROM ...
4655
+ ** SELECT max(x) FROM ...
4656
+ **
4657
+ ** If it is, then ask the code in where.c to attempt to sort results
4658
+ ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause.
4659
+ ** If where.c is able to produce results sorted in this order, then
4660
+ ** add vdbe code to break out of the processing loop after the
4661
+ ** first iteration (since the first iteration of the loop is
4662
+ ** guaranteed to operate on the row with the minimum or maximum
4663
+ ** value of x, the only row required).
4664
+ **
4665
+ ** A special flag must be passed to sqlite3WhereBegin() to slightly
4666
+ ** modify behavior as follows:
4667
+ **
4668
+ ** + If the query is a "SELECT min(x)", then the loop coded by
4669
+ ** where.c should not iterate over any values with a NULL value
4670
+ ** for x.
4671
+ **
4672
+ ** + The optimizer code in where.c (the thing that decides which
4673
+ ** index or indices to use) should place a different priority on
4674
+ ** satisfying the 'ORDER BY' clause than it does in other cases.
4675
+ ** Refer to code and comments in where.c for details.
4676
+ */
4677
+ ExprList pMinMax = null;
4678
+ int flag = minMaxQuery( p );
4679
+ if ( flag != 0 )
4680
+ {
4681
+ Debug.Assert( !ExprHasProperty( p.pEList.a[0].pExpr, EP_xIsSelect ) );
4682
+ pMinMax = sqlite3ExprListDup( db, p.pEList.a[0].pExpr.x.pList, 0 );
4683
+ pDel = pMinMax;
4684
+ if ( pMinMax != null )///* && 0 == db.mallocFailed */ )
4685
+ {
4686
+ pMinMax.a[0].sortOrder = (u8)( flag != WHERE_ORDERBY_MIN ? 1 : 0 );
4687
+ pMinMax.a[0].pExpr.op = TK_COLUMN;
4688
+ }
4689
+ }
4690
+
4691
+ /* This case runs if the aggregate has no GROUP BY clause. The
4692
+ ** processing is much simpler since there is only a single row
4693
+ ** of output.
4694
+ */
4695
+ resetAccumulator( pParse, sAggInfo );
4696
+ pWInfo = sqlite3WhereBegin( pParse, pTabList, pWhere, ref pMinMax, (byte)flag );
4697
+ if ( pWInfo == null )
4698
+ {
4699
+ sqlite3ExprListDelete( db, ref pDel );
4700
+ goto select_end;
4701
+ }
4702
+ updateAccumulator( pParse, sAggInfo );
4703
+ if ( pMinMax == null && flag != 0 )
4704
+ {
4705
+ sqlite3VdbeAddOp2( v, OP_Goto, 0, pWInfo.iBreak );
4706
+ #if SQLITE_DEBUG
4707
+ VdbeComment( v, "%s() by index",
4708
+ ( flag == WHERE_ORDERBY_MIN ? "min" : "max" ) );
4709
+ #endif
4710
+ }
4711
+ sqlite3WhereEnd( pWInfo );
4712
+ finalizeAggFunctions( pParse, sAggInfo );
4713
+ }
4714
+
4715
+ pOrderBy = null;
4716
+ sqlite3ExprIfFalse( pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL );
4717
+ selectInnerLoop( pParse, p, p.pEList, 0, 0, null, -1,
4718
+ pDest, addrEnd, addrEnd );
4719
+
4720
+ sqlite3ExprListDelete( db, ref pDel );
4721
+ }
4722
+ sqlite3VdbeResolveLabel( v, addrEnd );
4723
+
4724
+ } /* endif aggregate query */
4725
+
4726
+ /* If there is an ORDER BY clause, then we need to sort the results
4727
+ ** and send them to the callback one by one.
4728
+ */
4729
+ if ( pOrderBy != null )
4730
+ {
4731
+ generateSortTail( pParse, p, v, pEList.nExpr, pDest );
4732
+ }
4733
+
4734
+ /* Jump here to skip this query
4735
+ */
4736
+ sqlite3VdbeResolveLabel( v, iEnd );
4737
+
4738
+ /* The SELECT was successfully coded. Set the return code to 0
4739
+ ** to indicate no errors.
4740
+ */
4741
+ rc = 0;
4742
+
4743
+ /* Control jumps to here if an error is encountered above, or upon
4744
+ ** successful coding of the SELECT.
4745
+ */
4746
+ select_end:
4747
+
4748
+ /* Identify column names if results of the SELECT are to be output.
4749
+ */
4750
+ if ( rc == SQLITE_OK && pDest.eDest == SRT_Output )
4751
+ {
4752
+ generateColumnNames( pParse, pTabList, pEList );
4753
+ }
4754
+
4755
+ sqlite3DbFree( db, ref sAggInfo.aCol );
4756
+ sqlite3DbFree( db, ref sAggInfo.aFunc );
4757
+ return rc;
4758
+ }
4759
+
4760
+ #if SQLITE_DEBUG
4761
+ /*
4762
+ *******************************************************************************
4763
+ ** The following code is used for testing and debugging only. The code
4764
+ ** that follows does not appear in normal builds.
4765
+ **
4766
+ ** These routines are used to print out the content of all or part of a
4767
+ ** parse structures such as Select or Expr. Such printouts are useful
4768
+ ** for helping to understand what is happening inside the code generator
4769
+ ** during the execution of complex SELECT statements.
4770
+ **
4771
+ ** These routine are not called anywhere from within the normal
4772
+ ** code base. Then are intended to be called from within the debugger
4773
+ ** or from temporary "printf" statements inserted for debugging.
4774
+ */
4775
+ void sqlite3PrintExpr( Expr p )
4776
+ {
4777
+ if ( !ExprHasProperty( p, EP_IntValue ) && p.u.zToken != null )
4778
+ {
4779
+ sqlite3DebugPrintf( "(%s", p.u.zToken );
4780
+ }
4781
+ else
4782
+ {
4783
+ sqlite3DebugPrintf( "(%d", p.op );
4784
+ }
4785
+ if ( p.pLeft != null )
4786
+ {
4787
+ sqlite3DebugPrintf( " " );
4788
+ sqlite3PrintExpr( p.pLeft );
4789
+ }
4790
+ if ( p.pRight != null )
4791
+ {
4792
+ sqlite3DebugPrintf( " " );
4793
+ sqlite3PrintExpr( p.pRight );
4794
+ }
4795
+ sqlite3DebugPrintf( ")" );
4796
+ }
4797
+ void sqlite3PrintExprList( ExprList pList )
4798
+ {
4799
+ int i;
4800
+ for ( i = 0; i < pList.nExpr; i++ )
4801
+ {
4802
+ sqlite3PrintExpr( pList.a[i].pExpr );
4803
+ if ( i < pList.nExpr - 1 )
4804
+ {
4805
+ sqlite3DebugPrintf( ", " );
4806
+ }
4807
+ }
4808
+ }
4809
+ void sqlite3PrintSelect( Select p, int indent )
4810
+ {
4811
+ sqlite3DebugPrintf( "%*sSELECT(%p) ", indent, "", p );
4812
+ sqlite3PrintExprList( p.pEList );
4813
+ sqlite3DebugPrintf( "\n" );
4814
+ if ( p.pSrc != null )
4815
+ {
4816
+ string zPrefix;
4817
+ int i;
4818
+ zPrefix = "FROM";
4819
+ for ( i = 0; i < p.pSrc.nSrc; i++ )
4820
+ {
4821
+ SrcList_item pItem = p.pSrc.a[i];
4822
+ sqlite3DebugPrintf( "%*s ", indent + 6, zPrefix );
4823
+ zPrefix = "";
4824
+ if ( pItem.pSelect != null )
4825
+ {
4826
+ sqlite3DebugPrintf( "(\n" );
4827
+ sqlite3PrintSelect( pItem.pSelect, indent + 10 );
4828
+ sqlite3DebugPrintf( "%*s)", indent + 8, "" );
4829
+ }
4830
+ else if ( pItem.zName != null )
4831
+ {
4832
+ sqlite3DebugPrintf( "%s", pItem.zName );
4833
+ }
4834
+ if ( pItem.pTab != null )
4835
+ {
4836
+ sqlite3DebugPrintf( "(table: %s)", pItem.pTab.zName );
4837
+ }
4838
+ if ( pItem.zAlias != null )
4839
+ {
4840
+ sqlite3DebugPrintf( " AS %s", pItem.zAlias );
4841
+ }
4842
+ if ( i < p.pSrc.nSrc - 1 )
4843
+ {
4844
+ sqlite3DebugPrintf( "," );
4845
+ }
4846
+ sqlite3DebugPrintf( "\n" );
4847
+ }
4848
+ }
4849
+ if ( p.pWhere != null )
4850
+ {
4851
+ sqlite3DebugPrintf( "%*s WHERE ", indent, "" );
4852
+ sqlite3PrintExpr( p.pWhere );
4853
+ sqlite3DebugPrintf( "\n" );
4854
+ }
4855
+ if ( p.pGroupBy != null )
4856
+ {
4857
+ sqlite3DebugPrintf( "%*s GROUP BY ", indent, "" );
4858
+ sqlite3PrintExprList( p.pGroupBy );
4859
+ sqlite3DebugPrintf( "\n" );
4860
+ }
4861
+ if ( p.pHaving != null )
4862
+ {
4863
+ sqlite3DebugPrintf( "%*s HAVING ", indent, "" );
4864
+ sqlite3PrintExpr( p.pHaving );
4865
+ sqlite3DebugPrintf( "\n" );
4866
+ }
4867
+ if ( p.pOrderBy != null )
4868
+ {
4869
+ sqlite3DebugPrintf( "%*s ORDER BY ", indent, "" );
4870
+ sqlite3PrintExprList( p.pOrderBy );
4871
+ sqlite3DebugPrintf( "\n" );
4872
+ }
4873
+ }
4874
+ /* End of the structure debug printing code
4875
+ *****************************************************************************/
4876
+ #endif // * defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */
4877
+ }
4878
+ }