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
@@ -1,27 +1,53 @@
1
1
  module Sequel
2
2
  module Access
3
3
  module DatabaseMethods
4
+ # Access uses type :access as the database_type
4
5
  def database_type
5
6
  :access
6
7
  end
7
8
 
8
- def dataset(opts = nil)
9
- ds = super
10
- ds.extend(DatasetMethods)
11
- ds
12
- end
13
-
14
9
  # Doesn't work, due to security restrictions on MSysObjects
15
- def tables
16
- from(:MSysObjects).filter(:Type=>1, :Flags=>0).select_map(:Name).map{|x| x.to_sym}
10
+ #def tables
11
+ # from(:MSysObjects).filter(:Type=>1, :Flags=>0).select_map(:Name).map{|x| x.to_sym}
12
+ #end
13
+
14
+ # Access doesn't support renaming tables from an SQL query,
15
+ # so create a copy of the table and then drop the from table.
16
+ def rename_table(from_table, to_table)
17
+ create_table(to_table, :as=>from(from_table))
18
+ drop_table(from_table)
17
19
  end
18
20
 
21
+ # Access uses type Counter for an autoincrementing keys
19
22
  def serial_primary_key_options
20
23
  {:primary_key => true, :type=>:Counter}
21
24
  end
22
25
 
23
26
  private
24
27
 
28
+ def alter_table_op_sql(table, op)
29
+ case op[:op]
30
+ when :set_column_type
31
+ "ALTER COLUMN #{quote_identifier(op[:name])} #{type_literal(op)}"
32
+ else
33
+ super
34
+ end
35
+ end
36
+
37
+ # Access doesn't support CREATE TABLE AS, it only supports SELECT INTO.
38
+ # Emulating CREATE TABLE AS using SELECT INTO is only possible if a dataset
39
+ # is given as the argument, it can't work with a string, so raise an
40
+ # Error if a string is given.
41
+ def create_table_as(name, ds, options)
42
+ raise(Error, "must provide dataset instance as value of create_table :as option on Access") unless ds.is_a?(Sequel::Dataset)
43
+ run(ds.into(name).sql)
44
+ end
45
+
46
+ # The SQL to drop an index for the table.
47
+ def drop_index_sql(table, op)
48
+ "DROP INDEX #{quote_identifier(op[:name] || default_index_name(table, op[:columns]))} ON #{quote_schema_table(table)}"
49
+ end
50
+
25
51
  def identifier_input_method_default
26
52
  nil
27
53
  end
@@ -29,21 +55,220 @@ module Sequel
29
55
  def identifier_output_method_default
30
56
  nil
31
57
  end
58
+
59
+ # Access doesn't have a 64-bit integer type, so use integer and hope
60
+ # the user isn't using more than 32 bits.
61
+ def type_literal_generic_bignum(column)
62
+ :integer
63
+ end
64
+
65
+ # Access doesn't have a true boolean class, so it uses bit
66
+ def type_literal_generic_trueclass(column)
67
+ :bit
68
+ end
69
+
70
+ # Access uses image type for blobs
71
+ def type_literal_generic_file(column)
72
+ :image
73
+ end
32
74
  end
33
75
 
34
76
  module DatasetMethods
35
- SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'limit distinct columns from join where group order having compounds')
77
+ SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'select distinct limit columns into from join where group order having compounds')
78
+ DATE_FORMAT = '#%Y-%m-%d#'.freeze
79
+ TIMESTAMP_FORMAT = '#%Y-%m-%d %H:%M:%S#'.freeze
80
+ TOP = " TOP ".freeze
81
+ BRACKET_CLOSE = Dataset::BRACKET_CLOSE
82
+ BRACKET_OPEN = Dataset::BRACKET_OPEN
83
+ PAREN_CLOSE = Dataset::PAREN_CLOSE
84
+ PAREN_OPEN = Dataset::PAREN_OPEN
85
+ INTO = Dataset::INTO
86
+ FROM = Dataset::FROM
87
+ NOT_EQUAL = ' <> '.freeze
88
+ OPS = {:'%'=>' Mod '.freeze, :'||'=>' & '.freeze}
89
+ BOOL_FALSE = '0'.freeze
90
+ BOOL_TRUE = '-1'.freeze
91
+ DATE_FUNCTION = 'Date()'.freeze
92
+ NOW_FUNCTION = 'Now()'.freeze
93
+ TIME_FUNCTION = 'Time()'.freeze
94
+ CAST_TYPES = {String=>:CStr, Integer=>:CLng, Date=>:CDate, Time=>:CDate, DateTime=>:CDate, Numeric=>:CDec, BigDecimal=>:CDec, File=>:CStr, Float=>:CDbl, TrueClass=>:CBool, FalseClass=>:CBool}
95
+
96
+ EXTRACT_MAP = {:year=>"'yyyy'", :month=>"'m'", :day=>"'d'", :hour=>"'h'", :minute=>"'n'", :second=>"'s'"}
97
+ COMMA = Dataset::COMMA
98
+ DATEPART_OPEN = "datepart(".freeze
99
+
100
+ # Access doesn't support CASE, but it can be emulated with nested
101
+ # IIF function calls.
102
+ def case_expression_sql_append(sql, ce)
103
+ literal_append(sql, ce.with_merged_expression.conditions.reverse.inject(ce.default){|exp,(cond,val)| Sequel::SQL::Function.new(:IIF, cond, val, exp)})
104
+ end
105
+
106
+ # Access doesn't support CAST, it uses separate functions for
107
+ # type conversion
108
+ def cast_sql_append(sql, expr, type)
109
+ sql << CAST_TYPES.fetch(type, type).to_s
110
+ sql << PAREN_OPEN
111
+ literal_append(sql, expr)
112
+ sql << PAREN_CLOSE
113
+ end
114
+
115
+ def complex_expression_sql_append(sql, op, args)
116
+ case op
117
+ when :ILIKE
118
+ super(sql, :LIKE, args)
119
+ when :'NOT ILIKE'
120
+ super(sql, :'NOT LIKE', args)
121
+ when :'!='
122
+ sql << PAREN_OPEN
123
+ literal_append(sql, args.at(0))
124
+ sql << NOT_EQUAL
125
+ literal_append(sql, args.at(1))
126
+ sql << PAREN_CLOSE
127
+ when :'%', :'||'
128
+ sql << PAREN_OPEN
129
+ c = false
130
+ op_str = OPS[op]
131
+ args.each do |a|
132
+ sql << op_str if c
133
+ literal_append(sql, a)
134
+ c ||= true
135
+ end
136
+ sql << PAREN_CLOSE
137
+ when :extract
138
+ part = args.at(0)
139
+ raise(Sequel::Error, "unsupported extract argument: #{part.inspect}") unless format = EXTRACT_MAP[part]
140
+ sql << DATEPART_OPEN << format.to_s << COMMA
141
+ literal_append(sql, args.at(1))
142
+ sql << PAREN_CLOSE
143
+ else
144
+ super
145
+ end
146
+ end
147
+
148
+ # Use Date() and Now() for CURRENT_DATE and CURRENT_TIMESTAMP
149
+ def constant_sql_append(sql, constant)
150
+ case constant
151
+ when :CURRENT_DATE
152
+ sql << DATE_FUNCTION
153
+ when :CURRENT_TIMESTAMP
154
+ sql << NOW_FUNCTION
155
+ when :CURRENT_TIME
156
+ sql << TIME_FUNCTION
157
+ else
158
+ super
159
+ end
160
+ end
161
+
162
+ # Emulate cross join by using multiple tables in the FROM clause.
163
+ def cross_join(table)
164
+ clone(:from=>@opts[:from] + [table])
165
+ end
166
+
167
+ def emulated_function_sql_append(sql, f)
168
+ case f.f
169
+ when :char_length
170
+ literal_append(sql, SQL::Function.new(:len, f.args.first))
171
+ else
172
+ super
173
+ end
174
+ end
175
+
176
+ # Specify a table for a SELECT ... INTO query.
177
+ def into(table)
178
+ clone(:into => table)
179
+ end
36
180
 
181
+ # Access doesn't support INTERSECT or EXCEPT
37
182
  def supports_intersect_except?
38
183
  false
39
184
  end
40
185
 
186
+ # Access does not support IS TRUE
187
+ def supports_is_true?
188
+ false
189
+ end
190
+
191
+ # Access doesn't support JOIN USING
192
+ def supports_join_using?
193
+ false
194
+ end
195
+
196
+ # Access does not support multiple columns for the IN/NOT IN operators
197
+ def supports_multiple_column_in?
198
+ false
199
+ end
200
+
201
+ # Access doesn't support truncate, so do a delete instead.
202
+ def truncate
203
+ delete
204
+ nil
205
+ end
206
+
41
207
  private
42
208
 
43
- def quoted_identifier(v)
44
- "[#{v}]"
209
+ # Access uses # to quote dates
210
+ def literal_date(d)
211
+ d.strftime(DATE_FORMAT)
212
+ end
213
+
214
+ # Access uses # to quote datetimes
215
+ def literal_datetime(t)
216
+ t.strftime(TIMESTAMP_FORMAT)
217
+ end
218
+ alias literal_time literal_datetime
219
+
220
+ # Use 0 for false on MSSQL
221
+ def literal_false
222
+ BOOL_FALSE
223
+ end
224
+
225
+ # Use 0 for false on MSSQL
226
+ def literal_true
227
+ BOOL_TRUE
228
+ end
229
+
230
+ # Access requires parentheses when joining more than one table
231
+ def select_from_sql(sql)
232
+ if f = @opts[:from]
233
+ sql << FROM
234
+ if (j = @opts[:join]) && !j.empty?
235
+ sql << (PAREN_OPEN * j.length)
236
+ end
237
+ source_list_append(sql, f)
238
+ end
239
+ end
240
+
241
+ def select_into_sql(sql)
242
+ if i = @opts[:into]
243
+ sql << INTO
244
+ identifier_append(sql, i)
245
+ end
246
+ end
247
+
248
+ # Access requires parentheses when joining more than one table
249
+ def select_join_sql(sql)
250
+ if js = @opts[:join]
251
+ js.each do |j|
252
+ literal_append(sql, j)
253
+ sql << PAREN_CLOSE
254
+ end
255
+ end
256
+ end
257
+
258
+ # Access uses TOP for limits
259
+ def select_limit_sql(sql)
260
+ if l = @opts[:limit]
261
+ sql << TOP
262
+ literal_append(sql, l)
263
+ end
264
+ end
265
+
266
+ # Access uses [] for quoting identifiers
267
+ def quoted_identifier_append(sql, v)
268
+ sql << BRACKET_OPEN << v.to_s << BRACKET_CLOSE
45
269
  end
46
270
 
271
+ # Access requires the limit clause come before other clauses
47
272
  def select_clause_methods
48
273
  SELECT_CLAUSE_METHODS
49
274
  end
@@ -0,0 +1,216 @@
1
+ Sequel.require 'adapters/utils/split_alter_table'
2
+
3
+ module Sequel
4
+ module Cubrid
5
+ module DatabaseMethods
6
+ include Sequel::Database::SplitAlterTable
7
+
8
+ AUTOINCREMENT = 'AUTO_INCREMENT'.freeze
9
+ COLUMN_DEFINITION_ORDER = [:auto_increment, :default, :null, :unique, :primary_key, :references]
10
+
11
+ def database_type
12
+ :cubrid
13
+ end
14
+
15
+ def indexes(table, opts={})
16
+ m = output_identifier_meth
17
+ m2 = input_identifier_meth
18
+ indexes = {}
19
+ metadata_dataset.
20
+ from(:db_index___i).
21
+ join(:db_index_key___k, :index_name=>:index_name, :class_name=>:class_name).
22
+ where(:i__class_name=>m2.call(table), :is_primary_key=>'NO').
23
+ order(:k__key_order).
24
+ select(:i__index_name, :k__key_attr_name___column, :is_unique).
25
+ each do |row|
26
+ index = indexes[m.call(row[:index_name])] ||= {:columns=>[], :unique=>row[:is_unique]=='YES'}
27
+ index[:columns] << m.call(row[:column])
28
+ end
29
+ indexes
30
+ end
31
+
32
+ def supports_savepoints?
33
+ false
34
+ end
35
+
36
+ def schema_parse_table(table_name, opts)
37
+ m = output_identifier_meth(opts[:dataset])
38
+ m2 = input_identifier_meth(opts[:dataset])
39
+
40
+ pks = metadata_dataset.
41
+ from(:db_index___i).
42
+ join(:db_index_key___k, :index_name=>:index_name, :class_name=>:class_name).
43
+ where(:i__class_name=>m2.call(table_name), :is_primary_key=>'YES').
44
+ order(:k__key_order).
45
+ select_map(:k__key_attr_name).
46
+ map{|c| m.call(c)}
47
+
48
+ metadata_dataset.
49
+ from(:db_attribute).
50
+ where(:class_name=>m2.call(table_name)).
51
+ order(:def_order).
52
+ select(:attr_name, :data_type___db_type, :default_value___default, :is_nullable___allow_null).
53
+ map do |row|
54
+ name = m.call(row.delete(:attr_name))
55
+ row[:allow_null] = row[:allow_null] == 'YES'
56
+ row[:primary_key] = pks.include?(name)
57
+ row[:type] = schema_column_type(row[:db_type])
58
+ [name, row]
59
+ end
60
+ end
61
+
62
+ def tables(opts={})
63
+ _tables('CLASS')
64
+ end
65
+
66
+ def views(opts={})
67
+ _tables('VCLASS')
68
+ end
69
+
70
+ private
71
+
72
+ def _tables(type)
73
+ m = output_identifier_meth
74
+ metadata_dataset.
75
+ from(:db_class).
76
+ where(:is_system_class=>'NO', :class_type=>type).
77
+ select_map(:class_name).
78
+ map{|c| m.call(c)}
79
+ end
80
+
81
+ def alter_table_op_sql(table, op)
82
+ case op[:op]
83
+ when :rename_column
84
+ "RENAME COLUMN #{quote_identifier(op[:name])} AS #{quote_identifier(op[:new_name])}"
85
+ when :set_column_type, :set_column_null, :set_column_default
86
+ o = op[:op]
87
+ opts = schema(table).find{|x| x.first == op[:name]}
88
+ opts = opts ? opts.last.dup : {}
89
+ opts[:name] = o == :rename_column ? op[:new_name] : op[:name]
90
+ opts[:type] = o == :set_column_type ? op[:type] : opts[:db_type]
91
+ opts[:null] = o == :set_column_null ? op[:null] : opts[:allow_null]
92
+ opts[:default] = o == :set_column_default ? op[:default] : opts[:ruby_default]
93
+ opts.delete(:default) if opts[:default] == nil
94
+ "CHANGE COLUMN #{quote_identifier(op[:name])} #{column_definition_sql(op.merge(opts))}"
95
+ else
96
+ super
97
+ end
98
+ end
99
+
100
+ def alter_table_sql(table, op)
101
+ case op[:op]
102
+ when :drop_index
103
+ "ALTER TABLE #{quote_schema_table(table)} #{drop_index_sql(table, op)}"
104
+ else
105
+ super
106
+ end
107
+ end
108
+
109
+ def auto_increment_sql
110
+ AUTOINCREMENT
111
+ end
112
+
113
+ # CUBRID requires auto increment before primary key
114
+ def column_definition_order
115
+ COLUMN_DEFINITION_ORDER
116
+ end
117
+
118
+ # CUBRID requires FOREIGN KEY keywords before a column reference
119
+ def column_references_sql(column)
120
+ sql = super
121
+ sql = " FOREIGN KEY#{sql}" unless column[:columns]
122
+ sql
123
+ end
124
+
125
+ def connection_execute_method
126
+ :query
127
+ end
128
+
129
+ # CUBRID is case insensitive, so don't modify identifiers
130
+ def identifier_input_method_default
131
+ nil
132
+ end
133
+
134
+ # CUBRID is case insensitive, so don't modify identifiers
135
+ def identifier_output_method_default
136
+ nil
137
+ end
138
+
139
+ # CUBRID doesn't support booleans, it recommends using smallint.
140
+ def type_literal_generic_trueclass(column)
141
+ :smallint
142
+ end
143
+
144
+ # CUBRID uses clob for text types.
145
+ def uses_clob_for_text?
146
+ true
147
+ end
148
+ end
149
+
150
+ module DatasetMethods
151
+ SELECT_CLAUSE_METHODS = Sequel::Dataset.clause_methods(:select, %w'select distinct columns from join where group having compounds order limit')
152
+ LIMIT = Sequel::Dataset::LIMIT
153
+ COMMA = Sequel::Dataset::COMMA
154
+ BOOL_FALSE = '0'.freeze
155
+ BOOL_TRUE = '1'.freeze
156
+
157
+ def complex_expression_sql_append(sql, op, args)
158
+ case op
159
+ when :ILIKE
160
+ super(sql, :LIKE, [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1))])
161
+ when :"NOT ILIKE"
162
+ super(sql, :"NOT LIKE", [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1))])
163
+ else
164
+ super
165
+ end
166
+ end
167
+
168
+ def supports_join_using?
169
+ false
170
+ end
171
+
172
+ def supports_multiple_column_in?
173
+ false
174
+ end
175
+
176
+ def supports_timestamp_usecs?
177
+ false
178
+ end
179
+
180
+ # CUBRID supposedly supports TRUNCATE, but it appears not to work in my testing.
181
+ # Fallback to using DELETE.
182
+ def truncate
183
+ delete
184
+ nil
185
+ end
186
+
187
+ private
188
+
189
+ def literal_false
190
+ BOOL_FALSE
191
+ end
192
+
193
+ def literal_true
194
+ BOOL_TRUE
195
+ end
196
+
197
+ # CUBRID doesn't support CTEs or FOR UPDATE.
198
+ def select_clause_methods
199
+ SELECT_CLAUSE_METHODS
200
+ end
201
+
202
+ # CUBRID requires a limit to use an offset,
203
+ # and requires a FROM table if a limit is used.
204
+ def select_limit_sql(sql)
205
+ if @opts[:from] && (l = @opts[:limit])
206
+ sql << LIMIT
207
+ if o = @opts[:offset]
208
+ literal_append(sql, o)
209
+ sql << COMMA
210
+ end
211
+ literal_append(sql, l)
212
+ end
213
+ end
214
+ end
215
+ end
216
+ end