sequel 3.21.0 → 3.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (352) hide show
  1. data/CHANGELOG +1061 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +103 -63
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +67 -51
  7. data/doc/advanced_associations.rdoc +189 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/cheat_sheet.rdoc +21 -21
  10. data/doc/core_extensions.rdoc +374 -0
  11. data/doc/dataset_basics.rdoc +10 -10
  12. data/doc/dataset_filtering.rdoc +54 -42
  13. data/doc/mass_assignment.rdoc +56 -0
  14. data/doc/migration.rdoc +89 -557
  15. data/doc/model_hooks.rdoc +80 -29
  16. data/doc/object_model.rdoc +547 -0
  17. data/doc/opening_databases.rdoc +114 -53
  18. data/doc/prepared_statements.rdoc +41 -15
  19. data/doc/querying.rdoc +137 -56
  20. data/doc/reflection.rdoc +36 -10
  21. data/doc/release_notes/3.22.0.txt +39 -0
  22. data/doc/release_notes/3.23.0.txt +172 -0
  23. data/doc/release_notes/3.24.0.txt +420 -0
  24. data/doc/release_notes/3.25.0.txt +88 -0
  25. data/doc/release_notes/3.26.0.txt +88 -0
  26. data/doc/release_notes/3.27.0.txt +82 -0
  27. data/doc/release_notes/3.28.0.txt +304 -0
  28. data/doc/release_notes/3.29.0.txt +459 -0
  29. data/doc/release_notes/3.30.0.txt +135 -0
  30. data/doc/release_notes/3.31.0.txt +146 -0
  31. data/doc/release_notes/3.32.0.txt +202 -0
  32. data/doc/release_notes/3.33.0.txt +157 -0
  33. data/doc/release_notes/3.34.0.txt +671 -0
  34. data/doc/release_notes/3.35.0.txt +144 -0
  35. data/doc/release_notes/3.36.0.txt +245 -0
  36. data/doc/release_notes/3.37.0.txt +338 -0
  37. data/doc/release_notes/3.38.0.txt +234 -0
  38. data/doc/release_notes/3.39.0.txt +237 -0
  39. data/doc/schema_modification.rdoc +585 -0
  40. data/doc/sharding.rdoc +99 -8
  41. data/doc/sql.rdoc +154 -112
  42. data/doc/testing.rdoc +169 -0
  43. data/doc/thread_safety.rdoc +17 -0
  44. data/doc/transactions.rdoc +137 -0
  45. data/doc/validations.rdoc +1 -1
  46. data/doc/virtual_rows.rdoc +78 -43
  47. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  48. data/lib/sequel/adapters/ado.rb +40 -18
  49. data/lib/sequel/adapters/amalgalite.rb +17 -9
  50. data/lib/sequel/adapters/db2.rb +175 -86
  51. data/lib/sequel/adapters/dbi.rb +15 -15
  52. data/lib/sequel/adapters/do/mysql.rb +17 -11
  53. data/lib/sequel/adapters/do/postgres.rb +2 -61
  54. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  55. data/lib/sequel/adapters/do.rb +18 -36
  56. data/lib/sequel/adapters/firebird.rb +27 -208
  57. data/lib/sequel/adapters/ibmdb.rb +453 -0
  58. data/lib/sequel/adapters/informix.rb +6 -23
  59. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  60. data/lib/sequel/adapters/jdbc/db2.rb +56 -0
  61. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  62. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  63. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  64. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  65. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  66. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  67. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  68. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  69. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  70. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  71. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  73. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  74. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  75. data/lib/sequel/adapters/jdbc.rb +279 -97
  76. data/lib/sequel/adapters/mock.rb +372 -0
  77. data/lib/sequel/adapters/mysql.rb +125 -222
  78. data/lib/sequel/adapters/mysql2.rb +65 -56
  79. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  80. data/lib/sequel/adapters/odbc.rb +28 -9
  81. data/lib/sequel/adapters/openbase.rb +3 -5
  82. data/lib/sequel/adapters/oracle.rb +349 -53
  83. data/lib/sequel/adapters/postgres.rb +368 -138
  84. data/lib/sequel/adapters/shared/access.rb +32 -9
  85. data/lib/sequel/adapters/shared/db2.rb +343 -0
  86. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  87. data/lib/sequel/adapters/shared/informix.rb +53 -0
  88. data/lib/sequel/adapters/shared/mssql.rb +401 -116
  89. data/lib/sequel/adapters/shared/mysql.rb +424 -89
  90. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  91. data/lib/sequel/adapters/shared/oracle.rb +257 -45
  92. data/lib/sequel/adapters/shared/postgres.rb +675 -279
  93. data/lib/sequel/adapters/shared/progress.rb +5 -8
  94. data/lib/sequel/adapters/shared/sqlite.rb +285 -96
  95. data/lib/sequel/adapters/sqlite.rb +101 -39
  96. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  97. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  98. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  99. data/lib/sequel/adapters/swift.rb +28 -19
  100. data/lib/sequel/adapters/tinytds.rb +174 -22
  101. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  102. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  103. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  104. data/lib/sequel/ast_transformer.rb +194 -0
  105. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  106. data/lib/sequel/connection_pool/sharded_threaded.rb +33 -2
  107. data/lib/sequel/connection_pool/single.rb +5 -0
  108. data/lib/sequel/connection_pool/threaded.rb +43 -14
  109. data/lib/sequel/connection_pool.rb +10 -2
  110. data/lib/sequel/core.rb +143 -11
  111. data/lib/sequel/database/connecting.rb +38 -28
  112. data/lib/sequel/database/dataset.rb +4 -4
  113. data/lib/sequel/database/dataset_defaults.rb +63 -2
  114. data/lib/sequel/database/logging.rb +7 -2
  115. data/lib/sequel/database/misc.rb +190 -46
  116. data/lib/sequel/database/query.rb +272 -110
  117. data/lib/sequel/database/schema_generator.rb +103 -36
  118. data/lib/sequel/database/schema_methods.rb +300 -67
  119. data/lib/sequel/dataset/actions.rb +344 -90
  120. data/lib/sequel/dataset/features.rb +101 -8
  121. data/lib/sequel/dataset/graph.rb +42 -15
  122. data/lib/sequel/dataset/misc.rb +52 -25
  123. data/lib/sequel/dataset/mutation.rb +12 -7
  124. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  125. data/lib/sequel/dataset/query.rb +305 -54
  126. data/lib/sequel/dataset/sql.rb +720 -292
  127. data/lib/sequel/dataset.rb +8 -0
  128. data/lib/sequel/exceptions.rb +4 -0
  129. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  130. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  131. data/lib/sequel/extensions/blank.rb +4 -0
  132. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  133. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  134. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  135. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  136. data/lib/sequel/extensions/inflector.rb +4 -0
  137. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  138. data/lib/sequel/extensions/migration.rb +100 -11
  139. data/lib/sequel/extensions/named_timezones.rb +9 -0
  140. data/lib/sequel/extensions/null_dataset.rb +94 -0
  141. data/lib/sequel/extensions/pagination.rb +4 -0
  142. data/lib/sequel/extensions/pg_array.rb +537 -0
  143. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  144. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  145. data/lib/sequel/extensions/pg_hstore.rb +313 -0
  146. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  147. data/lib/sequel/extensions/pg_inet.rb +113 -0
  148. data/lib/sequel/extensions/pg_interval.rb +191 -0
  149. data/lib/sequel/extensions/pg_json.rb +208 -0
  150. data/lib/sequel/extensions/pg_range.rb +512 -0
  151. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  152. data/lib/sequel/extensions/pg_row.rb +572 -0
  153. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  154. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  155. data/lib/sequel/extensions/pretty_table.rb +17 -72
  156. data/lib/sequel/extensions/query.rb +8 -4
  157. data/lib/sequel/extensions/query_literals.rb +79 -0
  158. data/lib/sequel/extensions/schema_caching.rb +76 -0
  159. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  160. data/lib/sequel/extensions/select_remove.rb +39 -0
  161. data/lib/sequel/extensions/server_block.rb +140 -0
  162. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  163. data/lib/sequel/extensions/sql_expr.rb +8 -110
  164. data/lib/sequel/extensions/string_date_time.rb +4 -0
  165. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  166. data/lib/sequel/extensions/to_dot.rb +99 -83
  167. data/lib/sequel/model/associations.rb +1263 -409
  168. data/lib/sequel/model/base.rb +624 -171
  169. data/lib/sequel/model/errors.rb +1 -1
  170. data/lib/sequel/model/exceptions.rb +24 -2
  171. data/lib/sequel/model/inflections.rb +1 -1
  172. data/lib/sequel/model.rb +30 -11
  173. data/lib/sequel/no_core_ext.rb +2 -0
  174. data/lib/sequel/plugins/active_model.rb +13 -1
  175. data/lib/sequel/plugins/association_pks.rb +22 -4
  176. data/lib/sequel/plugins/caching.rb +25 -18
  177. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  178. data/lib/sequel/plugins/composition.rb +44 -12
  179. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  180. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  181. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  182. data/lib/sequel/plugins/dirty.rb +214 -0
  183. data/lib/sequel/plugins/eager_each.rb +59 -0
  184. data/lib/sequel/plugins/force_encoding.rb +6 -6
  185. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  186. data/lib/sequel/plugins/identity_map.rb +134 -15
  187. data/lib/sequel/plugins/instance_filters.rb +10 -0
  188. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  189. data/lib/sequel/plugins/json_serializer.rb +58 -6
  190. data/lib/sequel/plugins/list.rb +13 -2
  191. data/lib/sequel/plugins/many_through_many.rb +103 -51
  192. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  193. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  194. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  195. data/lib/sequel/plugins/pg_row.rb +121 -0
  196. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  197. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  198. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  199. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  200. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  201. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  202. data/lib/sequel/plugins/schema.rb +8 -3
  203. data/lib/sequel/plugins/serialization.rb +98 -49
  204. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  205. data/lib/sequel/plugins/sharding.rb +21 -54
  206. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  207. data/lib/sequel/plugins/static_cache.rb +99 -0
  208. data/lib/sequel/plugins/subclasses.rb +29 -3
  209. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  210. data/lib/sequel/plugins/timestamps.rb +1 -1
  211. data/lib/sequel/plugins/tree.rb +3 -3
  212. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  213. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  214. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  215. data/lib/sequel/plugins/validation_helpers.rb +55 -4
  216. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  217. data/lib/sequel/sql.rb +649 -122
  218. data/lib/sequel/timezones.rb +67 -40
  219. data/lib/sequel/version.rb +1 -1
  220. data/spec/adapters/db2_spec.rb +146 -0
  221. data/spec/adapters/firebird_spec.rb +1 -1
  222. data/spec/adapters/mssql_spec.rb +194 -66
  223. data/spec/adapters/mysql_spec.rb +475 -306
  224. data/spec/adapters/oracle_spec.rb +92 -117
  225. data/spec/adapters/postgres_spec.rb +1982 -325
  226. data/spec/adapters/spec_helper.rb +9 -6
  227. data/spec/adapters/sqlite_spec.rb +203 -75
  228. data/spec/core/connection_pool_spec.rb +218 -93
  229. data/spec/core/database_spec.rb +956 -522
  230. data/spec/core/dataset_spec.rb +1631 -1242
  231. data/spec/core/expression_filters_spec.rb +690 -334
  232. data/spec/core/mock_adapter_spec.rb +453 -0
  233. data/spec/core/object_graph_spec.rb +88 -129
  234. data/spec/core/schema_generator_spec.rb +4 -4
  235. data/spec/core/schema_spec.rb +556 -53
  236. data/spec/core/spec_helper.rb +7 -48
  237. data/spec/core_extensions_spec.rb +626 -0
  238. data/spec/extensions/active_model_spec.rb +13 -0
  239. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  240. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  241. data/spec/extensions/association_dependencies_spec.rb +15 -25
  242. data/spec/extensions/association_pks_spec.rb +66 -32
  243. data/spec/extensions/association_proxies_spec.rb +4 -4
  244. data/spec/extensions/boolean_readers_spec.rb +25 -25
  245. data/spec/extensions/caching_spec.rb +47 -51
  246. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  247. data/spec/extensions/columns_introspection_spec.rb +91 -0
  248. data/spec/extensions/composition_spec.rb +18 -13
  249. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  250. data/spec/extensions/constraint_validations_spec.rb +316 -0
  251. data/spec/extensions/dataset_associations_spec.rb +199 -0
  252. data/spec/extensions/defaults_setter_spec.rb +88 -0
  253. data/spec/extensions/dirty_spec.rb +155 -0
  254. data/spec/extensions/eager_each_spec.rb +34 -0
  255. data/spec/extensions/eval_inspect_spec.rb +67 -0
  256. data/spec/extensions/force_encoding_spec.rb +4 -2
  257. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  258. data/spec/extensions/identity_map_spec.rb +142 -24
  259. data/spec/extensions/inflector_spec.rb +0 -4
  260. data/spec/extensions/instance_filters_spec.rb +11 -21
  261. data/spec/extensions/instance_hooks_spec.rb +72 -0
  262. data/spec/extensions/json_serializer_spec.rb +49 -12
  263. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  264. data/spec/extensions/list_spec.rb +49 -40
  265. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  266. data/spec/extensions/many_through_many_spec.rb +368 -254
  267. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  268. data/spec/extensions/migration_spec.rb +140 -35
  269. data/spec/extensions/named_timezones_spec.rb +29 -11
  270. data/spec/extensions/nested_attributes_spec.rb +268 -89
  271. data/spec/extensions/null_dataset_spec.rb +85 -0
  272. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  273. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  274. data/spec/extensions/pg_array_spec.rb +320 -0
  275. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  276. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  277. data/spec/extensions/pg_hstore_spec.rb +194 -0
  278. data/spec/extensions/pg_inet_spec.rb +47 -0
  279. data/spec/extensions/pg_interval_spec.rb +72 -0
  280. data/spec/extensions/pg_json_spec.rb +99 -0
  281. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  282. data/spec/extensions/pg_range_spec.rb +395 -0
  283. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  284. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  285. data/spec/extensions/pg_row_spec.rb +323 -0
  286. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  287. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  288. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  289. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  290. data/spec/extensions/prepared_statements_spec.rb +87 -0
  291. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  292. data/spec/extensions/pretty_table_spec.rb +7 -6
  293. data/spec/extensions/query_literals_spec.rb +167 -0
  294. data/spec/extensions/query_spec.rb +9 -3
  295. data/spec/extensions/rcte_tree_spec.rb +50 -43
  296. data/spec/extensions/schema_caching_spec.rb +41 -0
  297. data/spec/extensions/schema_dumper_spec.rb +434 -49
  298. data/spec/extensions/schema_spec.rb +30 -49
  299. data/spec/extensions/select_remove_spec.rb +38 -0
  300. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  301. data/spec/extensions/serialization_spec.rb +86 -48
  302. data/spec/extensions/server_block_spec.rb +90 -0
  303. data/spec/extensions/sharding_spec.rb +69 -143
  304. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  305. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  306. data/spec/extensions/spec_helper.rb +34 -67
  307. data/spec/extensions/split_array_nil_spec.rb +24 -0
  308. data/spec/extensions/sql_expr_spec.rb +29 -60
  309. data/spec/extensions/static_cache_spec.rb +145 -0
  310. data/spec/extensions/subclasses_spec.rb +14 -0
  311. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  312. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  313. data/spec/extensions/timestamps_spec.rb +6 -6
  314. data/spec/extensions/to_dot_spec.rb +8 -11
  315. data/spec/extensions/touch_spec.rb +13 -14
  316. data/spec/extensions/tree_spec.rb +11 -26
  317. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  318. data/spec/extensions/update_primary_key_spec.rb +30 -24
  319. data/spec/extensions/validation_class_methods_spec.rb +58 -67
  320. data/spec/extensions/validation_helpers_spec.rb +31 -37
  321. data/spec/extensions/xml_serializer_spec.rb +29 -4
  322. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  323. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  324. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  325. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  326. data/spec/integration/associations_test.rb +659 -21
  327. data/spec/integration/database_test.rb +11 -5
  328. data/spec/integration/dataset_test.rb +717 -129
  329. data/spec/integration/eager_loader_test.rb +38 -54
  330. data/spec/integration/migrator_test.rb +2 -3
  331. data/spec/integration/model_test.rb +81 -2
  332. data/spec/integration/plugin_test.rb +604 -147
  333. data/spec/integration/prepared_statement_test.rb +272 -128
  334. data/spec/integration/schema_test.rb +367 -57
  335. data/spec/integration/spec_helper.rb +42 -32
  336. data/spec/integration/timezone_test.rb +38 -12
  337. data/spec/integration/transaction_test.rb +183 -8
  338. data/spec/integration/type_test.rb +31 -8
  339. data/spec/model/association_reflection_spec.rb +207 -8
  340. data/spec/model/associations_spec.rb +1206 -693
  341. data/spec/model/base_spec.rb +334 -100
  342. data/spec/model/dataset_methods_spec.rb +45 -27
  343. data/spec/model/eager_loading_spec.rb +828 -692
  344. data/spec/model/hooks_spec.rb +355 -67
  345. data/spec/model/model_spec.rb +251 -179
  346. data/spec/model/plugins_spec.rb +24 -13
  347. data/spec/model/record_spec.rb +506 -232
  348. data/spec/model/spec_helper.rb +16 -77
  349. data/spec/model/validations_spec.rb +38 -2
  350. data/spec/rcov.opts +2 -0
  351. metadata +209 -80
  352. data/spec/core/core_sql_spec.rb +0 -451
@@ -0,0 +1,199 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "Sequel::Plugins::DatasetAssociations" do
4
+ before do
5
+ @db = Sequel::Database.new
6
+ @Base = Class.new(Sequel::Model)
7
+ @Base.plugin :dataset_associations
8
+
9
+ @Artist = Class.new(@Base)
10
+ @Album = Class.new(@Base)
11
+ @Tag = Class.new(@Base)
12
+
13
+ @Artist.meta_def(:name){'Artist'}
14
+ @Album.meta_def(:name){'Album'}
15
+ @Tag.meta_def(:name){'Tag'}
16
+
17
+ @Artist.dataset = @db[:artists]
18
+ @Album.dataset = @db[:albums]
19
+ @Tag.dataset = @db[:tags]
20
+
21
+ @Artist.columns :id, :name
22
+ @Album.columns :id, :name, :artist_id
23
+ @Tag.columns :id, :name
24
+
25
+ @Artist.plugin :many_through_many
26
+ @Artist.one_to_many :albums, :class=>@Album
27
+ @Artist.one_to_one :first_album, :class=>@Album
28
+ @Album.many_to_one :artist, :class=>@Artist
29
+ @Album.many_to_many :tags, :class=>@Tag
30
+ @Tag.many_to_many :albums, :class=>@Album
31
+ @Artist.many_through_many :tags, [[:albums, :artist_id, :id], [:albums_tags, :album_id, :tag_id]], :class=>@Tag
32
+ end
33
+
34
+ it "should work for many_to_one associations" do
35
+ ds = @Album.artists
36
+ ds.should be_a_kind_of(Sequel::Dataset)
37
+ ds.model.should == @Artist
38
+ ds.sql.should == "SELECT * FROM artists WHERE (artists.id IN (SELECT albums.artist_id FROM albums))"
39
+ end
40
+
41
+ it "should work for one_to_many associations" do
42
+ ds = @Artist.albums
43
+ ds.should be_a_kind_of(Sequel::Dataset)
44
+ ds.model.should == @Album
45
+ ds.sql.should == "SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists))"
46
+ end
47
+
48
+ it "should work for one_to_one associations" do
49
+ ds = @Artist.first_albums
50
+ ds.should be_a_kind_of(Sequel::Dataset)
51
+ ds.model.should == @Album
52
+ ds.sql.should == "SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists))"
53
+ end
54
+
55
+ it "should work for many_to_many associations" do
56
+ ds = @Album.tags
57
+ ds.should be_a_kind_of(Sequel::Dataset)
58
+ ds.model.should == @Tag
59
+ ds.sql.should == "SELECT tags.* FROM tags WHERE (tags.id IN (SELECT albums_tags.tag_id FROM albums INNER JOIN albums_tags ON (albums_tags.album_id = albums.id)))"
60
+ end
61
+
62
+ it "should work for many_through_many associations" do
63
+ ds = @Artist.tags
64
+ ds.should be_a_kind_of(Sequel::Dataset)
65
+ ds.model.should == @Tag
66
+ ds.sql.should == "SELECT tags.* FROM tags WHERE (tags.id IN (SELECT albums_tags.tag_id FROM artists INNER JOIN albums ON (albums.artist_id = artists.id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id)))"
67
+ end
68
+
69
+ it "should have an associated method that takes an association symbol" do
70
+ ds = @Album.associated(:artist)
71
+ ds.should be_a_kind_of(Sequel::Dataset)
72
+ ds.model.should == @Artist
73
+ ds.sql.should == "SELECT * FROM artists WHERE (artists.id IN (SELECT albums.artist_id FROM albums))"
74
+ end
75
+
76
+ it "should raise an Error if an invalid association is given to associated" do
77
+ proc{@Album.associated(:foo)}.should raise_error(Sequel::Error)
78
+ end
79
+
80
+ it "should raise an Error if an unrecognized association type is used" do
81
+ @Album.association_reflection(:artist)[:type] = :foo
82
+ proc{@Album.artists}.should raise_error(Sequel::Error)
83
+ end
84
+
85
+ it "should work correctly when chaining" do
86
+ ds = @Artist.albums.tags
87
+ ds.should be_a_kind_of(Sequel::Dataset)
88
+ ds.model.should == @Tag
89
+ ds.sql.should == "SELECT tags.* FROM tags WHERE (tags.id IN (SELECT albums_tags.tag_id FROM albums INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE (albums.artist_id IN (SELECT artists.id FROM artists))))"
90
+ end
91
+
92
+ it "should deal correctly with filters before the association method" do
93
+ @Artist.filter(:id=>1).albums.sql.should == "SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists WHERE (id = 1)))"
94
+ end
95
+
96
+ it "should deal correctly with filters after the association method" do
97
+ @Artist.albums.filter(:id=>1).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id IN (SELECT artists.id FROM artists)) AND (id = 1))"
98
+ end
99
+
100
+ it "should deal correctly with block on the association" do
101
+ @Artist.one_to_many :albums, :clone=>:albums do |ds| ds.filter(:id=>1..100) end
102
+ @Artist.albums.sql.should == "SELECT * FROM albums WHERE ((albums.artist_id IN (SELECT artists.id FROM artists)) AND (id >= 1) AND (id <= 100))"
103
+ end
104
+
105
+ it "should deal correctly with :conditions option on the association" do
106
+ @Artist.one_to_many :albums, :clone=>:albums, :conditions=>{:id=>1..100}
107
+ @Artist.albums.sql.should == "SELECT * FROM albums WHERE ((albums.artist_id IN (SELECT artists.id FROM artists)) AND (id >= 1) AND (id <= 100))"
108
+ end
109
+
110
+ it "should deal correctly with :distinct option on the association" do
111
+ @Artist.one_to_many :albums, :clone=>:albums, :distinct=>true
112
+ @Artist.albums.sql.should == "SELECT DISTINCT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists))"
113
+ end
114
+
115
+ it "should deal correctly with :eager option on the association" do
116
+ @Artist.one_to_many :albums, :clone=>:albums, :eager=>:tags
117
+ @Artist.albums.opts[:eager].should == {:tags=>nil}
118
+ end
119
+
120
+ it "should deal correctly with :eager_block option on the association, ignoring the association block" do
121
+ @Artist.one_to_many :albums, :clone=>:albums, :eager_block=>proc{|ds| ds.filter(:id=>1..100)} do |ds| ds.filter(:id=>2..200) end
122
+ @Artist.albums.sql.should == "SELECT * FROM albums WHERE ((albums.artist_id IN (SELECT artists.id FROM artists)) AND (id >= 1) AND (id <= 100))"
123
+ end
124
+
125
+ it "should deal correctly with :extend option on the association" do
126
+ @Artist.one_to_many :albums, :clone=>:albums, :extend=>Module.new{def foo(x) filter(:id=>x) end}
127
+ @Artist.albums.foo(1).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id IN (SELECT artists.id FROM artists)) AND (id = 1))"
128
+ end
129
+
130
+ it "should deal correctly with :order option on the association" do
131
+ @Artist.one_to_many :albums, :clone=>:albums, :order=>:name
132
+ @Artist.albums.sql.should == "SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists)) ORDER BY name"
133
+ end
134
+
135
+ it "should deal correctly with :select option on the association" do
136
+ @Artist.one_to_many :albums, :clone=>:albums, :select=>[:id, :name]
137
+ @Artist.albums.sql.should == "SELECT id, name FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists))"
138
+ end
139
+ end
140
+
141
+ describe "Sequel::Plugins::DatasetAssociations with composite keys" do
142
+ before do
143
+ @db = Sequel::Database.new
144
+ @Base = Class.new(Sequel::Model)
145
+ @Base.plugin :dataset_associations
146
+
147
+ @Artist = Class.new(@Base)
148
+ @Album = Class.new(@Base)
149
+ @Tag = Class.new(@Base)
150
+
151
+ @Artist.meta_def(:name){'Artist'}
152
+ @Album.meta_def(:name){'Album'}
153
+ @Tag.meta_def(:name){'Tag'}
154
+
155
+ @Artist.dataset = @db[:artists]
156
+ @Album.dataset = @db[:albums]
157
+ @Tag.dataset = @db[:tags]
158
+
159
+ @Artist.set_primary_key([:id1, :id2])
160
+ @Album.set_primary_key([:id1, :id2])
161
+ @Tag.set_primary_key([:id1, :id2])
162
+
163
+ @Artist.columns :id1, :id2, :name
164
+ @Album.columns :id1, :id2, :name, :artist_id1, :artist_id2
165
+ @Tag.columns :id1, :id2, :name
166
+
167
+ @Artist.plugin :many_through_many
168
+ @Artist.one_to_many :albums, :class=>@Album, :key=>[:artist_id1, :artist_id2]
169
+ @Artist.one_to_one :first_album, :class=>@Album, :key=>[:artist_id1, :artist_id2]
170
+ @Album.many_to_one :artist, :class=>@Artist, :key=>[:artist_id1, :artist_id2]
171
+ @Album.many_to_many :tags, :class=>@Tag, :left_key=>[:album_id1, :album_id2], :right_key=>[:tag_id1, :tag_id2]
172
+ @Tag.many_to_many :albums, :class=>@Album, :right_key=>[:album_id1, :album_id2], :left_key=>[:tag_id1, :tag_id2]
173
+ @Artist.many_through_many :tags, [[:albums, [:artist_id1, :artist_id2], [:id1, :id2]], [:albums_tags, [:album_id1, :album_id2], [:tag_id1, :tag_id2]]], :class=>@Tag
174
+ end
175
+
176
+ it "should work for many_to_one associations" do
177
+ @Album.artists.sql.should == "SELECT * FROM artists WHERE ((artists.id1, artists.id2) IN (SELECT albums.artist_id1, albums.artist_id2 FROM albums))"
178
+ end
179
+
180
+ it "should work for one_to_many associations" do
181
+ @Artist.albums.sql.should == "SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists))"
182
+ end
183
+
184
+ it "should work for one_to_one associations" do
185
+ @Artist.first_albums.sql.should == "SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists))"
186
+ end
187
+
188
+ it "should work for many_to_many associations" do
189
+ @Album.tags.sql.should == "SELECT tags.* FROM tags WHERE ((tags.id1, tags.id2) IN (SELECT albums_tags.tag_id1, albums_tags.tag_id2 FROM albums INNER JOIN albums_tags ON ((albums_tags.album_id1 = albums.id1) AND (albums_tags.album_id2 = albums.id2))))"
190
+ end
191
+
192
+ it "should work for many_through_many associations" do
193
+ @Artist.tags.sql.should == "SELECT tags.* FROM tags WHERE ((tags.id1, tags.id2) IN (SELECT albums_tags.tag_id1, albums_tags.tag_id2 FROM artists INNER JOIN albums ON ((albums.artist_id1 = artists.id1) AND (albums.artist_id2 = artists.id2)) INNER JOIN albums_tags ON ((albums_tags.album_id1 = albums.id1) AND (albums_tags.album_id2 = albums.id2))))"
194
+ end
195
+
196
+ it "should work correctly when chaining" do
197
+ @Artist.albums.tags.sql.should == "SELECT tags.* FROM tags WHERE ((tags.id1, tags.id2) IN (SELECT albums_tags.tag_id1, albums_tags.tag_id2 FROM albums INNER JOIN albums_tags ON ((albums_tags.album_id1 = albums.id1) AND (albums_tags.album_id2 = albums.id2)) WHERE ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists))))"
198
+ end
199
+ end
@@ -0,0 +1,88 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "Sequel::Plugins::DefaultsSetter" do
4
+ before do
5
+ @db = db = Sequel::Database.new
6
+ @c = c = Class.new(Sequel::Model(db[:foo]))
7
+ @c.instance_variable_set(:@db_schema, {:a=>{}})
8
+ @c.plugin :defaults_setter
9
+ @c.columns :a
10
+ @pr = proc{|x| db.meta_def(:schema){|*| [[:a, {:ruby_default => x}]]}; c.dataset = c.dataset; c}
11
+ end
12
+ after do
13
+ Sequel.datetime_class = Time
14
+ end
15
+
16
+ it "should set default value upon initialization" do
17
+ @pr.call(2).new.values.should == {:a=>2}
18
+ end
19
+
20
+ it "should not mark the column as modified" do
21
+ @pr.call(2).new.changed_columns.should == []
22
+ end
23
+
24
+ it "should not set a default of nil" do
25
+ @pr.call(nil).new.values.should == {}
26
+ end
27
+
28
+ it "should set a default of false" do
29
+ @pr.call(false).new.values.should == {:a=>false}
30
+ end
31
+
32
+ it "should handle Sequel::CURRENT_DATE default by using the current Date" do
33
+ @pr.call(Sequel::CURRENT_DATE).new.a.should == Date.today
34
+ end
35
+
36
+ it "should handle Sequel::CURRENT_TIMESTAMP default by using the current Time" do
37
+ t = @pr.call(Sequel::CURRENT_TIMESTAMP).new.a
38
+ t.should be_a_kind_of(Time)
39
+ (t - Time.now).should < 1
40
+ end
41
+
42
+ it "should handle Sequel::CURRENT_TIMESTAMP default by using the current DateTime if Sequel.datetime_class is DateTime" do
43
+ Sequel.datetime_class = DateTime
44
+ t = @pr.call(Sequel::CURRENT_TIMESTAMP).new.a
45
+ t.should be_a_kind_of(DateTime)
46
+ (t - DateTime.now).should < 1/86400.0
47
+ end
48
+
49
+ it "should not override a given value" do
50
+ @pr.call(2)
51
+ @c.new('a'=>3).values.should == {:a=>3}
52
+ @c.new('a'=>nil).values.should == {:a=>nil}
53
+ end
54
+
55
+ it "should work correctly when subclassing" do
56
+ Class.new(@pr.call(2)).new.values.should == {:a=>2}
57
+ end
58
+
59
+ it "should contain the default values in default_values" do
60
+ @pr.call(2).default_values.should == {:a=>2}
61
+ @pr.call(nil).default_values.should == {}
62
+ end
63
+
64
+ it "should allow modifications of default values" do
65
+ @pr.call(2)
66
+ @c.default_values[:a] = 3
67
+ @c.new.values.should == {:a => 3}
68
+ end
69
+
70
+ it "should allow proc default values" do
71
+ @pr.call(2)
72
+ @c.default_values[:a] = proc{3}
73
+ @c.new.values.should == {:a => 3}
74
+ end
75
+
76
+ it "should have procs that set default values set them to nil" do
77
+ @pr.call(2)
78
+ @c.default_values[:a] = proc{nil}
79
+ @c.new.values.should == {:a => nil}
80
+ end
81
+
82
+ it "should work correctly on a model without a dataset" do
83
+ @pr.call(2)
84
+ c = Class.new(Sequel::Model(@db[:bar]))
85
+ c.plugin :defaults_setter
86
+ c.default_values.should == {:a=>2}
87
+ end
88
+ end
@@ -0,0 +1,155 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "Sequel::Plugins::Dirty" do
4
+ before do
5
+ @db = Sequel.mock(:fetch=>{:initial=>'i', :initial_changed=>'ic'}, :numrows=>1)
6
+ @c = Class.new(Sequel::Model(@db[:c]))
7
+ @c.plugin :dirty
8
+ @c.columns :initial, :initial_changed, :missing, :missing_changed
9
+ end
10
+
11
+ shared_examples_for "dirty plugin" do
12
+ it "initial_value should be the current value if value has not changed" do
13
+ @o.initial_value(:initial).should == 'i'
14
+ @o.initial_value(:missing).should == nil
15
+ end
16
+
17
+ it "initial_value should be the intial value if value has changed" do
18
+ @o.initial_value(:initial_changed).should == 'ic'
19
+ @o.initial_value(:missing_changed).should == nil
20
+ end
21
+
22
+ it "initial_value should handle case where initial value is reassigned later" do
23
+ @o.initial_changed = 'ic'
24
+ @o.initial_value(:initial_changed).should == 'ic'
25
+ @o.missing_changed = nil
26
+ @o.initial_value(:missing_changed).should == nil
27
+ end
28
+
29
+ it "changed_columns should handle case where initial value is reassigned later" do
30
+ @o.changed_columns.should == [:initial_changed, :missing_changed]
31
+ @o.initial_changed = 'ic'
32
+ @o.changed_columns.should == [:missing_changed]
33
+ @o.missing_changed = nil
34
+ @o.changed_columns.should == [:missing_changed]
35
+ end
36
+
37
+ it "column_change should give initial and current values if there has been a change made" do
38
+ @o.column_change(:initial_changed).should == ['ic', 'ic2']
39
+ @o.column_change(:missing_changed).should == [nil, 'mc2']
40
+ end
41
+
42
+ it "column_change should be nil if no change has been made" do
43
+ @o.column_change(:initial).should == nil
44
+ @o.column_change(:missing).should == nil
45
+ end
46
+
47
+ it "column_changed? should return whether the column has changed" do
48
+ @o.column_changed?(:initial).should == false
49
+ @o.column_changed?(:initial_changed).should == true
50
+ @o.column_changed?(:missing).should == false
51
+ @o.column_changed?(:missing_changed).should == true
52
+ end
53
+
54
+ it "column_changed? should handle case where initial value is reassigned later" do
55
+ @o.initial_changed = 'ic'
56
+ @o.column_changed?(:initial_changed).should == false
57
+ @o.missing_changed = nil
58
+ @o.column_changed?(:missing_changed).should == false
59
+ end
60
+
61
+ it "changed_columns should handle case where initial value is reassigned later" do
62
+ @o.changed_columns.should == [:initial_changed, :missing_changed]
63
+ @o.initial_changed = 'ic'
64
+ @o.changed_columns.should == [:missing_changed]
65
+ @o.missing_changed = nil
66
+ @o.changed_columns.should == [:missing_changed]
67
+ end
68
+
69
+ it "column_changes should give initial and current values" do
70
+ @o.column_changes.should == {:initial_changed=>['ic', 'ic2'], :missing_changed=>[nil, 'mc2']}
71
+ end
72
+
73
+ it "reset_column should reset the column to its initial value" do
74
+ @o.reset_column(:initial)
75
+ @o.initial.should == 'i'
76
+ @o.reset_column(:initial_changed)
77
+ @o.initial_changed.should == 'ic'
78
+ @o.reset_column(:missing)
79
+ @o.missing.should == nil
80
+ @o.reset_column(:missing_changed)
81
+ @o.missing_changed.should == nil
82
+ end
83
+
84
+ it "reset_column should remove missing values from the values" do
85
+ @o.reset_column(:missing)
86
+ @o.values.has_key?(:missing).should == false
87
+ @o.reset_column(:missing_changed)
88
+ @o.values.has_key?(:missing_changed).should == false
89
+ end
90
+
91
+ it "refresh should clear the cached initial values" do
92
+ @o.refresh
93
+ @o.column_changes.should == {}
94
+ end
95
+
96
+ it "will_change_column should be used to signal in-place modification to column" do
97
+ @o.will_change_column(:initial)
98
+ @o.initial << 'b'
99
+ @o.column_change(:initial).should == ['i', 'ib']
100
+ @o.will_change_column(:initial_changed)
101
+ @o.initial_changed << 'b'
102
+ @o.column_change(:initial_changed).should == ['ic', 'ic2b']
103
+ @o.will_change_column(:missing)
104
+ @o.values[:missing] = 'b'
105
+ @o.column_change(:missing).should == [nil, 'b']
106
+ @o.will_change_column(:missing_changed)
107
+ @o.missing_changed << 'b'
108
+ @o.column_change(:missing_changed).should == [nil, 'mc2b']
109
+ end
110
+
111
+ it "will_change_column should different types of existing objects" do
112
+ [nil, true, false, Class.new{undef_method :clone}.new, Class.new{def clone; raise TypeError; end}.new].each do |v|
113
+ o = @c.new(:initial=>v)
114
+ o.will_change_column(:initial)
115
+ o.initial = 'a'
116
+ o.column_change(:initial).should == [v, 'a']
117
+ end
118
+ end
119
+
120
+ it "save should clear the cached initial values" do
121
+ @o.save
122
+ @o.column_changes.should == {}
123
+ end
124
+
125
+ it "save_changes should clear the cached initial values" do
126
+ @o.save_changes
127
+ @o.column_changes.should == {}
128
+ end
129
+ end
130
+
131
+ describe "with new instance" do
132
+ before do
133
+ @o = @c.new(:initial=>'i', :initial_changed=>'ic')
134
+ @o.initial_changed = 'ic2'
135
+ @o.missing_changed = 'mc2'
136
+ end
137
+
138
+ it_should_behave_like "dirty plugin"
139
+ end
140
+
141
+ describe "with existing instance" do
142
+ before do
143
+ @o = @c[1]
144
+ @o.initial_changed = 'ic2'
145
+ @o.missing_changed = 'mc2'
146
+ end
147
+
148
+ it_should_behave_like "dirty plugin"
149
+
150
+ it "previous_changes should be the previous changes after saving" do
151
+ @o.save
152
+ @o.previous_changes.should == {:initial_changed=>['ic', 'ic2'], :missing_changed=>[nil, 'mc2']}
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,34 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "Sequel::Plugins::EagerEach" do
4
+ before do
5
+ @c = Class.new(Sequel::Model(:items))
6
+ @c.columns :id, :parent_id
7
+ @c.plugin :eager_each
8
+ @c.one_to_many :children, :class=>@c, :key=>:parent_id
9
+ @c.db.sqls
10
+ end
11
+
12
+ it "should make #each on an eager dataset do eager loading" do
13
+ a = []
14
+ ds = @c.eager(:children)
15
+ ds._fetch = [{:id=>1, :parent_id=>nil}, {:id=>2, :parent_id=>nil}]
16
+ @c.dataset._fetch = [{:id=>3, :parent_id=>1}, {:id=>4, :parent_id=>1}, {:id=>5, :parent_id=>2}, {:id=>6, :parent_id=>2}]
17
+ ds.each{|c| a << c}
18
+ a.should == [@c.load(:id=>1, :parent_id=>nil), @c.load(:id=>2, :parent_id=>nil)]
19
+ a.map{|c| c.associations[:children]}.should == [[@c.load(:id=>3, :parent_id=>1), @c.load(:id=>4, :parent_id=>1)], [@c.load(:id=>5, :parent_id=>2), @c.load(:id=>6, :parent_id=>2)]]
20
+ @c.db.sqls.should == ['SELECT * FROM items', 'SELECT * FROM items WHERE (items.parent_id IN (1, 2))']
21
+ end
22
+
23
+ it "should make #each on an eager_graph dataset do eager loading" do
24
+ a = []
25
+ ds = @c.eager_graph(:children)
26
+ ds._fetch = []
27
+ ds._fetch = [{:id=>1, :parent_id=>nil, :children_id=>3, :children_parent_id=>1}, {:id=>1, :parent_id=>nil, :children_id=>4, :children_parent_id=>1}, {:id=>2, :parent_id=>nil, :children_id=>5, :children_parent_id=>2}, {:id=>2, :parent_id=>nil, :children_id=>6, :children_parent_id=>2}]
28
+ ds.each{|c| a << c}
29
+ a.should == [@c.load(:id=>1, :parent_id=>nil), @c.load(:id=>2, :parent_id=>nil)]
30
+ a.map{|c| c.associations[:children]}.should == [[@c.load(:id=>3, :parent_id=>1), @c.load(:id=>4, :parent_id=>1)], [@c.load(:id=>5, :parent_id=>2), @c.load(:id=>6, :parent_id=>2)]]
31
+ @c.db.sqls.should == ['SELECT items.id, items.parent_id, children.id AS children_id, children.parent_id AS children_parent_id FROM items LEFT OUTER JOIN items AS children ON (children.parent_id = items.id)']
32
+ end
33
+
34
+ end
@@ -0,0 +1,67 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "eval_inspect extension" do
4
+ before do
5
+ @ds = Sequel.mock.dataset
6
+ @ds.meta_def(:supports_window_functions?){true}
7
+ @ds.meta_def(:literal_blob_append){|sql, s| sql << "X'#{s}'"}
8
+ end
9
+
10
+ specify "should make eval(obj.inspect) == obj for all Sequel::SQL::Expression subclasses" do
11
+ [
12
+ # Objects with components where eval(inspect) == self
13
+ Sequel::SQL::AliasedExpression.new(:b, :a),
14
+ Sequel::SQL::CaseExpression.new({:b=>:a}, :c),
15
+ Sequel::SQL::CaseExpression.new({:b=>:a}, :c, :d),
16
+ Sequel::SQL::Cast.new(:a, :b),
17
+ Sequel::SQL::ColumnAll.new(:a),
18
+ Sequel::SQL::ComplexExpression.new(:'=', :b, :a),
19
+ Sequel::SQL::Constant.new(:a),
20
+ Sequel::CURRENT_DATE,
21
+ Sequel::CURRENT_TIMESTAMP,
22
+ Sequel::CURRENT_TIME,
23
+ Sequel::SQLTRUE,
24
+ Sequel::SQLFALSE,
25
+ Sequel::NULL,
26
+ Sequel::NOTNULL,
27
+ Sequel::SQL::Function.new(:a, :b, :c),
28
+ Sequel::SQL::Identifier.new(:a),
29
+ Sequel::SQL::JoinClause.new(:inner, :b, :c),
30
+ Sequel::SQL::JoinOnClause.new({:d=>:a}, :inner, :b, :c),
31
+ Sequel::SQL::JoinUsingClause.new([:a], :inner, :b, :c),
32
+ Sequel::SQL::PlaceholderLiteralString.new('? = ?', [:a, :b]),
33
+ Sequel::SQL::PlaceholderLiteralString.new(':a = :b', [{:a=>:b, :b=>42}]),
34
+ Sequel::SQL::OrderedExpression.new(:a),
35
+ Sequel::SQL::OrderedExpression.new(:a, false),
36
+ Sequel::SQL::OrderedExpression.new(:a, false, :nulls=>:first),
37
+ Sequel::SQL::OrderedExpression.new(:a, false, :nulls=>:last),
38
+ Sequel::SQL::QualifiedIdentifier.new(:b, :a),
39
+ Sequel::SQL::Subscript.new(:a, [1, 2]),
40
+ Sequel::SQL::Window.new(:order=>:a, :partition=>:b),
41
+ Sequel::SQL::WindowFunction.new(Sequel::SQL::Function.new(:a, :b, :c), Sequel::SQL::Window.new(:order=>:a, :partition=>:b)),
42
+ Sequel::SQL::Wrapper.new(:a),
43
+
44
+ # Objects with components where eval(inspect) != self
45
+ Sequel::SQL::AliasedExpression.new(Sequel::SQL::Blob.new('s'), :a),
46
+ Sequel::SQL::AliasedExpression.new(Sequel::LiteralString.new('s'), :a),
47
+ Sequel::SQL::PlaceholderLiteralString.new('(a, b) IN ?', [Sequel::SQL::ValueList.new([[1, 2]])]),
48
+ Sequel::SQL::CaseExpression.new({{:d=>Sequel::LiteralString.new('e')}=>:a}, :c, :d),
49
+ Sequel::SQL::AliasedExpression.new(Date.new(2011, 10, 11), :a),
50
+ Sequel::SQL::AliasedExpression.new(Sequel::SQLTime.create(10, 20, 30, 500000.125), :a),
51
+ Sequel::SQL::AliasedExpression.new(DateTime.new(2011, 9, 11, 10, 20, 30), :a),
52
+ Sequel::SQL::AliasedExpression.new(DateTime.new(2011, 9, 11, 10, 20, 30, 0.25), :a),
53
+ Sequel::SQL::AliasedExpression.new(DateTime.new(2011, 9, 11, 10, 20, 30, -0.25), :a),
54
+ Sequel::SQL::AliasedExpression.new(Time.local(2011, 9, 11, 10, 20, 30), :a),
55
+ Sequel::SQL::AliasedExpression.new(Time.local(2011, 9, 11, 10, 20, 30, 500000.125), :a),
56
+ Sequel::SQL::AliasedExpression.new(Time.utc(2011, 9, 11, 10, 20, 30), :a),
57
+ Sequel::SQL::AliasedExpression.new(Time.utc(2011, 9, 11, 10, 20, 30, 500000.125), :a),
58
+ Sequel::SQL::AliasedExpression.new(BigDecimal.new('1.000000000000000000000000000000000000000000000001'), :a),
59
+ Sequel::SQL::AliasedExpression.new(Sequel::CURRENT_DATE, :a),
60
+ Sequel::SQL::AliasedExpression.new(Sequel::CURRENT_TIMESTAMP, :a),
61
+ ].each do |o|
62
+ v = eval(o.inspect)
63
+ v.should == o
64
+ @ds.literal(v).should == @ds.literal(o)
65
+ end
66
+ end
67
+ end
@@ -74,12 +74,13 @@ describe "force_encoding plugin" do
74
74
 
75
75
  specify "should work when saving new model instances" do
76
76
  o = @c.new
77
- @c.dataset = ds = MODEL_DB[:a]
77
+ ds = MODEL_DB[:a]
78
78
  def ds.first
79
79
  s = 'blah'
80
80
  s.force_encoding('US-ASCII')
81
81
  {:id=>1, :x=>s}
82
82
  end
83
+ @c.dataset = ds
83
84
  o.save
84
85
  o.x.should == 'blah'
85
86
  o.x.encoding.should == @e1
@@ -87,12 +88,13 @@ describe "force_encoding plugin" do
87
88
 
88
89
  specify "should work when refreshing model instances" do
89
90
  o = @c.load(:id=>1, :x=>'as')
90
- @c.dataset = ds = MODEL_DB[:a]
91
+ ds = MODEL_DB[:a]
91
92
  def ds.first
92
93
  s = 'blah'
93
94
  s.force_encoding('US-ASCII')
94
95
  {:id=>1, :x=>s}
95
96
  end
97
+ @c.dataset = ds
96
98
  o.refresh
97
99
  o.x.should == 'blah'
98
100
  o.x.encoding.should == @e1