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
@@ -26,6 +26,14 @@ module Sequel
26
26
  extend Metaprogramming
27
27
  include Metaprogramming
28
28
  include Enumerable
29
+ include SQL::AliasMethods
30
+ include SQL::BooleanMethods
31
+ include SQL::CastMethods
32
+ include SQL::ComplexExpressionMethods
33
+ include SQL::InequalityMethods
34
+ include SQL::NumericMethods
35
+ include SQL::OrderMethods
36
+ include SQL::StringMethods
29
37
  end
30
38
 
31
39
  require(%w"query actions features graph prepared_statements misc mutation sql", 'dataset')
@@ -44,6 +44,10 @@ module Sequel
44
44
  # and won't reraise it.
45
45
  class Rollback < Error ; end
46
46
 
47
+ # Exception that occurs when unbinding a dataset that has multiple different values
48
+ # for a given variable.
49
+ class UnbindDuplicate < Error; end
50
+
47
51
  class Error
48
52
  AdapterNotFound = Sequel::AdapterNotFound
49
53
  InvalidOperation = Sequel::InvalidOperation
@@ -0,0 +1,83 @@
1
+ # This _pretty_table extension is only for internal use.
2
+ # It adds the Sequel::PrettyTable class without modifying
3
+ # Sequel::Dataset.
4
+ #
5
+ # To load the extension:
6
+ #
7
+ # Sequel.extension :_pretty_table
8
+
9
+ module Sequel
10
+ module PrettyTable
11
+ # Prints nice-looking plain-text tables via puts
12
+ #
13
+ # +--+-------+
14
+ # |id|name |
15
+ # |--+-------|
16
+ # |1 |fasdfas|
17
+ # |2 |test |
18
+ # +--+-------+
19
+ def self.print(records, columns=nil)
20
+ puts string(records, columns)
21
+ end
22
+
23
+ # Return the string that #print will print via puts.
24
+ def self.string(records, columns = nil) # records is an array of hashes
25
+ columns ||= records.first.keys.sort_by{|x|x.to_s}
26
+ sizes = column_sizes(records, columns)
27
+ sep_line = separator_line(columns, sizes)
28
+
29
+ array = [sep_line, header_line(columns, sizes), sep_line]
30
+ records.each {|r| array << data_line(columns, sizes, r)}
31
+ array << sep_line
32
+ array.join("\n")
33
+ end
34
+
35
+ ### Private Module Methods ###
36
+
37
+ # Hash of the maximum size of the value for each column
38
+ def self.column_sizes(records, columns) # :nodoc:
39
+ sizes = Hash.new {0}
40
+ columns.each do |c|
41
+ s = c.to_s.size
42
+ sizes[c.to_sym] = s if s > sizes[c.to_sym]
43
+ end
44
+ records.each do |r|
45
+ columns.each do |c|
46
+ s = r[c].to_s.size
47
+ sizes[c.to_sym] = s if s > sizes[c.to_sym]
48
+ end
49
+ end
50
+ sizes
51
+ end
52
+
53
+ # String for each data line
54
+ def self.data_line(columns, sizes, record) # :nodoc:
55
+ '|' << columns.map {|c| format_cell(sizes[c], record[c])}.join('|') << '|'
56
+ end
57
+
58
+ # Format the value so it takes up exactly size characters
59
+ def self.format_cell(size, v) # :nodoc:
60
+ case v
61
+ when Bignum, Fixnum
62
+ "%#{size}d" % v
63
+ when Float
64
+ "%#{size}g" % v
65
+ else
66
+ "%-#{size}s" % v.to_s
67
+ end
68
+ end
69
+
70
+ # String for header line
71
+ def self.header_line(columns, sizes) # :nodoc:
72
+ '|' << columns.map {|c| "%-#{sizes[c]}s" % c.to_s}.join('|') << '|'
73
+ end
74
+
75
+ # String for separtor line
76
+ def self.separator_line(columns, sizes) # :nodoc:
77
+ '+' << columns.map {|c| '-' * sizes[c]}.join('+') << '+'
78
+ end
79
+
80
+ private_class_method :column_sizes, :data_line, :format_cell, :header_line, :separator_line
81
+ end
82
+ end
83
+
@@ -0,0 +1,109 @@
1
+ # The arbitrary_servers extension allows you to connect to arbitrary
2
+ # servers/shards that were not defined when you created the database.
3
+ # To use it, you first load the extension into the Database object:
4
+ #
5
+ # DB.extension :arbitrary_servers
6
+ #
7
+ # Then you can pass arbitrary connection options for the server/shard
8
+ # to use as a hash:
9
+ #
10
+ # DB[:table].server(:host=>'...', :database=>'...').all
11
+ #
12
+ # Because Sequel can never be sure that the connection will be reused,
13
+ # arbitrary connections are disconnected as soon as the outermost block
14
+ # that uses them exits. So this example uses the same connection:
15
+ #
16
+ # DB.transaction(:server=>{:host=>'...', :database=>'...'}) do |c|
17
+ # DB.transaction(:server=>{:host=>'...', :database=>'...'}) do |c2|
18
+ # # c == c2
19
+ # end
20
+ # end
21
+ #
22
+ # But this example does not:
23
+ #
24
+ # DB.transaction(:server=>{:host=>'...', :database=>'...'}) do |c|
25
+ # end
26
+ # DB.transaction(:server=>{:host=>'...', :database=>'...'}) do |c2|
27
+ # # c != c2
28
+ # end
29
+ #
30
+ # You can use this extension in conjunction with the server_block
31
+ # extension:
32
+ #
33
+ # DB.with_server(:host=>'...', :database=>'...') do
34
+ # DB.synchronize do
35
+ # # All of these use the host/database given to with_server
36
+ # DB[:table].insert(...)
37
+ # DB[:table].update(...)
38
+ # DB.tables
39
+ # DB[:table].all
40
+ # end
41
+ # end
42
+ #
43
+ # Anyone using this extension in conjunction with the server_block
44
+ # extension may want to do the following to so that you don't need
45
+ # to call synchronize separately:
46
+ #
47
+ # def DB.with_server(*)
48
+ # super{synchronize{yield}}
49
+ # end
50
+ #
51
+ # Note that this extension only works with the sharded threaded connection
52
+ # pool. If you are using the sharded single connection pool, you need
53
+ # to switch to the sharded threaded connection pool before using this
54
+ # extension.
55
+
56
+ module Sequel
57
+ module ArbitraryServers
58
+ private
59
+
60
+ # If server is a hash, create a new connection for
61
+ # it, and cache it first by thread and then server.
62
+ def acquire(thread, server)
63
+ if server.is_a?(Hash)
64
+ sync{@allocated[thread] ||= {}}[server] = make_new(server)
65
+ else
66
+ super
67
+ end
68
+ end
69
+
70
+ # If server is a hash, the entry for it probably doesn't
71
+ # exist in the @allocated hash, so check for existence to
72
+ # avoid calling nil.[]
73
+ def owned_connection(thread, server)
74
+ if server.is_a?(Hash)
75
+ if a = sync{@allocated[thread]}
76
+ a[server]
77
+ end
78
+ else
79
+ super
80
+ end
81
+ end
82
+
83
+ # If server is a hash, return it directly.
84
+ def pick_server(server)
85
+ if server.is_a?(Hash)
86
+ server
87
+ else
88
+ super
89
+ end
90
+ end
91
+
92
+ # If server is a hash, delete the thread from the allocated
93
+ # connections for that server. Additionally, if this was the last thread
94
+ # using that server, delete the server from the @allocated hash.
95
+ def release(thread, conn, server)
96
+ if server.is_a?(Hash)
97
+ a = @allocated[thread]
98
+ a.delete(server)
99
+ @allocated.delete(thread) if a.empty?
100
+ db.disconnect_connection(conn)
101
+ else
102
+ super
103
+ end
104
+ end
105
+ end
106
+
107
+ Database.register_extension(:arbitrary_servers){|db| db.pool.extend(ArbitraryServers)}
108
+ end
109
+
@@ -1,4 +1,8 @@
1
1
  # The blank extension adds the blank? method to all objects (e.g. Object#blank?).
2
+ #
3
+ # To load the extension:
4
+ #
5
+ # Sequel.extension :blank
2
6
 
3
7
  class FalseClass
4
8
  # false is always blank
@@ -0,0 +1,72 @@
1
+ # The columns_introspection extension attempts to introspect the
2
+ # selected columns for a dataset before issuing a query. If it
3
+ # thinks it can guess correctly at the columns the query will use,
4
+ # it will return the columns without issuing a database query.
5
+ # This method is not fool-proof, it's possible that some databases
6
+ # will use column names that Sequel does not expect.
7
+ #
8
+ # To attempt to introspect columns for a single dataset:
9
+ #
10
+ # ds.extension(:columns_introspection)
11
+ #
12
+ # To attempt to introspect columns for all datasets on a single database:
13
+ #
14
+ # DB.extension(:columns_introspection)
15
+ #
16
+ # To attempt to introspect columns for all datasets on all databases:
17
+ #
18
+ # Sequel.extension :columns_introspection
19
+ # Sequel::Dataset.introspect_all_columns
20
+
21
+ module Sequel
22
+ module ColumnsIntrospection
23
+ # Attempt to guess the columns that will be returned
24
+ # if there are columns selected, in order to skip a database
25
+ # query to retrieve the columns. This should work with
26
+ # Symbols, SQL::Identifiers, SQL::QualifiedIdentifiers, and
27
+ # SQL::AliasedExpressions.
28
+ def columns
29
+ return @columns if @columns
30
+ return columns_without_introspection unless cols = opts[:select] and !cols.empty?
31
+ probable_columns = cols.map{|c| probable_column_name(c)}
32
+ if probable_columns.all?
33
+ @columns = probable_columns
34
+ else
35
+ columns_without_introspection
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ # Return the probable name of the column, or nil if one
42
+ # cannot be determined.
43
+ def probable_column_name(c)
44
+ case c
45
+ when Symbol
46
+ _, c, a = split_symbol(c)
47
+ (a || c).to_sym
48
+ when SQL::Identifier
49
+ c.value.to_sym
50
+ when SQL::QualifiedIdentifier
51
+ col = c.column
52
+ col.is_a?(SQL::Identifier) ? col.value.to_sym : col.to_sym
53
+ when SQL::AliasedExpression
54
+ a = c.aliaz
55
+ a.is_a?(SQL::Identifier) ? a.value.to_sym : a.to_sym
56
+ end
57
+ end
58
+ end
59
+
60
+ class Dataset
61
+ alias columns_without_introspection columns
62
+
63
+ # Enable column introspection for every dataset.
64
+ def self.introspect_all_columns
65
+ include ColumnsIntrospection
66
+ remove_method(:columns) if instance_methods(false).map{|x| x.to_s}.include?('columns')
67
+ end
68
+ end
69
+
70
+ Dataset.register_extension(:columns_introspection, Sequel::ColumnsIntrospection)
71
+ end
72
+
@@ -0,0 +1,109 @@
1
+ # The connection_validator extension modifies a database's
2
+ # connection pool to validate that connections checked out
3
+ # from the pool are still valid, before yielding them for
4
+ # use. If it detects an invalid connection, it removes it
5
+ # from the pool and tries the next available connection,
6
+ # creating a new connection if no available connection is
7
+ # valid. Example of use:
8
+ #
9
+ # DB.extension(:connection_validator)
10
+ #
11
+ # As checking connections for validity involves issuing a
12
+ # query, which is potentially an expensive operation,
13
+ # the validation checks are only run if the connection has
14
+ # been idle for longer than a certain threshold. By default,
15
+ # that threshold is 3600 seconds (1 hour), but it can be
16
+ # modified by the user, set to -1 to always validate
17
+ # connections on checkout:
18
+ #
19
+ # DB.pool.connection_validation_timeout = -1
20
+ #
21
+ # Note that if you set the timeout to validate connections
22
+ # on every checkout, you should probably manually control
23
+ # connection checkouts on a coarse basis, using
24
+ # Database#synchonrize. In a web application, the optimal
25
+ # place for that would be a rack middleware. Validating
26
+ # connections on every checkout without setting up coarse
27
+ # connection checkouts will hurt performance, in some cases
28
+ # significantly. Note that setting up coarse connection
29
+ # checkouts reduces the concurrency level acheivable. For
30
+ # example, in a web application, using Database#synchronize
31
+ # in a rack middleware will limit the number of concurrent
32
+ # web requests to the number to connections in the database
33
+ # connection pool.
34
+ #
35
+ # Note that this extension only affects the default threaded
36
+ # and the sharded threaded connection pool. The single
37
+ # threaded and sharded single threaded connection pools are
38
+ # not affected. As the only reason to use the single threaded
39
+ # pools is for speed, and this extension makes the connection
40
+ # pool slower, there's not much point in modifying this
41
+ # extension to work with the single threaded pools. The
42
+ # threaded pools work fine even in single threaded code, so if
43
+ # you are currently using a single threaded pool and want to
44
+ # use this extension, switch to using a threaded pool.
45
+
46
+ module Sequel
47
+ module ConnectionValidator
48
+ class Retry < Error; end
49
+
50
+ # The number of seconds that need to pass since
51
+ # connection checkin before attempting to validate
52
+ # the connection when checking it out from the pool.
53
+ # Defaults to 3600 seconds (1 hour).
54
+ attr_accessor :connection_validation_timeout
55
+
56
+ # Initialize the data structures used by this extension.
57
+ def self.extended(pool)
58
+ pool.instance_eval do
59
+ @connection_timestamps ||= {}
60
+ @connection_validation_timeout = 3600
61
+ end
62
+
63
+ # Make sure the valid connection SQL query is precached,
64
+ # otherwise it's possible it will happen at runtime. While
65
+ # it should work correctly at runtime, it's better to avoid
66
+ # the possibility of failure altogether.
67
+ pool.db.send(:valid_connection_sql)
68
+ end
69
+
70
+ private
71
+
72
+ # Record the time the connection was checked back into the pool.
73
+ def checkin_connection(*)
74
+ conn = super
75
+ @connection_timestamps[conn] = Time.now
76
+ conn
77
+ end
78
+
79
+ # When acquiring a connection, if it has been
80
+ # idle for longer than the connection validation timeout,
81
+ # test the connection for validity. If it is not valid,
82
+ # disconnect the connection, and retry with a new connection.
83
+ def acquire(*a)
84
+ begin
85
+ if (conn = super) &&
86
+ (t = sync{@connection_timestamps.delete(conn)}) &&
87
+ Time.now - t > @connection_validation_timeout &&
88
+ !db.valid_connection?(conn)
89
+
90
+ if pool_type == :sharded_threaded
91
+ sync{allocated(a.last).delete(Thread.current)}
92
+ else
93
+ sync{@allocated.delete(Thread.current)}
94
+ end
95
+
96
+ db.disconnect_connection(conn)
97
+ raise Retry
98
+ end
99
+ rescue Retry
100
+ retry
101
+ end
102
+
103
+ conn
104
+ end
105
+ end
106
+
107
+ Database.register_extension(:connection_validator){|db| db.pool.extend(ConnectionValidator)}
108
+ end
109
+