sequel 3.21.0 → 3.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (352) hide show
  1. data/CHANGELOG +1061 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +103 -63
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +67 -51
  7. data/doc/advanced_associations.rdoc +189 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/cheat_sheet.rdoc +21 -21
  10. data/doc/core_extensions.rdoc +374 -0
  11. data/doc/dataset_basics.rdoc +10 -10
  12. data/doc/dataset_filtering.rdoc +54 -42
  13. data/doc/mass_assignment.rdoc +56 -0
  14. data/doc/migration.rdoc +89 -557
  15. data/doc/model_hooks.rdoc +80 -29
  16. data/doc/object_model.rdoc +547 -0
  17. data/doc/opening_databases.rdoc +114 -53
  18. data/doc/prepared_statements.rdoc +41 -15
  19. data/doc/querying.rdoc +137 -56
  20. data/doc/reflection.rdoc +36 -10
  21. data/doc/release_notes/3.22.0.txt +39 -0
  22. data/doc/release_notes/3.23.0.txt +172 -0
  23. data/doc/release_notes/3.24.0.txt +420 -0
  24. data/doc/release_notes/3.25.0.txt +88 -0
  25. data/doc/release_notes/3.26.0.txt +88 -0
  26. data/doc/release_notes/3.27.0.txt +82 -0
  27. data/doc/release_notes/3.28.0.txt +304 -0
  28. data/doc/release_notes/3.29.0.txt +459 -0
  29. data/doc/release_notes/3.30.0.txt +135 -0
  30. data/doc/release_notes/3.31.0.txt +146 -0
  31. data/doc/release_notes/3.32.0.txt +202 -0
  32. data/doc/release_notes/3.33.0.txt +157 -0
  33. data/doc/release_notes/3.34.0.txt +671 -0
  34. data/doc/release_notes/3.35.0.txt +144 -0
  35. data/doc/release_notes/3.36.0.txt +245 -0
  36. data/doc/release_notes/3.37.0.txt +338 -0
  37. data/doc/release_notes/3.38.0.txt +234 -0
  38. data/doc/release_notes/3.39.0.txt +237 -0
  39. data/doc/schema_modification.rdoc +585 -0
  40. data/doc/sharding.rdoc +99 -8
  41. data/doc/sql.rdoc +154 -112
  42. data/doc/testing.rdoc +169 -0
  43. data/doc/thread_safety.rdoc +17 -0
  44. data/doc/transactions.rdoc +137 -0
  45. data/doc/validations.rdoc +1 -1
  46. data/doc/virtual_rows.rdoc +78 -43
  47. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  48. data/lib/sequel/adapters/ado.rb +40 -18
  49. data/lib/sequel/adapters/amalgalite.rb +17 -9
  50. data/lib/sequel/adapters/db2.rb +175 -86
  51. data/lib/sequel/adapters/dbi.rb +15 -15
  52. data/lib/sequel/adapters/do/mysql.rb +17 -11
  53. data/lib/sequel/adapters/do/postgres.rb +2 -61
  54. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  55. data/lib/sequel/adapters/do.rb +18 -36
  56. data/lib/sequel/adapters/firebird.rb +27 -208
  57. data/lib/sequel/adapters/ibmdb.rb +453 -0
  58. data/lib/sequel/adapters/informix.rb +6 -23
  59. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  60. data/lib/sequel/adapters/jdbc/db2.rb +56 -0
  61. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  62. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  63. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  64. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  65. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  66. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  67. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  68. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  69. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  70. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  71. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  73. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  74. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  75. data/lib/sequel/adapters/jdbc.rb +279 -97
  76. data/lib/sequel/adapters/mock.rb +372 -0
  77. data/lib/sequel/adapters/mysql.rb +125 -222
  78. data/lib/sequel/adapters/mysql2.rb +65 -56
  79. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  80. data/lib/sequel/adapters/odbc.rb +28 -9
  81. data/lib/sequel/adapters/openbase.rb +3 -5
  82. data/lib/sequel/adapters/oracle.rb +349 -53
  83. data/lib/sequel/adapters/postgres.rb +368 -138
  84. data/lib/sequel/adapters/shared/access.rb +32 -9
  85. data/lib/sequel/adapters/shared/db2.rb +343 -0
  86. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  87. data/lib/sequel/adapters/shared/informix.rb +53 -0
  88. data/lib/sequel/adapters/shared/mssql.rb +401 -116
  89. data/lib/sequel/adapters/shared/mysql.rb +424 -89
  90. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  91. data/lib/sequel/adapters/shared/oracle.rb +257 -45
  92. data/lib/sequel/adapters/shared/postgres.rb +675 -279
  93. data/lib/sequel/adapters/shared/progress.rb +5 -8
  94. data/lib/sequel/adapters/shared/sqlite.rb +285 -96
  95. data/lib/sequel/adapters/sqlite.rb +101 -39
  96. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  97. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  98. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  99. data/lib/sequel/adapters/swift.rb +28 -19
  100. data/lib/sequel/adapters/tinytds.rb +174 -22
  101. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  102. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  103. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  104. data/lib/sequel/ast_transformer.rb +194 -0
  105. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  106. data/lib/sequel/connection_pool/sharded_threaded.rb +33 -2
  107. data/lib/sequel/connection_pool/single.rb +5 -0
  108. data/lib/sequel/connection_pool/threaded.rb +43 -14
  109. data/lib/sequel/connection_pool.rb +10 -2
  110. data/lib/sequel/core.rb +143 -11
  111. data/lib/sequel/database/connecting.rb +38 -28
  112. data/lib/sequel/database/dataset.rb +4 -4
  113. data/lib/sequel/database/dataset_defaults.rb +63 -2
  114. data/lib/sequel/database/logging.rb +7 -2
  115. data/lib/sequel/database/misc.rb +190 -46
  116. data/lib/sequel/database/query.rb +272 -110
  117. data/lib/sequel/database/schema_generator.rb +103 -36
  118. data/lib/sequel/database/schema_methods.rb +300 -67
  119. data/lib/sequel/dataset/actions.rb +344 -90
  120. data/lib/sequel/dataset/features.rb +101 -8
  121. data/lib/sequel/dataset/graph.rb +42 -15
  122. data/lib/sequel/dataset/misc.rb +52 -25
  123. data/lib/sequel/dataset/mutation.rb +12 -7
  124. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  125. data/lib/sequel/dataset/query.rb +305 -54
  126. data/lib/sequel/dataset/sql.rb +720 -292
  127. data/lib/sequel/dataset.rb +8 -0
  128. data/lib/sequel/exceptions.rb +4 -0
  129. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  130. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  131. data/lib/sequel/extensions/blank.rb +4 -0
  132. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  133. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  134. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  135. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  136. data/lib/sequel/extensions/inflector.rb +4 -0
  137. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  138. data/lib/sequel/extensions/migration.rb +100 -11
  139. data/lib/sequel/extensions/named_timezones.rb +9 -0
  140. data/lib/sequel/extensions/null_dataset.rb +94 -0
  141. data/lib/sequel/extensions/pagination.rb +4 -0
  142. data/lib/sequel/extensions/pg_array.rb +537 -0
  143. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  144. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  145. data/lib/sequel/extensions/pg_hstore.rb +313 -0
  146. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  147. data/lib/sequel/extensions/pg_inet.rb +113 -0
  148. data/lib/sequel/extensions/pg_interval.rb +191 -0
  149. data/lib/sequel/extensions/pg_json.rb +208 -0
  150. data/lib/sequel/extensions/pg_range.rb +512 -0
  151. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  152. data/lib/sequel/extensions/pg_row.rb +572 -0
  153. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  154. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  155. data/lib/sequel/extensions/pretty_table.rb +17 -72
  156. data/lib/sequel/extensions/query.rb +8 -4
  157. data/lib/sequel/extensions/query_literals.rb +79 -0
  158. data/lib/sequel/extensions/schema_caching.rb +76 -0
  159. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  160. data/lib/sequel/extensions/select_remove.rb +39 -0
  161. data/lib/sequel/extensions/server_block.rb +140 -0
  162. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  163. data/lib/sequel/extensions/sql_expr.rb +8 -110
  164. data/lib/sequel/extensions/string_date_time.rb +4 -0
  165. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  166. data/lib/sequel/extensions/to_dot.rb +99 -83
  167. data/lib/sequel/model/associations.rb +1263 -409
  168. data/lib/sequel/model/base.rb +624 -171
  169. data/lib/sequel/model/errors.rb +1 -1
  170. data/lib/sequel/model/exceptions.rb +24 -2
  171. data/lib/sequel/model/inflections.rb +1 -1
  172. data/lib/sequel/model.rb +30 -11
  173. data/lib/sequel/no_core_ext.rb +2 -0
  174. data/lib/sequel/plugins/active_model.rb +13 -1
  175. data/lib/sequel/plugins/association_pks.rb +22 -4
  176. data/lib/sequel/plugins/caching.rb +25 -18
  177. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  178. data/lib/sequel/plugins/composition.rb +44 -12
  179. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  180. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  181. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  182. data/lib/sequel/plugins/dirty.rb +214 -0
  183. data/lib/sequel/plugins/eager_each.rb +59 -0
  184. data/lib/sequel/plugins/force_encoding.rb +6 -6
  185. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  186. data/lib/sequel/plugins/identity_map.rb +134 -15
  187. data/lib/sequel/plugins/instance_filters.rb +10 -0
  188. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  189. data/lib/sequel/plugins/json_serializer.rb +58 -6
  190. data/lib/sequel/plugins/list.rb +13 -2
  191. data/lib/sequel/plugins/many_through_many.rb +103 -51
  192. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  193. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  194. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  195. data/lib/sequel/plugins/pg_row.rb +121 -0
  196. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  197. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  198. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  199. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  200. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  201. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  202. data/lib/sequel/plugins/schema.rb +8 -3
  203. data/lib/sequel/plugins/serialization.rb +98 -49
  204. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  205. data/lib/sequel/plugins/sharding.rb +21 -54
  206. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  207. data/lib/sequel/plugins/static_cache.rb +99 -0
  208. data/lib/sequel/plugins/subclasses.rb +29 -3
  209. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  210. data/lib/sequel/plugins/timestamps.rb +1 -1
  211. data/lib/sequel/plugins/tree.rb +3 -3
  212. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  213. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  214. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  215. data/lib/sequel/plugins/validation_helpers.rb +55 -4
  216. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  217. data/lib/sequel/sql.rb +649 -122
  218. data/lib/sequel/timezones.rb +67 -40
  219. data/lib/sequel/version.rb +1 -1
  220. data/spec/adapters/db2_spec.rb +146 -0
  221. data/spec/adapters/firebird_spec.rb +1 -1
  222. data/spec/adapters/mssql_spec.rb +194 -66
  223. data/spec/adapters/mysql_spec.rb +475 -306
  224. data/spec/adapters/oracle_spec.rb +92 -117
  225. data/spec/adapters/postgres_spec.rb +1982 -325
  226. data/spec/adapters/spec_helper.rb +9 -6
  227. data/spec/adapters/sqlite_spec.rb +203 -75
  228. data/spec/core/connection_pool_spec.rb +218 -93
  229. data/spec/core/database_spec.rb +956 -522
  230. data/spec/core/dataset_spec.rb +1631 -1242
  231. data/spec/core/expression_filters_spec.rb +690 -334
  232. data/spec/core/mock_adapter_spec.rb +453 -0
  233. data/spec/core/object_graph_spec.rb +88 -129
  234. data/spec/core/schema_generator_spec.rb +4 -4
  235. data/spec/core/schema_spec.rb +556 -53
  236. data/spec/core/spec_helper.rb +7 -48
  237. data/spec/core_extensions_spec.rb +626 -0
  238. data/spec/extensions/active_model_spec.rb +13 -0
  239. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  240. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  241. data/spec/extensions/association_dependencies_spec.rb +15 -25
  242. data/spec/extensions/association_pks_spec.rb +66 -32
  243. data/spec/extensions/association_proxies_spec.rb +4 -4
  244. data/spec/extensions/boolean_readers_spec.rb +25 -25
  245. data/spec/extensions/caching_spec.rb +47 -51
  246. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  247. data/spec/extensions/columns_introspection_spec.rb +91 -0
  248. data/spec/extensions/composition_spec.rb +18 -13
  249. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  250. data/spec/extensions/constraint_validations_spec.rb +316 -0
  251. data/spec/extensions/dataset_associations_spec.rb +199 -0
  252. data/spec/extensions/defaults_setter_spec.rb +88 -0
  253. data/spec/extensions/dirty_spec.rb +155 -0
  254. data/spec/extensions/eager_each_spec.rb +34 -0
  255. data/spec/extensions/eval_inspect_spec.rb +67 -0
  256. data/spec/extensions/force_encoding_spec.rb +4 -2
  257. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  258. data/spec/extensions/identity_map_spec.rb +142 -24
  259. data/spec/extensions/inflector_spec.rb +0 -4
  260. data/spec/extensions/instance_filters_spec.rb +11 -21
  261. data/spec/extensions/instance_hooks_spec.rb +72 -0
  262. data/spec/extensions/json_serializer_spec.rb +49 -12
  263. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  264. data/spec/extensions/list_spec.rb +49 -40
  265. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  266. data/spec/extensions/many_through_many_spec.rb +368 -254
  267. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  268. data/spec/extensions/migration_spec.rb +140 -35
  269. data/spec/extensions/named_timezones_spec.rb +29 -11
  270. data/spec/extensions/nested_attributes_spec.rb +268 -89
  271. data/spec/extensions/null_dataset_spec.rb +85 -0
  272. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  273. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  274. data/spec/extensions/pg_array_spec.rb +320 -0
  275. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  276. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  277. data/spec/extensions/pg_hstore_spec.rb +194 -0
  278. data/spec/extensions/pg_inet_spec.rb +47 -0
  279. data/spec/extensions/pg_interval_spec.rb +72 -0
  280. data/spec/extensions/pg_json_spec.rb +99 -0
  281. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  282. data/spec/extensions/pg_range_spec.rb +395 -0
  283. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  284. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  285. data/spec/extensions/pg_row_spec.rb +323 -0
  286. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  287. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  288. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  289. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  290. data/spec/extensions/prepared_statements_spec.rb +87 -0
  291. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  292. data/spec/extensions/pretty_table_spec.rb +7 -6
  293. data/spec/extensions/query_literals_spec.rb +167 -0
  294. data/spec/extensions/query_spec.rb +9 -3
  295. data/spec/extensions/rcte_tree_spec.rb +50 -43
  296. data/spec/extensions/schema_caching_spec.rb +41 -0
  297. data/spec/extensions/schema_dumper_spec.rb +434 -49
  298. data/spec/extensions/schema_spec.rb +30 -49
  299. data/spec/extensions/select_remove_spec.rb +38 -0
  300. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  301. data/spec/extensions/serialization_spec.rb +86 -48
  302. data/spec/extensions/server_block_spec.rb +90 -0
  303. data/spec/extensions/sharding_spec.rb +69 -143
  304. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  305. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  306. data/spec/extensions/spec_helper.rb +34 -67
  307. data/spec/extensions/split_array_nil_spec.rb +24 -0
  308. data/spec/extensions/sql_expr_spec.rb +29 -60
  309. data/spec/extensions/static_cache_spec.rb +145 -0
  310. data/spec/extensions/subclasses_spec.rb +14 -0
  311. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  312. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  313. data/spec/extensions/timestamps_spec.rb +6 -6
  314. data/spec/extensions/to_dot_spec.rb +8 -11
  315. data/spec/extensions/touch_spec.rb +13 -14
  316. data/spec/extensions/tree_spec.rb +11 -26
  317. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  318. data/spec/extensions/update_primary_key_spec.rb +30 -24
  319. data/spec/extensions/validation_class_methods_spec.rb +58 -67
  320. data/spec/extensions/validation_helpers_spec.rb +31 -37
  321. data/spec/extensions/xml_serializer_spec.rb +29 -4
  322. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  323. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  324. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  325. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  326. data/spec/integration/associations_test.rb +659 -21
  327. data/spec/integration/database_test.rb +11 -5
  328. data/spec/integration/dataset_test.rb +717 -129
  329. data/spec/integration/eager_loader_test.rb +38 -54
  330. data/spec/integration/migrator_test.rb +2 -3
  331. data/spec/integration/model_test.rb +81 -2
  332. data/spec/integration/plugin_test.rb +604 -147
  333. data/spec/integration/prepared_statement_test.rb +272 -128
  334. data/spec/integration/schema_test.rb +367 -57
  335. data/spec/integration/spec_helper.rb +42 -32
  336. data/spec/integration/timezone_test.rb +38 -12
  337. data/spec/integration/transaction_test.rb +183 -8
  338. data/spec/integration/type_test.rb +31 -8
  339. data/spec/model/association_reflection_spec.rb +207 -8
  340. data/spec/model/associations_spec.rb +1206 -693
  341. data/spec/model/base_spec.rb +334 -100
  342. data/spec/model/dataset_methods_spec.rb +45 -27
  343. data/spec/model/eager_loading_spec.rb +828 -692
  344. data/spec/model/hooks_spec.rb +355 -67
  345. data/spec/model/model_spec.rb +251 -179
  346. data/spec/model/plugins_spec.rb +24 -13
  347. data/spec/model/record_spec.rb +506 -232
  348. data/spec/model/spec_helper.rb +16 -77
  349. data/spec/model/validations_spec.rb +38 -2
  350. data/spec/rcov.opts +2 -0
  351. metadata +209 -80
  352. data/spec/core/core_sql_spec.rb +0 -451
@@ -1,9 +1,4 @@
1
1
  require 'sqlite3'
2
- begin
3
- SQLite3::Database.instance_method(:type_translation)
4
- rescue
5
- raise(Sequel::Error, "SQLite3::Database#type_translation is not defined. If you are using the sqlite3 gem, please install the sqlite3-ruby gem.")
6
- end
7
2
  Sequel.require 'adapters/shared/sqlite'
8
3
 
9
4
  module Sequel
@@ -11,21 +6,62 @@ module Sequel
11
6
  # for Sequel.
12
7
  module SQLite
13
8
  TYPE_TRANSLATOR = tt = Class.new do
14
- FALSE_VALUES = %w'0 false f no n'.freeze
15
- def boolean(s) !FALSE_VALUES.include?(s.downcase) end
16
- def blob(s) ::Sequel::SQL::Blob.new(s) end
17
- def integer(s) s.to_i end
18
- def float(s) s.to_f end
19
- def numeric(s) ::BigDecimal.new(s) rescue s end
20
- def date(s) ::Sequel.string_to_date(s) end
21
- def time(s) ::Sequel.string_to_time(s) end
22
- def timestamp(s) ::Sequel.database_to_application_timestamp(s) end
9
+ FALSE_VALUES = (%w'0 false f no n' + [0]).freeze
10
+
11
+ def blob(s)
12
+ Sequel::SQL::Blob.new(s.to_s)
13
+ end
14
+
15
+ def boolean(s)
16
+ s = s.downcase if s.is_a?(String)
17
+ !FALSE_VALUES.include?(s)
18
+ end
19
+
20
+ def date(s)
21
+ case s
22
+ when String
23
+ Sequel.string_to_date(s)
24
+ when Integer
25
+ Date.jd(s)
26
+ when Float
27
+ Date.jd(s.to_i)
28
+ else
29
+ raise Sequel::Error, "unhandled type when converting to date: #{s.inspect} (#{s.class.inspect})"
30
+ end
31
+ end
32
+
33
+ def integer(s)
34
+ s.to_i
35
+ end
36
+
37
+ def float(s)
38
+ s.to_f
39
+ end
40
+
41
+ def numeric(s)
42
+ s = s.to_s unless s.is_a?(String)
43
+ ::BigDecimal.new(s) rescue s
44
+ end
45
+
46
+ def time(s)
47
+ case s
48
+ when String
49
+ Sequel.string_to_time(s)
50
+ when Integer
51
+ Sequel::SQLTime.create(s/3600, (s % 3600)/60, s % 60)
52
+ when Float
53
+ s, f = s.divmod(1)
54
+ Sequel::SQLTime.create(s/3600, (s % 3600)/60, s % 60, (f*1000000).round)
55
+ else
56
+ raise Sequel::Error, "unhandled type when converting to date: #{s.inspect} (#{s.class.inspect})"
57
+ end
58
+ end
59
+
23
60
  end.new
24
61
 
25
62
  # Hash with string keys and callable values for converting SQLite types.
26
63
  SQLITE_TYPES = {}
27
64
  {
28
- %w'timestamp datetime' => tt.method(:timestamp),
29
65
  %w'date' => tt.method(:date),
30
66
  %w'time' => tt.method(:time),
31
67
  %w'bit bool boolean' => tt.method(:boolean),
@@ -51,6 +87,16 @@ module Sequel
51
87
  end
52
88
 
53
89
  private_class_method :uri_to_options
90
+
91
+ # The conversion procs to use for this database
92
+ attr_reader :conversion_procs
93
+
94
+ def initialize(opts={})
95
+ super
96
+ @conversion_procs = SQLITE_TYPES.dup
97
+ @conversion_procs['datetime'] = @conversion_procs['timestamp'] = method(:to_application_timestamp)
98
+ set_integer_booleans
99
+ end
54
100
 
55
101
  # Connect to the database. Since SQLite is a file based database,
56
102
  # the only options available are :database (to specify the database
@@ -72,11 +118,6 @@ module Sequel
72
118
  db
73
119
  end
74
120
 
75
- # Return instance of Sequel::SQLite::Dataset with the given options.
76
- def dataset(opts = nil)
77
- SQLite::Dataset.new(self, opts)
78
- end
79
-
80
121
  # Run the given SQL with the given arguments and yield each row.
81
122
  def execute(sql, opts={}, &block)
82
123
  _execute(:select, sql, opts, &block)
@@ -103,11 +144,20 @@ module Sequel
103
144
  _execute(:insert, sql, opts)
104
145
  end
105
146
 
106
- # Run the given SQL with the given arguments and return the first value of the first row.
107
- def single_value(sql, opts={})
108
- _execute(:single_value, sql, opts)
147
+ # Handle Integer and Float arguments, since SQLite can store timestamps as integers and floats.
148
+ def to_application_timestamp(s)
149
+ case s
150
+ when String
151
+ super
152
+ when Integer
153
+ super(Time.at(s).to_s)
154
+ when Float
155
+ super(DateTime.jd(s).to_s)
156
+ else
157
+ raise Sequel::Error, "unhandled type when converting to : #{s.inspect} (#{s.class.inspect})"
158
+ end
109
159
  end
110
-
160
+
111
161
  private
112
162
 
113
163
  # Yield an available connection. Rescue
@@ -117,12 +167,11 @@ module Sequel
117
167
  synchronize(opts[:server]) do |conn|
118
168
  return execute_prepared_statement(conn, type, sql, opts, &block) if sql.is_a?(Symbol)
119
169
  log_args = opts[:arguments]
120
- args = opts.fetch(:arguments, [])
170
+ args = {}
171
+ opts.fetch(:arguments, {}).each{|k, v| args[k] = prepared_statement_argument(v)}
121
172
  case type
122
173
  when :select
123
174
  log_yield(sql, log_args){conn.query(sql, args, &block)}
124
- when :single_value
125
- log_yield(sql, log_args){conn.get_first_value(sql, args)}
126
175
  when :insert
127
176
  log_yield(sql, log_args){conn.execute(sql, args)}
128
177
  conn.last_insert_row_id
@@ -160,7 +209,7 @@ module Sequel
160
209
 
161
210
  # Execute a prepared statement on the database using the given name.
162
211
  def execute_prepared_statement(conn, type, name, opts, &block)
163
- ps = prepared_statements[name]
212
+ ps = prepared_statement(name)
164
213
  sql = ps.prepared_sql
165
214
  args = opts[:arguments]
166
215
  ps_args = {}
@@ -173,13 +222,19 @@ module Sequel
173
222
  end
174
223
  end
175
224
  unless cps
176
- cps = conn.prepare(sql)
225
+ cps = log_yield("PREPARE #{name}: #{sql}"){conn.prepare(sql)}
177
226
  conn.prepared_statements[name] = [cps, sql]
178
227
  end
228
+ log_sql = "EXECUTE #{name}"
229
+ if ps.log_sql
230
+ log_sql << " ("
231
+ log_sql << sql
232
+ log_sql << ")"
233
+ end
179
234
  if block
180
- log_yield("Executing prepared statement #{name}", args){cps.execute(ps_args, &block)}
235
+ log_yield(log_sql, args){cps.execute(ps_args, &block)}
181
236
  else
182
- log_yield("Executing prepared statement #{name}", args){cps.execute!(ps_args){|r|}}
237
+ log_yield(log_sql, args){cps.execute!(ps_args){|r|}}
183
238
  case type
184
239
  when :insert
185
240
  conn.last_insert_row_id
@@ -204,6 +259,8 @@ module Sequel
204
259
  # Dataset class for SQLite datasets that use the ruby-sqlite3 driver.
205
260
  class Dataset < Sequel::Dataset
206
261
  include ::Sequel::SQLite::DatasetMethods
262
+
263
+ Database::DatasetClass = self
207
264
 
208
265
  PREPARED_ARG_PLACEHOLDER = ':'.freeze
209
266
 
@@ -217,7 +274,7 @@ module Sequel
217
274
  # but with the keys converted to strings.
218
275
  def map_to_prepared_args(hash)
219
276
  args = {}
220
- hash.each{|k,v| args[k.to_s] = v}
277
+ hash.each{|k,v| args[k.to_s.gsub('.', '__')] = v}
221
278
  args
222
279
  end
223
280
 
@@ -226,7 +283,12 @@ module Sequel
226
283
  # SQLite uses a : before the name of the argument for named
227
284
  # arguments.
228
285
  def prepared_arg(k)
229
- LiteralString.new("#{prepared_arg_placeholder}#{k}")
286
+ LiteralString.new("#{prepared_arg_placeholder}#{k.to_s.gsub('.', '__')}")
287
+ end
288
+
289
+ # Always assume a prepared argument.
290
+ def prepared_arg?(k)
291
+ true
230
292
  end
231
293
  end
232
294
 
@@ -287,14 +349,15 @@ module Sequel
287
349
  def fetch_rows(sql)
288
350
  execute(sql) do |result|
289
351
  i = -1
290
- type_procs = result.types.map{|t| SQLITE_TYPES[base_type_name(t)]}
352
+ cps = db.conversion_procs
353
+ type_procs = result.types.map{|t| cps[base_type_name(t)]}
291
354
  cols = result.columns.map{|c| i+=1; [output_identifier(c), i, type_procs[i]]}
292
355
  @columns = cols.map{|c| c.first}
293
356
  result.each do |values|
294
357
  row = {}
295
358
  cols.each do |name,i,type_proc|
296
359
  v = values[i]
297
- if type_proc && v.is_a?(String)
360
+ if type_proc && v
298
361
  v = type_proc.call(v)
299
362
  end
300
363
  row[name] = v
@@ -312,9 +375,8 @@ module Sequel
312
375
  ps.extend(PreparedStatementMethods)
313
376
  if name
314
377
  ps.prepared_statement_name = name
315
- db.prepared_statements[name] = ps
378
+ db.set_prepared_statement(name, ps)
316
379
  end
317
- ps.prepared_sql
318
380
  ps
319
381
  end
320
382
 
@@ -326,8 +388,8 @@ module Sequel
326
388
  end
327
389
 
328
390
  # Quote the string using the adapter class method.
329
- def literal_string(v)
330
- "'#{::SQLite3::Database.quote(v)}'"
391
+ def literal_string_append(sql, v)
392
+ sql << "'" << ::SQLite3::Database.quote(v) << "'"
331
393
  end
332
394
 
333
395
  # SQLite uses a : before the name of the argument as a placeholder.
@@ -1,3 +1,4 @@
1
+ require 'swift/db/mysql'
1
2
  Sequel.require 'adapters/shared/mysql'
2
3
 
3
4
  module Sequel
@@ -9,11 +10,6 @@ module Sequel
9
10
  module DatabaseMethods
10
11
  include Sequel::MySQL::DatabaseMethods
11
12
 
12
- # Return instance of Sequel::Swift::MySQL::Dataset with the given opts.
13
- def dataset(opts=nil)
14
- Sequel::Swift::MySQL::Dataset.new(self, opts)
15
- end
16
-
17
13
  private
18
14
 
19
15
  # The database name for the given database.
@@ -25,22 +21,24 @@ module Sequel
25
21
  def schema_column_type(db_type)
26
22
  db_type == 'tinyint(1)' ? :boolean : super
27
23
  end
24
+
25
+ # Apply the connectiong setting SQLs for every new connection.
26
+ def setup_connection(conn)
27
+ mysql_connection_setting_sqls.each{|sql| log_yield(sql){conn.execute(sql)}}
28
+ super
29
+ end
28
30
  end
29
31
 
30
32
  # Dataset class for MySQL datasets accessed via Swift.
31
33
  class Dataset < Swift::Dataset
32
34
  include Sequel::MySQL::DatasetMethods
33
-
34
- # Use execute_insert to execute the replace_sql.
35
- def replace(*args)
36
- execute_insert(replace_sql(*args))
37
- end
35
+ APOS = Dataset::APOS
38
36
 
39
37
  private
40
38
 
41
39
  # Use Swift's escape method for quoting.
42
- def literal_string(s)
43
- db.synchronize{|c| "'#{c.escape(s)}'"}
40
+ def literal_string_append(sql, s)
41
+ sql << APOS << db.synchronize{|c| c.escape(s)} << APOS
44
42
  end
45
43
  end
46
44
  end
@@ -1,33 +1,13 @@
1
+ require 'swift/db/postgres'
1
2
  Sequel.require 'adapters/shared/postgres'
2
3
 
3
4
  module Sequel
4
- Postgres::CONVERTED_EXCEPTIONS << ::SwiftError
5
+ Postgres::CONVERTED_EXCEPTIONS << ::Swift::Error
5
6
 
6
7
  module Swift
7
8
  # Adapter, Database, and Dataset support for accessing a PostgreSQL
8
9
  # database via Swift.
9
10
  module Postgres
10
- # Methods to add to the Swift adapter/connection to allow it to work
11
- # with the shared PostgreSQL code.
12
- module AdapterMethods
13
- include Sequel::Postgres::AdapterMethods
14
-
15
- # Log all SQL that goes through the execute method to the related
16
- # database object.
17
- def execute(sql, *args)
18
- @db.log_yield(sql){super}
19
- rescue SwiftError => e
20
- @db.send(:raise_error, e)
21
- end
22
-
23
- private
24
-
25
- # Swift specific method of getting specific values from a result set.
26
- def single_value(row)
27
- row.values.at(0)
28
- end
29
- end
30
-
31
11
  # Methods to add to Database instances that access PostgreSQL via Swift.
32
12
  module DatabaseMethods
33
13
  include Sequel::Postgres::DatabaseMethods
@@ -35,75 +15,29 @@ module Sequel
35
15
  # Add the primary_keys and primary_key_sequences instance variables,
36
16
  # so we can get the correct return values for inserted rows.
37
17
  def self.extended(db)
38
- db.instance_eval do
39
- @primary_keys = {}
40
- @primary_key_sequences = {}
41
- end
42
- end
43
-
44
- # Return instance of Sequel::Swift::Postgres::Dataset with the given opts.
45
- def dataset(opts=nil)
46
- Sequel::Swift::Postgres::Dataset.new(self, opts)
47
- end
48
-
49
- # Run the SELECT SQL on the database and yield the rows
50
- def execute(sql, opts={})
51
- synchronize(opts[:server]) do |conn|
52
- begin
53
- res = conn.execute(sql)
54
- yield res if block_given?
55
- nil
56
- rescue SwiftError => e
57
- raise_error(e)
58
- end
59
- end
60
- end
61
-
62
- # Run the DELETE/UPDATE SQL on the database and return the number
63
- # of matched rows.
64
- def execute_dui(sql, opts={})
65
- synchronize(opts[:server]) do |conn|
66
- begin
67
- conn.execute(sql).rows
68
- rescue SwiftError => e
69
- raise_error(e)
70
- end
71
- end
72
- end
73
-
74
- # Run the INSERT SQL on the database and return the primary key
75
- # for the record.
76
- def execute_insert(sql, opts={})
77
- synchronize(opts[:server]) do |conn|
78
- begin
79
- conn.execute(sql)
80
- insert_result(conn, opts[:table], opts[:values])
81
- rescue SwiftError => e
82
- raise_error(e)
83
- end
84
- end
18
+ db.send(:initialize_postgres_adapter)
85
19
  end
86
20
 
87
21
  private
88
22
 
89
- # Execute SQL on the connection.
90
- def log_connection_execute(conn, sql)
91
- conn.execute(sql)
23
+ # Remove all other options except for ones specifically handled, as
24
+ # otherwise swift passes them to dbic++ which passes them to PostgreSQL
25
+ # which can raise an error.
26
+ def server_opts(o)
27
+ o = super
28
+ so = {}
29
+ [:db, :user, :password, :host, :port].each{|s| so[s] = o[s] if o.has_key?(s)}
30
+ so
92
31
  end
93
32
 
94
33
  # Extend the adapter with the Swift PostgreSQL AdapterMethods.
95
34
  def setup_connection(conn)
96
35
  conn = super(conn)
97
- conn.extend(Sequel::Swift::Postgres::AdapterMethods)
98
- conn.db = self
99
- conn.apply_connection_settings
36
+ conn.native_bind_format = true
37
+ connection_configuration_sqls.each{|sql| log_yield(sql){conn.execute(sql)}}
100
38
  conn
101
39
  end
102
40
  end
103
-
104
- class Dataset < Swift::Dataset
105
- include Sequel::Postgres::DatasetMethods
106
- end
107
41
  end
108
42
  end
109
43
  end
@@ -1,3 +1,4 @@
1
+ require 'swift/db/sqlite3'
1
2
  Sequel.require 'adapters/shared/sqlite'
2
3
 
3
4
  module Sequel
@@ -8,10 +9,12 @@ module Sequel
8
9
  # Database instance methods for SQLite databases accessed via Swift.
9
10
  module DatabaseMethods
10
11
  include Sequel::SQLite::DatabaseMethods
11
-
12
- # Return instance of Sequel::Swift::SQL::Dataset with the given opts.
13
- def dataset(opts=nil)
14
- Sequel::Swift::SQLite::Dataset.new(self, opts)
12
+
13
+ # Set the correct pragmas on the connection.
14
+ def connect(opts)
15
+ c = super
16
+ connection_pragmas.each{|s| log_yield(s){c.execute(s)}}
17
+ c
15
18
  end
16
19
  end
17
20
 
@@ -22,8 +25,8 @@ module Sequel
22
25
  private
23
26
 
24
27
  # Use Swift's escape method for quoting.
25
- def literal_string(s)
26
- db.synchronize{|c| "#{c.escape(s)}"}
28
+ def literal_string_append(sql, s)
29
+ sql << APOS << db.synchronize{|c| c.escape(s)} << APOS
27
30
  end
28
31
  end
29
32
  end
@@ -1,11 +1,8 @@
1
- require 'swift'
2
-
3
1
  module Sequel
4
- # Module holding the Swift support for Sequel. Swift is a
5
- # ruby front-end for dbic++, a fast database access library
6
- # written in C++.
2
+ # Module holding the Swift DB support for Sequel. Swift DB is a
3
+ # collection of drivers used in Swift ORM.
7
4
  #
8
- # The Swift adapter currently supports PostgreSQL and MySQL:
5
+ # The Swift adapter currently supports PostgreSQL, MySQL and SQLite3
9
6
  #
10
7
  # Sequel.connect('swift://user:password@host/database?db_type=postgres')
11
8
  # Sequel.connect('swift://user:password@host/database?db_type=mysql')
@@ -15,17 +12,21 @@ module Sequel
15
12
  DATABASE_SETUP = {:postgres=>proc do |db|
16
13
  Sequel.ts_require 'adapters/swift/postgres'
17
14
  db.extend(Sequel::Swift::Postgres::DatabaseMethods)
15
+ db.extend_datasets Sequel::Postgres::DatasetMethods
18
16
  db.swift_class = ::Swift::DB::Postgres
19
17
  end,
20
18
  :mysql=>proc do |db|
21
19
  Sequel.ts_require 'adapters/swift/mysql'
22
20
  db.extend(Sequel::Swift::MySQL::DatabaseMethods)
21
+ db.dataset_class = Sequel::Swift::MySQL::Dataset
23
22
  db.swift_class = ::Swift::DB::Mysql
24
23
  end,
25
24
  :sqlite=>proc do |db|
26
25
  Sequel.ts_require 'adapters/swift/sqlite'
27
26
  db.extend(Sequel::Swift::SQLite::DatabaseMethods)
27
+ db.dataset_class = Sequel::Swift::SQLite::Dataset
28
28
  db.swift_class = ::Swift::DB::Sqlite3
29
+ db.set_integer_booleans
29
30
  end,
30
31
  }
31
32
 
@@ -56,14 +57,11 @@ module Sequel
56
57
 
57
58
  # Create an instance of swift_class for the given options.
58
59
  def connect(server)
59
- setup_connection(swift_class.new(server_opts(server)))
60
+ opts = server_opts(server)
61
+ opts[:pass] = opts[:password]
62
+ setup_connection(swift_class.new(opts))
60
63
  end
61
64
 
62
- # Return a Sequel::Swift::Dataset object for this database.
63
- def dataset(opts = nil)
64
- Swift::Dataset.new(self, opts)
65
- end
66
-
67
65
  # Execute the given SQL, yielding a Swift::Result if a block is given.
68
66
  def execute(sql, opts={})
69
67
  synchronize(opts[:server]) do |conn|
@@ -71,7 +69,7 @@ module Sequel
71
69
  res = log_yield(sql){conn.execute(sql)}
72
70
  yield res if block_given?
73
71
  nil
74
- rescue SwiftError => e
72
+ rescue ::Swift::Error => e
75
73
  raise_error(e)
76
74
  end
77
75
  end
@@ -82,8 +80,8 @@ module Sequel
82
80
  def execute_dui(sql, opts={})
83
81
  synchronize(opts[:server]) do |conn|
84
82
  begin
85
- log_yield(sql){conn.execute(sql).rows}
86
- rescue SwiftError => e
83
+ log_yield(sql){conn.execute(sql).affected_rows}
84
+ rescue ::Swift::Error => e
87
85
  raise_error(e)
88
86
  end
89
87
  end
@@ -95,7 +93,7 @@ module Sequel
95
93
  synchronize(opts[:server]) do |conn|
96
94
  begin
97
95
  log_yield(sql){conn.execute(sql).insert_id}
98
- rescue SwiftError => e
96
+ rescue ::Swift::Error => e
99
97
  raise_error(e)
100
98
  end
101
99
  end
@@ -134,11 +132,22 @@ module Sequel
134
132
  end
135
133
 
136
134
  class Dataset < Sequel::Dataset
135
+ Database::DatasetClass = self
136
+
137
137
  # Set the columns and yield the hashes to the block.
138
- def fetch_rows(sql, &block)
138
+ def fetch_rows(sql)
139
139
  execute(sql) do |res|
140
- @columns = res.fields
141
- res.each(&block)
140
+ col_map = {}
141
+ @columns = res.fields.map do |c|
142
+ col_map[c] = output_identifier(c)
143
+ end
144
+ res.each do |r|
145
+ h = {}
146
+ r.each do |k, v|
147
+ h[col_map[k]] = v.is_a?(StringIO) ? SQL::Blob.new(v.read) : v
148
+ end
149
+ yield h
150
+ end
142
151
  end
143
152
  self
144
153
  end