sequel 3.21.0 → 3.41.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 (363) hide show
  1. data/CHANGELOG +1131 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +106 -65
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +68 -52
  7. data/doc/advanced_associations.rdoc +201 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/bin_sequel.rdoc +144 -0
  10. data/doc/cheat_sheet.rdoc +21 -21
  11. data/doc/core_extensions.rdoc +374 -0
  12. data/doc/dataset_basics.rdoc +10 -10
  13. data/doc/dataset_filtering.rdoc +54 -42
  14. data/doc/mass_assignment.rdoc +56 -0
  15. data/doc/migration.rdoc +89 -557
  16. data/doc/model_hooks.rdoc +80 -29
  17. data/doc/object_model.rdoc +576 -0
  18. data/doc/opening_databases.rdoc +121 -53
  19. data/doc/prepared_statements.rdoc +41 -15
  20. data/doc/querying.rdoc +137 -56
  21. data/doc/reflection.rdoc +36 -10
  22. data/doc/release_notes/3.22.0.txt +39 -0
  23. data/doc/release_notes/3.23.0.txt +172 -0
  24. data/doc/release_notes/3.24.0.txt +420 -0
  25. data/doc/release_notes/3.25.0.txt +88 -0
  26. data/doc/release_notes/3.26.0.txt +88 -0
  27. data/doc/release_notes/3.27.0.txt +82 -0
  28. data/doc/release_notes/3.28.0.txt +304 -0
  29. data/doc/release_notes/3.29.0.txt +459 -0
  30. data/doc/release_notes/3.30.0.txt +135 -0
  31. data/doc/release_notes/3.31.0.txt +146 -0
  32. data/doc/release_notes/3.32.0.txt +202 -0
  33. data/doc/release_notes/3.33.0.txt +157 -0
  34. data/doc/release_notes/3.34.0.txt +671 -0
  35. data/doc/release_notes/3.35.0.txt +144 -0
  36. data/doc/release_notes/3.36.0.txt +245 -0
  37. data/doc/release_notes/3.37.0.txt +338 -0
  38. data/doc/release_notes/3.38.0.txt +234 -0
  39. data/doc/release_notes/3.39.0.txt +237 -0
  40. data/doc/release_notes/3.40.0.txt +73 -0
  41. data/doc/release_notes/3.41.0.txt +155 -0
  42. data/doc/schema_modification.rdoc +585 -0
  43. data/doc/sharding.rdoc +99 -8
  44. data/doc/sql.rdoc +154 -112
  45. data/doc/testing.rdoc +169 -0
  46. data/doc/thread_safety.rdoc +17 -0
  47. data/doc/transactions.rdoc +137 -0
  48. data/doc/validations.rdoc +1 -1
  49. data/doc/virtual_rows.rdoc +78 -43
  50. data/lib/sequel/adapters/ado/access.rb +334 -0
  51. data/lib/sequel/adapters/ado/mssql.rb +18 -12
  52. data/lib/sequel/adapters/ado.rb +69 -21
  53. data/lib/sequel/adapters/amalgalite.rb +17 -14
  54. data/lib/sequel/adapters/cubrid.rb +143 -0
  55. data/lib/sequel/adapters/db2.rb +178 -85
  56. data/lib/sequel/adapters/dbi.rb +19 -21
  57. data/lib/sequel/adapters/do/mysql.rb +17 -11
  58. data/lib/sequel/adapters/do/postgres.rb +2 -61
  59. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  60. data/lib/sequel/adapters/do.rb +20 -39
  61. data/lib/sequel/adapters/firebird.rb +33 -210
  62. data/lib/sequel/adapters/ibmdb.rb +452 -0
  63. data/lib/sequel/adapters/informix.rb +6 -29
  64. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  65. data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
  66. data/lib/sequel/adapters/jdbc/db2.rb +78 -0
  67. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  68. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  69. data/lib/sequel/adapters/jdbc/h2.rb +68 -31
  70. data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
  71. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  73. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  74. data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
  75. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  76. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  77. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  78. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  79. data/lib/sequel/adapters/jdbc/sqlserver.rb +72 -0
  80. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  81. data/lib/sequel/adapters/jdbc.rb +308 -114
  82. data/lib/sequel/adapters/mock.rb +372 -0
  83. data/lib/sequel/adapters/mysql.rb +130 -230
  84. data/lib/sequel/adapters/mysql2.rb +64 -63
  85. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  86. data/lib/sequel/adapters/odbc.rb +29 -10
  87. data/lib/sequel/adapters/openbase.rb +7 -11
  88. data/lib/sequel/adapters/oracle.rb +364 -57
  89. data/lib/sequel/adapters/postgres.rb +379 -145
  90. data/lib/sequel/adapters/shared/access.rb +236 -11
  91. data/lib/sequel/adapters/shared/cubrid.rb +216 -0
  92. data/lib/sequel/adapters/shared/db2.rb +353 -0
  93. data/lib/sequel/adapters/shared/firebird.rb +231 -0
  94. data/lib/sequel/adapters/shared/informix.rb +53 -0
  95. data/lib/sequel/adapters/shared/mssql.rb +412 -116
  96. data/lib/sequel/adapters/shared/mysql.rb +396 -89
  97. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
  98. data/lib/sequel/adapters/shared/oracle.rb +262 -45
  99. data/lib/sequel/adapters/shared/postgres.rb +688 -279
  100. data/lib/sequel/adapters/shared/progress.rb +5 -8
  101. data/lib/sequel/adapters/shared/sqlite.rb +317 -96
  102. data/lib/sequel/adapters/sqlite.rb +109 -46
  103. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  104. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  105. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  106. data/lib/sequel/adapters/swift.rb +31 -27
  107. data/lib/sequel/adapters/tinytds.rb +177 -25
  108. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  109. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  110. data/lib/sequel/adapters/utils/split_alter_table.rb +36 -0
  111. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  112. data/lib/sequel/ast_transformer.rb +194 -0
  113. data/lib/sequel/connection_pool/sharded_single.rb +23 -13
  114. data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
  115. data/lib/sequel/connection_pool/single.rb +11 -3
  116. data/lib/sequel/connection_pool/threaded.rb +69 -20
  117. data/lib/sequel/connection_pool.rb +20 -18
  118. data/lib/sequel/core.rb +143 -11
  119. data/lib/sequel/database/connecting.rb +66 -29
  120. data/lib/sequel/database/dataset.rb +4 -4
  121. data/lib/sequel/database/dataset_defaults.rb +63 -2
  122. data/lib/sequel/database/logging.rb +7 -2
  123. data/lib/sequel/database/misc.rb +192 -51
  124. data/lib/sequel/database/query.rb +299 -114
  125. data/lib/sequel/database/schema_generator.rb +103 -36
  126. data/lib/sequel/database/schema_methods.rb +310 -69
  127. data/lib/sequel/dataset/actions.rb +344 -90
  128. data/lib/sequel/dataset/features.rb +101 -8
  129. data/lib/sequel/dataset/graph.rb +42 -15
  130. data/lib/sequel/dataset/misc.rb +52 -25
  131. data/lib/sequel/dataset/mutation.rb +12 -7
  132. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  133. data/lib/sequel/dataset/query.rb +322 -68
  134. data/lib/sequel/dataset/sql.rb +716 -293
  135. data/lib/sequel/dataset.rb +8 -0
  136. data/lib/sequel/exceptions.rb +4 -0
  137. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  138. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  139. data/lib/sequel/extensions/blank.rb +4 -0
  140. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  141. data/lib/sequel/extensions/connection_validator.rb +109 -0
  142. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  143. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  144. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  145. data/lib/sequel/extensions/inflector.rb +4 -0
  146. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  147. data/lib/sequel/extensions/migration.rb +100 -11
  148. data/lib/sequel/extensions/named_timezones.rb +9 -0
  149. data/lib/sequel/extensions/null_dataset.rb +94 -0
  150. data/lib/sequel/extensions/pagination.rb +4 -0
  151. data/lib/sequel/extensions/pg_array.rb +539 -0
  152. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  153. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  154. data/lib/sequel/extensions/pg_hstore.rb +334 -0
  155. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  156. data/lib/sequel/extensions/pg_inet.rb +113 -0
  157. data/lib/sequel/extensions/pg_interval.rb +191 -0
  158. data/lib/sequel/extensions/pg_json.rb +212 -0
  159. data/lib/sequel/extensions/pg_range.rb +513 -0
  160. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  161. data/lib/sequel/extensions/pg_row.rb +576 -0
  162. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  163. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  164. data/lib/sequel/extensions/pretty_table.rb +17 -72
  165. data/lib/sequel/extensions/query.rb +8 -4
  166. data/lib/sequel/extensions/query_literals.rb +79 -0
  167. data/lib/sequel/extensions/schema_caching.rb +76 -0
  168. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  169. data/lib/sequel/extensions/select_remove.rb +39 -0
  170. data/lib/sequel/extensions/server_block.rb +140 -0
  171. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  172. data/lib/sequel/extensions/sql_expr.rb +8 -110
  173. data/lib/sequel/extensions/string_date_time.rb +4 -0
  174. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  175. data/lib/sequel/extensions/to_dot.rb +99 -83
  176. data/lib/sequel/model/associations.rb +1263 -409
  177. data/lib/sequel/model/base.rb +624 -171
  178. data/lib/sequel/model/errors.rb +1 -1
  179. data/lib/sequel/model/exceptions.rb +24 -2
  180. data/lib/sequel/model/inflections.rb +1 -1
  181. data/lib/sequel/model.rb +30 -11
  182. data/lib/sequel/no_core_ext.rb +2 -0
  183. data/lib/sequel/plugins/active_model.rb +13 -1
  184. data/lib/sequel/plugins/association_pks.rb +137 -16
  185. data/lib/sequel/plugins/caching.rb +25 -18
  186. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  187. data/lib/sequel/plugins/composition.rb +44 -12
  188. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  189. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  190. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  191. data/lib/sequel/plugins/dirty.rb +214 -0
  192. data/lib/sequel/plugins/eager_each.rb +59 -0
  193. data/lib/sequel/plugins/force_encoding.rb +6 -6
  194. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  195. data/lib/sequel/plugins/identity_map.rb +134 -15
  196. data/lib/sequel/plugins/instance_filters.rb +10 -0
  197. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  198. data/lib/sequel/plugins/json_serializer.rb +77 -6
  199. data/lib/sequel/plugins/list.rb +13 -2
  200. data/lib/sequel/plugins/many_through_many.rb +103 -51
  201. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  202. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  203. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  204. data/lib/sequel/plugins/pg_row.rb +121 -0
  205. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  206. data/lib/sequel/plugins/prepared_statements.rb +168 -0
  207. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  208. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  209. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  210. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  211. data/lib/sequel/plugins/schema.rb +8 -3
  212. data/lib/sequel/plugins/serialization.rb +98 -49
  213. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  214. data/lib/sequel/plugins/sharding.rb +21 -54
  215. data/lib/sequel/plugins/single_table_inheritance.rb +57 -12
  216. data/lib/sequel/plugins/static_cache.rb +99 -0
  217. data/lib/sequel/plugins/subclasses.rb +29 -3
  218. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  219. data/lib/sequel/plugins/timestamps.rb +1 -1
  220. data/lib/sequel/plugins/touch.rb +18 -6
  221. data/lib/sequel/plugins/tree.rb +3 -3
  222. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  223. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  224. data/lib/sequel/plugins/validation_class_methods.rb +2 -1
  225. data/lib/sequel/plugins/validation_helpers.rb +57 -4
  226. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  227. data/lib/sequel/sql.rb +721 -141
  228. data/lib/sequel/timezones.rb +67 -40
  229. data/lib/sequel/version.rb +1 -1
  230. data/spec/adapters/db2_spec.rb +146 -0
  231. data/spec/adapters/firebird_spec.rb +53 -39
  232. data/spec/adapters/mssql_spec.rb +261 -66
  233. data/spec/adapters/mysql_spec.rb +597 -352
  234. data/spec/adapters/oracle_spec.rb +92 -117
  235. data/spec/adapters/postgres_spec.rb +2103 -341
  236. data/spec/adapters/spec_helper.rb +16 -6
  237. data/spec/adapters/sqlite_spec.rb +237 -76
  238. data/spec/core/connection_pool_spec.rb +270 -141
  239. data/spec/core/database_spec.rb +980 -524
  240. data/spec/core/dataset_spec.rb +1658 -1243
  241. data/spec/core/expression_filters_spec.rb +741 -334
  242. data/spec/core/mock_adapter_spec.rb +453 -0
  243. data/spec/core/object_graph_spec.rb +88 -129
  244. data/spec/core/schema_generator_spec.rb +4 -4
  245. data/spec/core/schema_spec.rb +556 -53
  246. data/spec/core/spec_helper.rb +7 -48
  247. data/spec/core_extensions_spec.rb +626 -0
  248. data/spec/extensions/active_model_spec.rb +13 -0
  249. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  250. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  251. data/spec/extensions/association_dependencies_spec.rb +15 -25
  252. data/spec/extensions/association_pks_spec.rb +227 -33
  253. data/spec/extensions/association_proxies_spec.rb +4 -4
  254. data/spec/extensions/boolean_readers_spec.rb +25 -25
  255. data/spec/extensions/caching_spec.rb +47 -51
  256. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  257. data/spec/extensions/columns_introspection_spec.rb +91 -0
  258. data/spec/extensions/composition_spec.rb +18 -13
  259. data/spec/extensions/connection_validator_spec.rb +118 -0
  260. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  261. data/spec/extensions/constraint_validations_spec.rb +316 -0
  262. data/spec/extensions/dataset_associations_spec.rb +199 -0
  263. data/spec/extensions/defaults_setter_spec.rb +88 -0
  264. data/spec/extensions/dirty_spec.rb +155 -0
  265. data/spec/extensions/eager_each_spec.rb +34 -0
  266. data/spec/extensions/eval_inspect_spec.rb +67 -0
  267. data/spec/extensions/force_encoding_spec.rb +4 -2
  268. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  269. data/spec/extensions/identity_map_spec.rb +142 -24
  270. data/spec/extensions/inflector_spec.rb +0 -4
  271. data/spec/extensions/instance_filters_spec.rb +11 -21
  272. data/spec/extensions/instance_hooks_spec.rb +72 -0
  273. data/spec/extensions/json_serializer_spec.rb +49 -12
  274. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  275. data/spec/extensions/list_spec.rb +49 -40
  276. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  277. data/spec/extensions/many_through_many_spec.rb +368 -254
  278. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  279. data/spec/extensions/migration_spec.rb +140 -35
  280. data/spec/extensions/named_timezones_spec.rb +29 -11
  281. data/spec/extensions/nested_attributes_spec.rb +268 -89
  282. data/spec/extensions/null_dataset_spec.rb +85 -0
  283. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  284. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  285. data/spec/extensions/pg_array_spec.rb +324 -0
  286. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  287. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  288. data/spec/extensions/pg_hstore_spec.rb +200 -0
  289. data/spec/extensions/pg_inet_spec.rb +47 -0
  290. data/spec/extensions/pg_interval_spec.rb +72 -0
  291. data/spec/extensions/pg_json_spec.rb +99 -0
  292. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  293. data/spec/extensions/pg_range_spec.rb +395 -0
  294. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  295. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  296. data/spec/extensions/pg_row_spec.rb +340 -0
  297. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  298. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  299. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  300. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  301. data/spec/extensions/prepared_statements_spec.rb +87 -0
  302. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  303. data/spec/extensions/pretty_table_spec.rb +7 -6
  304. data/spec/extensions/query_literals_spec.rb +167 -0
  305. data/spec/extensions/query_spec.rb +9 -3
  306. data/spec/extensions/rcte_tree_spec.rb +50 -43
  307. data/spec/extensions/schema_caching_spec.rb +41 -0
  308. data/spec/extensions/schema_dumper_spec.rb +434 -49
  309. data/spec/extensions/schema_spec.rb +30 -49
  310. data/spec/extensions/select_remove_spec.rb +38 -0
  311. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  312. data/spec/extensions/serialization_spec.rb +86 -48
  313. data/spec/extensions/server_block_spec.rb +90 -0
  314. data/spec/extensions/sharding_spec.rb +69 -143
  315. data/spec/extensions/single_table_inheritance_spec.rb +65 -29
  316. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  317. data/spec/extensions/spec_helper.rb +34 -67
  318. data/spec/extensions/split_array_nil_spec.rb +24 -0
  319. data/spec/extensions/sql_expr_spec.rb +29 -60
  320. data/spec/extensions/static_cache_spec.rb +145 -0
  321. data/spec/extensions/subclasses_spec.rb +14 -0
  322. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  323. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  324. data/spec/extensions/timestamps_spec.rb +6 -6
  325. data/spec/extensions/to_dot_spec.rb +8 -11
  326. data/spec/extensions/touch_spec.rb +53 -14
  327. data/spec/extensions/tree_spec.rb +11 -26
  328. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  329. data/spec/extensions/update_primary_key_spec.rb +30 -24
  330. data/spec/extensions/validation_class_methods_spec.rb +77 -68
  331. data/spec/extensions/validation_helpers_spec.rb +48 -37
  332. data/spec/extensions/xml_serializer_spec.rb +29 -4
  333. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  334. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  335. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  336. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  337. data/spec/integration/associations_test.rb +659 -21
  338. data/spec/integration/database_test.rb +25 -5
  339. data/spec/integration/dataset_test.rb +729 -141
  340. data/spec/integration/eager_loader_test.rb +38 -54
  341. data/spec/integration/migrator_test.rb +2 -3
  342. data/spec/integration/model_test.rb +81 -2
  343. data/spec/integration/plugin_test.rb +871 -160
  344. data/spec/integration/prepared_statement_test.rb +272 -128
  345. data/spec/integration/schema_test.rb +377 -57
  346. data/spec/integration/spec_helper.rb +49 -32
  347. data/spec/integration/timezone_test.rb +38 -12
  348. data/spec/integration/transaction_test.rb +183 -8
  349. data/spec/integration/type_test.rb +40 -8
  350. data/spec/model/association_reflection_spec.rb +207 -8
  351. data/spec/model/associations_spec.rb +1206 -693
  352. data/spec/model/base_spec.rb +334 -100
  353. data/spec/model/dataset_methods_spec.rb +45 -27
  354. data/spec/model/eager_loading_spec.rb +828 -692
  355. data/spec/model/hooks_spec.rb +355 -67
  356. data/spec/model/model_spec.rb +251 -179
  357. data/spec/model/plugins_spec.rb +24 -13
  358. data/spec/model/record_spec.rb +506 -232
  359. data/spec/model/spec_helper.rb +16 -77
  360. data/spec/model/validations_spec.rb +38 -2
  361. data/spec/rcov.opts +2 -0
  362. metadata +223 -81
  363. data/spec/core/core_sql_spec.rb +0 -451
@@ -17,16 +17,20 @@ module Sequel
17
17
  Sequel.tsk_require 'do_postgres'
18
18
  Sequel.ts_require 'adapters/do/postgres'
19
19
  db.extend(Sequel::DataObjects::Postgres::DatabaseMethods)
20
+ db.extend_datasets Sequel::Postgres::DatasetMethods
20
21
  end,
21
22
  :mysql=>proc do |db|
22
23
  Sequel.tsk_require 'do_mysql'
23
24
  Sequel.ts_require 'adapters/do/mysql'
24
25
  db.extend(Sequel::DataObjects::MySQL::DatabaseMethods)
26
+ db.dataset_class = Sequel::DataObjects::MySQL::Dataset
25
27
  end,
26
28
  :sqlite3=>proc do |db|
27
29
  Sequel.tsk_require 'do_sqlite3'
28
30
  Sequel.ts_require 'adapters/do/sqlite'
29
31
  db.extend(Sequel::DataObjects::SQLite::DatabaseMethods)
32
+ db.extend_datasets Sequel::SQLite::DatasetMethods
33
+ db.set_integer_booleans
30
34
  end
31
35
  }
32
36
 
@@ -36,6 +40,8 @@ module Sequel
36
40
  # Sequel::DataObjects::Database object, or hack DataObjects (or Extlib) to
37
41
  # use a pool size at least as large as the pool size being used by Sequel.
38
42
  class Database < Sequel::Database
43
+ DISCONNECT_ERROR_RE = /terminating connection due to administrator command/
44
+
39
45
  set_adapter_scheme :do
40
46
 
41
47
  # Call the DATABASE_SETUP proc directly after initialization,
@@ -54,12 +60,11 @@ module Sequel
54
60
  def connect(server)
55
61
  setup_connection(::DataObjects::Connection.new(uri(server_opts(server))))
56
62
  end
57
-
58
- # Return a Sequel::DataObjects::Dataset object for this database.
59
- def dataset(opts = nil)
60
- DataObjects::Dataset.new(self, opts)
63
+
64
+ def disconnect_connection(conn)
65
+ conn.dispose
61
66
  end
62
-
67
+
63
68
  # Execute the given SQL. If a block is given, the DataObjects::Reader
64
69
  # created is yielded to it. A block should not be provided unless a
65
70
  # a SELECT statement is being used (or something else that returns rows).
@@ -114,40 +119,20 @@ module Sequel
114
119
 
115
120
  private
116
121
 
117
- # DataObjects uses a special transaction object to keep track of
118
- # transactions. Unfortunately, it tries to create a new connection
119
- # to do a transaction. So we close the connection created and
120
- # substitute our own.
121
- def begin_transaction(conn, opts={})
122
- return super if supports_savepoints?
123
- log_yield(TRANSACTION_BEGIN) do
124
- t = ::DataObjects::Transaction.create_for_uri(uri)
125
- t.instance_variable_get(:@connection).close
126
- t.instance_variable_set(:@connection, conn)
127
- t.begin
128
- t
129
- end
130
- end
131
-
132
- # DataObjects requires transactions be prepared before being
133
- # committed, so we do that.
134
- def commit_transaction(t, opts={})
135
- return super if supports_savepoints?
136
- log_yield(TRANSACTION_ROLLBACK) do
137
- t.prepare
138
- t.commit
139
- end
140
- end
141
-
142
122
  # Method to call on a statement object to execute SQL that does
143
123
  # not return any rows.
144
124
  def connection_execute_method
145
125
  :execute_non_query
146
126
  end
147
127
 
148
- # Close the given database connection.
149
- def disconnect_connection(c)
150
- c.close
128
+ # dataobjects uses the DataObjects::Error class as the main error class.
129
+ def database_error_classes
130
+ [::DataObjects::Error]
131
+ end
132
+
133
+ # Recognize DataObjects::ConnectionError instances as disconnect errors.
134
+ def disconnect_error?(e, opts)
135
+ super || (e.is_a?(::DataObjects::Error) && (e.is_a?(::DataObjects::ConnectionError) || e.message =~ DISCONNECT_ERROR_RE))
151
136
  end
152
137
 
153
138
  # Execute SQL on the connection by creating a command first
@@ -155,12 +140,6 @@ module Sequel
155
140
  log_yield(sql){conn.create_command(sql).execute_non_query}
156
141
  end
157
142
 
158
- # We use the transactions rollback method to rollback.
159
- def rollback_transaction(t, opts={})
160
- return super if supports_savepoints?
161
- log_yield(TRANSACTION_COMMIT){t.rollback}
162
- end
163
-
164
143
  # Allow extending the given connection when it is first created.
165
144
  # By default, just returns the connection.
166
145
  def setup_connection(conn)
@@ -170,6 +149,8 @@ module Sequel
170
149
 
171
150
  # Dataset class for Sequel::DataObjects::Database objects.
172
151
  class Dataset < Sequel::Dataset
152
+ Database::DatasetClass = self
153
+
173
154
  # Execute the SQL on the database and yield the rows as hashes
174
155
  # with symbol keys.
175
156
  def fetch_rows(sql)
@@ -1,213 +1,98 @@
1
1
  require 'fb'
2
+ Sequel.require 'adapters/shared/firebird'
2
3
 
3
4
  module Sequel
4
5
  # The Sequel Firebird adapter requires the ruby fb driver located at
5
6
  # http://github.com/wishdev/fb.
6
7
  module Firebird
7
8
  class Database < Sequel::Database
9
+ include Sequel::Firebird::DatabaseMethods
10
+
8
11
  set_adapter_scheme :firebird
9
12
 
10
- AUTO_INCREMENT = ''.freeze
11
- TEMPORARY = 'GLOBAL TEMPORARY '.freeze
13
+ DISCONNECT_ERRORS = /Unsuccessful execution caused by a system error that precludes successful execution of subsequent statements/
12
14
 
13
- # Add the primary_keys and primary_key_sequences instance variables,
15
+ # Add the primary_keys instance variables.
14
16
  # so we can get the correct return values for inserted rows.
15
17
  def initialize(*args)
16
18
  super
17
19
  @primary_keys = {}
18
- @primary_key_sequences = {}
19
20
  end
20
21
 
21
22
  def connect(server)
22
23
  opts = server_opts(server)
23
24
 
24
- db = Fb::Database.new(
25
+ Fb::Database.new(
25
26
  :database => "#{opts[:host]}:#{opts[:database]}",
26
27
  :username => opts[:user],
27
- :password => opts[:password])
28
- conn = db.connect
29
- conn.downcase_names = true
30
- conn
31
- end
32
-
33
- def create_trigger(*args)
34
- self << create_trigger_sql(*args)
35
- end
36
-
37
- def dataset(opts = nil)
38
- Firebird::Dataset.new(self, opts)
28
+ :password => opts[:password]).connect
39
29
  end
40
30
 
41
- def drop_sequence(name)
42
- self << drop_sequence_sql(name)
31
+ def disconnect_connection(conn)
32
+ begin
33
+ conn.close
34
+ rescue Fb::Error
35
+ nil
36
+ end
43
37
  end
44
38
 
45
39
  def execute(sql, opts={})
46
40
  begin
47
41
  synchronize(opts[:server]) do |conn|
42
+ if conn.transaction_started && !_trans(conn)
43
+ conn.rollback
44
+ raise DatabaseDisconnectError, "transaction accidently left open, rolling back and disconnecting"
45
+ end
48
46
  r = log_yield(sql){conn.execute(sql)}
49
47
  yield(r) if block_given?
50
48
  r
51
49
  end
52
- rescue => e
53
- raise_error(e, :classes=>[Fb::Error])
50
+ rescue Fb::Error => e
51
+ raise_error(e, :disconnect=>DISCONNECT_ERRORS.match(e.message))
54
52
  end
55
53
  end
56
54
 
57
- # Return primary key for the given table.
58
- def primary_key(table, server=nil)
59
- synchronize(server){|conn| primary_key_for_table(conn, table)}
60
- end
61
-
62
- # Returns primary key for the given table. This information is
63
- # cached, and if the primary key for a table is changed, the
64
- # @primary_keys instance variable should be reset manually.
65
- def primary_key_for_table(conn, table)
66
- @primary_keys[quote_identifier(table)] ||= conn.table_primary_key(quote_identifier(table))
67
- end
68
-
69
- def restart_sequence(*args)
70
- self << restart_sequence_sql(*args)
71
- end
72
-
73
- def sequences(opts={})
74
- ds = self[:"rdb$generators"].server(opts[:server]).filter(:"rdb$system_flag" => 0).select(:"rdb$generator_name")
75
- block_given? ? yield(ds) : ds.map{|r| ds.send(:output_identifier, r[:"rdb$generator_name"])}
76
- end
77
-
78
- def tables(opts={})
79
- ds = self[:"rdb$relations"].server(opts[:server]).filter(:"rdb$view_blr" => nil, Sequel::SQL::Function.new(:COALESCE, :"rdb$system_flag", 0) => 0).select(:"rdb$relation_name")
80
- block_given? ? yield(ds) : ds.map{|r| ds.send(:output_identifier, r[:"rdb$relation_name"])}
81
- end
82
-
83
55
  private
84
56
 
85
- # Use Firebird specific syntax for add column
86
- def alter_table_sql(table, op)
87
- case op[:op]
88
- when :add_column
89
- "ALTER TABLE #{quote_schema_table(table)} ADD #{column_definition_sql(op)}"
90
- when :drop_column
91
- "ALTER TABLE #{quote_schema_table(table)} DROP #{column_definition_sql(op)}"
92
- when :rename_column
93
- "ALTER TABLE #{quote_schema_table(table)} ALTER #{quote_identifier(op[:name])} TO #{quote_identifier(op[:new_name])}"
94
- when :set_column_type
95
- "ALTER TABLE #{quote_schema_table(table)} ALTER #{quote_identifier(op[:name])} TYPE #{type_literal(op)}"
96
- else
97
- super(table, op)
98
- end
99
- end
100
-
101
- def auto_increment_sql()
102
- AUTO_INCREMENT
103
- end
104
-
105
57
  def begin_transaction(conn, opts={})
106
- log_yield(TRANSACTION_BEGIN){conn.transaction}
107
- conn
108
- end
109
-
110
- def commit_transaction(conn, opts={})
111
- log_yield(TRANSACTION_COMMIT){conn.commit}
112
- end
113
-
114
- def create_sequence_sql(name, opts={})
115
- "CREATE SEQUENCE #{quote_identifier(name)}"
116
- end
117
-
118
- # Firebird gets an override because of the mess of creating a
119
- # sequence and trigger for auto-incrementing primary keys.
120
- def create_table_from_generator(name, generator, options)
121
- drop_statement, create_statements = create_table_sql_list(name, generator, options)
122
- (execute_ddl(drop_statement) rescue nil) if drop_statement
123
- create_statements.each{|sql| execute_ddl(sql)}
124
- end
125
-
126
- def create_table_sql_list(name, generator, options={})
127
- statements = [create_table_sql(name, generator, options)]
128
- drop_seq_statement = nil
129
- generator.columns.each do |c|
130
- if c[:auto_increment]
131
- c[:sequence_name] ||= "seq_#{name}_#{c[:name]}"
132
- unless c[:create_sequence] == false
133
- drop_seq_statement = drop_sequence_sql(c[:sequence_name])
134
- statements << create_sequence_sql(c[:sequence_name])
135
- statements << restart_sequence_sql(c[:sequence_name], {:restart_position => c[:sequence_start_position]}) if c[:sequence_start_position]
136
- end
137
- unless c[:create_trigger] == false
138
- c[:trigger_name] ||= "BI_#{name}_#{c[:name]}"
139
- c[:quoted_name] = quote_identifier(c[:name])
140
- trigger_definition = <<-END
141
- begin
142
- if ((new.#{c[:quoted_name]} is null) or (new.#{c[:quoted_name]} = 0)) then
143
- begin
144
- new.#{c[:quoted_name]} = next value for #{c[:sequence_name]};
145
- end
146
- end
147
- END
148
- statements << create_trigger_sql(name, c[:trigger_name], trigger_definition, {:events => [:insert]})
149
- end
58
+ log_yield(TRANSACTION_BEGIN) do
59
+ begin
60
+ conn.transaction
61
+ rescue Fb::Error => e
62
+ conn.rollback
63
+ raise_error(e, :disconnect=>true)
150
64
  end
151
65
  end
152
- [drop_seq_statement, statements]
153
66
  end
154
67
 
155
- def create_trigger_sql(table, name, definition, opts={})
156
- events = opts[:events] ? Array(opts[:events]) : [:insert, :update, :delete]
157
- whence = opts[:after] ? 'AFTER' : 'BEFORE'
158
- inactive = opts[:inactive] ? 'INACTIVE' : 'ACTIVE'
159
- position = opts.fetch(:position, 0)
160
- sql = <<-end_sql
161
- CREATE TRIGGER #{quote_identifier(name)} for #{quote_identifier(table)}
162
- #{inactive} #{whence} #{events.map{|e| e.to_s.upcase}.join(' OR ')} position #{position}
163
- as #{definition}
164
- end_sql
165
- sql
68
+ def commit_transaction(conn, opts={})
69
+ log_yield(TRANSACTION_COMMIT){conn.commit}
166
70
  end
167
71
 
168
72
  def database_error_classes
169
73
  [Fb::Error]
170
74
  end
171
75
 
172
- def disconnect_connection(c)
173
- c.close
174
- end
175
-
176
- def drop_sequence_sql(name)
177
- "DROP SEQUENCE #{quote_identifier(name)}"
178
- end
179
-
180
- def restart_sequence_sql(name, opts={})
181
- seq_name = quote_identifier(name)
182
- "ALTER SEQUENCE #{seq_name} RESTART WITH #{opts[:restart_position]}"
183
- end
184
-
185
76
  def rollback_transaction(conn, opts={})
186
77
  log_yield(TRANSACTION_ROLLBACK){conn.rollback}
187
78
  end
188
-
189
- def type_literal_generic_string(column)
190
- column[:text] ? :"BLOB SUB_TYPE TEXT" : super
191
- end
192
79
  end
193
80
 
194
81
  # Dataset class for Firebird datasets
195
82
  class Dataset < Sequel::Dataset
196
- BOOL_TRUE = '1'.freeze
197
- BOOL_FALSE = '0'.freeze
198
- NULL = LiteralString.new('NULL').freeze
199
- COMMA_SEPARATOR = ', '.freeze
200
- SELECT_CLAUSE_METHODS = clause_methods(:select, %w'with distinct limit columns from join where group having compounds order')
83
+ include Sequel::Firebird::DatasetMethods
84
+
85
+ Database::DatasetClass = self
201
86
 
202
87
  # Yield all rows returned by executing the given SQL and converting
203
88
  # the types.
204
89
  def fetch_rows(sql)
205
90
  execute(sql) do |s|
206
91
  begin
207
- @columns = s.fields.map{|c| output_identifier(c.name)}
208
- s.fetchall(:symbols_hash).each do |r|
92
+ @columns = columns = s.fields.map{|c| output_identifier(c.name)}
93
+ s.fetchall.each do |r|
209
94
  h = {}
210
- r.each{|k,v| h[output_identifier(k)] = v}
95
+ r.zip(columns).each{|v, c| h[c] = v}
211
96
  yield h
212
97
  end
213
98
  ensure
@@ -216,68 +101,6 @@ module Sequel
216
101
  end
217
102
  self
218
103
  end
219
-
220
- # Insert given values into the database.
221
- def insert(*values)
222
- if !@opts[:sql]
223
- clone(default_server_opts(:sql=>insert_returning_pk_sql(*values))).single_value
224
- else
225
- execute_insert(insert_sql(*values), :table=>opts[:from].first,
226
- :values=>values.size == 1 ? values.first : values)
227
- end
228
- end
229
-
230
- # Use the RETURNING clause to return the primary key of the inserted record, if it exists
231
- def insert_returning_pk_sql(*values)
232
- pk = db.primary_key(opts[:from].first)
233
- insert_returning_sql(pk ? Sequel::SQL::Identifier.new(pk) : NULL, *values)
234
- end
235
-
236
- # Use the RETURNING clause to return the columns listed in returning.
237
- def insert_returning_sql(returning, *values)
238
- "#{insert_sql(*values)} RETURNING #{column_list(Array(returning))}"
239
- end
240
-
241
- # Insert a record returning the record inserted
242
- def insert_select(*values)
243
- naked.clone(default_server_opts(:sql=>insert_returning_sql(nil, *values))).single_record
244
- end
245
-
246
- def requires_sql_standard_datetimes?
247
- true
248
- end
249
-
250
- # The order of clauses in the SELECT SQL statement
251
- def select_clause_methods
252
- SELECT_CLAUSE_METHODS
253
- end
254
-
255
- def select_limit_sql(sql)
256
- sql << " FIRST #{@opts[:limit]}" if @opts[:limit]
257
- sql << " SKIP #{@opts[:offset]}" if @opts[:offset]
258
- end
259
-
260
- # Firebird does not support INTERSECT or EXCEPT
261
- def supports_intersect_except?
262
- false
263
- end
264
-
265
- private
266
-
267
- def hash_row(stmt, row)
268
- @columns.inject({}) do |m, c|
269
- m[c] = row.shift
270
- m
271
- end
272
- end
273
-
274
- def literal_false
275
- BOOL_FALSE
276
- end
277
-
278
- def literal_true
279
- BOOL_TRUE
280
- end
281
104
  end
282
105
  end
283
106
  end