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,4189 @@
1
+ using System;
2
+ using System.Diagnostics;
3
+ using System.IO;
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 SQLite parser
29
+ ** when syntax rules are reduced. The routines in this file handle the
30
+ ** following kinds of SQL syntax:
31
+ **
32
+ ** CREATE TABLE
33
+ ** DROP TABLE
34
+ ** CREATE INDEX
35
+ ** DROP INDEX
36
+ ** creating ID lists
37
+ ** BEGIN TRANSACTION
38
+ ** COMMIT
39
+ ** ROLLBACK
40
+ *************************************************************************
41
+ ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
42
+ ** C#-SQLite is an independent reimplementation of the SQLite software library
43
+ **
44
+ ** SQLITE_SOURCE_ID: 2010-03-09 19:31:43 4ae453ea7be69018d8c16eb8dabe05617397dc4d
45
+ **
46
+ ** $Header$
47
+ *************************************************************************
48
+ */
49
+ //#include "sqliteInt.h"
50
+
51
+ /*
52
+ ** This routine is called when a new SQL statement is beginning to
53
+ ** be parsed. Initialize the pParse structure as needed.
54
+ */
55
+ static void sqlite3BeginParse( Parse pParse, int explainFlag )
56
+ {
57
+ pParse.explain = (byte)explainFlag;
58
+ pParse.nVar = 0;
59
+ }
60
+
61
+ #if !SQLITE_OMIT_SHARED_CACHE
62
+ /*
63
+ ** The TableLock structure is only used by the sqlite3TableLock() and
64
+ ** codeTableLocks() functions.
65
+ */
66
+ //struct TableLock {
67
+ // int iDb; /* The database containing the table to be locked */
68
+ // int iTab; /* The root page of the table to be locked */
69
+ // u8 isWriteLock; /* True for write lock. False for a read lock */
70
+ // string zName; /* Name of the table */
71
+ //};
72
+
73
+ public class TableLock
74
+ {
75
+ public int iDb; /* The database containing the table to be locked */
76
+ public int iTab; /* The root page of the table to be locked */
77
+ public u8 isWriteLock; /* True for write lock. False for a read lock */
78
+ public string zName; /* Name of the table */
79
+ }
80
+ /*
81
+ ** Record the fact that we want to lock a table at run-time.
82
+ **
83
+ ** The table to be locked has root page iTab and is found in database iDb.
84
+ ** A read or a write lock can be taken depending on isWritelock.
85
+ **
86
+ ** This routine just records the fact that the lock is desired. The
87
+ ** code to make the lock occur is generated by a later call to
88
+ ** codeTableLocks() which occurs during sqlite3FinishCoding().
89
+ */
90
+ void sqlite3TableLock(
91
+ Parse *pParse, /* Parsing context */
92
+ int iDb, /* Index of the database containing the table to lock */
93
+ int iTab, /* Root page number of the table to be locked */
94
+ u8 isWriteLock, /* True for a write lock */
95
+ const char *zName /* Name of the table to be locked */
96
+ ){
97
+ Parse *pToplevel = sqlite3ParseToplevel(pParse);
98
+ int i;
99
+ int nBytes;
100
+ TableLock *p;
101
+ assert( iDb>=0 );
102
+
103
+ for(i=0; i<pToplevel->nTableLock; i++){
104
+ p = &pToplevel->aTableLock[i];
105
+ if( p->iDb==iDb && p->iTab==iTab ){
106
+ p->isWriteLock = (p->isWriteLock || isWriteLock);
107
+ return;
108
+ }
109
+ }
110
+
111
+ nBytes = sizeof(TableLock) * (pToplevel->nTableLock+1);
112
+ pToplevel->aTableLock =
113
+ sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes);
114
+ if( pToplevel->aTableLock ){
115
+ p = &pToplevel->aTableLock[pToplevel->nTableLock++];
116
+ p->iDb = iDb;
117
+ p->iTab = iTab;
118
+ p->isWriteLock = isWriteLock;
119
+ p->zName = zName;
120
+ }else{
121
+ pToplevel->nTableLock = 0;
122
+ pToplevel->db->mallocFailed = 1;
123
+ }
124
+ }
125
+
126
+ /*
127
+ ** Code an OP_TableLock instruction for each table locked by the
128
+ ** statement (configured by calls to sqlite3TableLock()).
129
+ */
130
+ static void codeTableLocks( Parse pParse )
131
+ {
132
+ int i;
133
+ Vdbe pVdbe;
134
+
135
+ pVdbe = sqlite3GetVdbe( pParse );
136
+ Debug.Assert( pVdbe != null ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */
137
+
138
+ for ( i = 0 ; i < pParse.nTableLock ; i++ )
139
+ {
140
+ TableLock p = pParse.aTableLock[i];
141
+ int p1 = p.iDb;
142
+ sqlite3VdbeAddOp4( pVdbe, OP_TableLock, p1, p.iTab, p.isWriteLock,
143
+ p.zName, P4_STATIC );
144
+ }
145
+ }
146
+ #else
147
+ // #define codeTableLocks(x)
148
+ static void codeTableLocks( Parse pParse ) { }
149
+ #endif
150
+
151
+ /*
152
+ ** This routine is called after a single SQL statement has been
153
+ ** parsed and a VDBE program to execute that statement has been
154
+ ** prepared. This routine puts the finishing touches on the
155
+ ** VDBE program and resets the pParse structure for the next
156
+ ** parse.
157
+ **
158
+ ** Note that if an error occurred, it might be the case that
159
+ ** no VDBE code was generated.
160
+ */
161
+ static void sqlite3FinishCoding( Parse pParse )
162
+ {
163
+ sqlite3 db;
164
+ Vdbe v;
165
+
166
+ db = pParse.db;
167
+ // if ( db.mallocFailed != 0 ) return;
168
+ if ( pParse.nested != 0 ) return;
169
+ if ( pParse.nErr != 0 ) return;
170
+
171
+ /* Begin by generating some termination code at the end of the
172
+ ** vdbe program
173
+ */
174
+ v = sqlite3GetVdbe( pParse );
175
+ Debug.Assert( 0 == pParse.isMultiWrite
176
+ || sqlite3VdbeAssertMayAbort( v, pParse.mayAbort ) != 0 );
177
+ if ( v != null )
178
+ {
179
+ sqlite3VdbeAddOp0( v, OP_Halt );
180
+
181
+ /* The cookie mask contains one bit for each database file open.
182
+ ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
183
+ ** set for each database that is used. Generate code to start a
184
+ ** transaction on each used database and to verify the schema cookie
185
+ ** on each used database.
186
+ */
187
+ if ( pParse.cookieGoto > 0 )
188
+ {
189
+ u32 mask;
190
+ int iDb;
191
+ sqlite3VdbeJumpHere( v, pParse.cookieGoto - 1 );
192
+ for ( iDb = 0, mask = 1; iDb < db.nDb; mask <<= 1, iDb++ )
193
+ {
194
+ if ( ( mask & pParse.cookieMask ) == 0 ) continue;
195
+ sqlite3VdbeUsesBtree( v, iDb );
196
+ sqlite3VdbeAddOp2( v, OP_Transaction, iDb, ( mask & pParse.writeMask ) != 0 );
197
+ if ( db.init.busy == 0 )
198
+ {
199
+ sqlite3VdbeAddOp2( v, OP_VerifyCookie, iDb, pParse.cookieValue[iDb] );
200
+ }
201
+ }
202
+ #if !SQLITE_OMIT_VIRTUALTABLE
203
+ {
204
+ int i;
205
+ for(i=0; i<pParse.nVtabLock; i++){
206
+ char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
207
+ sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
208
+ }
209
+ pParse.nVtabLock = 0;
210
+ }
211
+ #endif
212
+
213
+ /* Once all the cookies have been verified and transactions opened,
214
+ ** obtain the required table-locks. This is a no-op unless the
215
+ ** shared-cache feature is enabled.
216
+ */
217
+ codeTableLocks( pParse );
218
+
219
+ /* Initialize any AUTOINCREMENT data structures required.
220
+ */
221
+ sqlite3AutoincrementBegin( pParse );
222
+
223
+ /* Finally, jump back to the beginning of the executable code. */
224
+ sqlite3VdbeAddOp2( v, OP_Goto, 0, pParse.cookieGoto );
225
+ }
226
+ }
227
+
228
+
229
+ /* Get the VDBE program ready for execution
230
+ */
231
+ if ( v != null && ALWAYS( pParse.nErr == 0 ) /* && 0 == db.mallocFailed */ )
232
+ {
233
+ #if SQLITE_DEBUG
234
+ TextWriter trace = ( db.flags & SQLITE_VdbeTrace ) != 0 ? Console.Out : null;
235
+ sqlite3VdbeTrace( v, trace );
236
+ #endif
237
+ Debug.Assert( pParse.iCacheLevel == 0 ); /* Disables and re-enables match */
238
+ /* A minimum of one cursor is required if autoincrement is used
239
+ * See ticket [a696379c1f08866] */
240
+ if ( pParse.pAinc != null && pParse.nTab == 0 ) pParse.nTab = 1;
241
+ sqlite3VdbeMakeReady( v, pParse.nVar, pParse.nMem,
242
+ pParse.nTab, pParse.nMaxArg, pParse.explain,
243
+ ( pParse.isMultiWrite != 0 && pParse.mayAbort != 0 ) ? 1 : 0 );
244
+ pParse.rc = SQLITE_DONE;
245
+ pParse.colNamesSet = 0;
246
+ }
247
+ else
248
+ {
249
+ pParse.rc = SQLITE_ERROR;
250
+ }
251
+ pParse.nTab = 0;
252
+ pParse.nMem = 0;
253
+ pParse.nSet = 0;
254
+ pParse.nVar = 0;
255
+ pParse.cookieMask = 0;
256
+ pParse.cookieGoto = 0;
257
+ }
258
+
259
+ /*
260
+ ** Run the parser and code generator recursively in order to generate
261
+ ** code for the SQL statement given onto the end of the pParse context
262
+ ** currently under construction. When the parser is run recursively
263
+ ** this way, the final OP_Halt is not appended and other initialization
264
+ ** and finalization steps are omitted because those are handling by the
265
+ ** outermost parser.
266
+ **
267
+ ** Not everything is nestable. This facility is designed to permit
268
+ ** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use
269
+ ** care if you decide to try to use this routine for some other purposes.
270
+ */
271
+ static void sqlite3NestedParse( Parse pParse, string zFormat, params object[] ap )
272
+ {
273
+ // va_list ap;
274
+ string zSql; // char *zSql;
275
+ string zErrMsg = "";// char* zErrMsg = 0;
276
+ sqlite3 db = pParse.db;
277
+ //# define SAVE_SZ (Parse.Length - offsetof(Parse,nVar))
278
+ // char saveBuf[SAVE_SZ];
279
+
280
+ if ( pParse.nErr != 0 ) return;
281
+ Debug.Assert( pParse.nested < 10 ); /* Nesting should only be of limited depth */
282
+ va_start( ap, zFormat );
283
+ zSql = sqlite3VMPrintf( db, zFormat, ap );
284
+ va_end( ap );
285
+ //if( zSql=="" ){
286
+ // return; /* A malloc must have failed */
287
+ //}
288
+ pParse.nested++;
289
+ pParse.SaveMembers(); // memcpy(saveBuf, pParse.nVar, SAVE_SZ);
290
+ pParse.ResetMembers(); // memset(pParse.nVar, 0, SAVE_SZ);
291
+ sqlite3RunParser( pParse, zSql, ref zErrMsg );
292
+ sqlite3DbFree( db, ref zErrMsg );
293
+ sqlite3DbFree( db, ref zSql );
294
+ pParse.RestoreMembers(); // memcpy(pParse.nVar, saveBuf, SAVE_SZ);
295
+ pParse.nested--;
296
+ }
297
+
298
+ /*
299
+ ** Locate the in-memory structure that describes a particular database
300
+ ** table given the name of that table and (optionally) the name of the
301
+ ** database containing the table. Return NULL if not found.
302
+ **
303
+ ** If zDatabase is 0, all databases are searched for the table and the
304
+ ** first matching table is returned. (No checking for duplicate table
305
+ ** names is done.) The search order is TEMP first, then MAIN, then any
306
+ ** auxiliary databases added using the ATTACH command.
307
+ **
308
+ ** See also sqlite3LocateTable().
309
+ */
310
+ static Table sqlite3FindTable( sqlite3 db, string zName, string zDatabase )
311
+ {
312
+ Table p = null;
313
+ int i;
314
+ int nName;
315
+ Debug.Assert( zName != null );
316
+ nName = sqlite3Strlen30( zName );
317
+ for ( i = OMIT_TEMPDB; i < db.nDb; i++ )
318
+ {
319
+ int j = ( i < 2 ) ? i ^ 1 : i; /* Search TEMP before MAIN */
320
+ if ( zDatabase != null && sqlite3StrICmp( zDatabase, db.aDb[j].zName ) != 0 ) continue;
321
+ p = (Table)sqlite3HashFind( db.aDb[j].pSchema.tblHash, zName, nName );
322
+ if ( p != null ) break;
323
+ }
324
+ return p;
325
+ }
326
+
327
+ /*
328
+ ** Locate the in-memory structure that describes a particular database
329
+ ** table given the name of that table and (optionally) the name of the
330
+ ** database containing the table. Return NULL if not found. Also leave an
331
+ ** error message in pParse.zErrMsg.
332
+ **
333
+ ** The difference between this routine and sqlite3FindTable() is that this
334
+ ** routine leaves an error message in pParse.zErrMsg where
335
+ ** sqlite3FindTable() does not.
336
+ */
337
+ static Table sqlite3LocateTable(
338
+ Parse pParse, /* context in which to report errors */
339
+ int isView, /* True if looking for a VIEW rather than a TABLE */
340
+ string zName, /* Name of the table we are looking for */
341
+ string zDbase /* Name of the database. Might be NULL */
342
+ )
343
+ {
344
+ Table p;
345
+
346
+ /* Read the database schema. If an error occurs, leave an error message
347
+ ** and code in pParse and return NULL. */
348
+ if ( SQLITE_OK != sqlite3ReadSchema( pParse ) )
349
+ {
350
+ return null;
351
+ }
352
+
353
+ p = sqlite3FindTable( pParse.db, zName, zDbase );
354
+ if ( p == null )
355
+ {
356
+ string zMsg = isView != 0 ? "no such view" : "no such table";
357
+ if ( zDbase != null )
358
+ {
359
+ sqlite3ErrorMsg( pParse, "%s: %s.%s", zMsg, zDbase, zName );
360
+ }
361
+ else
362
+ {
363
+ sqlite3ErrorMsg( pParse, "%s: %s", zMsg, zName );
364
+ }
365
+ pParse.checkSchema = 1;
366
+ }
367
+ return p;
368
+ }
369
+
370
+ /*
371
+ ** Locate the in-memory structure that describes
372
+ ** a particular index given the name of that index
373
+ ** and the name of the database that contains the index.
374
+ ** Return NULL if not found.
375
+ **
376
+ ** If zDatabase is 0, all databases are searched for the
377
+ ** table and the first matching index is returned. (No checking
378
+ ** for duplicate index names is done.) The search order is
379
+ ** TEMP first, then MAIN, then any auxiliary databases added
380
+ ** using the ATTACH command.
381
+ */
382
+ static Index sqlite3FindIndex( sqlite3 db, string zName, string zDb )
383
+ {
384
+ Index p = null;
385
+ int i;
386
+ int nName = sqlite3Strlen30( zName );
387
+ for ( i = OMIT_TEMPDB; i < db.nDb; i++ )
388
+ {
389
+ int j = ( i < 2 ) ? i ^ 1 : i; /* Search TEMP before MAIN */
390
+ Schema pSchema = db.aDb[j].pSchema;
391
+ Debug.Assert( pSchema != null );
392
+ if ( zDb != null && sqlite3StrICmp( zDb, db.aDb[j].zName ) != 0 ) continue;
393
+ p = (Index)sqlite3HashFind( pSchema.idxHash, zName, nName );
394
+ if ( p != null ) break;
395
+ }
396
+ return p;
397
+ }
398
+
399
+ /*
400
+ ** Reclaim the memory used by an index
401
+ */
402
+ static void freeIndex( ref Index p )
403
+ {
404
+ sqlite3 db = p.pTable.dbMem;
405
+ #if !SQLITE_OMIT_ANALYZE
406
+ sqlite3DeleteIndexSamples( p );
407
+ #endif
408
+ sqlite3DbFree( db, ref p.zColAff );
409
+ sqlite3DbFree( db, ref p );
410
+ }
411
+
412
+ /*
413
+ ** Remove the given index from the index hash table, and free
414
+ ** its memory structures.
415
+ **
416
+ ** The index is removed from the database hash tables but
417
+ ** it is not unlinked from the Table that it indexes.
418
+ ** Unlinking from the Table must be done by the calling function.
419
+ */
420
+ static void sqlite3DeleteIndex( Index p )
421
+ {
422
+ Index pOld;
423
+ string zName = p.zName;
424
+
425
+ pOld = (Index)sqlite3HashInsert( ref p.pSchema.idxHash, zName,
426
+ sqlite3Strlen30( zName ), null );
427
+ Debug.Assert( pOld == null || pOld == p );
428
+ freeIndex( ref p );
429
+ }
430
+
431
+ /*
432
+ ** For the index called zIdxName which is found in the database iDb,
433
+ ** unlike that index from its Table then remove the index from
434
+ ** the index hash table and free all memory structures associated
435
+ ** with the index.
436
+ */
437
+ static void sqlite3UnlinkAndDeleteIndex( sqlite3 db, int iDb, string zIdxName )
438
+ {
439
+ Index pIndex;
440
+ int len;
441
+ Hash pHash = db.aDb[iDb].pSchema.idxHash;
442
+
443
+ len = sqlite3Strlen30( zIdxName );
444
+ pIndex = (Index)sqlite3HashInsert( ref pHash, zIdxName, len, null );
445
+ if ( pIndex != null )
446
+ {
447
+ if ( pIndex.pTable.pIndex == pIndex )
448
+ {
449
+ pIndex.pTable.pIndex = pIndex.pNext;
450
+ }
451
+ else
452
+ {
453
+ Index p;
454
+ /* Justification of ALWAYS(); The index must be on the list of
455
+ ** indices. */
456
+ p = pIndex.pTable.pIndex;
457
+ while ( ALWAYS( p != null ) && p.pNext != pIndex ) { p = p.pNext; }
458
+ if ( ALWAYS( p != null && p.pNext == pIndex ) )
459
+ {
460
+ p.pNext = pIndex.pNext;
461
+ }
462
+ }
463
+ freeIndex( ref pIndex );
464
+ }
465
+ db.flags |= SQLITE_InternChanges;
466
+ }
467
+
468
+ /*
469
+ ** Erase all schema information from the in-memory hash tables of
470
+ ** a single database. This routine is called to reclaim memory
471
+ ** before the database closes. It is also called during a rollback
472
+ ** if there were schema changes during the transaction or if a
473
+ ** schema-cookie mismatch occurs.
474
+ **
475
+ ** If iDb==0 then reset the internal schema tables for all database
476
+ ** files. If iDb>=1 then reset the internal schema for only the
477
+ ** single file indicated.
478
+ */
479
+ static void sqlite3ResetInternalSchema( sqlite3 db, int iDb )
480
+ {
481
+ int i, j;
482
+ Debug.Assert( iDb >= 0 && iDb < db.nDb );
483
+
484
+ if ( iDb == 0 )
485
+ {
486
+ sqlite3BtreeEnterAll( db );
487
+ }
488
+ for ( i = iDb; i < db.nDb; i++ )
489
+ {
490
+ Db pDb = db.aDb[i];
491
+ if ( pDb.pSchema != null )
492
+ {
493
+ Debug.Assert( i == 1 || ( pDb.pBt != null && sqlite3BtreeHoldsMutex( pDb.pBt ) ) );
494
+ Debug.Assert( i == 1 || ( pDb.pBt != null ) );
495
+ sqlite3SchemaFree( pDb.pSchema );
496
+ }
497
+ if ( iDb > 0 ) return;
498
+ }
499
+ Debug.Assert( iDb == 0 );
500
+ db.flags &= ~SQLITE_InternChanges;
501
+ sqlite3VtabUnlockList( db );
502
+ sqlite3BtreeLeaveAll( db );
503
+ /* If one or more of the auxiliary database files has been closed,
504
+ ** then remove them from the auxiliary database list. We take the
505
+ ** opportunity to do this here since we have just deleted all of the
506
+ ** schema hash tables and therefore do not have to make any changes
507
+ ** to any of those tables.
508
+ */
509
+ for ( i = j = 2; i < db.nDb; i++ )
510
+ {
511
+ Db pDb = db.aDb[i];
512
+ if ( pDb.pBt == null )
513
+ {
514
+ sqlite3DbFree( db, ref pDb.zName );
515
+ continue;
516
+ }
517
+ if ( j < i )
518
+ {
519
+ db.aDb[j] = db.aDb[i];
520
+ }
521
+ j++;
522
+ }
523
+ if ( db.nDb != j ) db.aDb[j] = new Db();//memset(db.aDb[j], 0, (db.nDb-j)*sizeof(db.aDb[j]));
524
+ db.nDb = j;
525
+ if ( db.nDb <= 2 && db.aDb != db.aDbStatic )
526
+ {
527
+ Array.Copy( db.aDb, db.aDbStatic, 2 );// memcpy(db.aDbStatic, db.aDb, 2*sizeof(db.aDb[0]));
528
+ sqlite3DbFree( db, ref db.aDb );
529
+ //db.aDb = db.aDbStatic;
530
+ }
531
+ }
532
+
533
+ /*
534
+ ** This routine is called when a commit occurs.
535
+ */
536
+ static void sqlite3CommitInternalChanges( sqlite3 db )
537
+ {
538
+ db.flags &= ~SQLITE_InternChanges;
539
+ }
540
+
541
+ /*
542
+ ** Clear the column names from a table or view.
543
+ */
544
+ static void sqliteResetColumnNames( Table pTable )
545
+ {
546
+ int i;
547
+ Column pCol;
548
+ sqlite3 db = pTable.dbMem;
549
+ testcase( db == null );
550
+ Debug.Assert( pTable != null );
551
+ for ( i = 0; i < pTable.nCol; i++ )
552
+ {
553
+ pCol = pTable.aCol[i];
554
+ if ( pCol != null )
555
+ {
556
+ sqlite3DbFree( db, ref pCol.zName );
557
+ sqlite3ExprDelete( db, ref pCol.pDflt );
558
+ sqlite3DbFree( db, ref pCol.zDflt );
559
+ sqlite3DbFree( db, ref pCol.zType );
560
+ sqlite3DbFree( db, ref pCol.zColl );
561
+ }
562
+ }
563
+ pTable.aCol = null; sqlite3DbFree( db, ref pTable.aCol );
564
+ pTable.nCol = 0;
565
+ }
566
+
567
+ /*
568
+ ** Remove the memory data structures associated with the given
569
+ ** Table. No changes are made to disk by this routine.
570
+ **
571
+ ** This routine just deletes the data structure. It does not unlink
572
+ ** the table data structure from the hash table. But it does destroy
573
+ ** memory structures of the indices and foreign keys associated with
574
+ ** the table.
575
+ */
576
+ static void sqlite3DeleteTable( ref Table pTable )
577
+ {
578
+ Index pIndex; Index pNext;
579
+ sqlite3 db;
580
+
581
+ if ( pTable == null ) return;
582
+ db = pTable.dbMem;
583
+ testcase( db == null );
584
+
585
+ /* Do not delete the table until the reference count reaches zero. */
586
+ pTable.nRef--;
587
+ if ( pTable.nRef > 0 )
588
+ {
589
+ return;
590
+ }
591
+ Debug.Assert( pTable.nRef == 0 );
592
+
593
+ /* Delete all indices associated with this table
594
+ */
595
+ for ( pIndex = pTable.pIndex; pIndex != null; pIndex = pNext )
596
+ {
597
+ pNext = pIndex.pNext;
598
+ Debug.Assert( pIndex.pSchema == pTable.pSchema );
599
+ sqlite3DeleteIndex( pIndex );
600
+ }
601
+
602
+ /* Delete any foreign keys attached to this table. */
603
+ sqlite3FkDelete( pTable );
604
+
605
+ /* Delete the Table structure itself.
606
+ */
607
+ sqliteResetColumnNames( pTable );
608
+ sqlite3DbFree( db, ref pTable.zName );
609
+ sqlite3DbFree( db, ref pTable.zColAff );
610
+ sqlite3SelectDelete( db, ref pTable.pSelect );
611
+ #if !SQLITE_OMIT_CHECK
612
+ sqlite3ExprDelete( db, ref pTable.pCheck );
613
+ #endif
614
+ sqlite3VtabClear( pTable );
615
+ sqlite3DbFree( db, ref pTable );
616
+ }
617
+
618
+ /*
619
+ ** Unlink the given table from the hash tables and the delete the
620
+ ** table structure with all its indices and foreign keys.
621
+ */
622
+ static void sqlite3UnlinkAndDeleteTable( sqlite3 db, int iDb, string zTabName )
623
+ {
624
+ Table p;
625
+ Db pDb;
626
+
627
+ Debug.Assert( db != null );
628
+ Debug.Assert( iDb >= 0 && iDb < db.nDb );
629
+ Debug.Assert( zTabName != null );
630
+ testcase( zTabName.Length == 0 ); /* Zero-length table names are allowed */
631
+ pDb = db.aDb[iDb];
632
+ p = (Table)sqlite3HashInsert( ref pDb.pSchema.tblHash, zTabName,
633
+ sqlite3Strlen30( zTabName ), null );
634
+ sqlite3DeleteTable( ref p );
635
+ db.flags |= SQLITE_InternChanges;
636
+ }
637
+
638
+ /*
639
+ ** Given a token, return a string that consists of the text of that
640
+ ** token. Space to hold the returned string
641
+ ** is obtained from sqliteMalloc() and must be freed by the calling
642
+ ** function.
643
+ **
644
+ ** Any quotation marks (ex: "name", 'name', [name], or `name`) that
645
+ ** surround the body of the token are removed.
646
+ **
647
+ ** Tokens are often just pointers into the original SQL text and so
648
+ ** are not \000 terminated and are not persistent. The returned string
649
+ ** is \000 terminated and is persistent.
650
+ */
651
+ static string sqlite3NameFromToken( sqlite3 db, Token pName )
652
+ {
653
+ string zName;
654
+ if ( pName != null && pName.z != null )
655
+ {
656
+ zName = pName.z.Substring( 0, pName.n );//sqlite3DbStrNDup(db, (char*)pName.z, pName.n);
657
+ sqlite3Dequote( ref zName );
658
+ }
659
+ else
660
+ {
661
+ return null;
662
+ }
663
+ return zName;
664
+ }
665
+
666
+ /*
667
+ ** Open the sqlite_master table stored in database number iDb for
668
+ ** writing. The table is opened using cursor 0.
669
+ */
670
+ static void sqlite3OpenMasterTable( Parse p, int iDb )
671
+ {
672
+ Vdbe v = sqlite3GetVdbe( p );
673
+ sqlite3TableLock( p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE( iDb ) );
674
+ sqlite3VdbeAddOp3( v, OP_OpenWrite, 0, MASTER_ROOT, iDb );
675
+ sqlite3VdbeChangeP4( v, -1, (int)5, P4_INT32 ); /* 5 column table */
676
+ if ( p.nTab == 0 )
677
+ {
678
+ p.nTab = 1;
679
+ }
680
+ }
681
+
682
+ /*
683
+ ** Parameter zName points to a nul-terminated buffer containing the name
684
+ ** of a database ("main", "temp" or the name of an attached db). This
685
+ ** function returns the index of the named database in db->aDb[], or
686
+ ** -1 if the named db cannot be found.
687
+ */
688
+ static int sqlite3FindDbName( sqlite3 db, string zName )
689
+ {
690
+ int i = -1; /* Database number */
691
+ if ( zName != null )
692
+ {
693
+ Db pDb;
694
+ int n = sqlite3Strlen30( zName );
695
+ for ( i = ( db.nDb - 1 ); i >= 0; i-- )
696
+ {
697
+ pDb = db.aDb[i];
698
+ if ( ( OMIT_TEMPDB == 0 || i != 1 ) && n == sqlite3Strlen30( pDb.zName ) &&
699
+ 0 == sqlite3StrICmp( pDb.zName, zName ) )
700
+ {
701
+ break;
702
+ }
703
+ }
704
+ }
705
+ return i;
706
+ }
707
+
708
+ /*
709
+ ** The token *pName contains the name of a database (either "main" or
710
+ ** "temp" or the name of an attached db). This routine returns the
711
+ ** index of the named database in db->aDb[], or -1 if the named db
712
+ ** does not exist.
713
+ */
714
+ static int sqlite3FindDb( sqlite3 db, Token pName )
715
+ {
716
+ int i; /* Database number */
717
+ string zName; /* Name we are searching for */
718
+ zName = sqlite3NameFromToken( db, pName );
719
+ i = sqlite3FindDbName( db, zName );
720
+ sqlite3DbFree( db, ref zName );
721
+ return i;
722
+ }
723
+
724
+ /* The table or view or trigger name is passed to this routine via tokens
725
+ ** pName1 and pName2. If the table name was fully qualified, for example:
726
+ **
727
+ ** CREATE TABLE xxx.yyy (...);
728
+ **
729
+ ** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
730
+ ** the table name is not fully qualified, i.e.:
731
+ **
732
+ ** CREATE TABLE yyy(...);
733
+ **
734
+ ** Then pName1 is set to "yyy" and pName2 is "".
735
+ **
736
+ ** This routine sets the ppUnqual pointer to point at the token (pName1 or
737
+ ** pName2) that stores the unqualified table name. The index of the
738
+ ** database "xxx" is returned.
739
+ */
740
+ static int sqlite3TwoPartName(
741
+ Parse pParse, /* Parsing and code generating context */
742
+ Token pName1, /* The "xxx" in the name "xxx.yyy" or "xxx" */
743
+ Token pName2, /* The "yyy" in the name "xxx.yyy" */
744
+ ref Token pUnqual /* Write the unqualified object name here */
745
+ )
746
+ {
747
+ int iDb; /* Database holding the object */
748
+ sqlite3 db = pParse.db;
749
+
750
+ if ( ALWAYS( pName2 != null ) && pName2.n > 0 )
751
+ {
752
+ if ( db.init.busy != 0 )
753
+ {
754
+ sqlite3ErrorMsg( pParse, "corrupt database" );
755
+ pParse.nErr++;
756
+ return -1;
757
+ }
758
+ pUnqual = pName2;
759
+ iDb = sqlite3FindDb( db, pName1 );
760
+ if ( iDb < 0 )
761
+ {
762
+ sqlite3ErrorMsg( pParse, "unknown database %T", pName1 );
763
+ pParse.nErr++;
764
+ return -1;
765
+ }
766
+ }
767
+ else
768
+ {
769
+ Debug.Assert( db.init.iDb == 0 || db.init.busy != 0 );
770
+ iDb = db.init.iDb;
771
+ pUnqual = pName1;
772
+ }
773
+ return iDb;
774
+ }
775
+
776
+ /*
777
+ ** This routine is used to check if the UTF-8 string zName is a legal
778
+ ** unqualified name for a new schema object (table, index, view or
779
+ ** trigger). All names are legal except those that begin with the string
780
+ ** "sqlite_" (in upper, lower or mixed case). This portion of the namespace
781
+ ** is reserved for internal use.
782
+ */
783
+ static int sqlite3CheckObjectName( Parse pParse, string zName )
784
+ {
785
+ if ( 0 == pParse.db.init.busy && pParse.nested == 0
786
+ && ( pParse.db.flags & SQLITE_WriteSchema ) == 0
787
+ && 0 == sqlite3StrNICmp( zName, "sqlite_", 7 ) )
788
+ {
789
+ sqlite3ErrorMsg( pParse, "object name reserved for internal use: %s", zName );
790
+ return SQLITE_ERROR;
791
+ }
792
+ return SQLITE_OK;
793
+ }
794
+
795
+ /*
796
+ ** Begin constructing a new table representation in memory. This is
797
+ ** the first of several action routines that get called in response
798
+ ** to a CREATE TABLE statement. In particular, this routine is called
799
+ ** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp
800
+ ** flag is true if the table should be stored in the auxiliary database
801
+ ** file instead of in the main database file. This is normally the case
802
+ ** when the "TEMP" or "TEMPORARY" keyword occurs in between
803
+ ** CREATE and TABLE.
804
+ **
805
+ ** The new table record is initialized and put in pParse.pNewTable.
806
+ ** As more of the CREATE TABLE statement is parsed, additional action
807
+ ** routines will be called to add more information to this record.
808
+ ** At the end of the CREATE TABLE statement, the sqlite3EndTable() routine
809
+ ** is called to complete the construction of the new table record.
810
+ */
811
+ static void sqlite3StartTable(
812
+ Parse pParse, /* Parser context */
813
+ Token pName1, /* First part of the name of the table or view */
814
+ Token pName2, /* Second part of the name of the table or view */
815
+ int isTemp, /* True if this is a TEMP table */
816
+ int isView, /* True if this is a VIEW */
817
+ int isVirtual, /* True if this is a VIRTUAL table */
818
+ int noErr /* Do nothing if table already exists */
819
+ )
820
+ {
821
+ Table pTable;
822
+ string zName = null; /* The name of the new table */
823
+ sqlite3 db = pParse.db;
824
+ Vdbe v;
825
+ int iDb; /* Database number to create the table in */
826
+ Token pName = new Token(); /* Unqualified name of the table to create */
827
+
828
+ /* The table or view name to create is passed to this routine via tokens
829
+ ** pName1 and pName2. If the table name was fully qualified, for example:
830
+ **
831
+ ** CREATE TABLE xxx.yyy (...);
832
+ **
833
+ ** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
834
+ ** the table name is not fully qualified, i.e.:
835
+ **
836
+ ** CREATE TABLE yyy(...);
837
+ **
838
+ ** Then pName1 is set to "yyy" and pName2 is "".
839
+ **
840
+ ** The call below sets the pName pointer to point at the token (pName1 or
841
+ ** pName2) that stores the unqualified table name. The variable iDb is
842
+ ** set to the index of the database that the table or view is to be
843
+ ** created in.
844
+ */
845
+ iDb = sqlite3TwoPartName( pParse, pName1, pName2, ref pName );
846
+ if ( iDb < 0 ) return;
847
+ if ( OMIT_TEMPDB == 0 && isTemp != 0 && iDb > 1 )
848
+ {
849
+ /* If creating a temp table, the name may not be qualified */
850
+ sqlite3ErrorMsg( pParse, "temporary table name must be unqualified" );
851
+ return;
852
+ }
853
+ if ( OMIT_TEMPDB == 0 && isTemp != 0 ) iDb = 1;
854
+
855
+ pParse.sNameToken = pName;
856
+ zName = sqlite3NameFromToken( db, pName );
857
+ if ( zName == null ) return;
858
+ if ( SQLITE_OK != sqlite3CheckObjectName( pParse, zName ) )
859
+ {
860
+ goto begin_table_error;
861
+ }
862
+ if ( db.init.iDb == 1 ) isTemp = 1;
863
+ #if !SQLITE_OMIT_AUTHORIZATION
864
+ Debug.Assert( (isTemp & 1)==isTemp );
865
+ {
866
+ int code;
867
+ char *zDb = db.aDb[iDb].zName;
868
+ if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
869
+ goto begin_table_error;
870
+ }
871
+ if( isView ){
872
+ if( OMIT_TEMPDB ==0&& isTemp ){
873
+ code = SQLITE_CREATE_TEMP_VIEW;
874
+ }else{
875
+ code = SQLITE_CREATE_VIEW;
876
+ }
877
+ }else{
878
+ if( OMIT_TEMPDB ==0&& isTemp ){
879
+ code = SQLITE_CREATE_TEMP_TABLE;
880
+ }else{
881
+ code = SQLITE_CREATE_TABLE;
882
+ }
883
+ }
884
+ if( !isVirtual && sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){
885
+ goto begin_table_error;
886
+ }
887
+ }
888
+ #endif
889
+
890
+ /* Make sure the new table name does not collide with an existing
891
+ ** index or table name in the same database. Issue an error message if
892
+ ** it does. The exception is if the statement being parsed was passed
893
+ ** to an sqlite3_declare_vtab() call. In that case only the column names
894
+ ** and types will be used, so there is no need to test for namespace
895
+ ** collisions.
896
+ */
897
+ if ( !IN_DECLARE_VTAB )
898
+ {
899
+ if ( SQLITE_OK != sqlite3ReadSchema( pParse ) )
900
+ {
901
+ goto begin_table_error;
902
+ }
903
+ pTable = sqlite3FindTable( db, zName, db.aDb[iDb].zName );
904
+ if ( pTable != null )
905
+ {
906
+ if ( noErr == 0 )
907
+ {
908
+ sqlite3ErrorMsg( pParse, "table %T already exists", pName );
909
+ }
910
+ goto begin_table_error;
911
+ }
912
+ if ( sqlite3FindIndex( db, zName, null ) != null && ( iDb == 0 || 0 == db.init.busy ) )
913
+ {
914
+ sqlite3ErrorMsg( pParse, "there is already an index named %s", zName );
915
+ goto begin_table_error;
916
+ }
917
+ }
918
+
919
+ pTable = new Table();// sqlite3DbMallocZero(db, Table).Length;
920
+ if ( pTable == null )
921
+ {
922
+ // db.mallocFailed = 1;
923
+ pParse.rc = SQLITE_NOMEM;
924
+ pParse.nErr++;
925
+ goto begin_table_error;
926
+ }
927
+ pTable.zName = zName;
928
+ pTable.iPKey = -1;
929
+ pTable.pSchema = db.aDb[iDb].pSchema;
930
+ pTable.nRef = 1;
931
+ pTable.dbMem = null;
932
+ Debug.Assert( pParse.pNewTable == null );
933
+ pParse.pNewTable = pTable;
934
+
935
+ /* If this is the magic sqlite_sequence table used by autoincrement,
936
+ ** then record a pointer to this table in the main database structure
937
+ ** so that INSERT can find the table easily.
938
+ */
939
+ #if !SQLITE_OMIT_AUTOINCREMENT
940
+ if ( pParse.nested == 0 && zName == "sqlite_sequence" )
941
+ {
942
+ pTable.pSchema.pSeqTab = pTable;
943
+ }
944
+ #endif
945
+
946
+ /* Begin generating the code that will insert the table record into
947
+ ** the SQLITE_MASTER table. Note in particular that we must go ahead
948
+ ** and allocate the record number for the table entry now. Before any
949
+ ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause
950
+ ** indices to be created and the table record must come before the
951
+ ** indices. Hence, the record number for the table must be allocated
952
+ ** now.
953
+ */
954
+ if ( 0 == db.init.busy && ( v = sqlite3GetVdbe( pParse ) ) != null )
955
+ {
956
+ int j1;
957
+ int fileFormat;
958
+ int reg1, reg2, reg3;
959
+ sqlite3BeginWriteOperation( pParse, 0, iDb );
960
+
961
+ if ( isVirtual != 0 )
962
+ {
963
+ sqlite3VdbeAddOp0( v, OP_VBegin );
964
+ }
965
+
966
+ /* If the file format and encoding in the database have not been set,
967
+ ** set them now.
968
+ */
969
+ reg1 = pParse.regRowid = ++pParse.nMem;
970
+ reg2 = pParse.regRoot = ++pParse.nMem;
971
+ reg3 = ++pParse.nMem;
972
+ sqlite3VdbeAddOp3( v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT );
973
+ sqlite3VdbeUsesBtree( v, iDb );
974
+ j1 = sqlite3VdbeAddOp1( v, OP_If, reg3 );
975
+ fileFormat = ( db.flags & SQLITE_LegacyFileFmt ) != 0 ?
976
+ 1 : SQLITE_MAX_FILE_FORMAT;
977
+ sqlite3VdbeAddOp2( v, OP_Integer, fileFormat, reg3 );
978
+ sqlite3VdbeAddOp3( v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, reg3 );
979
+ sqlite3VdbeAddOp2( v, OP_Integer, ENC( db ), reg3 );
980
+ sqlite3VdbeAddOp3( v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, reg3 );
981
+ sqlite3VdbeJumpHere( v, j1 );
982
+
983
+ /* This just creates a place-holder record in the sqlite_master table.
984
+ ** The record created does not contain anything yet. It will be replaced
985
+ ** by the real entry in code generated at sqlite3EndTable().
986
+ **
987
+ ** The rowid for the new entry is left in register pParse->regRowid.
988
+ ** The root page number of the new table is left in reg pParse->regRoot.
989
+ ** The rowid and root page number values are needed by the code that
990
+ ** sqlite3EndTable will generate.
991
+ */
992
+ if ( isView != 0 || isVirtual != 0 )
993
+ {
994
+ sqlite3VdbeAddOp2( v, OP_Integer, 0, reg2 );
995
+ }
996
+ else
997
+ {
998
+ sqlite3VdbeAddOp2( v, OP_CreateTable, iDb, reg2 );
999
+ }
1000
+ sqlite3OpenMasterTable( pParse, iDb );
1001
+ sqlite3VdbeAddOp2( v, OP_NewRowid, 0, reg1 );
1002
+ sqlite3VdbeAddOp2( v, OP_Null, 0, reg3 );
1003
+ sqlite3VdbeAddOp3( v, OP_Insert, 0, reg3, reg1 );
1004
+ sqlite3VdbeChangeP5( v, OPFLAG_APPEND );
1005
+ sqlite3VdbeAddOp0( v, OP_Close );
1006
+ }
1007
+
1008
+ /* Normal (non-error) return. */
1009
+ return;
1010
+
1011
+ /* If an error occurs, we jump here */
1012
+ begin_table_error:
1013
+ sqlite3DbFree( db, ref zName );
1014
+ return;
1015
+ }
1016
+
1017
+ /*
1018
+ ** This macro is used to compare two strings in a case-insensitive manner.
1019
+ ** It is slightly faster than calling sqlite3StrICmp() directly, but
1020
+ ** produces larger code.
1021
+ **
1022
+ ** WARNING: This macro is not compatible with the strcmp() family. It
1023
+ ** returns true if the two strings are equal, otherwise false.
1024
+ */
1025
+ //#define STRICMP(x, y) (\
1026
+ //sqlite3UpperToLower[*(unsigned char *)(x)]== \
1027
+ //sqlite3UpperToLower[*(unsigned char *)(y)] \
1028
+ //&& sqlite3StrICmp((x)+1,(y)+1)==0 )
1029
+
1030
+ /*
1031
+ ** Add a new column to the table currently being constructed.
1032
+ **
1033
+ ** The parser calls this routine once for each column declaration
1034
+ ** in a CREATE TABLE statement. sqlite3StartTable() gets called
1035
+ ** first to get things going. Then this routine is called for each
1036
+ ** column.
1037
+ */
1038
+ static void sqlite3AddColumn( Parse pParse, Token pName )
1039
+ {
1040
+ Table p;
1041
+ int i;
1042
+ string z;
1043
+ Column pCol;
1044
+ sqlite3 db = pParse.db;
1045
+ if ( ( p = pParse.pNewTable ) == null ) return;
1046
+ #if SQLITE_MAX_COLUMN || !SQLITE_MAX_COLUMN
1047
+ if ( p.nCol + 1 > db.aLimit[SQLITE_LIMIT_COLUMN] )
1048
+ {
1049
+ sqlite3ErrorMsg( pParse, "too many columns on %s", p.zName );
1050
+ return;
1051
+ }
1052
+ #endif
1053
+ z = sqlite3NameFromToken( db, pName );
1054
+ if ( z == null ) return;
1055
+ for ( i = 0; i < p.nCol; i++ )
1056
+ {
1057
+ if ( 0 == sqlite3StrICmp( z, p.aCol[i].zName ) )
1058
+ {//STRICMP(z, p.aCol[i].zName) ){
1059
+ sqlite3ErrorMsg( pParse, "duplicate column name: %s", z );
1060
+ sqlite3DbFree( db, ref z );
1061
+ return;
1062
+ }
1063
+ }
1064
+ if ( ( p.nCol & 0x7 ) == 0 )
1065
+ {
1066
+ //aNew = sqlite3DbRealloc(db,p.aCol,(p.nCol+8)*sizeof(p.aCol[0]));
1067
+ //if( aNew==0 ){
1068
+ // sqlite3DbFree(db,ref z);
1069
+ // return;
1070
+ //}
1071
+ Array.Resize( ref p.aCol, p.nCol + 8 );
1072
+ }
1073
+ p.aCol[p.nCol] = new Column();
1074
+ pCol = p.aCol[p.nCol];
1075
+ //memset(pCol, 0, sizeof(p.aCol[0]));
1076
+ pCol.zName = z;
1077
+
1078
+ /* If there is no type specified, columns have the default affinity
1079
+ ** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will
1080
+ ** be called next to set pCol.affinity correctly.
1081
+ */
1082
+ pCol.affinity = SQLITE_AFF_NONE;
1083
+ p.nCol++;
1084
+ }
1085
+
1086
+ /*
1087
+ ** This routine is called by the parser while in the middle of
1088
+ ** parsing a CREATE TABLE statement. A "NOT NULL" constraint has
1089
+ ** been seen on a column. This routine sets the notNull flag on
1090
+ ** the column currently under construction.
1091
+ */
1092
+ static void sqlite3AddNotNull( Parse pParse, int onError )
1093
+ {
1094
+ Table p;
1095
+ p = pParse.pNewTable;
1096
+ if ( p == null || NEVER( p.nCol < 1 ) ) return;
1097
+ p.aCol[p.nCol - 1].notNull = (u8)onError;
1098
+ }
1099
+
1100
+ /*
1101
+ ** Scan the column type name zType (length nType) and return the
1102
+ ** associated affinity type.
1103
+ **
1104
+ ** This routine does a case-independent search of zType for the
1105
+ ** substrings in the following table. If one of the substrings is
1106
+ ** found, the corresponding affinity is returned. If zType contains
1107
+ ** more than one of the substrings, entries toward the top of
1108
+ ** the table take priority. For example, if zType is 'BLOBINT',
1109
+ ** SQLITE_AFF_INTEGER is returned.
1110
+ **
1111
+ ** Substring | Affinity
1112
+ ** --------------------------------
1113
+ ** 'INT' | SQLITE_AFF_INTEGER
1114
+ ** 'CHAR' | SQLITE_AFF_TEXT
1115
+ ** 'CLOB' | SQLITE_AFF_TEXT
1116
+ ** 'TEXT' | SQLITE_AFF_TEXT
1117
+ ** 'BLOB' | SQLITE_AFF_NONE
1118
+ ** 'REAL' | SQLITE_AFF_REAL
1119
+ ** 'FLOA' | SQLITE_AFF_REAL
1120
+ ** 'DOUB' | SQLITE_AFF_REAL
1121
+ **
1122
+ ** If none of the substrings in the above table are found,
1123
+ ** SQLITE_AFF_NUMERIC is returned.
1124
+ */
1125
+ static char sqlite3AffinityType( string zIn )
1126
+ {
1127
+ //u32 h = 0;
1128
+ //char aff = SQLITE_AFF_NUMERIC;
1129
+ zIn = zIn.ToLower();
1130
+ if ( zIn.Contains( "char" ) || zIn.Contains( "clob" ) || zIn.Contains( "text" ) ) return SQLITE_AFF_TEXT;
1131
+ if ( zIn.Contains( "blob" ) ) return SQLITE_AFF_NONE;
1132
+ if ( zIn.Contains( "doub" ) || zIn.Contains( "floa" ) || zIn.Contains( "real" ) ) return SQLITE_AFF_REAL;
1133
+ if ( zIn.Contains( "int" ) ) return SQLITE_AFF_INTEGER;
1134
+ return SQLITE_AFF_NUMERIC;
1135
+ // string zEnd = pType.z.Substring(pType.n);
1136
+
1137
+ // while( zIn!=zEnd ){
1138
+ // h = (h<<8) + sqlite3UpperToLower[*zIn];
1139
+ // zIn++;
1140
+ // if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
1141
+ // aff = SQLITE_AFF_TEXT;
1142
+ // }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */
1143
+ // aff = SQLITE_AFF_TEXT;
1144
+ // }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */
1145
+ // aff = SQLITE_AFF_TEXT;
1146
+ // }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
1147
+ // && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
1148
+ // aff = SQLITE_AFF_NONE;
1149
+ //#if !SQLITE_OMIT_FLOATING_POINT
1150
+ // }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
1151
+ // && aff==SQLITE_AFF_NUMERIC ){
1152
+ // aff = SQLITE_AFF_REAL;
1153
+ // }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */
1154
+ // && aff==SQLITE_AFF_NUMERIC ){
1155
+ // aff = SQLITE_AFF_REAL;
1156
+ // }else if( h==(('d'<<24)+('o'<<16)+('u'<<8)+'b') /* DOUB */
1157
+ // && aff==SQLITE_AFF_NUMERIC ){
1158
+ // aff = SQLITE_AFF_REAL;
1159
+ //#endif
1160
+ // }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */
1161
+ // aff = SQLITE_AFF_INTEGER;
1162
+ // break;
1163
+ // }
1164
+ // }
1165
+
1166
+ // return aff;
1167
+ }
1168
+
1169
+ /*
1170
+ ** This routine is called by the parser while in the middle of
1171
+ ** parsing a CREATE TABLE statement. The pFirst token is the first
1172
+ ** token in the sequence of tokens that describe the type of the
1173
+ ** column currently under construction. pLast is the last token
1174
+ ** in the sequence. Use this information to construct a string
1175
+ ** that contains the typename of the column and store that string
1176
+ ** in zType.
1177
+ */
1178
+ static void sqlite3AddColumnType( Parse pParse, Token pType )
1179
+ {
1180
+ Table p;
1181
+ Column pCol;
1182
+
1183
+ p = pParse.pNewTable;
1184
+ if ( p == null || NEVER( p.nCol < 1 ) ) return;
1185
+ pCol = p.aCol[p.nCol - 1];
1186
+ Debug.Assert( pCol.zType == null );
1187
+ pCol.zType = sqlite3NameFromToken( pParse.db, pType );
1188
+ pCol.affinity = sqlite3AffinityType( pCol.zType );
1189
+ }
1190
+
1191
+
1192
+ /*
1193
+ ** The expression is the default value for the most recently added column
1194
+ ** of the table currently under construction.
1195
+ **
1196
+ ** Default value expressions must be constant. Raise an exception if this
1197
+ ** is not the case.
1198
+ **
1199
+ ** This routine is called by the parser while in the middle of
1200
+ ** parsing a CREATE TABLE statement.
1201
+ */
1202
+ static void sqlite3AddDefaultValue( Parse pParse, ExprSpan pSpan )
1203
+ {
1204
+ Table p;
1205
+ Column pCol;
1206
+ sqlite3 db = pParse.db;
1207
+ p = pParse.pNewTable;
1208
+ if ( p != null )
1209
+ {
1210
+ pCol = ( p.aCol[p.nCol - 1] );
1211
+ if ( sqlite3ExprIsConstantOrFunction( pSpan.pExpr ) == 0 )
1212
+ {
1213
+ sqlite3ErrorMsg( pParse, "default value of column [%s] is not constant",
1214
+ pCol.zName );
1215
+ }
1216
+ else
1217
+ {
1218
+ /* A copy of pExpr is used instead of the original, as pExpr contains
1219
+ ** tokens that point to volatile memory. The 'span' of the expression
1220
+ ** is required by pragma table_info.
1221
+ */
1222
+ sqlite3ExprDelete( db, ref pCol.pDflt );
1223
+ pCol.pDflt = sqlite3ExprDup( db, pSpan.pExpr, EXPRDUP_REDUCE );
1224
+ sqlite3DbFree( db, ref pCol.zDflt );
1225
+ pCol.zDflt = pSpan.zStart.Substring( 0, pSpan.zStart.Length - pSpan.zEnd.Length );
1226
+ //sqlite3DbStrNDup( db, pSpan.zStart,
1227
+ // (int)( pSpan.zEnd.Length - pSpan.zStart.Length ) );
1228
+ }
1229
+ }
1230
+ sqlite3ExprDelete( db, ref pSpan.pExpr );
1231
+ }
1232
+
1233
+ /*
1234
+ ** Designate the PRIMARY KEY for the table. pList is a list of names
1235
+ ** of columns that form the primary key. If pList is NULL, then the
1236
+ ** most recently added column of the table is the primary key.
1237
+ **
1238
+ ** A table can have at most one primary key. If the table already has
1239
+ ** a primary key (and this is the second primary key) then create an
1240
+ ** error.
1241
+ **
1242
+ ** If the PRIMARY KEY is on a single column whose datatype is INTEGER,
1243
+ ** then we will try to use that column as the rowid. Set the Table.iPKey
1244
+ ** field of the table under construction to be the index of the
1245
+ ** INTEGER PRIMARY KEY column. Table.iPKey is set to -1 if there is
1246
+ ** no INTEGER PRIMARY KEY.
1247
+ **
1248
+ ** If the key is not an INTEGER PRIMARY KEY, then create a unique
1249
+ ** index for the key. No index is created for INTEGER PRIMARY KEYs.
1250
+ */
1251
+ // OVERLOADS, so I don't need to rewrite parse.c
1252
+ static void sqlite3AddPrimaryKey( Parse pParse, int null_2, int onError, int autoInc, int sortOrder )
1253
+ { sqlite3AddPrimaryKey( pParse, null, onError, autoInc, sortOrder ); }
1254
+ static void sqlite3AddPrimaryKey(
1255
+ Parse pParse, /* Parsing context */
1256
+ ExprList pList, /* List of field names to be indexed */
1257
+ int onError, /* What to do with a uniqueness conflict */
1258
+ int autoInc, /* True if the AUTOINCREMENT keyword is present */
1259
+ int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */
1260
+ )
1261
+ {
1262
+ Table pTab = pParse.pNewTable;
1263
+ string zType = null;
1264
+ int iCol = -1, i;
1265
+ if ( pTab == null || IN_DECLARE_VTAB ) goto primary_key_exit;
1266
+ if ( ( pTab.tabFlags & TF_HasPrimaryKey ) != 0 )
1267
+ {
1268
+ sqlite3ErrorMsg( pParse,
1269
+ "table \"%s\" has more than one primary key", pTab.zName );
1270
+ goto primary_key_exit;
1271
+ }
1272
+ pTab.tabFlags |= TF_HasPrimaryKey;
1273
+ if ( pList == null )
1274
+ {
1275
+ iCol = pTab.nCol - 1;
1276
+ pTab.aCol[iCol].isPrimKey = 1;
1277
+ }
1278
+ else
1279
+ {
1280
+ for ( i = 0; i < pList.nExpr; i++ )
1281
+ {
1282
+ for ( iCol = 0; iCol < pTab.nCol; iCol++ )
1283
+ {
1284
+ if ( sqlite3StrICmp( pList.a[i].zName, pTab.aCol[iCol].zName ) == 0 )
1285
+ {
1286
+ break;
1287
+ }
1288
+ }
1289
+ if ( iCol < pTab.nCol )
1290
+ {
1291
+ pTab.aCol[iCol].isPrimKey = 1;
1292
+ }
1293
+ }
1294
+ if ( pList.nExpr > 1 ) iCol = -1;
1295
+ }
1296
+ if ( iCol >= 0 && iCol < pTab.nCol )
1297
+ {
1298
+ zType = pTab.aCol[iCol].zType;
1299
+ }
1300
+ if ( zType != null && sqlite3StrICmp( zType, "INTEGER" ) == 0
1301
+ && sortOrder == SQLITE_SO_ASC )
1302
+ {
1303
+ pTab.iPKey = iCol;
1304
+ pTab.keyConf = (byte)onError;
1305
+ Debug.Assert( autoInc == 0 || autoInc == 1 );
1306
+ pTab.tabFlags |= (u8)( autoInc * TF_Autoincrement );
1307
+ }
1308
+ else if ( autoInc != 0 )
1309
+ {
1310
+ #if !SQLITE_OMIT_AUTOINCREMENT
1311
+ sqlite3ErrorMsg( pParse, "AUTOINCREMENT is only allowed on an " +
1312
+ "INTEGER PRIMARY KEY" );
1313
+ #endif
1314
+ }
1315
+ else
1316
+ {
1317
+ Index p;
1318
+ p = sqlite3CreateIndex( pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0 );
1319
+ if ( p != null )
1320
+ {
1321
+ p.autoIndex = 2;
1322
+ }
1323
+ pList = null;
1324
+ }
1325
+
1326
+ primary_key_exit:
1327
+ sqlite3ExprListDelete( pParse.db, ref pList );
1328
+ return;
1329
+ }
1330
+
1331
+ /*
1332
+ ** Add a new CHECK constraint to the table currently under construction.
1333
+ */
1334
+ static void sqlite3AddCheckConstraint(
1335
+ Parse pParse, /* Parsing context */
1336
+ Expr pCheckExpr /* The check expression */
1337
+ )
1338
+ {
1339
+ sqlite3 db = pParse.db;
1340
+ #if !SQLITE_OMIT_CHECK
1341
+ Table pTab = pParse.pNewTable;
1342
+ if ( pTab != null && !IN_DECLARE_VTAB )
1343
+ {
1344
+ pTab.pCheck = sqlite3ExprAnd( db, pTab.pCheck, pCheckExpr );
1345
+ }
1346
+ else
1347
+ #endif
1348
+ {
1349
+ sqlite3ExprDelete( db, ref pCheckExpr );
1350
+ }
1351
+ }
1352
+ /*
1353
+ ** Set the collation function of the most recently parsed table column
1354
+ ** to the CollSeq given.
1355
+ */
1356
+ static void sqlite3AddCollateType( Parse pParse, Token pToken )
1357
+ {
1358
+ Table p;
1359
+ int i;
1360
+ string zColl; /* Dequoted name of collation sequence */
1361
+ sqlite3 db;
1362
+
1363
+ if ( ( p = pParse.pNewTable ) == null ) return;
1364
+ i = p.nCol - 1;
1365
+ db = p.dbMem;
1366
+ zColl = sqlite3NameFromToken( db, pToken );
1367
+ if ( zColl == null ) return;
1368
+
1369
+ if ( sqlite3LocateCollSeq( pParse, zColl ) != null )
1370
+ {
1371
+ Index pIdx;
1372
+ p.aCol[i].zColl = zColl;
1373
+
1374
+ /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
1375
+ ** then an index may have been created on this column before the
1376
+ ** collation type was added. Correct this if it is the case.
1377
+ */
1378
+ for ( pIdx = p.pIndex; pIdx != null; pIdx = pIdx.pNext )
1379
+ {
1380
+ Debug.Assert( pIdx.nColumn == 1 );
1381
+ if ( pIdx.aiColumn[0] == i )
1382
+ {
1383
+ pIdx.azColl[0] = p.aCol[i].zColl;
1384
+ }
1385
+ }
1386
+ }
1387
+ else
1388
+ {
1389
+ sqlite3DbFree( db, ref zColl );
1390
+ }
1391
+ }
1392
+
1393
+ /*
1394
+ ** This function returns the collation sequence for database native text
1395
+ ** encoding identified by the string zName, length nName.
1396
+ **
1397
+ ** If the requested collation sequence is not available, or not available
1398
+ ** in the database native encoding, the collation factory is invoked to
1399
+ ** request it. If the collation factory does not supply such a sequence,
1400
+ ** and the sequence is available in another text encoding, then that is
1401
+ ** returned instead.
1402
+ **
1403
+ ** If no versions of the requested collations sequence are available, or
1404
+ ** another error occurs, NULL is returned and an error message written into
1405
+ ** pParse.
1406
+ **
1407
+ ** This routine is a wrapper around sqlite3FindCollSeq(). This routine
1408
+ ** invokes the collation factory if the named collation cannot be found
1409
+ ** and generates an error message.
1410
+ **
1411
+ ** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq()
1412
+ */
1413
+ static CollSeq sqlite3LocateCollSeq( Parse pParse, string zName )
1414
+ {
1415
+ sqlite3 db = pParse.db;
1416
+ u8 enc = db.aDb[0].pSchema.enc;// ENC(db);
1417
+ u8 initbusy = db.init.busy;
1418
+ CollSeq pColl;
1419
+
1420
+ pColl = sqlite3FindCollSeq( db, enc, zName, initbusy );
1421
+ if ( 0 == initbusy && ( pColl == null || pColl.xCmp == null ) )
1422
+ {
1423
+ pColl = sqlite3GetCollSeq( db, enc, pColl, zName );
1424
+ if ( pColl == null )
1425
+ {
1426
+ sqlite3ErrorMsg( pParse, "no such collation sequence: %s", zName );
1427
+ }
1428
+ }
1429
+
1430
+ return pColl;
1431
+ }
1432
+
1433
+
1434
+ /*
1435
+ ** Generate code that will increment the schema cookie.
1436
+ **
1437
+ ** The schema cookie is used to determine when the schema for the
1438
+ ** database changes. After each schema change, the cookie value
1439
+ ** changes. When a process first reads the schema it records the
1440
+ ** cookie. Thereafter, whenever it goes to access the database,
1441
+ ** it checks the cookie to make sure the schema has not changed
1442
+ ** since it was last read.
1443
+ **
1444
+ ** This plan is not completely bullet-proof. It is possible for
1445
+ ** the schema to change multiple times and for the cookie to be
1446
+ ** set back to prior value. But schema changes are infrequent
1447
+ ** and the probability of hitting the same cookie value is only
1448
+ ** 1 chance in 2^32. So we're safe enough.
1449
+ */
1450
+ static void sqlite3ChangeCookie( Parse pParse, int iDb )
1451
+ {
1452
+ int r1 = sqlite3GetTempReg( pParse );
1453
+ sqlite3 db = pParse.db;
1454
+ Vdbe v = pParse.pVdbe;
1455
+ sqlite3VdbeAddOp2( v, OP_Integer, db.aDb[iDb].pSchema.schema_cookie + 1, r1 );
1456
+ sqlite3VdbeAddOp3( v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, r1 );
1457
+ sqlite3ReleaseTempReg( pParse, r1 );
1458
+ }
1459
+
1460
+ /*
1461
+ ** Measure the number of characters needed to output the given
1462
+ ** identifier. The number returned includes any quotes used
1463
+ ** but does not include the null terminator.
1464
+ **
1465
+ ** The estimate is conservative. It might be larger that what is
1466
+ ** really needed.
1467
+ */
1468
+ static int identLength( string z )
1469
+ {
1470
+ int n;
1471
+ for ( n = 0; n < z.Length; n++ )
1472
+ {
1473
+ if ( z[n] == (byte)'"' ) { n++; }
1474
+ }
1475
+ return n + 2;
1476
+ }
1477
+
1478
+
1479
+ /*
1480
+ ** The first parameter is a pointer to an output buffer. The second
1481
+ ** parameter is a pointer to an integer that contains the offset at
1482
+ ** which to write into the output buffer. This function copies the
1483
+ ** nul-terminated string pointed to by the third parameter, zSignedIdent,
1484
+ ** to the specified offset in the buffer and updates *pIdx to refer
1485
+ ** to the first byte after the last byte written before returning.
1486
+ **
1487
+ ** If the string zSignedIdent consists entirely of alpha-numeric
1488
+ ** characters, does not begin with a digit and is not an SQL keyword,
1489
+ ** then it is copied to the output buffer exactly as it is. Otherwise,
1490
+ ** it is quoted using double-quotes.
1491
+ */
1492
+ static void identPut( StringBuilder z, ref int pIdx, string zSignedIdent )
1493
+ {
1494
+ string zIdent = zSignedIdent;
1495
+ int i; int j; bool needQuote;
1496
+ i = pIdx;
1497
+ for ( j = 0; j < zIdent.Length; j++ )
1498
+ {
1499
+ if ( !sqlite3Isalnum( zIdent[j] ) && zIdent[j] != '_' ) break;
1500
+ }
1501
+ needQuote = sqlite3Isdigit( zIdent[0] ) || sqlite3KeywordCode( zIdent, j ) != TK_ID;
1502
+ if ( !needQuote )
1503
+ {
1504
+ needQuote = ( j < zIdent.Length && zIdent[j] != 0 );
1505
+ }
1506
+ if ( needQuote ) { if ( i == z.Length ) z.Append( '\0' ); z[i++] = '"'; }
1507
+ for ( j = 0; j < zIdent.Length; j++ )
1508
+ {
1509
+ if ( i == z.Length ) z.Append( '\0' );
1510
+ z[i++] = zIdent[j];
1511
+ if ( zIdent[j] == '"' ) { if ( i == z.Length ) z.Append( '\0' ); z[i++] = '"'; }
1512
+ }
1513
+ if ( needQuote ) { if ( i == z.Length ) z.Append( '\0' ); z[i++] = '"'; }
1514
+ //z[i] = 0;
1515
+ pIdx = i;
1516
+ }
1517
+
1518
+ /*
1519
+ ** Generate a CREATE TABLE statement appropriate for the given
1520
+ ** table. Memory to hold the text of the statement is obtained
1521
+ ** from sqliteMalloc() and must be freed by the calling function.
1522
+ */
1523
+ static string createTableStmt( sqlite3 db, Table p )
1524
+ {
1525
+ int i, k, n;
1526
+ StringBuilder zStmt;
1527
+ string zSep; string zSep2; string zEnd;
1528
+ Column pCol;
1529
+ n = 0;
1530
+ for ( i = 0; i < p.nCol; i++ )
1531
+ {//, pCol++){
1532
+ pCol = p.aCol[i];
1533
+ n += identLength( pCol.zName ) + 5;
1534
+ }
1535
+ n += identLength( p.zName );
1536
+ if ( n < 50 )
1537
+ {
1538
+ zSep = "";
1539
+ zSep2 = ",";
1540
+ zEnd = ")";
1541
+ }
1542
+ else
1543
+ {
1544
+ zSep = "\n ";
1545
+ zSep2 = ",\n ";
1546
+ zEnd = "\n)";
1547
+ }
1548
+ n += 35 + 6 * p.nCol;
1549
+ zStmt = new StringBuilder( n );
1550
+ //zStmt = sqlite3Malloc( n );
1551
+ //if( zStmt==0 ){
1552
+ // db.mallocFailed = 1;
1553
+ // return 0;
1554
+ //}
1555
+ //sqlite3_snprintf(n, zStmt,"CREATE TABLE ");
1556
+ zStmt.Append( "CREATE TABLE " );
1557
+ k = sqlite3Strlen30( zStmt );
1558
+ identPut( zStmt, ref k, p.zName );
1559
+ zStmt.Append( '(' );//zStmt[k++] = '(';
1560
+ for ( i = 0; i < p.nCol; i++ )
1561
+ {//, pCol++){
1562
+ pCol = p.aCol[i];
1563
+ string[] azType = new string[] {
1564
+ /* SQLITE_AFF_TEXT */ " TEXT",
1565
+ /* SQLITE_AFF_NONE */ "",
1566
+ /* SQLITE_AFF_NUMERIC */ " NUM",
1567
+ /* SQLITE_AFF_INTEGER */ " INT",
1568
+ /* SQLITE_AFF_REAL */ " REAL"
1569
+ };
1570
+ int len;
1571
+ string zType;
1572
+
1573
+ zStmt.Append( zSep );// sqlite3_snprintf(n-k, zStmt[k], zSep);
1574
+ k = sqlite3Strlen30( zStmt );// k += strlen(zStmt[k]);
1575
+ zSep = zSep2;
1576
+ identPut( zStmt, ref k, pCol.zName );
1577
+ Debug.Assert( pCol.affinity - SQLITE_AFF_TEXT >= 0 );
1578
+ Debug.Assert( pCol.affinity - SQLITE_AFF_TEXT < azType.Length );//sizeof(azType)/sizeof(azType[0]) );
1579
+ testcase( pCol.affinity == SQLITE_AFF_TEXT );
1580
+ testcase( pCol.affinity == SQLITE_AFF_NONE );
1581
+ testcase( pCol.affinity == SQLITE_AFF_NUMERIC );
1582
+ testcase( pCol.affinity == SQLITE_AFF_INTEGER );
1583
+ testcase( pCol.affinity == SQLITE_AFF_REAL );
1584
+
1585
+ zType = azType[pCol.affinity - SQLITE_AFF_TEXT];
1586
+ len = sqlite3Strlen30( zType );
1587
+ Debug.Assert( pCol.affinity == SQLITE_AFF_NONE
1588
+ || pCol.affinity == sqlite3AffinityType( zType ) );
1589
+ zStmt.Append( zType );// memcpy( &zStmt[k], zType, len );
1590
+ k += len;
1591
+ Debug.Assert( k <= n );
1592
+ }
1593
+ zStmt.Append( zEnd );//sqlite3_snprintf(n-k, zStmt[k], "%s", zEnd);
1594
+ return zStmt.ToString();
1595
+ }
1596
+
1597
+ /*
1598
+ ** This routine is called to report the final ")" that terminates
1599
+ ** a CREATE TABLE statement.
1600
+ **
1601
+ ** The table structure that other action routines have been building
1602
+ ** is added to the internal hash tables, assuming no errors have
1603
+ ** occurred.
1604
+ **
1605
+ ** An entry for the table is made in the master table on disk, unless
1606
+ ** this is a temporary table or db.init.busy==1. When db.init.busy==1
1607
+ ** it means we are reading the sqlite_master table because we just
1608
+ ** connected to the database or because the sqlite_master table has
1609
+ ** recently changed, so the entry for this table already exists in
1610
+ ** the sqlite_master table. We do not want to create it again.
1611
+ **
1612
+ ** If the pSelect argument is not NULL, it means that this routine
1613
+ ** was called to create a table generated from a
1614
+ ** "CREATE TABLE ... AS SELECT ..." statement. The column names of
1615
+ ** the new table will match the result set of the SELECT.
1616
+ */
1617
+ // OVERLOADS, so I don't need to rewrite parse.c
1618
+ static void sqlite3EndTable( Parse pParse, Token pCons, Token pEnd, int null_4 )
1619
+ { sqlite3EndTable( pParse, pCons, pEnd, null ); }
1620
+ static void sqlite3EndTable( Parse pParse, int null_2, int null_3, Select pSelect )
1621
+ { sqlite3EndTable( pParse, null, null, pSelect ); }
1622
+
1623
+ static void sqlite3EndTable(
1624
+ Parse pParse, /* Parse context */
1625
+ Token pCons, /* The ',' token after the last column defn. */
1626
+ Token pEnd, /* The final ')' token in the CREATE TABLE */
1627
+ Select pSelect /* Select from a "CREATE ... AS SELECT" */
1628
+ )
1629
+ {
1630
+ Table p;
1631
+ sqlite3 db = pParse.db;
1632
+ int iDb;
1633
+
1634
+ if ( ( pEnd == null && pSelect == null ) /*|| db.mallocFailed != 0 */ )
1635
+ {
1636
+ return;
1637
+ }
1638
+ p = pParse.pNewTable;
1639
+ if ( p == null ) return;
1640
+
1641
+ Debug.Assert( 0 == db.init.busy || pSelect == null );
1642
+
1643
+ iDb = sqlite3SchemaToIndex( db, p.pSchema );
1644
+
1645
+ #if !SQLITE_OMIT_CHECK
1646
+ /* Resolve names in all CHECK constraint expressions.
1647
+ */
1648
+ if ( p.pCheck != null )
1649
+ {
1650
+ SrcList sSrc; /* Fake SrcList for pParse.pNewTable */
1651
+ NameContext sNC; /* Name context for pParse.pNewTable */
1652
+
1653
+ sNC = new NameContext();// memset(sNC, 0, sizeof(sNC));
1654
+ sSrc = new SrcList();// memset(sSrc, 0, sizeof(sSrc));
1655
+ sSrc.nSrc = 1;
1656
+ sSrc.a = new SrcList_item[1];
1657
+ sSrc.a[0] = new SrcList_item();
1658
+ sSrc.a[0].zName = p.zName;
1659
+ sSrc.a[0].pTab = p;
1660
+ sSrc.a[0].iCursor = -1;
1661
+ sNC.pParse = pParse;
1662
+ sNC.pSrcList = sSrc;
1663
+ sNC.isCheck = 1;
1664
+ if ( sqlite3ResolveExprNames( sNC, ref p.pCheck ) != 0 )
1665
+ {
1666
+ return;
1667
+ }
1668
+ }
1669
+ #endif // * !SQLITE_OMIT_CHECK) */
1670
+
1671
+ /* If the db.init.busy is 1 it means we are reading the SQL off the
1672
+ ** "sqlite_master" or "sqlite_temp_master" table on the disk.
1673
+ ** So do not write to the disk again. Extract the root page number
1674
+ ** for the table from the db.init.newTnum field. (The page number
1675
+ ** should have been put there by the sqliteOpenCb routine.)
1676
+ */
1677
+ if ( db.init.busy != 0 )
1678
+ {
1679
+ p.tnum = db.init.newTnum;
1680
+ }
1681
+
1682
+ /* If not initializing, then create a record for the new table
1683
+ ** in the SQLITE_MASTER table of the database.
1684
+ **
1685
+ ** If this is a TEMPORARY table, write the entry into the auxiliary
1686
+ ** file instead of into the main database file.
1687
+ */
1688
+ if ( 0 == db.init.busy )
1689
+ {
1690
+ int n;
1691
+ Vdbe v;
1692
+ String zType = ""; /* "view" or "table" */
1693
+ String zType2 = ""; /* "VIEW" or "TABLE" */
1694
+ String zStmt = ""; /* Text of the CREATE TABLE or CREATE VIEW statement */
1695
+
1696
+ v = sqlite3GetVdbe( pParse );
1697
+ if ( NEVER( v == null ) ) return;
1698
+
1699
+ sqlite3VdbeAddOp1( v, OP_Close, 0 );
1700
+
1701
+ /*
1702
+ ** Initialize zType for the new view or table.
1703
+ */
1704
+ if ( p.pSelect == null )
1705
+ {
1706
+ /* A regular table */
1707
+ zType = "table";
1708
+ zType2 = "TABLE";
1709
+ #if !SQLITE_OMIT_VIEW
1710
+ }
1711
+ else
1712
+ {
1713
+ /* A view */
1714
+ zType = "view";
1715
+ zType2 = "VIEW";
1716
+ #endif
1717
+ }
1718
+
1719
+ /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT
1720
+ ** statement to populate the new table. The root-page number for the
1721
+ ** new table is in register pParse->regRoot.
1722
+ **
1723
+ ** Once the SELECT has been coded by sqlite3Select(), it is in a
1724
+ ** suitable state to query for the column names and types to be used
1725
+ ** by the new table.
1726
+ **
1727
+ ** A shared-cache write-lock is not required to write to the new table,
1728
+ ** as a schema-lock must have already been obtained to create it. Since
1729
+ ** a schema-lock excludes all other database users, the write-lock would
1730
+ ** be redundant.
1731
+ */
1732
+ if ( pSelect != null )
1733
+ {
1734
+ SelectDest dest = new SelectDest();
1735
+ Table pSelTab;
1736
+
1737
+ Debug.Assert( pParse.nTab == 1 );
1738
+ sqlite3VdbeAddOp3( v, OP_OpenWrite, 1, pParse.regRoot, iDb );
1739
+ sqlite3VdbeChangeP5( v, 1 );
1740
+ pParse.nTab = 2;
1741
+ sqlite3SelectDestInit( dest, SRT_Table, 1 );
1742
+ sqlite3Select( pParse, pSelect, ref dest );
1743
+ sqlite3VdbeAddOp1( v, OP_Close, 1 );
1744
+ if ( pParse.nErr == 0 )
1745
+ {
1746
+ pSelTab = sqlite3ResultSetOfSelect( pParse, pSelect );
1747
+ if ( pSelTab == null ) return;
1748
+ Debug.Assert( p.aCol == null );
1749
+ p.nCol = pSelTab.nCol;
1750
+ p.aCol = pSelTab.aCol;
1751
+ pSelTab.nCol = 0;
1752
+ pSelTab.aCol = null;
1753
+ sqlite3DeleteTable( ref pSelTab );
1754
+ }
1755
+ }
1756
+
1757
+ /* Compute the complete text of the CREATE statement */
1758
+ if ( pSelect != null )
1759
+ {
1760
+ zStmt = createTableStmt( db, p );
1761
+ }
1762
+ else
1763
+ {
1764
+ n = (int)( pParse.sNameToken.z.Length - pEnd.z.Length ) + 1;
1765
+ zStmt = sqlite3MPrintf( db,
1766
+ "CREATE %s %.*s", zType2, n, pParse.sNameToken.z
1767
+ );
1768
+ }
1769
+
1770
+ /* A slot for the record has already been allocated in the
1771
+ ** SQLITE_MASTER table. We just need to update that slot with all
1772
+ ** the information we've collected.
1773
+ */
1774
+ sqlite3NestedParse( pParse,
1775
+ "UPDATE %Q.%s " +
1776
+ "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q " +
1777
+ "WHERE rowid=#%d",
1778
+ db.aDb[iDb].zName, SCHEMA_TABLE( iDb ),
1779
+ zType,
1780
+ p.zName,
1781
+ p.zName,
1782
+ pParse.regRoot,
1783
+ zStmt,
1784
+ pParse.regRowid
1785
+ );
1786
+ sqlite3DbFree( db, ref zStmt );
1787
+ sqlite3ChangeCookie( pParse, iDb );
1788
+
1789
+ #if !SQLITE_OMIT_AUTOINCREMENT
1790
+ /* Check to see if we need to create an sqlite_sequence table for
1791
+ ** keeping track of autoincrement keys.
1792
+ */
1793
+ if ( ( p.tabFlags & TF_Autoincrement ) != 0 )
1794
+ {
1795
+ Db pDb = db.aDb[iDb];
1796
+ if ( pDb.pSchema.pSeqTab == null )
1797
+ {
1798
+ sqlite3NestedParse( pParse,
1799
+ "CREATE TABLE %Q.sqlite_sequence(name,seq)",
1800
+ pDb.zName
1801
+ );
1802
+ }
1803
+ }
1804
+ #endif
1805
+
1806
+ /* Reparse everything to update our internal data structures */
1807
+ sqlite3VdbeAddOp4( v, OP_ParseSchema, iDb, 0, 0,
1808
+ sqlite3MPrintf( db, "tbl_name='%q'", p.zName ), P4_DYNAMIC );
1809
+ }
1810
+
1811
+
1812
+ /* Add the table to the in-memory representation of the database.
1813
+ */
1814
+ if ( db.init.busy != 0 )
1815
+ {
1816
+ Table pOld;
1817
+ Schema pSchema = p.pSchema;
1818
+ pOld = (Table)sqlite3HashInsert( ref pSchema.tblHash, p.zName,
1819
+ sqlite3Strlen30( p.zName ), p );
1820
+ if ( pOld != null )
1821
+ {
1822
+ Debug.Assert( p == pOld ); /* Malloc must have failed inside HashInsert() */
1823
+ // db.mallocFailed = 1;
1824
+ return;
1825
+ }
1826
+ pParse.pNewTable = null;
1827
+ db.nTable++;
1828
+ db.flags |= SQLITE_InternChanges;
1829
+
1830
+ #if !SQLITE_OMIT_ALTERTABLE
1831
+ if ( p.pSelect == null )
1832
+ {
1833
+ string zName = pParse.sNameToken.z;
1834
+ int nName;
1835
+ Debug.Assert( pSelect == null && pCons != null && pEnd != null );
1836
+ if ( pCons.z == null )
1837
+ {
1838
+ pCons = pEnd;
1839
+ }
1840
+ nName = zName.Length - pCons.z.Length;
1841
+ p.addColOffset = 13 + nName; // sqlite3Utf8CharLen(zName, nName);
1842
+ }
1843
+ #endif
1844
+ }
1845
+ }
1846
+
1847
+ #if !SQLITE_OMIT_VIEW
1848
+ /*
1849
+ ** The parser calls this routine in order to create a new VIEW
1850
+ */
1851
+ static void sqlite3CreateView(
1852
+ Parse pParse, /* The parsing context */
1853
+ Token pBegin, /* The CREATE token that begins the statement */
1854
+ Token pName1, /* The token that holds the name of the view */
1855
+ Token pName2, /* The token that holds the name of the view */
1856
+ Select pSelect, /* A SELECT statement that will become the new view */
1857
+ int isTemp, /* TRUE for a TEMPORARY view */
1858
+ int noErr /* Suppress error messages if VIEW already exists */
1859
+ )
1860
+ {
1861
+ Table p;
1862
+ int n;
1863
+ string z;//const char *z;
1864
+ Token sEnd;
1865
+ DbFixer sFix = new DbFixer();
1866
+ Token pName = null;
1867
+ int iDb;
1868
+ sqlite3 db = pParse.db;
1869
+
1870
+ if ( pParse.nVar > 0 )
1871
+ {
1872
+ sqlite3ErrorMsg( pParse, "parameters are not allowed in views" );
1873
+ sqlite3SelectDelete( db, ref pSelect );
1874
+ return;
1875
+ }
1876
+ sqlite3StartTable( pParse, pName1, pName2, isTemp, 1, 0, noErr );
1877
+ p = pParse.pNewTable;
1878
+ if ( p == null )
1879
+ {
1880
+ sqlite3SelectDelete( db, ref pSelect );
1881
+ return;
1882
+ }
1883
+ Debug.Assert( pParse.nErr == 0 ); /* If sqlite3StartTable return non-NULL then
1884
+ ** there could not have been an error */
1885
+ sqlite3TwoPartName( pParse, pName1, pName2, ref pName );
1886
+ iDb = sqlite3SchemaToIndex( db, p.pSchema );
1887
+ if ( sqlite3FixInit( sFix, pParse, iDb, "view", pName ) != 0
1888
+ && sqlite3FixSelect( sFix, pSelect ) != 0
1889
+ )
1890
+ {
1891
+ sqlite3SelectDelete( db, ref pSelect );
1892
+ return;
1893
+ }
1894
+
1895
+ /* Make a copy of the entire SELECT statement that defines the view.
1896
+ ** This will force all the Expr.token.z values to be dynamically
1897
+ ** allocated rather than point to the input string - which means that
1898
+ ** they will persist after the current sqlite3_exec() call returns.
1899
+ */
1900
+ p.pSelect = sqlite3SelectDup( db, pSelect, EXPRDUP_REDUCE );
1901
+ sqlite3SelectDelete( db, ref pSelect );
1902
+ //if ( db.mallocFailed != 0 )
1903
+ //{
1904
+ // return;
1905
+ //}
1906
+ if ( 0 == db.init.busy )
1907
+ {
1908
+ sqlite3ViewGetColumnNames( pParse, p );
1909
+ }
1910
+
1911
+ /* Locate the end of the CREATE VIEW statement. Make sEnd point to
1912
+ ** the end.
1913
+ */
1914
+ sEnd = pParse.sLastToken;
1915
+ if ( ALWAYS( sEnd.z[0] != 0 ) && sEnd.z[0] != ';' )
1916
+ {
1917
+ sEnd.z = sEnd.z.Substring( sEnd.n );
1918
+ }
1919
+ sEnd.n = 0;
1920
+ n = (int)( pBegin.z.Length - sEnd.z.Length );//sEnd.z - pBegin.z;
1921
+ z = pBegin.z;
1922
+ while ( ALWAYS( n > 0 ) && sqlite3Isspace( z[n - 1] ) ) { n--; }
1923
+ sEnd.z = z.Substring( n - 1 );
1924
+ sEnd.n = 1;
1925
+
1926
+ /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */
1927
+ sqlite3EndTable( pParse, null, sEnd, null );
1928
+ return;
1929
+ }
1930
+ #endif // * SQLITE_OMIT_VIEW */
1931
+
1932
+ #if !SQLITE_OMIT_VIEW || !SQLITE_OMIT_VIRTUALTABLE
1933
+ /*
1934
+ ** The Table structure pTable is really a VIEW. Fill in the names of
1935
+ ** the columns of the view in the pTable structure. Return the number
1936
+ ** of errors. If an error is seen leave an error message in pParse.zErrMsg.
1937
+ */
1938
+ static int sqlite3ViewGetColumnNames( Parse pParse, Table pTable )
1939
+ {
1940
+ Table pSelTab; /* A fake table from which we get the result set */
1941
+ Select pSel; /* Copy of the SELECT that implements the view */
1942
+ int nErr = 0; /* Number of errors encountered */
1943
+ int n; /* Temporarily holds the number of cursors assigned */
1944
+ sqlite3 db = pParse.db; /* Database connection for malloc errors */
1945
+ dxAuth xAuth; //)(void*,int,const char*,const char*,const char*,const char*);
1946
+
1947
+ Debug.Assert( pTable != null );
1948
+
1949
+ #if !SQLITE_OMIT_VIRTUALTABLE
1950
+ if ( sqlite3VtabCallConnect( pParse, pTable ) )
1951
+ {
1952
+ return SQLITE_ERROR;
1953
+ }
1954
+ #endif
1955
+ if ( IsVirtual( pTable ) ) return 0;
1956
+
1957
+ #if !SQLITE_OMIT_VIEW
1958
+ /* A positive nCol means the columns names for this view are
1959
+ ** already known.
1960
+ */
1961
+ if ( pTable.nCol > 0 ) return 0;
1962
+
1963
+ /* A negative nCol is a special marker meaning that we are currently
1964
+ ** trying to compute the column names. If we enter this routine with
1965
+ ** a negative nCol, it means two or more views form a loop, like this:
1966
+ **
1967
+ ** CREATE VIEW one AS SELECT * FROM two;
1968
+ ** CREATE VIEW two AS SELECT * FROM one;
1969
+ **
1970
+ ** Actually, the error above is now caught prior to reaching this point.
1971
+ ** But the following test is still important as it does come up
1972
+ ** in the following:
1973
+ **
1974
+ ** CREATE TABLE main.ex1(a);
1975
+ ** CREATE TEMP VIEW ex1 AS SELECT a FROM ex1;
1976
+ ** SELECT * FROM temp.ex1;
1977
+ */
1978
+ if ( pTable.nCol < 0 )
1979
+ {
1980
+ sqlite3ErrorMsg( pParse, "view %s is circularly defined", pTable.zName );
1981
+ return 1;
1982
+ }
1983
+ Debug.Assert( pTable.nCol >= 0 );
1984
+
1985
+ /* If we get this far, it means we need to compute the table names.
1986
+ ** Note that the call to sqlite3ResultSetOfSelect() will expand any
1987
+ ** "*" elements in the results set of the view and will assign cursors
1988
+ ** to the elements of the FROM clause. But we do not want these changes
1989
+ ** to be permanent. So the computation is done on a copy of the SELECT
1990
+ ** statement that defines the view.
1991
+ */
1992
+ Debug.Assert( pTable.pSelect != null );
1993
+ pSel = sqlite3SelectDup( db, pTable.pSelect, 0 );
1994
+ if ( pSel != null )
1995
+ {
1996
+ u8 enableLookaside = db.lookaside.bEnabled;
1997
+ n = pParse.nTab;
1998
+ sqlite3SrcListAssignCursors( pParse, pSel.pSrc );
1999
+ pTable.nCol = -1;
2000
+ db.lookaside.bEnabled = 0;
2001
+ #if !SQLITE_OMIT_AUTHORIZATION
2002
+ xAuth = db.xAuth;
2003
+ db.xAuth = 0;
2004
+ pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
2005
+ db.xAuth = xAuth;
2006
+ #else
2007
+ pSelTab = sqlite3ResultSetOfSelect( pParse, pSel );
2008
+ #endif
2009
+ db.lookaside.bEnabled = enableLookaside;
2010
+ pParse.nTab = n;
2011
+ if ( pSelTab != null )
2012
+ {
2013
+ Debug.Assert( pTable.aCol == null );
2014
+ pTable.nCol = pSelTab.nCol;
2015
+ pTable.aCol = pSelTab.aCol;
2016
+ pSelTab.nCol = 0;
2017
+ pSelTab.aCol = null;
2018
+ sqlite3DeleteTable( ref pSelTab );
2019
+ pTable.pSchema.flags |= DB_UnresetViews;
2020
+ }
2021
+ else
2022
+ {
2023
+ pTable.nCol = 0;
2024
+ nErr++;
2025
+ }
2026
+ sqlite3SelectDelete( db, ref pSel );
2027
+ }
2028
+ else
2029
+ {
2030
+ nErr++;
2031
+ }
2032
+ #endif // * SQLITE_OMIT_VIEW */
2033
+ return nErr;
2034
+ }
2035
+ #endif // * !SQLITE_OMIT_VIEW) || !SQLITE_OMIT_VIRTUALTABLE) */
2036
+
2037
+ #if !SQLITE_OMIT_VIEW
2038
+ /*
2039
+ ** Clear the column names from every VIEW in database idx.
2040
+ */
2041
+ static void sqliteViewResetAll( sqlite3 db, int idx )
2042
+ {
2043
+ HashElem i;
2044
+ if ( !DbHasProperty( db, idx, DB_UnresetViews ) ) return;
2045
+ //for(i=sqliteHashFirst(&db.aDb[idx].pSchema.tblHash); i;i=sqliteHashNext(i)){
2046
+ for ( i = db.aDb[idx].pSchema.tblHash.first; i != null; i = i.next )
2047
+ {
2048
+ Table pTab = (Table)i.data;// sqliteHashData( i );
2049
+ if ( pTab.pSelect != null )
2050
+ {
2051
+ sqliteResetColumnNames( pTab );
2052
+ }
2053
+ }
2054
+ DbClearProperty( db, idx, DB_UnresetViews );
2055
+ }
2056
+ #else
2057
+ //# define sqliteViewResetAll(A,B)
2058
+ #endif // * SQLITE_OMIT_VIEW */
2059
+
2060
+ /*
2061
+ ** This function is called by the VDBE to adjust the internal schema
2062
+ ** used by SQLite when the btree layer moves a table root page. The
2063
+ ** root-page of a table or index in database iDb has changed from iFrom
2064
+ ** to iTo.
2065
+ **
2066
+ ** Ticket #1728: The symbol table might still contain information
2067
+ ** on tables and/or indices that are the process of being deleted.
2068
+ ** If you are unlucky, one of those deleted indices or tables might
2069
+ ** have the same rootpage number as the real table or index that is
2070
+ ** being moved. So we cannot stop searching after the first match
2071
+ ** because the first match might be for one of the deleted indices
2072
+ ** or tables and not the table/index that is actually being moved.
2073
+ ** We must continue looping until all tables and indices with
2074
+ ** rootpage==iFrom have been converted to have a rootpage of iTo
2075
+ ** in order to be certain that we got the right one.
2076
+ */
2077
+ #if !SQLITE_OMIT_AUTOVACUUM
2078
+ static void sqlite3RootPageMoved( Db pDb, int iFrom, int iTo )
2079
+ {
2080
+ HashElem pElem;
2081
+ Hash pHash;
2082
+
2083
+ pHash = pDb.pSchema.tblHash;
2084
+ for ( pElem = pHash.first; pElem != null; pElem = pElem.next )// ( pElem = sqliteHashFirst( pHash ) ; pElem ; pElem = sqliteHashNext( pElem ) )
2085
+ {
2086
+ Table pTab = (Table)pElem.data;// sqliteHashData( pElem );
2087
+ if ( pTab.tnum == iFrom )
2088
+ {
2089
+ pTab.tnum = iTo;
2090
+ }
2091
+ }
2092
+ pHash = pDb.pSchema.idxHash;
2093
+ for ( pElem = pHash.first; pElem != null; pElem = pElem.next )// ( pElem = sqliteHashFirst( pHash ) ; pElem ; pElem = sqliteHashNext( pElem ) )
2094
+ {
2095
+ Index pIdx = (Index)pElem.data;// sqliteHashData( pElem );
2096
+ if ( pIdx.tnum == iFrom )
2097
+ {
2098
+ pIdx.tnum = iTo;
2099
+ }
2100
+ }
2101
+ }
2102
+ #endif
2103
+
2104
+ /*
2105
+ ** Write code to erase the table with root-page iTable from database iDb.
2106
+ ** Also write code to modify the sqlite_master table and internal schema
2107
+ ** if a root-page of another table is moved by the btree-layer whilst
2108
+ ** erasing iTable (this can happen with an auto-vacuum database).
2109
+ */
2110
+ static void destroyRootPage( Parse pParse, int iTable, int iDb )
2111
+ {
2112
+ Vdbe v = sqlite3GetVdbe( pParse );
2113
+ int r1 = sqlite3GetTempReg( pParse );
2114
+ sqlite3VdbeAddOp3( v, OP_Destroy, iTable, r1, iDb );
2115
+ sqlite3MayAbort( pParse );
2116
+ #if !SQLITE_OMIT_AUTOVACUUM
2117
+ /* OP_Destroy stores an in integer r1. If this integer
2118
+ ** is non-zero, then it is the root page number of a table moved to
2119
+ ** location iTable. The following code modifies the sqlite_master table to
2120
+ ** reflect this.
2121
+ **
2122
+ ** The "#NNN" in the SQL is a special constant that means whatever value
2123
+ ** is in register NNN. See grammar rules associated with the TK_REGISTER
2124
+ ** token for additional information.
2125
+ */
2126
+ sqlite3NestedParse( pParse,
2127
+ "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
2128
+ pParse.db.aDb[iDb].zName, SCHEMA_TABLE( iDb ), iTable, r1, r1 );
2129
+ #endif
2130
+ sqlite3ReleaseTempReg( pParse, r1 );
2131
+ }
2132
+
2133
+ /*
2134
+ ** Write VDBE code to erase table pTab and all associated indices on disk.
2135
+ ** Code to update the sqlite_master tables and internal schema definitions
2136
+ ** in case a root-page belonging to another table is moved by the btree layer
2137
+ ** is also added (this can happen with an auto-vacuum database).
2138
+ */
2139
+ static void destroyTable( Parse pParse, Table pTab )
2140
+ {
2141
+ #if SQLITE_OMIT_AUTOVACUUM
2142
+ Index pIdx;
2143
+ int iDb = sqlite3SchemaToIndex( pParse.db, pTab.pSchema );
2144
+ destroyRootPage( pParse, pTab.tnum, iDb );
2145
+ for ( pIdx = pTab.pIndex ; pIdx != null ; pIdx = pIdx.pNext )
2146
+ {
2147
+ destroyRootPage( pParse, pIdx.tnum, iDb );
2148
+ }
2149
+ #else
2150
+ /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM
2151
+ ** is not defined), then it is important to call OP_Destroy on the
2152
+ ** table and index root-pages in order, starting with the numerically
2153
+ ** largest root-page number. This guarantees that none of the root-pages
2154
+ ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the
2155
+ ** following were coded:
2156
+ **
2157
+ ** OP_Destroy 4 0
2158
+ ** ...
2159
+ ** OP_Destroy 5 0
2160
+ **
2161
+ ** and root page 5 happened to be the largest root-page number in the
2162
+ ** database, then root page 5 would be moved to page 4 by the
2163
+ ** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit
2164
+ ** a free-list page.
2165
+ */
2166
+ int iTab = pTab.tnum;
2167
+ int iDestroyed = 0;
2168
+
2169
+ while ( true )
2170
+ {
2171
+ Index pIdx;
2172
+ int iLargest = 0;
2173
+
2174
+ if ( iDestroyed == 0 || iTab < iDestroyed )
2175
+ {
2176
+ iLargest = iTab;
2177
+ }
2178
+ for ( pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext )
2179
+ {
2180
+ int iIdx = pIdx.tnum;
2181
+ Debug.Assert( pIdx.pSchema == pTab.pSchema );
2182
+ if ( ( iDestroyed == 0 || ( iIdx < iDestroyed ) ) && iIdx > iLargest )
2183
+ {
2184
+ iLargest = iIdx;
2185
+ }
2186
+ }
2187
+ if ( iLargest == 0 )
2188
+ {
2189
+ return;
2190
+ }
2191
+ else
2192
+ {
2193
+ int iDb = sqlite3SchemaToIndex( pParse.db, pTab.pSchema );
2194
+ destroyRootPage( pParse, iLargest, iDb );
2195
+ iDestroyed = iLargest;
2196
+ }
2197
+ }
2198
+ #endif
2199
+ }
2200
+
2201
+ /*
2202
+ ** This routine is called to do the work of a DROP TABLE statement.
2203
+ ** pName is the name of the table to be dropped.
2204
+ */
2205
+ static void sqlite3DropTable( Parse pParse, SrcList pName, int isView, int noErr )
2206
+ {
2207
+ Table pTab;
2208
+ Vdbe v;
2209
+ sqlite3 db = pParse.db;
2210
+ int iDb;
2211
+
2212
+ //if ( db.mallocFailed != 0 )
2213
+ //{
2214
+ // goto exit_drop_table;
2215
+ //}
2216
+ Debug.Assert( pParse.nErr == 0 );
2217
+ Debug.Assert( pName.nSrc == 1 );
2218
+ if (noErr != 0) db.suppressErr++;
2219
+ pTab = sqlite3LocateTable(pParse, isView,
2220
+ pName.a[0].zName, pName.a[0].zDatabase );
2221
+ if (noErr != 0) db.suppressErr--;
2222
+
2223
+ if ( pTab == null )
2224
+ {
2225
+ goto exit_drop_table;
2226
+ }
2227
+ iDb = sqlite3SchemaToIndex( db, pTab.pSchema );
2228
+ Debug.Assert( iDb >= 0 && iDb < db.nDb );
2229
+
2230
+ /* If pTab is a virtual table, call ViewGetColumnNames() to ensure
2231
+ ** it is initialized.
2232
+ */
2233
+ if ( IsVirtual( pTab ) && sqlite3ViewGetColumnNames( pParse, pTab ) != 0 )
2234
+ {
2235
+ goto exit_drop_table;
2236
+ }
2237
+ #if !SQLITE_OMIT_AUTHORIZATION
2238
+ {
2239
+ int code;
2240
+ string zTab = SCHEMA_TABLE(iDb);
2241
+ string zDb = db.aDb[iDb].zName;
2242
+ string zArg2 = 0;
2243
+ if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){
2244
+ goto exit_drop_table;
2245
+ }
2246
+ if( isView ){
2247
+ if( OMIT_TEMPDB ==0&& iDb==1 ){
2248
+ code = SQLITE_DROP_TEMP_VIEW;
2249
+ }else{
2250
+ code = SQLITE_DROP_VIEW;
2251
+ }
2252
+ }else if( IsVirtual(pTab) ){
2253
+ code = SQLITE_DROP_VTABLE;
2254
+ zArg2 = sqlite3GetVTable(db, pTab)->pMod->zName;
2255
+ }else{
2256
+ if( OMIT_TEMPDB ==0&& iDb==1 ){
2257
+ code = SQLITE_DROP_TEMP_TABLE;
2258
+ }else{
2259
+ code = SQLITE_DROP_TABLE;
2260
+ }
2261
+ }
2262
+ if( sqlite3AuthCheck(pParse, code, pTab.zName, zArg2, zDb) ){
2263
+ goto exit_drop_table;
2264
+ }
2265
+ if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab.zName, 0, zDb) ){
2266
+ goto exit_drop_table;
2267
+ }
2268
+ }
2269
+ #endif
2270
+ if ( sqlite3StrNICmp( pTab.zName, "sqlite_", 7 ) == 0 )
2271
+ {
2272
+ sqlite3ErrorMsg( pParse, "table %s may not be dropped", pTab.zName );
2273
+ goto exit_drop_table;
2274
+ }
2275
+
2276
+ #if !SQLITE_OMIT_VIEW
2277
+ /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
2278
+ ** on a table.
2279
+ */
2280
+ if ( isView != 0 && pTab.pSelect == null )
2281
+ {
2282
+ sqlite3ErrorMsg( pParse, "use DROP TABLE to delete table %s", pTab.zName );
2283
+ goto exit_drop_table;
2284
+ }
2285
+ if ( 0 == isView && pTab.pSelect != null )
2286
+ {
2287
+ sqlite3ErrorMsg( pParse, "use DROP VIEW to delete view %s", pTab.zName );
2288
+ goto exit_drop_table;
2289
+ }
2290
+ #endif
2291
+
2292
+ /* Generate code to remove the table from the master table
2293
+ ** on disk.
2294
+ */
2295
+ v = sqlite3GetVdbe( pParse );
2296
+ if ( v != null )
2297
+ {
2298
+ Trigger pTrigger;
2299
+ Db pDb = db.aDb[iDb];
2300
+ sqlite3BeginWriteOperation( pParse, 1, iDb );
2301
+
2302
+ #if !SQLITE_OMIT_VIRTUALTABLE
2303
+ if ( IsVirtual( pTab ) )
2304
+ {
2305
+ sqlite3VdbeAddOp0( v, OP_VBegin );
2306
+ }
2307
+ #endif
2308
+ sqlite3FkDropTable( pParse, pName, pTab );
2309
+
2310
+ /* Drop all triggers associated with the table being dropped. Code
2311
+ ** is generated to remove entries from sqlite_master and/or
2312
+ ** sqlite_temp_master if required.
2313
+ */
2314
+ pTrigger = sqlite3TriggerList( pParse, pTab );
2315
+ while ( pTrigger != null )
2316
+ {
2317
+ Debug.Assert( pTrigger.pSchema == pTab.pSchema ||
2318
+ pTrigger.pSchema == db.aDb[1].pSchema );
2319
+ sqlite3DropTriggerPtr( pParse, pTrigger );
2320
+ pTrigger = pTrigger.pNext;
2321
+ }
2322
+
2323
+ #if !SQLITE_OMIT_AUTOINCREMENT
2324
+ /* Remove any entries of the sqlite_sequence table associated with
2325
+ ** the table being dropped. This is done before the table is dropped
2326
+ ** at the btree level, in case the sqlite_sequence table needs to
2327
+ ** move as a result of the drop (can happen in auto-vacuum mode).
2328
+ */
2329
+ if ( ( pTab.tabFlags & TF_Autoincrement ) != 0 )
2330
+ {
2331
+ sqlite3NestedParse( pParse,
2332
+ "DELETE FROM %s.sqlite_sequence WHERE name=%Q",
2333
+ pDb.zName, pTab.zName
2334
+ );
2335
+ }
2336
+ #endif
2337
+
2338
+ /* Drop all SQLITE_MASTER table and index entries that refer to the
2339
+ ** table. The program name loops through the master table and deletes
2340
+ ** every row that refers to a table of the same name as the one being
2341
+ ** dropped. Triggers are handled seperately because a trigger can be
2342
+ ** created in the temp database that refers to a table in another
2343
+ ** database.
2344
+ */
2345
+ sqlite3NestedParse( pParse,
2346
+ "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
2347
+ pDb.zName, SCHEMA_TABLE( iDb ), pTab.zName );
2348
+
2349
+ /* Drop any statistics from the sqlite_stat1 table, if it exists */
2350
+ if ( sqlite3FindTable( db, "sqlite_stat1", db.aDb[iDb].zName ) != null )
2351
+ {
2352
+ sqlite3NestedParse( pParse,
2353
+ "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q", pDb.zName, pTab.zName
2354
+ );
2355
+ }
2356
+
2357
+ if ( 0 == isView && !IsVirtual( pTab ) )
2358
+ {
2359
+ destroyTable( pParse, pTab );
2360
+ }
2361
+
2362
+ /* Remove the table entry from SQLite's internal schema and modify
2363
+ ** the schema cookie.
2364
+ */
2365
+ if ( IsVirtual( pTab ) )
2366
+ {
2367
+ sqlite3VdbeAddOp4( v, OP_VDestroy, iDb, 0, 0, pTab.zName, 0 );
2368
+ }
2369
+ sqlite3VdbeAddOp4( v, OP_DropTable, iDb, 0, 0, pTab.zName, 0 );
2370
+ sqlite3ChangeCookie( pParse, iDb );
2371
+ }
2372
+ sqliteViewResetAll( db, iDb );
2373
+
2374
+ exit_drop_table:
2375
+ sqlite3SrcListDelete( db, ref pName );
2376
+ }
2377
+
2378
+ /*
2379
+ ** This routine is called to create a new foreign key on the table
2380
+ ** currently under construction. pFromCol determines which columns
2381
+ ** in the current table point to the foreign key. If pFromCol==0 then
2382
+ ** connect the key to the last column inserted. pTo is the name of
2383
+ ** the table referred to. pToCol is a list of tables in the other
2384
+ ** pTo table that the foreign key points to. flags contains all
2385
+ ** information about the conflict resolution algorithms specified
2386
+ ** in the ON DELETE, ON UPDATE and ON INSERT clauses.
2387
+ **
2388
+ ** An FKey structure is created and added to the table currently
2389
+ ** under construction in the pParse.pNewTable field.
2390
+ **
2391
+ ** The foreign key is set for IMMEDIATE processing. A subsequent call
2392
+ ** to sqlite3DeferForeignKey() might change this to DEFERRED.
2393
+ */
2394
+ // OVERLOADS, so I don't need to rewrite parse.c
2395
+ static void sqlite3CreateForeignKey( Parse pParse, int null_2, Token pTo, ExprList pToCol, int flags )
2396
+ { sqlite3CreateForeignKey( pParse, null, pTo, pToCol, flags ); }
2397
+ static void sqlite3CreateForeignKey(
2398
+ Parse pParse, /* Parsing context */
2399
+ ExprList pFromCol, /* Columns in this table that point to other table */
2400
+ Token pTo, /* Name of the other table */
2401
+ ExprList pToCol, /* Columns in the other table */
2402
+ int flags /* Conflict resolution algorithms. */
2403
+ )
2404
+ {
2405
+ sqlite3 db = pParse.db;
2406
+ #if !SQLITE_OMIT_FOREIGN_KEY
2407
+ FKey pFKey = null;
2408
+ FKey pNextTo;
2409
+ Table p = pParse.pNewTable;
2410
+ int nByte;
2411
+ int i;
2412
+ int nCol;
2413
+ //string z;
2414
+
2415
+ Debug.Assert( pTo != null );
2416
+ if ( p == null || IN_DECLARE_VTAB ) goto fk_end;
2417
+ if ( pFromCol == null )
2418
+ {
2419
+ int iCol = p.nCol - 1;
2420
+ if ( NEVER( iCol < 0 ) ) goto fk_end;
2421
+ if ( pToCol != null && pToCol.nExpr != 1 )
2422
+ {
2423
+ sqlite3ErrorMsg( pParse, "foreign key on %s" +
2424
+ " should reference only one column of table %T",
2425
+ p.aCol[iCol].zName, pTo );
2426
+ goto fk_end;
2427
+ }
2428
+ nCol = 1;
2429
+ }
2430
+ else if ( pToCol != null && pToCol.nExpr != pFromCol.nExpr )
2431
+ {
2432
+ sqlite3ErrorMsg( pParse,
2433
+ "number of columns in foreign key does not match the number of " +
2434
+ "columns in the referenced table" );
2435
+ goto fk_end;
2436
+ }
2437
+ else
2438
+ {
2439
+ nCol = pFromCol.nExpr;
2440
+ }
2441
+ //nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey.aCol[0]) + pTo.n + 1;
2442
+ //if( pToCol ){
2443
+ // for(i=0; i<pToCol.nExpr; i++){
2444
+ // nByte += sqlite3Strlen30(pToCol->a[i].zName) + 1;
2445
+ // }
2446
+ //}
2447
+ pFKey = new FKey();//sqlite3DbMallocZero(db, nByte );
2448
+ if ( pFKey == null )
2449
+ {
2450
+ goto fk_end;
2451
+ }
2452
+ pFKey.pFrom = p;
2453
+ pFKey.pNextFrom = p.pFKey;
2454
+ //z = pFKey.aCol[nCol].zCol;
2455
+ pFKey.aCol = new FKey.sColMap[nCol];// z;
2456
+ pFKey.aCol[0] = new FKey.sColMap();
2457
+ pFKey.zTo = pTo.z.Substring( 0, pTo.n ); //memcpy( z, pTo.z, pTo.n );
2458
+ //z[pTo.n] = 0;
2459
+ sqlite3Dequote( ref pFKey.zTo );
2460
+ //z += pTo.n + 1;
2461
+ pFKey.nCol = nCol;
2462
+ if ( pFromCol == null )
2463
+ {
2464
+ pFKey.aCol[0].iFrom = p.nCol - 1;
2465
+ }
2466
+ else
2467
+ {
2468
+ for ( i = 0; i < nCol; i++ )
2469
+ {
2470
+ if ( pFKey.aCol[i] == null ) pFKey.aCol[i] = new FKey.sColMap();
2471
+ int j;
2472
+ for ( j = 0; j < p.nCol; j++ )
2473
+ {
2474
+ if ( sqlite3StrICmp( p.aCol[j].zName, pFromCol.a[i].zName ) == 0 )
2475
+ {
2476
+ pFKey.aCol[i].iFrom = j;
2477
+ break;
2478
+ }
2479
+ }
2480
+ if ( j >= p.nCol )
2481
+ {
2482
+ sqlite3ErrorMsg( pParse,
2483
+ "unknown column \"%s\" in foreign key definition",
2484
+ pFromCol.a[i].zName );
2485
+ goto fk_end;
2486
+ }
2487
+ }
2488
+ }
2489
+ if ( pToCol != null )
2490
+ {
2491
+ for ( i = 0; i < nCol; i++ )
2492
+ {
2493
+ int n = sqlite3Strlen30( pToCol.a[i].zName );
2494
+ if ( pFKey.aCol[i] == null ) pFKey.aCol[i] = new FKey.sColMap();
2495
+ pFKey.aCol[i].zCol = pToCol.a[i].zName;
2496
+ //memcpy( z, pToCol.a[i].zName, n );
2497
+ //z[n] = 0;
2498
+ //z += n + 1;
2499
+ }
2500
+ }
2501
+ pFKey.isDeferred = 0;
2502
+ pFKey.aAction[0] = (u8)( flags & 0xff ); /* ON DELETE action */
2503
+ pFKey.aAction[1] = (u8)( ( flags >> 8 ) & 0xff ); /* ON UPDATE action */
2504
+
2505
+ pNextTo = (FKey)sqlite3HashInsert( ref p.pSchema.fkeyHash,
2506
+ pFKey.zTo, sqlite3Strlen30( pFKey.zTo ), pFKey
2507
+ );
2508
+ //if( pNextTo==pFKey ){
2509
+ // db.mallocFailed = 1;
2510
+ // goto fk_end;
2511
+ //}
2512
+ if ( pNextTo != null )
2513
+ {
2514
+ Debug.Assert( pNextTo.pPrevTo == null );
2515
+ pFKey.pNextTo = pNextTo;
2516
+ pNextTo.pPrevTo = pFKey;
2517
+ }
2518
+ /* Link the foreign key to the table as the last step.
2519
+ */
2520
+ p.pFKey = pFKey;
2521
+ pFKey = null;
2522
+
2523
+ fk_end:
2524
+ sqlite3DbFree( db, ref pFKey );
2525
+ #endif // * !SQLITE_OMIT_FOREIGN_KEY) */
2526
+ sqlite3ExprListDelete( db, ref pFromCol );
2527
+ sqlite3ExprListDelete( db, ref pToCol );
2528
+ }
2529
+
2530
+ /*
2531
+ ** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED
2532
+ ** clause is seen as part of a foreign key definition. The isDeferred
2533
+ ** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE.
2534
+ ** The behavior of the most recently created foreign key is adjusted
2535
+ ** accordingly.
2536
+ */
2537
+ static void sqlite3DeferForeignKey( Parse pParse, int isDeferred )
2538
+ {
2539
+ #if !SQLITE_OMIT_FOREIGN_KEY
2540
+ Table pTab;
2541
+ FKey pFKey;
2542
+ if ( ( pTab = pParse.pNewTable ) == null || ( pFKey = pTab.pFKey ) == null ) return;
2543
+ Debug.Assert( isDeferred == 0 || isDeferred == 1 ); /* EV: R-30323-21917 */
2544
+ pFKey.isDeferred = (u8)isDeferred;
2545
+ #endif
2546
+ }
2547
+
2548
+ /*
2549
+ ** Generate code that will erase and refill index pIdx. This is
2550
+ ** used to initialize a newly created index or to recompute the
2551
+ ** content of an index in response to a REINDEX command.
2552
+ **
2553
+ ** if memRootPage is not negative, it means that the index is newly
2554
+ ** created. The register specified by memRootPage contains the
2555
+ ** root page number of the index. If memRootPage is negative, then
2556
+ ** the index already exists and must be cleared before being refilled and
2557
+ ** the root page number of the index is taken from pIndex.tnum.
2558
+ */
2559
+ static void sqlite3RefillIndex( Parse pParse, Index pIndex, int memRootPage )
2560
+ {
2561
+ Table pTab = pIndex.pTable; /* The table that is indexed */
2562
+ int iTab = pParse.nTab++; /* Btree cursor used for pTab */
2563
+ int iIdx = pParse.nTab++; /* Btree cursor used for pIndex */
2564
+ int addr1; /* Address of top of loop */
2565
+ int tnum; /* Root page of index */
2566
+ Vdbe v; /* Generate code into this virtual machine */
2567
+ KeyInfo pKey; /* KeyInfo for index */
2568
+ int regIdxKey; /* Registers containing the index key */
2569
+ int regRecord; /* Register holding assemblied index record */
2570
+ sqlite3 db = pParse.db; /* The database connection */
2571
+ int iDb = sqlite3SchemaToIndex( db, pIndex.pSchema );
2572
+
2573
+ #if !SQLITE_OMIT_AUTHORIZATION
2574
+ if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex.zName, 0,
2575
+ db.aDb[iDb].zName ) ){
2576
+ return;
2577
+ }
2578
+ #endif
2579
+
2580
+ /* Require a write-lock on the table to perform this operation */
2581
+ sqlite3TableLock( pParse, iDb, pTab.tnum, 1, pTab.zName );
2582
+ v = sqlite3GetVdbe( pParse );
2583
+ if ( v == null ) return;
2584
+ if ( memRootPage >= 0 )
2585
+ {
2586
+ tnum = memRootPage;
2587
+ }
2588
+ else
2589
+ {
2590
+ tnum = pIndex.tnum;
2591
+ sqlite3VdbeAddOp2( v, OP_Clear, tnum, iDb );
2592
+ }
2593
+ pKey = sqlite3IndexKeyinfo( pParse, pIndex );
2594
+ sqlite3VdbeAddOp4( v, OP_OpenWrite, iIdx, tnum, iDb,
2595
+ pKey, P4_KEYINFO_HANDOFF );
2596
+ if ( memRootPage >= 0 )
2597
+ {
2598
+ sqlite3VdbeChangeP5( v, 1 );
2599
+ }
2600
+ sqlite3OpenTable( pParse, iTab, iDb, pTab, OP_OpenRead );
2601
+ addr1 = sqlite3VdbeAddOp2( v, OP_Rewind, iTab, 0 );
2602
+ regRecord = sqlite3GetTempReg( pParse );
2603
+ regIdxKey = sqlite3GenerateIndexKey( pParse, pIndex, iTab, regRecord, true );
2604
+ if ( pIndex.onError != OE_None )
2605
+ {
2606
+ int regRowid = regIdxKey + pIndex.nColumn;
2607
+ int j2 = sqlite3VdbeCurrentAddr( v ) + 2;
2608
+ int pRegKey = regIdxKey;// SQLITE_INT_TO_PTR( regIdxKey );
2609
+
2610
+ /* The registers accessed by the OP_IsUnique opcode were allocated
2611
+ ** using sqlite3GetTempRange() inside of the sqlite3GenerateIndexKey()
2612
+ ** call above. Just before that function was freed they were released
2613
+ ** (made available to the compiler for reuse) using
2614
+ ** sqlite3ReleaseTempRange(). So in some ways having the OP_IsUnique
2615
+ ** opcode use the values stored within seems dangerous. However, since
2616
+ ** we can be sure that no other temp registers have been allocated
2617
+ ** since sqlite3ReleaseTempRange() was called, it is safe to do so.
2618
+ */
2619
+ sqlite3VdbeAddOp4( v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32 );
2620
+ sqlite3HaltConstraint(
2621
+ pParse, OE_Abort, "indexed columns are not unique", P4_STATIC );
2622
+ }
2623
+ sqlite3VdbeAddOp2( v, OP_IdxInsert, iIdx, regRecord );
2624
+ sqlite3VdbeChangeP5( v, OPFLAG_USESEEKRESULT );
2625
+ sqlite3ReleaseTempReg( pParse, regRecord );
2626
+ sqlite3VdbeAddOp2( v, OP_Next, iTab, addr1 + 1 );
2627
+ sqlite3VdbeJumpHere( v, addr1 );
2628
+ sqlite3VdbeAddOp1( v, OP_Close, iTab );
2629
+ sqlite3VdbeAddOp1( v, OP_Close, iIdx );
2630
+ }
2631
+
2632
+ /*
2633
+ ** Create a new index for an SQL table. pName1.pName2 is the name of the index
2634
+ ** and pTblList is the name of the table that is to be indexed. Both will
2635
+ ** be NULL for a primary key or an index that is created to satisfy a
2636
+ ** UNIQUE constraint. If pTable and pIndex are NULL, use pParse.pNewTable
2637
+ ** as the table to be indexed. pParse.pNewTable is a table that is
2638
+ ** currently being constructed by a CREATE TABLE statement.
2639
+ **
2640
+ ** pList is a list of columns to be indexed. pList will be NULL if this
2641
+ ** is a primary key or unique-constraint on the most recent column added
2642
+ ** to the table currently under construction.
2643
+ **
2644
+ ** If the index is created successfully, return a pointer to the new Index
2645
+ ** structure. This is used by sqlite3AddPrimaryKey() to mark the index
2646
+ ** as the tables primary key (Index.autoIndex==2).
2647
+ */
2648
+ // OVERLOADS, so I don't need to rewrite parse.c
2649
+ static Index sqlite3CreateIndex( Parse pParse, int null_2, int null_3, int null_4, int null_5, int onError, int null_7, int null_8, int sortOrder, int ifNotExist )
2650
+ { return sqlite3CreateIndex( pParse, null, null, null, null, onError, null, null, sortOrder, ifNotExist ); }
2651
+ static Index sqlite3CreateIndex( Parse pParse, int null_2, int null_3, int null_4, ExprList pList, int onError, int null_7, int null_8, int sortOrder, int ifNotExist )
2652
+ { return sqlite3CreateIndex( pParse, null, null, null, pList, onError, null, null, sortOrder, ifNotExist ); }
2653
+ static Index sqlite3CreateIndex(
2654
+ Parse pParse, /* All information about this Parse */
2655
+ Token pName1, /* First part of index name. May be NULL */
2656
+ Token pName2, /* Second part of index name. May be NULL */
2657
+ SrcList pTblName, /* Table to index. Use pParse.pNewTable if 0 */
2658
+ ExprList pList, /* A list of columns to be indexed */
2659
+ int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
2660
+ Token pStart, /* The CREATE token that begins this statement */
2661
+ Token pEnd, /* The ")" that closes the CREATE INDEX statement */
2662
+ int sortOrder, /* Sort order of primary key when pList==NULL */
2663
+ int ifNotExist /* Omit error if index already exists */
2664
+ )
2665
+ {
2666
+ Index pRet = null; /* Pointer to return */
2667
+ Table pTab = null; /* Table to be indexed */
2668
+ Index pIndex = null; /* The index to be created */
2669
+ string zName = null; /* Name of the index */
2670
+ int nName; /* Number of characters in zName */
2671
+ int i, j;
2672
+ Token nullId = new Token(); /* Fake token for an empty ID list */
2673
+ DbFixer sFix = new DbFixer(); /* For assigning database names to pTable */
2674
+ int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */
2675
+ sqlite3 db = pParse.db;
2676
+ Db pDb; /* The specific table containing the indexed database */
2677
+ int iDb; /* Index of the database that is being written */
2678
+ Token pName = null; /* Unqualified name of the index to create */
2679
+ ExprList_item pListItem; /* For looping over pList */
2680
+ int nCol;
2681
+ int nExtra = 0;
2682
+ StringBuilder zExtra = new StringBuilder();
2683
+
2684
+ Debug.Assert( pStart == null || pEnd != null ); /* pEnd must be non-NULL if pStart is */
2685
+ Debug.Assert( pParse.nErr == 0 ); /* Never called with prior errors */
2686
+ if ( /* db.mallocFailed != 0 || */ IN_DECLARE_VTAB )
2687
+ {
2688
+ goto exit_create_index;
2689
+ }
2690
+ if ( SQLITE_OK != sqlite3ReadSchema( pParse ) )
2691
+ {
2692
+ goto exit_create_index;
2693
+ }
2694
+
2695
+ /*
2696
+ ** Find the table that is to be indexed. Return early if not found.
2697
+ */
2698
+ if ( pTblName != null )
2699
+ {
2700
+
2701
+ /* Use the two-part index name to determine the database
2702
+ ** to search for the table. 'Fix' the table name to this db
2703
+ ** before looking up the table.
2704
+ */
2705
+ Debug.Assert( pName1 != null && pName2 != null );
2706
+ iDb = sqlite3TwoPartName( pParse, pName1, pName2, ref pName );
2707
+ if ( iDb < 0 ) goto exit_create_index;
2708
+
2709
+ #if !SQLITE_OMIT_TEMPDB
2710
+ /* If the index name was unqualified, check if the the table
2711
+ ** is a temp table. If so, set the database to 1. Do not do this
2712
+ ** if initialising a database schema.
2713
+ */
2714
+ if ( 0 == db.init.busy )
2715
+ {
2716
+ pTab = sqlite3SrcListLookup( pParse, pTblName );
2717
+ if ( pName2.n == 0 && pTab != null && pTab.pSchema == db.aDb[1].pSchema )
2718
+ {
2719
+ iDb = 1;
2720
+ }
2721
+ }
2722
+ #endif
2723
+
2724
+ if ( sqlite3FixInit( sFix, pParse, iDb, "index", pName ) != 0 &&
2725
+ sqlite3FixSrcList( sFix, pTblName ) != 0
2726
+ )
2727
+ {
2728
+ /* Because the parser constructs pTblName from a single identifier,
2729
+ ** sqlite3FixSrcList can never fail. */
2730
+ Debugger.Break();
2731
+ }
2732
+ pTab = sqlite3LocateTable( pParse, 0, pTblName.a[0].zName,
2733
+ pTblName.a[0].zDatabase );
2734
+ if ( pTab == null /*|| db.mallocFailed != 0 */ ) goto exit_create_index;
2735
+ Debug.Assert( db.aDb[iDb].pSchema == pTab.pSchema );
2736
+ }
2737
+ else
2738
+ {
2739
+ Debug.Assert( pName == null );
2740
+ pTab = pParse.pNewTable;
2741
+ if ( pTab == null ) goto exit_create_index;
2742
+ iDb = sqlite3SchemaToIndex( db, pTab.pSchema );
2743
+ }
2744
+ pDb = db.aDb[iDb];
2745
+
2746
+ Debug.Assert( pTab != null );
2747
+ Debug.Assert( pParse.nErr == 0 );
2748
+ if ( sqlite3StrNICmp( pTab.zName, "sqlite_", 7 ) == 0
2749
+ && sqlite3StrNICmp( pTab.zName, 7, "altertab_", 9 ) != 0 )
2750
+ {
2751
+ sqlite3ErrorMsg( pParse, "table %s may not be indexed", pTab.zName );
2752
+ goto exit_create_index;
2753
+ }
2754
+ #if !SQLITE_OMIT_VIEW
2755
+ if ( pTab.pSelect != null )
2756
+ {
2757
+ sqlite3ErrorMsg( pParse, "views may not be indexed" );
2758
+ goto exit_create_index;
2759
+ }
2760
+ #endif
2761
+ if ( IsVirtual( pTab ) )
2762
+ {
2763
+ sqlite3ErrorMsg( pParse, "virtual tables may not be indexed" );
2764
+ goto exit_create_index;
2765
+ }
2766
+
2767
+ /*
2768
+ ** Find the name of the index. Make sure there is not already another
2769
+ ** index or table with the same name.
2770
+ **
2771
+ ** Exception: If we are reading the names of permanent indices from the
2772
+ ** sqlite_master table (because some other process changed the schema) and
2773
+ ** one of the index names collides with the name of a temporary table or
2774
+ ** index, then we will continue to process this index.
2775
+ **
2776
+ ** If pName==0 it means that we are
2777
+ ** dealing with a primary key or UNIQUE constraint. We have to invent our
2778
+ ** own name.
2779
+ */
2780
+ if ( pName != null )
2781
+ {
2782
+ zName = sqlite3NameFromToken( db, pName );
2783
+ if ( zName == null ) goto exit_create_index;
2784
+ if ( SQLITE_OK != sqlite3CheckObjectName( pParse, zName ) )
2785
+ {
2786
+ goto exit_create_index;
2787
+ }
2788
+ if ( 0 == db.init.busy )
2789
+ {
2790
+ if ( sqlite3FindTable( db, zName, null ) != null )
2791
+ {
2792
+ sqlite3ErrorMsg( pParse, "there is already a table named %s", zName );
2793
+ goto exit_create_index;
2794
+ }
2795
+ }
2796
+ if ( sqlite3FindIndex( db, zName, pDb.zName ) != null )
2797
+ {
2798
+ if ( ifNotExist == 0 )
2799
+ {
2800
+ sqlite3ErrorMsg( pParse, "index %s already exists", zName );
2801
+ }
2802
+ goto exit_create_index;
2803
+ }
2804
+ }
2805
+ else
2806
+ {
2807
+ int n = 0;
2808
+ Index pLoop;
2809
+ for ( pLoop = pTab.pIndex, n = 1; pLoop != null; pLoop = pLoop.pNext, n++ ) { }
2810
+ zName = sqlite3MPrintf( db, "sqlite_autoindex_%s_%d", pTab.zName, n );
2811
+ if ( zName == null )
2812
+ {
2813
+ goto exit_create_index;
2814
+ }
2815
+ }
2816
+
2817
+ /* Check for authorization to create an index.
2818
+ */
2819
+ #if !SQLITE_OMIT_AUTHORIZATION
2820
+ {
2821
+ string zDb = pDb.zName;
2822
+ if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){
2823
+ goto exit_create_index;
2824
+ }
2825
+ i = SQLITE_CREATE_INDEX;
2826
+ if( OMIT_TEMPDB ==0&& iDb==1 ) i = SQLITE_CREATE_TEMP_INDEX;
2827
+ if( sqlite3AuthCheck(pParse, i, zName, pTab.zName, zDb) ){
2828
+ goto exit_create_index;
2829
+ }
2830
+ }
2831
+ #endif
2832
+
2833
+ /* If pList==0, it means this routine was called to make a primary
2834
+ ** key out of the last column added to the table under construction.
2835
+ ** So create a fake list to simulate this.
2836
+ */
2837
+ if ( pList == null )
2838
+ {
2839
+ nullId.z = pTab.aCol[pTab.nCol - 1].zName;
2840
+ nullId.n = sqlite3Strlen30( nullId.z );
2841
+ pList = sqlite3ExprListAppend( pParse, null, null );
2842
+ if ( pList == null ) goto exit_create_index;
2843
+ sqlite3ExprListSetName( pParse, pList, nullId, 0 );
2844
+ pList.a[0].sortOrder = (u8)sortOrder;
2845
+ }
2846
+
2847
+ /* Figure out how many bytes of space are required to store explicitly
2848
+ ** specified collation sequence names.
2849
+ */
2850
+ for ( i = 0; i < pList.nExpr; i++ )
2851
+ {
2852
+ Expr pExpr = pList.a[i].pExpr;
2853
+ if ( pExpr != null )
2854
+ {
2855
+ CollSeq pColl = pExpr.pColl;
2856
+ /* Either pColl!=0 or there was an OOM failure. But if an OOM
2857
+ ** failure we have quit before reaching this point. */
2858
+ if ( ALWAYS( pColl != null ) )
2859
+ {
2860
+ nExtra += ( 1 + sqlite3Strlen30( pColl.zName ) );
2861
+ }
2862
+ }
2863
+ }
2864
+
2865
+ /*
2866
+ ** Allocate the index structure.
2867
+ */
2868
+ nName = sqlite3Strlen30( zName );
2869
+ nCol = pList.nExpr;
2870
+ pIndex = new Index();
2871
+ // sqlite3DbMallocZero( db,
2872
+ // Index.Length + /* Index structure */
2873
+ // sizeof( int ) * nCol + /* Index.aiColumn */
2874
+ // sizeof( int ) * ( nCol + 1 ) + /* Index.aiRowEst */
2875
+ // sizeof( char* ) * nCol + /* Index.azColl */
2876
+ // u8.Length * nCol + /* Index.aSortOrder */
2877
+ // nName + 1 + /* Index.zName */
2878
+ // nExtra /* Collation sequence names */
2879
+ //);
2880
+ //if ( db.mallocFailed != 0 )
2881
+ //{
2882
+ // goto exit_create_index;
2883
+ //}
2884
+ pIndex.azColl = new string[nCol + 1];//(char**)(pIndex[1]);
2885
+ pIndex.aiColumn = new int[nCol + 1];//(int *)(pIndex->azColl[nCol]);
2886
+ pIndex.aiRowEst = new int[nCol + 1];//(unsigned *)(pIndex->aiColumn[nCol]);
2887
+ pIndex.aSortOrder = new byte[nCol + 1];//(u8 *)(pIndex->aiRowEst[nCol+1]);
2888
+ //pIndex.zName = null;// (char*)( &pIndex->aSortOrder[nCol] );
2889
+ zExtra = new StringBuilder( nName + 1 );// (char*)( &pIndex.zName[nName + 1] );
2890
+ if ( zName.Length == nName ) pIndex.zName = zName;
2891
+ else { pIndex.zName = zName.Substring( 0, nName ); }// memcpy( pIndex.zName, zName, nName + 1 );
2892
+ pIndex.pTable = pTab;
2893
+ pIndex.nColumn = pList.nExpr;
2894
+ pIndex.onError = (u8)onError;
2895
+ pIndex.autoIndex = (u8)( pName == null ? 1 : 0 );
2896
+ pIndex.pSchema = db.aDb[iDb].pSchema;
2897
+
2898
+ /* Check to see if we should honor DESC requests on index columns
2899
+ */
2900
+ if ( pDb.pSchema.file_format >= 4 )
2901
+ {
2902
+ sortOrderMask = 1; /* Honor DESC */
2903
+ }
2904
+ else
2905
+ {
2906
+ sortOrderMask = 0; /* Ignore DESC */
2907
+ }
2908
+
2909
+ /* Scan the names of the columns of the table to be indexed and
2910
+ ** load the column indices into the Index structure. Report an error
2911
+ ** if any column is not found.
2912
+ **
2913
+ ** TODO: Add a test to make sure that the same column is not named
2914
+ ** more than once within the same index. Only the first instance of
2915
+ ** the column will ever be used by the optimizer. Note that using the
2916
+ ** same column more than once cannot be an error because that would
2917
+ ** break backwards compatibility - it needs to be a warning.
2918
+ */
2919
+ for ( i = 0; i < pList.nExpr; i++ )
2920
+ {//, pListItem++){
2921
+ pListItem = pList.a[i];
2922
+ string zColName = pListItem.zName;
2923
+ Column pTabCol;
2924
+ byte requestedSortOrder;
2925
+ string zColl; /* Collation sequence name */
2926
+
2927
+ for ( j = 0; j < pTab.nCol; j++ )
2928
+ {//, pTabCol++){
2929
+ pTabCol = pTab.aCol[j];
2930
+ if ( sqlite3StrICmp( zColName, pTabCol.zName ) == 0 ) break;
2931
+ }
2932
+ if ( j >= pTab.nCol )
2933
+ {
2934
+ sqlite3ErrorMsg( pParse, "table %s has no column named %s",
2935
+ pTab.zName, zColName );
2936
+ goto exit_create_index;
2937
+ }
2938
+ pIndex.aiColumn[i] = j;
2939
+ /* Justification of the ALWAYS(pListItem->pExpr->pColl): Because of
2940
+ ** the way the "idxlist" non-terminal is constructed by the parser,
2941
+ ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl
2942
+ ** must exist or else there must have been an OOM error. But if there
2943
+ ** was an OOM error, we would never reach this point. */
2944
+ if ( pListItem.pExpr != null && ALWAYS( pListItem.pExpr.pColl ) )
2945
+ {
2946
+ int nColl;
2947
+ zColl = pListItem.pExpr.pColl.zName;
2948
+ nColl = sqlite3Strlen30( zColl );
2949
+ Debug.Assert( nExtra >= nColl );
2950
+ zExtra = new StringBuilder( zColl.Substring( 0, nColl ) );// memcpy( zExtra, zColl, nColl );
2951
+ zColl = zExtra.ToString();
2952
+ //zExtra += nColl;
2953
+ nExtra -= nColl;
2954
+ }
2955
+ else
2956
+ {
2957
+ zColl = pTab.aCol[j].zColl;
2958
+ if ( zColl == null )
2959
+ {
2960
+ zColl = db.pDfltColl.zName;
2961
+ }
2962
+ }
2963
+ if ( 0 == db.init.busy && sqlite3LocateCollSeq( pParse, zColl ) == null )
2964
+ {
2965
+ goto exit_create_index;
2966
+ }
2967
+ pIndex.azColl[i] = zColl;
2968
+ requestedSortOrder = (u8)( ( pListItem.sortOrder & sortOrderMask ) != 0 ? 1 : 0 );
2969
+ pIndex.aSortOrder[i] = (u8)requestedSortOrder;
2970
+ }
2971
+ sqlite3DefaultRowEst( pIndex );
2972
+
2973
+ if ( pTab == pParse.pNewTable )
2974
+ {
2975
+ /* This routine has been called to create an automatic index as a
2976
+ ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or
2977
+ ** a PRIMARY KEY or UNIQUE clause following the column definitions.
2978
+ ** i.e. one of:
2979
+ **
2980
+ ** CREATE TABLE t(x PRIMARY KEY, y);
2981
+ ** CREATE TABLE t(x, y, UNIQUE(x, y));
2982
+ **
2983
+ ** Either way, check to see if the table already has such an index. If
2984
+ ** so, don't bother creating this one. This only applies to
2985
+ ** automatically created indices. Users can do as they wish with
2986
+ ** explicit indices.
2987
+ **
2988
+ ** Two UNIQUE or PRIMARY KEY constraints are considered equivalent
2989
+ ** (and thus suppressing the second one) even if they have different
2990
+ ** sort orders.
2991
+ **
2992
+ ** If there are different collating sequences or if the columns of
2993
+ ** the constraint occur in different orders, then the constraints are
2994
+ ** considered distinct and both result in separate indices.
2995
+ */
2996
+ Index pIdx;
2997
+ for ( pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext )
2998
+ {
2999
+ int k;
3000
+ Debug.Assert( pIdx.onError != OE_None );
3001
+ Debug.Assert( pIdx.autoIndex != 0 );
3002
+ Debug.Assert( pIndex.onError != OE_None );
3003
+
3004
+ if ( pIdx.nColumn != pIndex.nColumn ) continue;
3005
+ for ( k = 0; k < pIdx.nColumn; k++ )
3006
+ {
3007
+ string z1;
3008
+ string z2;
3009
+ if ( pIdx.aiColumn[k] != pIndex.aiColumn[k] ) break;
3010
+ z1 = pIdx.azColl[k];
3011
+ z2 = pIndex.azColl[k];
3012
+ if ( z1 != z2 && sqlite3StrICmp( z1, z2 ) != 0 ) break;
3013
+ }
3014
+ if ( k == pIdx.nColumn )
3015
+ {
3016
+ if ( pIdx.onError != pIndex.onError )
3017
+ {
3018
+ /* This constraint creates the same index as a previous
3019
+ ** constraint specified somewhere in the CREATE TABLE statement.
3020
+ ** However the ON CONFLICT clauses are different. If both this
3021
+ ** constraint and the previous equivalent constraint have explicit
3022
+ ** ON CONFLICT clauses this is an error. Otherwise, use the
3023
+ ** explicitly specified behavior for the index.
3024
+ */
3025
+ if ( !( pIdx.onError == OE_Default || pIndex.onError == OE_Default ) )
3026
+ {
3027
+ sqlite3ErrorMsg( pParse,
3028
+ "conflicting ON CONFLICT clauses specified", 0 );
3029
+ }
3030
+ if ( pIdx.onError == OE_Default )
3031
+ {
3032
+ pIdx.onError = pIndex.onError;
3033
+ }
3034
+ }
3035
+ goto exit_create_index;
3036
+ }
3037
+ }
3038
+ }
3039
+
3040
+ /* Link the new Index structure to its table and to the other
3041
+ ** in-memory database structures.
3042
+ */
3043
+ if ( db.init.busy != 0 )
3044
+ {
3045
+ Index p;
3046
+ p = (Index)sqlite3HashInsert( ref pIndex.pSchema.idxHash,
3047
+ pIndex.zName, sqlite3Strlen30( pIndex.zName ),
3048
+ pIndex );
3049
+ if ( p != null )
3050
+ {
3051
+ Debug.Assert( p == pIndex ); /* Malloc must have failed */
3052
+ // db.mallocFailed = 1;
3053
+ goto exit_create_index;
3054
+ }
3055
+ db.flags |= SQLITE_InternChanges;
3056
+ if ( pTblName != null )
3057
+ {
3058
+ pIndex.tnum = db.init.newTnum;
3059
+ }
3060
+ }
3061
+
3062
+ /* If the db.init.busy is 0 then create the index on disk. This
3063
+ ** involves writing the index into the master table and filling in the
3064
+ ** index with the current table contents.
3065
+ **
3066
+ ** The db.init.busy is 0 when the user first enters a CREATE INDEX
3067
+ ** command. db.init.busy is 1 when a database is opened and
3068
+ ** CREATE INDEX statements are read out of the master table. In
3069
+ ** the latter case the index already exists on disk, which is why
3070
+ ** we don't want to recreate it.
3071
+ **
3072
+ ** If pTblName==0 it means this index is generated as a primary key
3073
+ ** or UNIQUE constraint of a CREATE TABLE statement. Since the table
3074
+ ** has just been created, it contains no data and the index initialization
3075
+ ** step can be skipped.
3076
+ */
3077
+ else //if ( 0 == db.init.busy )
3078
+ {
3079
+ Vdbe v;
3080
+ string zStmt;
3081
+ int iMem = ++pParse.nMem;
3082
+
3083
+ v = sqlite3GetVdbe( pParse );
3084
+ if ( v == null ) goto exit_create_index;
3085
+
3086
+
3087
+ /* Create the rootpage for the index
3088
+ */
3089
+ sqlite3BeginWriteOperation( pParse, 1, iDb );
3090
+ sqlite3VdbeAddOp2( v, OP_CreateIndex, iDb, iMem );
3091
+
3092
+ /* Gather the complete text of the CREATE INDEX statement into
3093
+ ** the zStmt variable
3094
+ */
3095
+ if ( pStart != null )
3096
+ {
3097
+ Debug.Assert( pEnd != null );
3098
+ /* A named index with an explicit CREATE INDEX statement */
3099
+ zStmt = sqlite3MPrintf( db, "CREATE%s INDEX %.*s",
3100
+ onError == OE_None ? "" : " UNIQUE",
3101
+ pName.z.Length - pEnd.z.Length + 1,
3102
+ pName.z );
3103
+ }
3104
+ else
3105
+ {
3106
+ /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
3107
+ /* zStmt = sqlite3MPrintf(""); */
3108
+ zStmt = null;
3109
+ }
3110
+
3111
+ /* Add an entry in sqlite_master for this index
3112
+ */
3113
+ sqlite3NestedParse( pParse,
3114
+ "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
3115
+ db.aDb[iDb].zName, SCHEMA_TABLE( iDb ),
3116
+ pIndex.zName,
3117
+ pTab.zName,
3118
+ iMem,
3119
+ zStmt
3120
+ );
3121
+ sqlite3DbFree( db, ref zStmt );
3122
+
3123
+ /* Fill the index with data and reparse the schema. Code an OP_Expire
3124
+ ** to invalidate all pre-compiled statements.
3125
+ */
3126
+ if ( pTblName != null )
3127
+ {
3128
+ sqlite3RefillIndex( pParse, pIndex, iMem );
3129
+ sqlite3ChangeCookie( pParse, iDb );
3130
+ sqlite3VdbeAddOp4( v, OP_ParseSchema, iDb, 0, 0,
3131
+ sqlite3MPrintf( db, "name='%q'", pIndex.zName ), P4_DYNAMIC );
3132
+ sqlite3VdbeAddOp1( v, OP_Expire, 0 );
3133
+ }
3134
+ }
3135
+
3136
+ /* When adding an index to the list of indices for a table, make
3137
+ ** sure all indices labeled OE_Replace come after all those labeled
3138
+ ** OE_Ignore. This is necessary for the correct constraint check
3139
+ ** processing (in sqlite3GenerateConstraintChecks()) as part of
3140
+ ** UPDATE and INSERT statements.
3141
+ */
3142
+ if ( db.init.busy != 0 || pTblName == null )
3143
+ {
3144
+ if ( onError != OE_Replace || pTab.pIndex == null
3145
+ || pTab.pIndex.onError == OE_Replace )
3146
+ {
3147
+ pIndex.pNext = pTab.pIndex;
3148
+ pTab.pIndex = pIndex;
3149
+ }
3150
+ else
3151
+ {
3152
+ Index pOther = pTab.pIndex;
3153
+ while ( pOther.pNext != null && pOther.pNext.onError != OE_Replace )
3154
+ {
3155
+ pOther = pOther.pNext;
3156
+ }
3157
+ pIndex.pNext = pOther.pNext;
3158
+ pOther.pNext = pIndex;
3159
+ }
3160
+ pRet = pIndex;
3161
+ pIndex = null;
3162
+ }
3163
+
3164
+ /* Clean up before exiting */
3165
+ exit_create_index:
3166
+ if ( pIndex != null )
3167
+ {
3168
+ //sqlite3_free( ref pIndex.zColAff );
3169
+ sqlite3DbFree( db, ref pIndex );
3170
+ }
3171
+ sqlite3ExprListDelete( db, ref pList );
3172
+ sqlite3SrcListDelete( db, ref pTblName );
3173
+ sqlite3DbFree( db, ref zName );
3174
+ return pRet;
3175
+ }
3176
+
3177
+ /*
3178
+ ** Fill the Index.aiRowEst[] array with default information - information
3179
+ ** to be used when we have not run the ANALYZE command.
3180
+ **
3181
+ ** aiRowEst[0] is suppose to contain the number of elements in the index.
3182
+ ** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the
3183
+ ** number of rows in the table that match any particular value of the
3184
+ ** first column of the index. aiRowEst[2] is an estimate of the number
3185
+ ** of rows that match any particular combiniation of the first 2 columns
3186
+ ** of the index. And so forth. It must always be the case that
3187
+ *
3188
+ ** aiRowEst[N]<=aiRowEst[N-1]
3189
+ ** aiRowEst[N]>=1
3190
+ **
3191
+ ** Apart from that, we have little to go on besides intuition as to
3192
+ ** how aiRowEst[] should be initialized. The numbers generated here
3193
+ ** are based on typical values found in actual indices.
3194
+ */
3195
+ static void sqlite3DefaultRowEst( Index pIdx )
3196
+ {
3197
+ int[] a = pIdx.aiRowEst;
3198
+ int i;
3199
+ Debug.Assert( a != null );
3200
+ a[0] = 1000000;
3201
+ for ( i = pIdx.nColumn; i >= 5; i-- )
3202
+ {
3203
+ a[i] = 5;
3204
+ }
3205
+ while ( i >= 1 )
3206
+ {
3207
+ a[i] = 11 - i;
3208
+ i--;
3209
+ }
3210
+ if ( pIdx.onError != OE_None )
3211
+ {
3212
+ a[pIdx.nColumn] = 1;
3213
+ }
3214
+ }
3215
+
3216
+ /*
3217
+ ** This routine will drop an existing named index. This routine
3218
+ ** implements the DROP INDEX statement.
3219
+ */
3220
+ static void sqlite3DropIndex( Parse pParse, SrcList pName, int ifExists )
3221
+ {
3222
+ Index pIndex;
3223
+ Vdbe v;
3224
+ sqlite3 db = pParse.db;
3225
+ int iDb;
3226
+
3227
+ Debug.Assert( pParse.nErr == 0 ); /* Never called with prior errors */
3228
+ //if ( db.mallocFailed != 0 )
3229
+ //{
3230
+ // goto exit_drop_index;
3231
+ //}
3232
+ Debug.Assert( pName.nSrc == 1 );
3233
+ if ( SQLITE_OK != sqlite3ReadSchema( pParse ) )
3234
+ {
3235
+ goto exit_drop_index;
3236
+ }
3237
+ pIndex = sqlite3FindIndex( db, pName.a[0].zName, pName.a[0].zDatabase );
3238
+ if ( pIndex == null )
3239
+ {
3240
+ if ( ifExists == 0 )
3241
+ {
3242
+ sqlite3ErrorMsg( pParse, "no such index: %S", pName, 0 );
3243
+ }
3244
+ pParse.checkSchema = 1;
3245
+ goto exit_drop_index;
3246
+ }
3247
+ if ( pIndex.autoIndex != 0 )
3248
+ {
3249
+ sqlite3ErrorMsg( pParse, "index associated with UNIQUE " +
3250
+ "or PRIMARY KEY constraint cannot be dropped", 0 );
3251
+ goto exit_drop_index;
3252
+ }
3253
+ iDb = sqlite3SchemaToIndex( db, pIndex.pSchema );
3254
+ #if !SQLITE_OMIT_AUTHORIZATION
3255
+ {
3256
+ int code = SQLITE_DROP_INDEX;
3257
+ Table pTab = pIndex.pTable;
3258
+ string zDb = db.aDb[iDb].zName;
3259
+ string zTab = SCHEMA_TABLE(iDb);
3260
+ if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
3261
+ goto exit_drop_index;
3262
+ }
3263
+ if( OMIT_TEMPDB ==0&& iDb ) code = SQLITE_DROP_TEMP_INDEX;
3264
+ if( sqlite3AuthCheck(pParse, code, pIndex.zName, pTab.zName, zDb) ){
3265
+ goto exit_drop_index;
3266
+ }
3267
+ }
3268
+ #endif
3269
+
3270
+ /* Generate code to remove the index and from the master table */
3271
+ v = sqlite3GetVdbe( pParse );
3272
+ if ( v != null )
3273
+ {
3274
+ sqlite3BeginWriteOperation( pParse, 1, iDb );
3275
+ sqlite3NestedParse( pParse,
3276
+ "DELETE FROM %Q.%s WHERE name=%Q",
3277
+ db.aDb[iDb].zName, SCHEMA_TABLE( iDb ),
3278
+ pIndex.zName
3279
+ );
3280
+ if ( sqlite3FindTable( db, "sqlite_stat1", db.aDb[iDb].zName ) != null )
3281
+ {
3282
+ sqlite3NestedParse( pParse,
3283
+ "DELETE FROM %Q.sqlite_stat1 WHERE idx=%Q",
3284
+ db.aDb[iDb].zName, pIndex.zName
3285
+ );
3286
+ }
3287
+ sqlite3ChangeCookie( pParse, iDb );
3288
+ destroyRootPage( pParse, pIndex.tnum, iDb );
3289
+ sqlite3VdbeAddOp4( v, OP_DropIndex, iDb, 0, 0, pIndex.zName, 0 );
3290
+ }
3291
+
3292
+ exit_drop_index:
3293
+ sqlite3SrcListDelete( db, ref pName );
3294
+ }
3295
+
3296
+ /*
3297
+ ** pArray is a pointer to an array of objects. Each object in the
3298
+ ** array is szEntry bytes in size. This routine allocates a new
3299
+ ** object on the end of the array.
3300
+ **
3301
+ ** pnEntry is the number of entries already in use. pnAlloc is
3302
+ ** the previously allocated size of the array. initSize is the
3303
+ ** suggested initial array size allocation.
3304
+ **
3305
+ ** The index of the new entry is returned in pIdx.
3306
+ **
3307
+ ** This routine returns a pointer to the array of objects. This
3308
+ ** might be the same as the pArray parameter or it might be a different
3309
+ ** pointer if the array was resized.
3310
+ */
3311
+ static T[] sqlite3ArrayAllocate<T>(
3312
+ sqlite3 db, /* Connection to notify of malloc failures */
3313
+ T[] pArray, /* Array of objects. Might be reallocated */
3314
+ int szEntry, /* Size of each object in the array */
3315
+ int initSize, /* Suggested initial allocation, in elements */
3316
+ ref int pnEntry, /* Number of objects currently in use */
3317
+ ref int pnAlloc, /* Current size of the allocation, in elements */
3318
+ ref int pIdx /* Write the index of a new slot here */
3319
+ ) where T : new()
3320
+ {
3321
+ //char* z;
3322
+ if ( pnEntry >= pnAlloc )
3323
+ {
3324
+ //void* pNew;
3325
+ int newSize;
3326
+ newSize = ( pnAlloc ) * 2 + initSize;
3327
+ //pNew = sqlite3DbRealloc(db, pArray, newSize * szEntry);
3328
+ //if (pNew == 0)
3329
+ //{
3330
+ // pIdx = -1;
3331
+ // return pArray;
3332
+ //}
3333
+ pnAlloc = newSize; //sqlite3DbMallocSize(db, pNew)/szEntry;
3334
+ //pArray = pNew;
3335
+ Array.Resize( ref pArray, newSize );
3336
+ }
3337
+ pArray[pnEntry] = new T();
3338
+ //z = (char*)pArray;
3339
+ //memset(z[*pnEntry * szEntry], 0, szEntry);
3340
+ pIdx = pnEntry;
3341
+ ++pnEntry;
3342
+ return pArray;
3343
+ }
3344
+
3345
+ /*
3346
+ ** Append a new element to the given IdList. Create a new IdList if
3347
+ ** need be.
3348
+ **
3349
+ ** A new IdList is returned, or NULL if malloc() fails.
3350
+ */
3351
+ // OVERLOADS, so I don't need to rewrite parse.c
3352
+ static IdList sqlite3IdListAppend( sqlite3 db, int null_2, Token pToken )
3353
+ { return sqlite3IdListAppend( db, null, pToken ); }
3354
+ static IdList sqlite3IdListAppend( sqlite3 db, IdList pList, Token pToken )
3355
+ {
3356
+ int i = 0;
3357
+ if ( pList == null )
3358
+ {
3359
+ pList = new IdList();//sqlite3DbMallocZero(db, sizeof(IdList));
3360
+ if ( pList == null ) return null;
3361
+ pList.nAlloc = 0;
3362
+ }
3363
+ pList.a = (IdList_item[])sqlite3ArrayAllocate(
3364
+ db,
3365
+ pList.a,
3366
+ -1,//sizeof(pList.a[0]),
3367
+ 5,
3368
+ ref pList.nId,
3369
+ ref pList.nAlloc,
3370
+ ref i
3371
+ );
3372
+ if ( i < 0 )
3373
+ {
3374
+ sqlite3IdListDelete( db, ref pList );
3375
+ return null;
3376
+ }
3377
+ pList.a[i].zName = sqlite3NameFromToken( db, pToken );
3378
+ return pList;
3379
+ }
3380
+
3381
+ /*
3382
+ ** Delete an IdList.
3383
+ */
3384
+ static void sqlite3IdListDelete( sqlite3 db, ref IdList pList )
3385
+ {
3386
+ int i;
3387
+ if ( pList == null ) return;
3388
+ for ( i = 0; i < pList.nId; i++ )
3389
+ {
3390
+ sqlite3DbFree( db, ref pList.a[i].zName );
3391
+ }
3392
+ sqlite3DbFree( db, ref pList.a );
3393
+ sqlite3DbFree( db, ref pList );
3394
+ }
3395
+
3396
+ /*
3397
+ ** Return the index in pList of the identifier named zId. Return -1
3398
+ ** if not found.
3399
+ */
3400
+ static int sqlite3IdListIndex( IdList pList, string zName )
3401
+ {
3402
+ int i;
3403
+ if ( pList == null ) return -1;
3404
+ for ( i = 0; i < pList.nId; i++ )
3405
+ {
3406
+ if ( sqlite3StrICmp( pList.a[i].zName, zName ) == 0 ) return i;
3407
+ }
3408
+ return -1;
3409
+ }
3410
+
3411
+ /*
3412
+ ** Expand the space allocated for the given SrcList object by
3413
+ ** creating nExtra new slots beginning at iStart. iStart is zero based.
3414
+ ** New slots are zeroed.
3415
+ **
3416
+ ** For example, suppose a SrcList initially contains two entries: A,B.
3417
+ ** To append 3 new entries onto the end, do this:
3418
+ **
3419
+ ** sqlite3SrcListEnlarge(db, pSrclist, 3, 2);
3420
+ **
3421
+ ** After the call above it would contain: A, B, nil, nil, nil.
3422
+ ** If the iStart argument had been 1 instead of 2, then the result
3423
+ ** would have been: A, nil, nil, nil, B. To prepend the new slots,
3424
+ ** the iStart value would be 0. The result then would
3425
+ ** be: nil, nil, nil, A, B.
3426
+ **
3427
+ ** If a memory allocation fails the SrcList is unchanged. The
3428
+ ** db.mallocFailed flag will be set to true.
3429
+ */
3430
+ static SrcList sqlite3SrcListEnlarge(
3431
+ sqlite3 db, /* Database connection to notify of OOM errors */
3432
+ SrcList pSrc, /* The SrcList to be enlarged */
3433
+ int nExtra, /* Number of new slots to add to pSrc.a[] */
3434
+ int iStart /* Index in pSrc.a[] of first new slot */
3435
+ )
3436
+ {
3437
+ int i;
3438
+
3439
+ /* Sanity checking on calling parameters */
3440
+ Debug.Assert( iStart >= 0 );
3441
+ Debug.Assert( nExtra >= 1 );
3442
+ Debug.Assert( pSrc != null );
3443
+ Debug.Assert( iStart <= pSrc.nSrc );
3444
+
3445
+ /* Allocate additional space if needed */
3446
+ if ( pSrc.nSrc + nExtra > pSrc.nAlloc )
3447
+ {
3448
+ int nAlloc = pSrc.nSrc + nExtra;
3449
+ int nGot;
3450
+ // sqlite3DbRealloc(db, pSrc,
3451
+ // sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc.a[0]) );
3452
+ pSrc.nAlloc = (i16)nAlloc;
3453
+ Array.Resize( ref pSrc.a, nAlloc );
3454
+ // nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
3455
+ //pSrc->nAlloc = (u16)nGot;
3456
+ }
3457
+
3458
+ /* Move existing slots that come after the newly inserted slots
3459
+ ** out of the way */
3460
+ for ( i = pSrc.nSrc - 1; i >= iStart; i-- )
3461
+ {
3462
+ pSrc.a[i + nExtra] = pSrc.a[i];
3463
+ }
3464
+ pSrc.nSrc += (i16)nExtra;
3465
+
3466
+ /* Zero the newly allocated slots */
3467
+ //memset(&pSrc.a[iStart], 0, sizeof(pSrc.a[0])*nExtra);
3468
+ for ( i = iStart; i < iStart + nExtra; i++ )
3469
+ {
3470
+ pSrc.a[i] = new SrcList_item();
3471
+ pSrc.a[i].iCursor = -1;
3472
+ }
3473
+
3474
+ /* Return a pointer to the enlarged SrcList */
3475
+ return pSrc;
3476
+ }
3477
+
3478
+
3479
+ /*
3480
+ ** Append a new table name to the given SrcList. Create a new SrcList if
3481
+ ** need be. A new entry is created in the SrcList even if pTable is NULL.
3482
+ **
3483
+ ** A SrcList is returned, or NULL if there is an OOM error. The returned
3484
+ ** SrcList might be the same as the SrcList that was input or it might be
3485
+ ** a new one. If an OOM error does occurs, then the prior value of pList
3486
+ ** that is input to this routine is automatically freed.
3487
+ **
3488
+ ** If pDatabase is not null, it means that the table has an optional
3489
+ ** database name prefix. Like this: "database.table". The pDatabase
3490
+ ** points to the table name and the pTable points to the database name.
3491
+ ** The SrcList.a[].zName field is filled with the table name which might
3492
+ ** come from pTable (if pDatabase is NULL) or from pDatabase.
3493
+ ** SrcList.a[].zDatabase is filled with the database name from pTable,
3494
+ ** or with NULL if no database is specified.
3495
+ **
3496
+ ** In other words, if call like this:
3497
+ **
3498
+ ** sqlite3SrcListAppend(D,A,B,0);
3499
+ **
3500
+ ** Then B is a table name and the database name is unspecified. If called
3501
+ ** like this:
3502
+ **
3503
+ ** sqlite3SrcListAppend(D,A,B,C);
3504
+ **
3505
+ ** Then C is the table name and B is the database name. If C is defined
3506
+ ** then so is B. In other words, we never have a case where:
3507
+ **
3508
+ ** sqlite3SrcListAppend(D,A,0,C);
3509
+ **
3510
+ ** Both pTable and pDatabase are assumed to be quoted. They are dequoted
3511
+ ** before being added to the SrcList.
3512
+ */
3513
+ // OVERLOADS, so I don't need to rewrite parse.c
3514
+ static SrcList sqlite3SrcListAppend( sqlite3 db, int null_2, Token pTable, int null_4 )
3515
+ {
3516
+ return sqlite3SrcListAppend( db, null, pTable, null );
3517
+ }
3518
+ static SrcList sqlite3SrcListAppend( sqlite3 db, int null_2, Token pTable, Token pDatabase )
3519
+ {
3520
+ return sqlite3SrcListAppend( db, null, pTable, pDatabase );
3521
+ }
3522
+ static SrcList sqlite3SrcListAppend(
3523
+ sqlite3 db, /* Connection to notify of malloc failures */
3524
+ SrcList pList, /* Append to this SrcList. NULL creates a new SrcList */
3525
+ Token pTable, /* Table to append */
3526
+ Token pDatabase /* Database of the table */
3527
+ )
3528
+ {
3529
+ SrcList_item pItem;
3530
+ Debug.Assert( pDatabase == null || pTable != null ); /* Cannot have C without B */
3531
+ if ( pList == null )
3532
+ {
3533
+ pList = new SrcList();//sqlite3DbMallocZero(db, SrcList.Length );
3534
+ //if ( pList == null ) return null;
3535
+ pList.nAlloc = 1;
3536
+ pList.a = new SrcList_item[1];
3537
+ }
3538
+ pList = sqlite3SrcListEnlarge( db, pList, 1, pList.nSrc );
3539
+ //if ( db.mallocFailed != 0 )
3540
+ //{
3541
+ // sqlite3SrcListDelete( db, ref pList );
3542
+ // return null;
3543
+ //}
3544
+ pItem = pList.a[pList.nSrc - 1];
3545
+ if ( pDatabase != null && String.IsNullOrEmpty( pDatabase.z ) )
3546
+ {
3547
+ pDatabase = null;
3548
+ }
3549
+ if ( pDatabase != null )
3550
+ {
3551
+ Token pTemp = pDatabase;
3552
+ pDatabase = pTable;
3553
+ pTable = pTemp;
3554
+ }
3555
+ pItem.zName = sqlite3NameFromToken( db, pTable );
3556
+ pItem.zDatabase = sqlite3NameFromToken( db, pDatabase );
3557
+ return pList;
3558
+ }
3559
+
3560
+ /*
3561
+ ** Assign VdbeCursor index numbers to all tables in a SrcList
3562
+ */
3563
+ static void sqlite3SrcListAssignCursors( Parse pParse, SrcList pList )
3564
+ {
3565
+ int i;
3566
+ SrcList_item pItem;
3567
+ Debug.Assert( pList != null /* || pParse.db.mallocFailed != 0 */ );
3568
+ if ( pList != null )
3569
+ {
3570
+ for ( i = 0; i < pList.nSrc; i++ )
3571
+ {
3572
+ pItem = pList.a[i];
3573
+ if ( pItem.iCursor >= 0 ) break;
3574
+ pItem.iCursor = pParse.nTab++;
3575
+ if ( pItem.pSelect != null )
3576
+ {
3577
+ sqlite3SrcListAssignCursors( pParse, pItem.pSelect.pSrc );
3578
+ }
3579
+ }
3580
+ }
3581
+ }
3582
+
3583
+ /*
3584
+ ** Delete an entire SrcList including all its substructure.
3585
+ */
3586
+ static void sqlite3SrcListDelete( sqlite3 db, ref SrcList pList )
3587
+ {
3588
+ int i;
3589
+ SrcList_item pItem;
3590
+ if ( pList == null ) return;
3591
+ for ( i = 0; i < pList.nSrc; i++ )
3592
+ {//, pItem++){
3593
+ pItem = pList.a[i];
3594
+ sqlite3DbFree( db, ref pItem.zDatabase );
3595
+ sqlite3DbFree( db, ref pItem.zName );
3596
+ sqlite3DbFree( db, ref pItem.zAlias );
3597
+ sqlite3DbFree( db, ref pItem.zIndex );
3598
+ sqlite3DeleteTable( ref pItem.pTab );
3599
+ sqlite3SelectDelete( db, ref pItem.pSelect );
3600
+ sqlite3ExprDelete( db, ref pItem.pOn );
3601
+ sqlite3IdListDelete( db, ref pItem.pUsing );
3602
+ }
3603
+ sqlite3DbFree( db, ref pList );
3604
+ }
3605
+
3606
+ /*
3607
+ ** This routine is called by the parser to add a new term to the
3608
+ ** end of a growing FROM clause. The "p" parameter is the part of
3609
+ ** the FROM clause that has already been constructed. "p" is NULL
3610
+ ** if this is the first term of the FROM clause. pTable and pDatabase
3611
+ ** are the name of the table and database named in the FROM clause term.
3612
+ ** pDatabase is NULL if the database name qualifier is missing - the
3613
+ ** usual case. If the term has a alias, then pAlias points to the
3614
+ ** alias token. If the term is a subquery, then pSubquery is the
3615
+ ** SELECT statement that the subquery encodes. The pTable and
3616
+ ** pDatabase parameters are NULL for subqueries. The pOn and pUsing
3617
+ ** parameters are the content of the ON and USING clauses.
3618
+ **
3619
+ ** Return a new SrcList which encodes is the FROM with the new
3620
+ ** term added.
3621
+ */
3622
+ // OVERLOADS, so I don't need to rewrite parse.c
3623
+ static SrcList sqlite3SrcListAppendFromTerm( Parse pParse, SrcList p, int null_3, int null_4, Token pAlias, Select pSubquery, Expr pOn, IdList pUsing )
3624
+ {
3625
+ return sqlite3SrcListAppendFromTerm( pParse, p, null, null, pAlias, pSubquery, pOn, pUsing );
3626
+ }
3627
+ static SrcList sqlite3SrcListAppendFromTerm( Parse pParse, SrcList p, Token pTable, Token pDatabase, Token pAlias, int null_6, Expr pOn, IdList pUsing )
3628
+ {
3629
+ return sqlite3SrcListAppendFromTerm( pParse, p, pTable, pDatabase, pAlias, null, pOn, pUsing );
3630
+ }
3631
+ static SrcList sqlite3SrcListAppendFromTerm(
3632
+ Parse pParse, /* Parsing context */
3633
+ SrcList p, /* The left part of the FROM clause already seen */
3634
+ Token pTable, /* Name of the table to add to the FROM clause */
3635
+ Token pDatabase, /* Name of the database containing pTable */
3636
+ Token pAlias, /* The right-hand side of the AS subexpression */
3637
+ Select pSubquery, /* A subquery used in place of a table name */
3638
+ Expr pOn, /* The ON clause of a join */
3639
+ IdList pUsing /* The USING clause of a join */
3640
+ )
3641
+ {
3642
+ SrcList_item pItem;
3643
+ sqlite3 db = pParse.db;
3644
+ if ( null == p && ( pOn != null || pUsing != null ) )
3645
+ {
3646
+ sqlite3ErrorMsg( pParse, "a JOIN clause is required before %s",
3647
+ ( pOn != null ? "ON" : "USING" )
3648
+ );
3649
+ goto append_from_error;
3650
+ }
3651
+ p = sqlite3SrcListAppend( db, p, pTable, pDatabase );
3652
+ //if ( p == null || NEVER( p.nSrc == 0 ) )
3653
+ //{
3654
+ // goto append_from_error;
3655
+ //}
3656
+ pItem = p.a[p.nSrc - 1];
3657
+ Debug.Assert( pAlias != null );
3658
+ if ( pAlias.n != 0 )
3659
+ {
3660
+ pItem.zAlias = sqlite3NameFromToken( db, pAlias );
3661
+ }
3662
+ pItem.pSelect = pSubquery;
3663
+ pItem.pOn = pOn;
3664
+ pItem.pUsing = pUsing;
3665
+ return p;
3666
+ append_from_error:
3667
+ Debug.Assert( p == null );
3668
+ sqlite3ExprDelete( db, ref pOn );
3669
+ sqlite3IdListDelete( db, ref pUsing );
3670
+ sqlite3SelectDelete( db, ref pSubquery );
3671
+ return null;
3672
+ }
3673
+
3674
+ /*
3675
+ ** Add an INDEXED BY or NOT INDEXED clause to the most recently added
3676
+ ** element of the source-list passed as the second argument.
3677
+ */
3678
+ static void sqlite3SrcListIndexedBy( Parse pParse, SrcList p, Token pIndexedBy )
3679
+ {
3680
+ Debug.Assert( pIndexedBy != null );
3681
+ if ( p != null && ALWAYS( p.nSrc > 0 ) )
3682
+ {
3683
+ SrcList_item pItem = p.a[p.nSrc - 1];
3684
+ Debug.Assert( 0 == pItem.notIndexed && pItem.zIndex == null );
3685
+ if ( pIndexedBy.n == 1 && null == pIndexedBy.z )
3686
+ {
3687
+ /* A "NOT INDEXED" clause was supplied. See parse.y
3688
+ ** construct "indexed_opt" for details. */
3689
+ pItem.notIndexed = 1;
3690
+ }
3691
+ else
3692
+ {
3693
+ pItem.zIndex = sqlite3NameFromToken( pParse.db, pIndexedBy );
3694
+ }
3695
+ }
3696
+ }
3697
+
3698
+ /*
3699
+ ** When building up a FROM clause in the parser, the join operator
3700
+ ** is initially attached to the left operand. But the code generator
3701
+ ** expects the join operator to be on the right operand. This routine
3702
+ ** Shifts all join operators from left to right for an entire FROM
3703
+ ** clause.
3704
+ **
3705
+ ** Example: Suppose the join is like this:
3706
+ **
3707
+ ** A natural cross join B
3708
+ **
3709
+ ** The operator is "natural cross join". The A and B operands are stored
3710
+ ** in p.a[0] and p.a[1], respectively. The parser initially stores the
3711
+ ** operator with A. This routine shifts that operator over to B.
3712
+ */
3713
+ static void sqlite3SrcListShiftJoinType( SrcList p )
3714
+ {
3715
+ if ( p != null && p.a != null )
3716
+ {
3717
+ int i;
3718
+ for ( i = p.nSrc - 1; i > 0; i-- )
3719
+ {
3720
+ p.a[i].jointype = p.a[i - 1].jointype;
3721
+ }
3722
+ p.a[0].jointype = 0;
3723
+ }
3724
+ }
3725
+
3726
+ /*
3727
+ ** Begin a transaction
3728
+ */
3729
+ static void sqlite3BeginTransaction( Parse pParse, int type )
3730
+ {
3731
+ sqlite3 db;
3732
+ Vdbe v;
3733
+ int i;
3734
+
3735
+ Debug.Assert( pParse != null );
3736
+ db = pParse.db;
3737
+ Debug.Assert( db != null );
3738
+ /* if( db.aDb[0].pBt==0 ) return; */
3739
+ if ( sqlite3AuthCheck( pParse, SQLITE_TRANSACTION, "BEGIN", null, null ) != 0 )
3740
+ {
3741
+ return;
3742
+ }
3743
+ v = sqlite3GetVdbe( pParse );
3744
+ if ( v == null ) return;
3745
+ if ( type != TK_DEFERRED )
3746
+ {
3747
+ for ( i = 0; i < db.nDb; i++ )
3748
+ {
3749
+ sqlite3VdbeAddOp2( v, OP_Transaction, i, ( type == TK_EXCLUSIVE ) ? 2 : 1 );
3750
+ sqlite3VdbeUsesBtree( v, i );
3751
+ }
3752
+ }
3753
+ sqlite3VdbeAddOp2( v, OP_AutoCommit, 0, 0 );
3754
+ }
3755
+
3756
+ /*
3757
+ ** Commit a transaction
3758
+ */
3759
+ static void sqlite3CommitTransaction( Parse pParse )
3760
+ {
3761
+ sqlite3 db;
3762
+ Vdbe v;
3763
+
3764
+ Debug.Assert( pParse != null );
3765
+ db = pParse.db;
3766
+ Debug.Assert( db != null );
3767
+ /* if( db.aDb[0].pBt==0 ) return; */
3768
+ if ( sqlite3AuthCheck( pParse, SQLITE_TRANSACTION, "COMMIT", null, null ) != 0 )
3769
+ {
3770
+ return;
3771
+ }
3772
+ v = sqlite3GetVdbe( pParse );
3773
+ if ( v != null )
3774
+ {
3775
+ sqlite3VdbeAddOp2( v, OP_AutoCommit, 1, 0 );
3776
+ }
3777
+ }
3778
+
3779
+ /*
3780
+ ** Rollback a transaction
3781
+ */
3782
+ static void sqlite3RollbackTransaction( Parse pParse )
3783
+ {
3784
+ sqlite3 db;
3785
+ Vdbe v;
3786
+
3787
+ Debug.Assert( pParse != null );
3788
+ db = pParse.db;
3789
+ Debug.Assert( db != null );
3790
+ /* if( db.aDb[0].pBt==0 ) return; */
3791
+ if ( sqlite3AuthCheck( pParse, SQLITE_TRANSACTION, "ROLLBACK", null, null ) != 0 )
3792
+ {
3793
+ return;
3794
+ }
3795
+ v = sqlite3GetVdbe( pParse );
3796
+ if ( v != null )
3797
+ {
3798
+ sqlite3VdbeAddOp2( v, OP_AutoCommit, 1, 1 );
3799
+ }
3800
+ }
3801
+
3802
+ /*
3803
+ ** This function is called by the parser when it parses a command to create,
3804
+ ** release or rollback an SQL savepoint.
3805
+ */
3806
+ static void sqlite3Savepoint( Parse pParse, int op, Token pName )
3807
+ {
3808
+ string zName = sqlite3NameFromToken( pParse.db, pName );
3809
+ if ( zName != null )
3810
+ {
3811
+ Vdbe v = sqlite3GetVdbe( pParse );
3812
+ #if !SQLITE_OMIT_AUTHORIZATION
3813
+ byte az[] = { "BEGIN", "RELEASE", "ROLLBACK" };
3814
+ Debug.Assert( !SAVEPOINT_BEGIN && SAVEPOINT_RELEASE==1 && SAVEPOINT_ROLLBACK==2 );
3815
+ #endif
3816
+ if ( null == v
3817
+ #if !SQLITE_OMIT_AUTHORIZATION
3818
+ || sqlite3AuthCheck(pParse, SQLITE_SAVEPOINT, az[op], zName, 0)
3819
+ #endif
3820
+ )
3821
+ {
3822
+ sqlite3DbFree( pParse.db, ref zName );
3823
+ return;
3824
+ }
3825
+ sqlite3VdbeAddOp4( v, OP_Savepoint, op, 0, 0, zName, P4_DYNAMIC );
3826
+ }
3827
+ }
3828
+
3829
+ /*
3830
+ ** Make sure the TEMP database is open and available for use. Return
3831
+ ** the number of errors. Leave any error messages in the pParse structure.
3832
+ */
3833
+ static int sqlite3OpenTempDatabase( Parse pParse )
3834
+ {
3835
+ sqlite3 db = pParse.db;
3836
+ if ( db.aDb[1].pBt == null && pParse.explain == 0 )
3837
+ {
3838
+ int rc;
3839
+ Btree pBt = null;
3840
+ const int flags =
3841
+ SQLITE_OPEN_READWRITE |
3842
+ SQLITE_OPEN_CREATE |
3843
+ SQLITE_OPEN_EXCLUSIVE |
3844
+ SQLITE_OPEN_DELETEONCLOSE |
3845
+ SQLITE_OPEN_TEMP_DB;
3846
+
3847
+ rc = sqlite3BtreeFactory( db, null, false, SQLITE_DEFAULT_CACHE_SIZE, flags, ref pBt);
3848
+ if ( rc != SQLITE_OK )
3849
+ {
3850
+ sqlite3ErrorMsg( pParse, "unable to open a temporary database " +
3851
+ "file for storing temporary tables" );
3852
+ pParse.rc = rc;
3853
+ return 1;
3854
+ }
3855
+ db.aDb[1].pBt = pBt;
3856
+ Debug.Assert( db.aDb[1].pSchema != null );
3857
+ if ( SQLITE_NOMEM == sqlite3BtreeSetPageSize( pBt, db.nextPagesize, -1, 0 ) )
3858
+ {
3859
+ // db.mallocFailed = 1;
3860
+ }
3861
+ sqlite3PagerJournalMode( sqlite3BtreePager( pBt ), db.dfltJournalMode );
3862
+ }
3863
+ return 0;
3864
+ }
3865
+
3866
+ /*
3867
+ ** Generate VDBE code that will verify the schema cookie and start
3868
+ ** a read-transaction for all named database files.
3869
+ **
3870
+ ** It is important that all schema cookies be verified and all
3871
+ ** read transactions be started before anything else happens in
3872
+ ** the VDBE program. But this routine can be called after much other
3873
+ ** code has been generated. So here is what we do:
3874
+ **
3875
+ ** The first time this routine is called, we code an OP_Goto that
3876
+ ** will jump to a subroutine at the end of the program. Then we
3877
+ ** record every database that needs its schema verified in the
3878
+ ** pParse.cookieMask field. Later, after all other code has been
3879
+ ** generated, the subroutine that does the cookie verifications and
3880
+ ** starts the transactions will be coded and the OP_Goto P2 value
3881
+ ** will be made to point to that subroutine. The generation of the
3882
+ ** cookie verification subroutine code happens in sqlite3FinishCoding().
3883
+ **
3884
+ ** If iDb<0 then code the OP_Goto only - don't set flag to verify the
3885
+ ** schema on any databases. This can be used to position the OP_Goto
3886
+ ** early in the code, before we know if any database tables will be used.
3887
+ */
3888
+ static void sqlite3CodeVerifySchema( Parse pParse, int iDb )
3889
+ {
3890
+ Parse pToplevel = sqlite3ParseToplevel( pParse );
3891
+
3892
+ if ( pToplevel.cookieGoto == 0 )
3893
+ {
3894
+ Vdbe v = sqlite3GetVdbe( pToplevel );
3895
+ if ( v == null ) return; /* This only happens if there was a prior error */
3896
+ pToplevel.cookieGoto = sqlite3VdbeAddOp2( v, OP_Goto, 0, 0 ) + 1;
3897
+ }
3898
+ if ( iDb >= 0 )
3899
+ {
3900
+ sqlite3 db = pToplevel.db;
3901
+ int mask;
3902
+ Debug.Assert( iDb < db.nDb );
3903
+ Debug.Assert( db.aDb[iDb].pBt != null || iDb == 1 );
3904
+ Debug.Assert( iDb < SQLITE_MAX_ATTACHED + 2 );
3905
+ mask = (int)( 1 << iDb );
3906
+ if ( ( pToplevel.cookieMask & mask ) == 0 )
3907
+ {
3908
+ pToplevel.cookieMask |= (u32)mask;
3909
+ pToplevel.cookieValue[iDb] = db.aDb[iDb].pSchema.schema_cookie;
3910
+ if ( 0 == OMIT_TEMPDB && iDb == 1 )
3911
+ {
3912
+ sqlite3OpenTempDatabase( pToplevel );
3913
+ }
3914
+ }
3915
+ }
3916
+ }
3917
+
3918
+ /*
3919
+ ** Generate VDBE code that prepares for doing an operation that
3920
+ ** might change the database.
3921
+ **
3922
+ ** This routine starts a new transaction if we are not already within
3923
+ ** a transaction. If we are already within a transaction, then a checkpoint
3924
+ ** is set if the setStatement parameter is true. A checkpoint should
3925
+ ** be set for operations that might fail (due to a constraint) part of
3926
+ ** the way through and which will need to undo some writes without having to
3927
+ ** rollback the whole transaction. For operations where all constraints
3928
+ ** can be checked before any changes are made to the database, it is never
3929
+ ** necessary to undo a write and the checkpoint should not be set.
3930
+ */
3931
+ static void sqlite3BeginWriteOperation( Parse pParse, int setStatement, int iDb )
3932
+ {
3933
+ Parse pToplevel = sqlite3ParseToplevel( pParse );
3934
+ sqlite3CodeVerifySchema( pParse, iDb );
3935
+ pToplevel.writeMask |= (u32)( 1 << iDb );
3936
+ pToplevel.isMultiWrite |= (u8)setStatement;
3937
+ }
3938
+
3939
+ /*
3940
+ ** Indicate that the statement currently under construction might write
3941
+ ** more than one entry (example: deleting one row then inserting another,
3942
+ ** inserting multiple rows in a table, or inserting a row and index entries.)
3943
+ ** If an abort occurs after some of these writes have completed, then it will
3944
+ ** be necessary to undo the completed writes.
3945
+ */
3946
+ static void sqlite3MultiWrite( Parse pParse )
3947
+ {
3948
+ Parse pToplevel = sqlite3ParseToplevel( pParse );
3949
+ pToplevel.isMultiWrite = 1;
3950
+ }
3951
+
3952
+ /*
3953
+ ** The code generator calls this routine if is discovers that it is
3954
+ ** possible to abort a statement prior to completion. In order to
3955
+ ** perform this abort without corrupting the database, we need to make
3956
+ ** sure that the statement is protected by a statement transaction.
3957
+ **
3958
+ ** Technically, we only need to set the mayAbort flag if the
3959
+ ** isMultiWrite flag was previously set. There is a time dependency
3960
+ ** such that the abort must occur after the multiwrite. This makes
3961
+ ** some statements involving the REPLACE conflict resolution algorithm
3962
+ ** go a little faster. But taking advantage of this time dependency
3963
+ ** makes it more difficult to prove that the code is correct (in
3964
+ ** particular, it prevents us from writing an effective
3965
+ ** implementation of sqlite3AssertMayAbort()) and so we have chosen
3966
+ ** to take the safe route and skip the optimization.
3967
+ */
3968
+ static void sqlite3MayAbort( Parse pParse )
3969
+ {
3970
+ Parse pToplevel = sqlite3ParseToplevel( pParse );
3971
+ pToplevel.mayAbort = 1;
3972
+ }
3973
+
3974
+ /*
3975
+ ** Code an OP_Halt that causes the vdbe to return an SQLITE_CONSTRAINT
3976
+ ** error. The onError parameter determines which (if any) of the statement
3977
+ ** and/or current transaction is rolled back.
3978
+ */
3979
+ static void sqlite3HaltConstraint( Parse pParse, int onError, string p4, int p4type )
3980
+ {
3981
+ Vdbe v = sqlite3GetVdbe( pParse );
3982
+ if ( onError == OE_Abort )
3983
+ {
3984
+ sqlite3MayAbort( pParse );
3985
+ }
3986
+ sqlite3VdbeAddOp4( v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, p4, p4type );
3987
+ }
3988
+
3989
+ static void sqlite3HaltConstraint( Parse pParse, int onError, byte[] p4, int p4type )
3990
+ {
3991
+ Vdbe v = sqlite3GetVdbe( pParse );
3992
+ if ( onError == OE_Abort )
3993
+ {
3994
+ sqlite3MayAbort( pParse );
3995
+ }
3996
+ sqlite3VdbeAddOp4( v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, p4, p4type );
3997
+ }
3998
+
3999
+ /*
4000
+ ** Check to see if pIndex uses the collating sequence pColl. Return
4001
+ ** true if it does and false if it does not.
4002
+ */
4003
+ #if !SQLITE_OMIT_REINDEX
4004
+ static bool collationMatch( string zColl, Index pIndex )
4005
+ {
4006
+ int i;
4007
+ Debug.Assert( zColl != null );
4008
+ for ( i = 0; i < pIndex.nColumn; i++ )
4009
+ {
4010
+ string z = pIndex.azColl[i];
4011
+ Debug.Assert( z != null );
4012
+ if ( 0 == sqlite3StrICmp( z, zColl ) )
4013
+ {
4014
+ return true;
4015
+ }
4016
+ }
4017
+ return false;
4018
+ }
4019
+ #endif
4020
+
4021
+ /*
4022
+ ** Recompute all indices of pTab that use the collating sequence pColl.
4023
+ ** If pColl == null then recompute all indices of pTab.
4024
+ */
4025
+ #if !SQLITE_OMIT_REINDEX
4026
+ static void reindexTable( Parse pParse, Table pTab, string zColl )
4027
+ {
4028
+ Index pIndex; /* An index associated with pTab */
4029
+
4030
+ for ( pIndex = pTab.pIndex; pIndex != null; pIndex = pIndex.pNext )
4031
+ {
4032
+ if ( zColl == null || collationMatch( zColl, pIndex ) )
4033
+ {
4034
+ int iDb = sqlite3SchemaToIndex( pParse.db, pTab.pSchema );
4035
+ sqlite3BeginWriteOperation( pParse, 0, iDb );
4036
+ sqlite3RefillIndex( pParse, pIndex, -1 );
4037
+ }
4038
+ }
4039
+ }
4040
+ #endif
4041
+
4042
+ /*
4043
+ ** Recompute all indices of all tables in all databases where the
4044
+ ** indices use the collating sequence pColl. If pColl == null then recompute
4045
+ ** all indices everywhere.
4046
+ */
4047
+ #if !SQLITE_OMIT_REINDEX
4048
+ static void reindexDatabases( Parse pParse, string zColl )
4049
+ {
4050
+ Db pDb; /* A single database */
4051
+ int iDb; /* The database index number */
4052
+ sqlite3 db = pParse.db; /* The database connection */
4053
+ HashElem k; /* For looping over tables in pDb */
4054
+ Table pTab; /* A table in the database */
4055
+
4056
+ for ( iDb = 0; iDb < db.nDb; iDb++ )//, pDb++ )
4057
+ {
4058
+ pDb = db.aDb[iDb];
4059
+ Debug.Assert( pDb != null );
4060
+ for ( k = pDb.pSchema.tblHash.first; k != null; k = k.next ) //for ( k = sqliteHashFirst( pDb.pSchema.tblHash ) ; k != null ; k = sqliteHashNext( k ) )
4061
+ {
4062
+ pTab = (Table)k.data;// sqliteHashData( k );
4063
+ reindexTable( pParse, pTab, zColl );
4064
+ }
4065
+ }
4066
+ }
4067
+ #endif
4068
+
4069
+ /*
4070
+ ** Generate code for the REINDEX command.
4071
+ **
4072
+ ** REINDEX -- 1
4073
+ ** REINDEX <collation> -- 2
4074
+ ** REINDEX ?<database>.?<tablename> -- 3
4075
+ ** REINDEX ?<database>.?<indexname> -- 4
4076
+ **
4077
+ ** Form 1 causes all indices in all attached databases to be rebuilt.
4078
+ ** Form 2 rebuilds all indices in all databases that use the named
4079
+ ** collating function. Forms 3 and 4 rebuild the named index or all
4080
+ ** indices associated with the named table.
4081
+ */
4082
+ #if !SQLITE_OMIT_REINDEX
4083
+ // OVERLOADS, so I don't need to rewrite parse.c
4084
+ static void sqlite3Reindex( Parse pParse, int null_2, int null_3 )
4085
+ { sqlite3Reindex( pParse, null, null ); }
4086
+ static void sqlite3Reindex( Parse pParse, Token pName1, Token pName2 )
4087
+ {
4088
+ CollSeq pColl; /* Collating sequence to be reindexed, or NULL */
4089
+ string z; /* Name of a table or index */
4090
+ string zDb; /* Name of the database */
4091
+ Table pTab; /* A table in the database */
4092
+ Index pIndex; /* An index associated with pTab */
4093
+ int iDb; /* The database index number */
4094
+ sqlite3 db = pParse.db; /* The database connection */
4095
+ Token pObjName = new Token(); /* Name of the table or index to be reindexed */
4096
+
4097
+ /* Read the database schema. If an error occurs, leave an error message
4098
+ ** and code in pParse and return NULL. */
4099
+ if ( SQLITE_OK != sqlite3ReadSchema( pParse ) )
4100
+ {
4101
+ return;
4102
+ }
4103
+
4104
+ if ( pName1 == null )
4105
+ {
4106
+ reindexDatabases( pParse, null );
4107
+ return;
4108
+ }
4109
+ else if ( NEVER( pName2 == null ) || pName2.z == null || pName2.z.Length == 0 )
4110
+ {
4111
+ string zColl;
4112
+ Debug.Assert( pName1.z != null );
4113
+ zColl = sqlite3NameFromToken( pParse.db, pName1 );
4114
+ if ( zColl == null ) return;
4115
+ pColl = sqlite3FindCollSeq( db, ENC( db ), zColl, 0 );
4116
+ if ( pColl != null )
4117
+ {
4118
+ reindexDatabases( pParse, zColl );
4119
+ sqlite3DbFree( db, ref zColl );
4120
+ return;
4121
+ }
4122
+ sqlite3DbFree( db, ref zColl );
4123
+ }
4124
+ iDb = sqlite3TwoPartName( pParse, pName1, pName2, ref pObjName );
4125
+ if ( iDb < 0 ) return;
4126
+ z = sqlite3NameFromToken( db, pObjName );
4127
+ if ( z == null ) return;
4128
+ zDb = db.aDb[iDb].zName;
4129
+ pTab = sqlite3FindTable( db, z, zDb );
4130
+ if ( pTab != null )
4131
+ {
4132
+ reindexTable( pParse, pTab, null );
4133
+ sqlite3DbFree( db, ref z );
4134
+ return;
4135
+ }
4136
+ pIndex = sqlite3FindIndex( db, z, zDb );
4137
+ sqlite3DbFree( db, ref z );
4138
+ if ( pIndex != null )
4139
+ {
4140
+ sqlite3BeginWriteOperation( pParse, 0, iDb );
4141
+ sqlite3RefillIndex( pParse, pIndex, -1 );
4142
+ return;
4143
+ }
4144
+ sqlite3ErrorMsg( pParse, "unable to identify the object to be reindexed" );
4145
+ }
4146
+ #endif
4147
+
4148
+ /*
4149
+ ** Return a dynamicly allocated KeyInfo structure that can be used
4150
+ ** with OP_OpenRead or OP_OpenWrite to access database index pIdx.
4151
+ **
4152
+ ** If successful, a pointer to the new structure is returned. In this case
4153
+ ** the caller is responsible for calling sqlite3DbFree(db, ) on the returned
4154
+ ** pointer. If an error occurs (out of memory or missing collation
4155
+ ** sequence), NULL is returned and the state of pParse updated to reflect
4156
+ ** the error.
4157
+ */
4158
+ static KeyInfo sqlite3IndexKeyinfo( Parse pParse, Index pIdx )
4159
+ {
4160
+ int i;
4161
+ int nCol = pIdx.nColumn;
4162
+ //int nBytes = KeyInfo.Length + (nCol - 1) * CollSeq*.Length + nCol;
4163
+ sqlite3 db = pParse.db;
4164
+ KeyInfo pKey = new KeyInfo();// (KeyInfo*)sqlite3DbMallocZero(db, nBytes);
4165
+
4166
+ if ( pKey != null )
4167
+ {
4168
+ pKey.db = pParse.db;
4169
+ pKey.aSortOrder = new byte[nCol];
4170
+ pKey.aColl = new CollSeq[nCol];// (u8*)&(pKey.aColl[nCol]);
4171
+ // Debug.Assert(pKey.aSortOrder[nCol] == &(((u8*)pKey)[nBytes]));
4172
+ for ( i = 0; i < nCol; i++ )
4173
+ {
4174
+ string zColl = pIdx.azColl[i];
4175
+ Debug.Assert( zColl != null );
4176
+ pKey.aColl[i] = sqlite3LocateCollSeq( pParse, zColl );
4177
+ pKey.aSortOrder[i] = pIdx.aSortOrder[i];
4178
+ }
4179
+ pKey.nField = (u16)nCol;
4180
+ }
4181
+
4182
+ if ( pParse.nErr != 0 )
4183
+ {
4184
+ pKey = null; sqlite3DbFree( db, ref pKey );
4185
+ }
4186
+ return pKey;
4187
+ }
4188
+ }
4189
+ }