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
data/doc/querying.rdoc CHANGED
@@ -10,7 +10,9 @@ aims to be a gentle introduction to Sequel's querying support.
10
10
 
11
11
  While you can easily use raw SQL with Sequel, a large part of the
12
12
  advantage you get from using Sequel is Sequel's ability to abstract
13
- SQL from you and give you a much nicer interface.
13
+ SQL from you and give you a much nicer interface. Sequel also ships with
14
+ a {core_extensions extension}[link:files/doc/core_extensions_rdoc.html],
15
+ which better integrates Sequel's DSL into the ruby language.
14
16
 
15
17
  == Retrieving Objects
16
18
 
@@ -57,7 +59,7 @@ Any options you pass to +first+ will be used as a filter:
57
59
  # SELECT * FROM artists WHERE (name = 'YJM') LIMIT 1
58
60
  => #<Artist @values={:name=>"YJM", :id=>1}>
59
61
 
60
- artist = Artist.first(:name.like('Y%'))
62
+ artist = Artist.first(Sequel.like(:name, 'Y%'))
61
63
  # SELECT * FROM artists WHERE (name LIKE 'Y%') LIMIT 1
62
64
  => #<Artist @values={:name=>"YJM", :id=>1}>
63
65
 
@@ -69,12 +71,12 @@ requires an argument:
69
71
  => {:name=>"YJM", :id=>1}
70
72
 
71
73
  Note that while Model.[] allows you to pass a primary key directly,
72
- Dataset#[] does not.
74
+ Dataset#[] does not (unless it is a model dataset).
73
75
 
74
76
  ==== Using +last+
75
77
 
76
78
  If you want the last record in the dataset,
77
- <tt>Sequel::Dataset#last</tt> is an obvious method to use. Note first
79
+ <tt>Sequel::Dataset#last</tt> is an obvious method to use. Note
78
80
  that last requires that the dataset be ordered. Without an order, any
79
81
  object can be considered the first as well as the last.
80
82
 
@@ -162,22 +164,38 @@ It's also common to want to order such a map, so Sequel provides a
162
164
  # SELECT name FROM artists ORDER BY name
163
165
  => ["AS", "YJM"]
164
166
 
167
+ In all of these cases, you can provide an array of column symbols and
168
+ an array of arrays of values will be returned:
169
+
170
+ artist_names = Artist.select_map([:id, :name])
171
+ # SELECT id, name FROM artists
172
+ => [[1, "YJM"], [2, "AS"]]
173
+
165
174
  ==== As a Hash
166
175
 
167
176
  Sequel makes it easy to take an SQL query and return it as a ruby hash,
168
177
  using the +to_hash+ method:
169
178
 
170
- artist_names = Artist.to_hash(:name, :id)
179
+ artist_names = Artist.to_hash(:id, :name)
171
180
  # SELECT * FROM artists
172
- => {"YJM"=>1, "AS"=>2}
181
+ => {1=>"YJM", 2=>"AS"}
173
182
 
174
183
  As you can see, the +to_hash+ method uses the first symbol as the key
175
184
  and the second symbol as the value. So if you swap the two arguments the hash
176
185
  will have its keys and values transposed:
177
186
 
178
- artist_names = Artist.to_hash(:id, :name)
187
+ artist_names = Artist.to_hash(:name, :id)
179
188
  # SELECT * FROM artists
180
- => {1=>"YJM", 2=>"AS"}
189
+ => {"YJM"=>1, "AS"=>2}
190
+
191
+ Now what if you have multiple values for the same key? By default, +to_hash+
192
+ will just have the last matching value. If you care about all matching values,
193
+ use +to_hash_groups+, which makes the values of the array an array of matching
194
+ values, in the order they were received:
195
+
196
+ artist_names = Artist.to_hash_groups(:name, :id)
197
+ # SELECT * FROM artists
198
+ => {"YJM"=>[1, 10, ...], "AS"=>[2, 20, ...]}
181
199
 
182
200
  If you only provide one argument to +to_hash+, it uses the entire hash
183
201
  or model object as the value:
@@ -186,6 +204,12 @@ or model object as the value:
186
204
  # SELECT * FROM artists
187
205
  => {"YJM"=>{:id=>1, :name=>"YJM"}, "AS"=>{:id=>2, :name=>"AS"}}
188
206
 
207
+ and +to_hash_groups+ works similarly:
208
+
209
+ artist_names = DB[:artists].to_hash_groups(:name)
210
+ # SELECT * FROM artists
211
+ => {"YJM"=>[{:id=>1, :name=>"YJM"}, {:id=>10, :name=>"YJM"}], ...}
212
+
189
213
  Model datasets have a +to_hash+ method that can be called without any
190
214
  arguments, in which case it will use the primary key as the key and
191
215
  the model object as the value. This can be used to easily create an
@@ -196,6 +220,9 @@ identity map:
196
220
  => {1=>#<Artist @values={:id=>1, :name=>"YGM"}>,
197
221
  2=>#<Artist @values={:id=>2, :name=>"AS"}>}
198
222
 
223
+ There is no equivalent handling to +to_hash_groups+, since there would
224
+ only be one matching record, as the primary key must be unique.
225
+
199
226
  Note that +to_hash+ never modifies the columns selected. However, just
200
227
  like Sequel has a +select_map+ method to modify the columns selected and
201
228
  return an array, Sequel also has a +select_hash+ method to modify the
@@ -205,6 +232,12 @@ columns selected and return a hash:
205
232
  # SELECT name, id FROM artists
206
233
  => {"YJM"=>1, "AS"=>2}
207
234
 
235
+ Likewise, +select_hash_groups+ also exists:
236
+
237
+ artist_names = Artist.select_hash_groups(:name, :id)
238
+ # SELECT name, id FROM artists
239
+ => {"YJM"=>[1, 10, ...], "AS"=>[2, 20, ...]}
240
+
208
241
  == Modifying datasets
209
242
 
210
243
  Note that the retrieval methods discussed above just return
@@ -232,7 +265,7 @@ table +artists+:
232
265
  Let's say we are only interested in the artists whose names
233
266
  start with "A":
234
267
 
235
- ds2 = ds1.where(:name.like('A%'))
268
+ ds2 = ds1.where(Sequel.like(:name, 'A%'))
236
269
  # SELECT * FROM artists WHERE name LIKE 'A%'
237
270
 
238
271
  Here we see that +where+ returns a dataset that adds a +WHERE+
@@ -282,47 +315,47 @@ of condition is used depends on the values in the hash.
282
315
  Unless Sequel has special support for the value's class, it uses a simple
283
316
  equality statement:
284
317
 
285
- Artist.filter(:id=>1)
318
+ Artist.where(:id=>1)
286
319
  # SELECT * FROM artists WHERE id = 1
287
320
 
288
- Artist.filter(:name=>'YJM')
321
+ Artist.where(:name=>'YJM')
289
322
  # SELECT * FROM artists WHERE name = 'YJM'
290
323
 
291
324
  For arrays, Sequel uses the IN operator.
292
325
 
293
- Artist.filter(:id=>[1, 2])
326
+ Artist.where(:id=>[1, 2])
294
327
  # SELECT * FROM artists WHERE id IN (1, 2)
295
328
 
296
329
  For datasets, Sequel uses the IN operator with a subselect:
297
330
 
298
- Artist.filter(:id=>Album.select(:artist_id))
331
+ Artist.where(:id=>Album.select(:artist_id))
299
332
  # SELECT * FROM artists WHERE id IN (
300
333
  # SELECT artist_id FROM albums)
301
334
 
302
335
  For boolean values such as nil, true, and false, Sequel uses the IS operator:
303
336
 
304
- Artist.filter(:id=>nil)
337
+ Artist.where(:id=>nil)
305
338
  # SELECT * FROM artists WHERE id IS NULL
306
339
 
307
340
  For ranges, Sequel uses a pair of inequality statements:
308
341
 
309
- Artist.filter(:id=>1..5)
342
+ Artist.where(:id=>1..5)
310
343
  # SELECT * FROM artists WHERE id >= 1 AND id <= 5
311
344
 
312
345
  Finally, for regexps, Sequel uses an SQL regular expression. Note that this
313
346
  is probably only supported on PostgreSQL and MySQL.
314
347
 
315
- Artist.filter(:name=>/JM$/)
348
+ Artist.where(:name=>/JM$/)
316
349
  # SELECT * FROM artists WHERE name ~ 'JM$'
317
350
 
318
351
  If there are multiple arguments in the hash, the filters are ANDed together:
319
352
 
320
- Artist.filter(:id=>1, :name=>/JM$/)
353
+ Artist.where(:id=>1, :name=>/JM$/)
321
354
  # SELECT * FROM artists WHERE id = 1 AND name ~ 'JM$'
322
355
 
323
- This works the same as if you used two separate filter calls:
356
+ This works the same as if you used two separate +where+ calls:
324
357
 
325
- Artist.filter(:id=>1).filter(:name=>/JM$/)
358
+ Artist.where(:id=>1).where(:name=>/JM$/)
326
359
  # SELECT * FROM artists WHERE id = 1 AND name ~ 'JM$'
327
360
 
328
361
  === Array of Two Element Arrays
@@ -331,14 +364,14 @@ If you use an array of two element arrays, it is treated as a hash. The only
331
364
  advantage to using an array of two element arrays is that it allows you to
332
365
  duplicate keys, so you can do:
333
366
 
334
- Artist.filter([[:name, /JM$/], [:name, /^YJ/]])
367
+ Artist.where([[:name, /JM$/], [:name, /^YJ/]])
335
368
  # SELECT * FROM artists WHERE name ~ 'JM$' AND name ~ '^YJ'
336
369
 
337
370
  === Virtual Row Blocks
338
371
 
339
- If a block is passed to filter, it is treated as a virtual row block:
372
+ If a block is passed to a filter, it is treated as a virtual row block:
340
373
 
341
- Artist.filter{id > 5}
374
+ Artist.where{id > 5}
342
375
  # SELECT * FROM artists WHERE id > 5
343
376
 
344
377
  You can learn more about virtual row blocks in the {"Virtual Rows" guide}[link:files/doc/virtual_rows_rdoc.html].
@@ -346,7 +379,7 @@ You can learn more about virtual row blocks in the {"Virtual Rows" guide}[link:f
346
379
  You can provide both regular arguments and a block, in which case the results
347
380
  will be ANDed together:
348
381
 
349
- Artist.filter(:name=>'A'...'M'){id > 5}
382
+ Artist.where(:name=>'A'...'M'){id > 5}
350
383
  # SELECT * FROM artists WHERE name >= 'A' AND name < 'M' AND id > 5
351
384
 
352
385
  === Symbols
@@ -363,28 +396,30 @@ Sequel has a DSL that allows easily creating SQL expressions. These SQL
363
396
  expressions are instances of subclasses of Sequel::SQL::Expression. You've
364
397
  already seen an example earlier:
365
398
 
366
- Artist.filter(:name.like('Y%'))
399
+ Artist.where(Sequel.like(:name, 'Y%'))
367
400
  # SELECT * FROM artists WHERE name LIKE 'Y%'
368
401
 
369
- In this case Symbol#like returns a Sequel::SQL::BooleanExpression object,
402
+ In this case Sequel.like returns a Sequel::SQL::BooleanExpression object,
370
403
  which is used directly in the filter.
371
404
 
372
405
  You can use the DSL to create arbitrarily complex expressions. SQL::Expression
373
- objects support the & operator for +AND+, the | operator for +OR+, and the ~ operator
374
- for inversion:
406
+ objects can be created via singleton methods on the Sequel module. The most common
407
+ method is Sequel.expr, which takes any object and wraps it in a SQL::Expression
408
+ object. In most cases, the SQL::Expression returned supports the & operator for
409
+ +AND+, the | operator for +OR+, and the ~ operator for inversion:
375
410
 
376
- Artist.filter(:name.like('Y%') & ({:b=>1} | ~{:c=>3}))
411
+ Artist.where(Sequel.like(:name, 'Y%') & (Sequel.expr(:b=>1) | Sequel.~(:c=>3)))
377
412
  # SELECT * FROM artists WHERE name LIKE 'Y%' AND (b = 1 OR c != 3)
378
413
 
379
414
  You can combine these expression operators with the virtual row support:
380
415
 
381
- Artist.filter{(a > 1) & ~((b(c) < 1) | d)}
416
+ Artist.where{(a > 1) & ~((b(c) < 1) | d)}
382
417
  # SELECT * FROM artists WHERE a > 1 AND b(c) >= 1 AND NOT d
383
418
 
384
419
  Note the use of parentheses when using the & and | operators, as they have lower
385
420
  precedence than other operators. The following will not work:
386
421
 
387
- Artist.filter{a > 1 & ~(b(c) < 1 | d)}
422
+ Artist.where{a > 1 & ~(b(c) < 1 | d)}
388
423
  # Raises a TypeError, as it calls Integer#| with a Sequel::SQL::Identifier
389
424
 
390
425
  === Strings with Placeholders
@@ -392,24 +427,24 @@ precedence than other operators. The following will not work:
392
427
  Assuming you want to get your hands dirty and write some SQL, Sequel allows you
393
428
  to use strings using placeholders for the values:
394
429
 
395
- Artist.filter("name LIKE ?", 'Y%')
430
+ Artist.where("name LIKE ?", 'Y%')
396
431
  # SELECT * FROM artists WHERE name LIKE 'Y%'
397
432
 
398
433
  This is the most common type of placeholder, where each question mark is substituted
399
434
  with the next argument:
400
435
 
401
- Artist.filter("name LIKE ? AND id = ?", 'Y%', 5)
436
+ Artist.where("name LIKE ? AND id = ?", 'Y%', 5)
402
437
  # SELECT * FROM artists WHERE name LIKE 'Y%' AND id = 5
403
438
 
404
439
  You can also use named placeholders with a hash, where the named placeholders use
405
440
  colons before the placeholder names:
406
441
 
407
- Artist.filter("name LIKE :name AND id = :id", :name=>'Y%', :id=>5)
442
+ Artist.where("name LIKE :name AND id = :id", :name=>'Y%', :id=>5)
408
443
  # SELECT * FROM artists WHERE name LIKE 'Y%' AND id = 5
409
444
 
410
445
  You don't have to provide any placeholders if you don't want to:
411
446
 
412
- Artist.filter("id = 2")
447
+ Artist.where("id = 2")
413
448
  # SELECT * FROM artists WHERE id = 2
414
449
 
415
450
  However, if you are using any untrusted input, you should definitely be using placeholders.
@@ -417,9 +452,9 @@ In general, unless you are hardcoding values in the strings, you should use plac
417
452
  You should never pass a string that has been built using interpolation, unless you are
418
453
  sure of what you are doing.
419
454
 
420
- Artist.filter("id = #{params[:id]}") # Don't do this!
421
- Artist.filter("id = ?", params[:id]) # Do this instead
422
- Artist.filter(:id=>params[:id]) # Even better
455
+ Artist.where("id = #{params[:id]}") # Don't do this!
456
+ Artist.where("id = ?", params[:id]) # Do this instead
457
+ Artist.where(:id=>params[:id]) # Even better
423
458
 
424
459
  === Inverting
425
460
 
@@ -427,12 +462,12 @@ You may be wondering how to specify a not equals condition in Sequel, or the NOT
427
462
  operator. Sequel has generic support for inverting conditions, so to write a not
428
463
  equals condition, you write an equals condition, and invert it:
429
464
 
430
- Artist.filter(:id=>5).invert
465
+ Artist.where(:id=>5).invert
431
466
  # SELECT * FROM artists WHERE id != 5
432
467
 
433
468
  Note that +invert+ inverts the entire filter:
434
469
 
435
- Artist.filter(:id=>5).filter{name > 'A'}.invert
470
+ Artist.where(:id=>5).where{name > 'A'}.invert
436
471
  # SELECT * FROM artists WHERE id != 5 OR name <= 'A'
437
472
 
438
473
  In general, +invert+ is used rarely, since +exclude+ allows you to invert only specific
@@ -441,7 +476,7 @@ filters:
441
476
  Artist.exclude(:id=>5)
442
477
  # SELECT * FROM artists WHERE id != 5
443
478
 
444
- Artist.filter(:id=>5).exclude{name > 'A'}
479
+ Artist.where(:id=>5).exclude{name > 'A'}
445
480
  # SELECT * FROM artists WHERE id = 5 OR name <= 'A'
446
481
 
447
482
  So to do a NOT IN with an array:
@@ -451,14 +486,14 @@ So to do a NOT IN with an array:
451
486
 
452
487
  Or to use the NOT LIKE operator:
453
488
 
454
- Artist.exclude(:name.like('%J%'))
489
+ Artist.exclude(Sequel.like(:name, '%J%'))
455
490
  # SELECT * FROM artists WHERE name NOT LIKE '%J%'
456
491
 
457
492
  === Removing
458
493
 
459
494
  To remove all existing filters, use +unfiltered+:
460
495
 
461
- Artist.filter(:id=>1).unfiltered
496
+ Artist.where(:id=>1).unfiltered
462
497
  # SELECT * FROM artists
463
498
 
464
499
  == Ordering
@@ -474,7 +509,7 @@ You can specify multiple arguments to order by more than one column:
474
509
  Album.order(:artist_id, :id)
475
510
  # SELECT * FROM album ORDER BY artist_id, id
476
511
 
477
- Note that unlike +filter+, +order+ replaces an existing order, it does not
512
+ Note that unlike +where+, +order+ replaces an existing order, it does not
478
513
  append to an existing order:
479
514
 
480
515
  Artist.order(:id).order(:name)
@@ -499,15 +534,15 @@ order, using +reverse+:
499
534
  # SELECT FROM artists ORDER BY id DESC
500
535
 
501
536
  As you might expect, +reverse+ is not used all that much. In general,
502
- <tt>Symbol#desc</tt> is used more commonly to specify a descending order
537
+ <tt>Sequel.desc</tt> is used more commonly to specify a descending order
503
538
  for columns:
504
539
 
505
- Artist.order(:id.desc)
540
+ Artist.order(Sequel.desc(:id))
506
541
  # SELECT FROM artists ORDER BY id DESC
507
542
 
508
543
  This allows you to easily use both ascending and descending orders:
509
544
 
510
- Artist.order(:name, :id.desc)
545
+ Artist.order(:name, Sequel.desc(:id))
511
546
  # SELECT FROM artists ORDER BY name, id DESC
512
547
 
513
548
  === Removing
@@ -559,6 +594,12 @@ columns, use +select_all+:
559
594
  Artist.select(:id).select_all
560
595
  # SELECT * FROM artists
561
596
 
597
+ To select all columns from a given table, provide an argument to
598
+ +select_all+:
599
+
600
+ Artist.select_all(:artists)
601
+ # SELECT artists.* FROM artists
602
+
562
603
  === Distinct
563
604
 
564
605
  To treat duplicate rows as a single row when retrieving the records,
@@ -613,6 +654,17 @@ and Sequel provides a +group_and_count+ method to make this easier:
613
654
 
614
655
  This will return the number of albums for each artist_id.
615
656
 
657
+ If you want to select and group on the same columns, you can use +select_group+:
658
+
659
+ Album.select_group(:artist_id)
660
+ # SELECT artist_id FROM albums GROUP BY artist_id
661
+
662
+ Usually you would add a +select_append+ call after that, to add some sort of
663
+ aggregation:
664
+
665
+ Album.select_group(:artist_id).select_append{sum(num_tracks).as(tracks)}
666
+ # SELECT artist_id, sum(num_tracks) AS tracks FROM albums GROUP BY artist_id
667
+
616
668
  == Having
617
669
 
618
670
  The SQL HAVING clause is similar to the WHERE clause, except that
@@ -632,12 +684,9 @@ will add to the HAVING clause instead of the WHERE clause:
632
684
  # SELECT artist_id, COUNT(*) AS count FROM albums
633
685
  # GROUP BY artist_id HAVING count >= 10 AND count < 15
634
686
 
635
- Unlike +filter+, +where+ always affects the WHERE clause:
636
-
637
- Album.group_and_count(:artist_id).
638
- having{count >= 10}.where(:name.like('A%'))
639
- # SELECT artist_id, COUNT(*) AS count FROM albums
640
- # WHERE name LIKE 'A%' GROUP BY artist_id HAVING count >= 10
687
+ This can be confusing, so it is recommended that you always use
688
+ either +having+ or +where+ instead of +filter+, indicating which
689
+ clause that would want affected.
641
690
 
642
691
  Both the WHERE clause and the HAVING clause are removed by +unfiltered+:
643
692
 
@@ -678,7 +727,7 @@ can also provide a model class:
678
727
 
679
728
  Or a dataset, in which case a subselect is used:
680
729
 
681
- Album.join(Artist.filter{name < 'A'}, :id=>:artist_id)
730
+ Album.join(Artist.where{name < 'A'}, :id=>:artist_id)
682
731
  # SELECT * FROM albums
683
732
  # INNER JOIN (SELECT * FROM artists WHERE (name < 'A')) AS t1
684
733
  # ON (t1.id = albums.artist_id)
@@ -746,6 +795,19 @@ as a hash, but allows for duplicate keys:
746
795
  And just like in the hash case, unqualified symbol elements in the
747
796
  array are implicitly qualified.
748
797
 
798
+ By default, Sequel only qualifies unqualified symbols in the conditions. However,
799
+ You can provide an options hash with a <tt>:qualify=>:deep</tt> option to do a deep
800
+ qualification, which can qualify subexpressions. For example, let's say you are doing
801
+ a JOIN using case insensitive string comparison:
802
+
803
+ Album.join(:artists, {Sequel.function(:lower, :name) =>
804
+ Sequel.function(:lower, :artist_name)},
805
+ :qualify => :deep)
806
+ # SELECT * FROM albums INNER JOIN artists
807
+ # ON (lower(artists.name) = lower(albums.artist_name))
808
+
809
+ Note how the arguments to lower were qualified correctly in both cases.
810
+
749
811
  ==== USING Joins
750
812
 
751
813
  The most common type of join conditions is a JOIN ON, as displayed
@@ -788,7 +850,7 @@ and artists tables, but only want albums where the artist's name
788
850
  comes before the album's name.
789
851
 
790
852
  Album.join(:artists, :id=>:artist_id) do |j, lj, js|
791
- :name.qualify(j) < :name.qualify(lj)
853
+ Sequel.qualify(j, :name) < Sequel.qualify(lj, :name)
792
854
  end
793
855
  # SELECT * FROM albums INNER JOIN artists
794
856
  # ON artists.id = albums.artist_id
@@ -888,6 +950,25 @@ With either of these methods, you can use placeholders:
888
950
  DB[:albums].with_sql("SELECT * FROM artists WHERE id = :id", :id=>5)
889
951
  # SELECT * FROM artists WHERE id = 5
890
952
 
953
+ Note that if you specify the dataset using custom SQL, you can still call the dataset
954
+ modification methods, but in many cases they will appear to have no affect:
955
+
956
+ DB["SELECT * FROM artists"].select(:name).order(:id)
957
+ # SELECT * FROM artists
958
+
959
+ If you must drop down to using custom SQL, it's recommended that you only do so for
960
+ specific parts of a query. For example, if the reason you are using custom SQL is
961
+ to use a custom operator in the database in the SELECT clause:
962
+
963
+ DB["SELECT name, (foo !@# ?) AS baz FROM artists", 'bar']
964
+
965
+ it's better to use Sequel's DSL, and use a literal string for the custom operator:
966
+
967
+ DB[:artists].select(:name, Sequel.lit("(foo !@# ?)", 'bar').as(:baz))
968
+
969
+ That way Sequel's method chaining still works, and it increases Sequel's ability to
970
+ introspect the code.
971
+
891
972
  == Checking for Records
892
973
 
893
974
  If you just want to know whether the current dataset would return any rows, use <tt>empty?</tt>:
@@ -896,11 +977,11 @@ If you just want to know whether the current dataset would return any rows, use
896
977
  # SELECT 1 FROM albums LIMIT 1
897
978
  => false
898
979
 
899
- Album.filter(:id=>0).empty?
980
+ Album.where(:id=>0).empty?
900
981
  # SELECT 1 FROM albums WHERE id = 0 LIMIT 1
901
982
  => true
902
983
 
903
- Album.filter(:name.like('R%')).empty?
984
+ Album.where(Sequel.like(:name, 'R%')).empty?
904
985
  # SELECT 1 FROM albums WHERE name LIKE 'R%' LIMIT 1
905
986
  => false
906
987
 
data/doc/reflection.rdoc CHANGED
@@ -4,9 +4,9 @@ Sequel supports reflection information in multiple ways.
4
4
 
5
5
  == Adapter in Use
6
6
 
7
- You can get the adapter in use using Database.adapter_scheme. As this is a class method, you generally need to do DB.class.adapter_scheme:
7
+ You can get the adapter in use using Database#adapter_scheme:
8
8
 
9
- DB.class.adapter_scheme # e.g. :postgres, :jdbc, :odbc
9
+ DB.adapter_scheme # e.g. :postgres, :jdbc, :odbc
10
10
 
11
11
  == Database Connected To
12
12
 
@@ -16,28 +16,54 @@ In some cases, the adapter scheme will be the same as the database to which you
16
16
 
17
17
  == Tables in the Database
18
18
 
19
- On many database types/adapters, Database#tables exists and gives an array of table name symbols:
19
+ Database#tables gives an array of table name symbols:
20
20
 
21
21
  DB.tables # [:table1, :table2, :table3, ...]
22
22
 
23
+ == Views in the Database
24
+
25
+ Database#views and gives an array of view name symbols:
26
+
27
+ DB.views # [:view1, :view2, :view3, ...]
28
+
23
29
  == Indexes on a table
24
30
 
25
- On a few database types/adapters, Database#indexes takes a table name gives a hash of index information. Keys are index names, values are subhashes with the keys :columns and :unique :
31
+ Database#indexes takes a table name gives a hash of index information. Keys are index names, values are subhashes with the keys :columns and :unique :
26
32
 
27
33
  DB.indexes(:table1) # {:index1=>{:columns=>[:column1], :unique=>false}, :index2=>{:columns=>[:column2, :column3], :unique=>true}}
28
34
 
29
35
  Index information generally does not include partial indexes, functional indexes, or indexes on the primary key of the table.
30
36
 
37
+ == Foreign Key Information for a Table
38
+
39
+ Database#foreign_key_list takes a table name and gives an array of hashes of foreign key information:
40
+
41
+ DB.foreign_key_list(:table1) # [{:columns=>[:column1], :table=>:referenced_table, :key=>[:referenced_column1]}]
42
+
43
+ At least the following entries will be present in the hash:
44
+
45
+ :columns :: An array of columns in the given table
46
+ :table :: The table referenced by the columns
47
+ :key :: An array of columns referenced (in the table specified by :table), but can be nil on certain adapters
48
+ if the primary key is referenced.
49
+
50
+ The hash may also contain entries for:
51
+
52
+ :deferrable :: Whether the constraint is deferrable
53
+ :name :: The name of the constraint
54
+ :on_delete :: The action to take ON DELETE
55
+ :on_update :: The action to take ON UPDATE
56
+
31
57
  == Column Information for a Table
32
58
 
33
59
  Database#schema takes a table symbol and returns column information in an array with each element being an array with two elements. The first elements of the subarray is a column symbol, and the second element is a hash of information about that column. The hash should include the following keys:
34
60
 
35
- * :allow_null - Whether NULL/nil is an allowed value for this column. Used by the Sequel::Model typecasting code.
36
- * :db_type - The type of column the database provided, as a string. Used by the schema_dumper plugin for a more specific type translation.
37
- * :default - The default value of the column, as either a string or nil. Uses a database specific format. Used by the schema_dumper plugin for converting to a ruby value.
38
- * :primary_key - Whether this column is one of the primary key columns for the table. Used by the Sequel::Model code to determine primary key columns.
39
- * :ruby_default - The default value of the column as a ruby object, or nil if there is no default or the default could not be successfully parsed into a ruby object.
40
- * :type - The type of column, as a symbol (e.g. :string). Used by the Sequel::Model typecasting code.
61
+ :allow_null :: Whether NULL/nil is an allowed value for this column. Used by the Sequel::Model typecasting code.
62
+ :db_type :: The type of column the database provided, as a string. Used by the schema_dumper plugin for a more specific type translation.
63
+ :default :: The default value of the column, as either a string or nil. Uses a database specific format. Used by the schema_dumper plugin for converting to a ruby value.
64
+ :primary_key :: Whether this column is one of the primary key columns for the table. Used by the Sequel::Model code to determine primary key columns.
65
+ :ruby_default :: The default value of the column as a ruby object, or nil if there is no default or the default could not be successfully parsed into a ruby object.
66
+ :type :: The type of column, as a symbol (e.g. :string). Used by the Sequel::Model typecasting code.
41
67
 
42
68
  Example:
43
69
 
@@ -0,0 +1,39 @@
1
+ = New Features
2
+
3
+ * Support COLLATE in column definitions. At least MySQL and Microsoft
4
+ SQL Server support them, and PostgreSQL 9.1 should as well.
5
+
6
+ * When connecting to Microsoft SQL Server, you can use the
7
+ mssql_unicode_strings accessor to turn of the default usage
8
+ of unicode strings (N'') and use regular strings (''). This
9
+ can improve performance, but changes the behavior. It's
10
+ set to true by default for backwards compatibility. You can
11
+ change it at both the dataset and database level:
12
+
13
+ DB.mssql_unicode_strings = false # default for datasets
14
+ dataset.mssql_unicode_strings = false # just this dataset
15
+
16
+ * In the oracle adapter, if Sequel.application_timezone is :utc, set
17
+ the timezone for the connection to use the 00:00 timezone.
18
+
19
+ = Other Improvements
20
+
21
+ * In the single_table_inheritance plugin, correctly handle a
22
+ multi-level class hierarchy so that loading instances from a
23
+ middle level of the hierarchy can return instances of subclasses.
24
+
25
+ * Don't use a schema when creating a temporary table, even if
26
+ default_schema is set.
27
+
28
+ * Fix the migrator when a default_schema is used.
29
+
30
+ * In the ado adapter, assume a connection to SQL Server if the
31
+ :conn_string is given and doesn't indicate Access/Jet.
32
+
33
+ * Fix fetching rows in the tinytds adapter when the
34
+ identifier_output_method is nil.
35
+
36
+ * The tinytds adapter now checks for disconnect errors, but it might
37
+ not be reliable until the next release of tiny_tds.
38
+
39
+ * The odbc adapter now handles ODBC::Time instances correctly.