sequel 4.41.0 → 4.42.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (256) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +98 -0
  3. data/README.rdoc +23 -10
  4. data/doc/active_record.rdoc +4 -4
  5. data/doc/advanced_associations.rdoc +2 -2
  6. data/doc/association_basics.rdoc +5 -2
  7. data/doc/cheat_sheet.rdoc +3 -3
  8. data/doc/core_extensions.rdoc +2 -2
  9. data/doc/dataset_basics.rdoc +4 -4
  10. data/doc/dataset_filtering.rdoc +1 -1
  11. data/doc/migration.rdoc +19 -1
  12. data/doc/prepared_statements.rdoc +2 -2
  13. data/doc/release_notes/4.42.0.txt +221 -0
  14. data/doc/testing.rdoc +3 -1
  15. data/lib/sequel/adapters/ado/access.rb +0 -1
  16. data/lib/sequel/adapters/ado/mssql.rb +0 -1
  17. data/lib/sequel/adapters/do/mysql.rb +0 -1
  18. data/lib/sequel/adapters/do/postgres.rb +0 -1
  19. data/lib/sequel/adapters/do/sqlite3.rb +0 -1
  20. data/lib/sequel/adapters/ibmdb.rb +21 -25
  21. data/lib/sequel/adapters/jdbc.rb +8 -16
  22. data/lib/sequel/adapters/jdbc/as400.rb +0 -1
  23. data/lib/sequel/adapters/jdbc/cubrid.rb +0 -1
  24. data/lib/sequel/adapters/jdbc/db2.rb +0 -1
  25. data/lib/sequel/adapters/jdbc/derby.rb +0 -1
  26. data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -1
  27. data/lib/sequel/adapters/jdbc/h2.rb +0 -1
  28. data/lib/sequel/adapters/jdbc/hsqldb.rb +0 -1
  29. data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -1
  30. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -1
  31. data/lib/sequel/adapters/jdbc/jtds.rb +0 -1
  32. data/lib/sequel/adapters/jdbc/mssql.rb +0 -1
  33. data/lib/sequel/adapters/jdbc/mysql.rb +0 -1
  34. data/lib/sequel/adapters/jdbc/oracle.rb +0 -1
  35. data/lib/sequel/adapters/jdbc/postgresql.rb +0 -13
  36. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +0 -1
  37. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -1
  38. data/lib/sequel/adapters/jdbc/sqlserver.rb +3 -4
  39. data/lib/sequel/adapters/mock.rb +54 -12
  40. data/lib/sequel/adapters/mysql.rb +1 -1
  41. data/lib/sequel/adapters/mysql2.rb +11 -17
  42. data/lib/sequel/adapters/odbc/mssql.rb +0 -1
  43. data/lib/sequel/adapters/oracle.rb +8 -20
  44. data/lib/sequel/adapters/postgres.rb +11 -29
  45. data/lib/sequel/adapters/shared/access.rb +5 -12
  46. data/lib/sequel/adapters/shared/cubrid.rb +4 -13
  47. data/lib/sequel/adapters/shared/db2.rb +4 -2
  48. data/lib/sequel/adapters/shared/firebird.rb +2 -4
  49. data/lib/sequel/adapters/shared/informix.rb +4 -2
  50. data/lib/sequel/adapters/shared/mssql.rb +3 -5
  51. data/lib/sequel/adapters/shared/mysql.rb +4 -14
  52. data/lib/sequel/adapters/shared/oracle.rb +1 -3
  53. data/lib/sequel/adapters/shared/postgres.rb +16 -38
  54. data/lib/sequel/adapters/shared/progress.rb +0 -2
  55. data/lib/sequel/adapters/shared/sqlanywhere.rb +0 -2
  56. data/lib/sequel/adapters/shared/sqlite.rb +20 -16
  57. data/lib/sequel/adapters/sqlite.rb +8 -20
  58. data/lib/sequel/adapters/swift/mysql.rb +0 -1
  59. data/lib/sequel/adapters/swift/postgres.rb +0 -1
  60. data/lib/sequel/adapters/swift/sqlite.rb +0 -1
  61. data/lib/sequel/adapters/tinytds.rb +4 -12
  62. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +1 -1
  63. data/lib/sequel/adapters/utils/mysql_mysql2.rb +2 -2
  64. data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +11 -34
  65. data/lib/sequel/adapters/utils/stored_procedures.rb +9 -22
  66. data/lib/sequel/adapters/utils/unmodified_identifiers.rb +26 -0
  67. data/lib/sequel/ast_transformer.rb +2 -2
  68. data/lib/sequel/database/dataset.rb +1 -1
  69. data/lib/sequel/database/dataset_defaults.rb +0 -66
  70. data/lib/sequel/database/features.rb +6 -0
  71. data/lib/sequel/database/misc.rb +31 -17
  72. data/lib/sequel/database/query.rb +7 -4
  73. data/lib/sequel/database/schema_methods.rb +1 -1
  74. data/lib/sequel/dataset.rb +8 -8
  75. data/lib/sequel/dataset/actions.rb +140 -46
  76. data/lib/sequel/dataset/features.rb +1 -5
  77. data/lib/sequel/dataset/graph.rb +7 -8
  78. data/lib/sequel/dataset/misc.rb +127 -56
  79. data/lib/sequel/dataset/mutation.rb +9 -20
  80. data/lib/sequel/dataset/placeholder_literalizer.rb +10 -1
  81. data/lib/sequel/dataset/prepared_statements.rb +102 -46
  82. data/lib/sequel/dataset/query.rb +155 -72
  83. data/lib/sequel/dataset/sql.rb +26 -9
  84. data/lib/sequel/extensions/columns_introspection.rb +3 -1
  85. data/lib/sequel/extensions/core_extensions.rb +5 -5
  86. data/lib/sequel/extensions/core_refinements.rb +5 -5
  87. data/lib/sequel/extensions/duplicate_columns_handler.rb +4 -2
  88. data/lib/sequel/extensions/freeze_datasets.rb +69 -0
  89. data/lib/sequel/extensions/identifier_mangling.rb +196 -0
  90. data/lib/sequel/extensions/looser_typecasting.rb +11 -7
  91. data/lib/sequel/extensions/migration.rb +1 -1
  92. data/lib/sequel/extensions/null_dataset.rb +5 -2
  93. data/lib/sequel/extensions/pagination.rb +42 -23
  94. data/lib/sequel/extensions/pg_enum.rb +3 -3
  95. data/lib/sequel/extensions/query.rb +3 -3
  96. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +15 -8
  97. data/lib/sequel/model/associations.rb +25 -8
  98. data/lib/sequel/model/base.rb +88 -29
  99. data/lib/sequel/model/dataset_module.rb +37 -0
  100. data/lib/sequel/plugins/association_pks.rb +4 -4
  101. data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
  102. data/lib/sequel/plugins/constraint_validations.rb +1 -2
  103. data/lib/sequel/plugins/csv_serializer.rb +2 -2
  104. data/lib/sequel/plugins/dataset_associations.rb +8 -8
  105. data/lib/sequel/plugins/eager_each.rb +2 -2
  106. data/lib/sequel/plugins/instance_filters.rb +1 -1
  107. data/lib/sequel/plugins/json_serializer.rb +2 -2
  108. data/lib/sequel/plugins/lazy_attributes.rb +1 -1
  109. data/lib/sequel/plugins/list.rb +4 -4
  110. data/lib/sequel/plugins/prepared_statements.rb +2 -4
  111. data/lib/sequel/plugins/prepared_statements_associations.rb +1 -3
  112. data/lib/sequel/plugins/prepared_statements_with_pk.rb +1 -1
  113. data/lib/sequel/plugins/rcte_tree.rb +13 -13
  114. data/lib/sequel/plugins/sharding.rb +1 -1
  115. data/lib/sequel/plugins/single_table_inheritance.rb +9 -4
  116. data/lib/sequel/plugins/tactical_eager_loading.rb +4 -4
  117. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  118. data/lib/sequel/plugins/validation_helpers.rb +1 -1
  119. data/lib/sequel/plugins/xml_serializer.rb +2 -2
  120. data/lib/sequel/sql.rb +69 -36
  121. data/lib/sequel/version.rb +1 -1
  122. data/spec/adapters/db2_spec.rb +10 -0
  123. data/spec/adapters/firebird_spec.rb +1 -1
  124. data/spec/adapters/mssql_spec.rb +4 -5
  125. data/spec/adapters/mysql_spec.rb +9 -9
  126. data/spec/adapters/postgres_spec.rb +67 -68
  127. data/spec/adapters/spec_helper.rb +6 -1
  128. data/spec/adapters/sqlite_spec.rb +29 -15
  129. data/spec/core/connection_pool_spec.rb +14 -14
  130. data/spec/core/database_spec.rb +38 -180
  131. data/spec/core/dataset_mutation_spec.rb +253 -0
  132. data/spec/core/dataset_spec.rb +394 -537
  133. data/spec/core/expression_filters_spec.rb +34 -32
  134. data/spec/core/mock_adapter_spec.rb +27 -35
  135. data/spec/core/placeholder_literalizer_spec.rb +2 -4
  136. data/spec/core/schema_generator_spec.rb +4 -4
  137. data/spec/core/schema_spec.rb +1 -2
  138. data/spec/core_extensions_spec.rb +22 -29
  139. data/spec/extensions/active_model_spec.rb +6 -6
  140. data/spec/extensions/association_dependencies_spec.rb +2 -2
  141. data/spec/extensions/blacklist_security_spec.rb +3 -3
  142. data/spec/extensions/boolean_readers_spec.rb +12 -12
  143. data/spec/extensions/caching_spec.rb +13 -10
  144. data/spec/extensions/class_table_inheritance_spec.rb +38 -43
  145. data/spec/extensions/column_conflicts_spec.rb +1 -3
  146. data/spec/extensions/columns_introspection_spec.rb +2 -3
  147. data/spec/extensions/composition_spec.rb +5 -3
  148. data/spec/extensions/constraint_validations_plugin_spec.rb +5 -5
  149. data/spec/extensions/constraint_validations_spec.rb +14 -8
  150. data/spec/extensions/core_refinements_spec.rb +22 -29
  151. data/spec/extensions/csv_serializer_spec.rb +7 -6
  152. data/spec/extensions/date_arithmetic_spec.rb +15 -15
  153. data/spec/extensions/defaults_setter_spec.rb +2 -2
  154. data/spec/extensions/delay_add_association_spec.rb +1 -1
  155. data/spec/extensions/dirty_spec.rb +19 -10
  156. data/spec/extensions/duplicate_columns_handler_spec.rb +12 -18
  157. data/spec/extensions/eager_each_spec.rb +12 -16
  158. data/spec/extensions/empty_array_consider_nulls_spec.rb +1 -1
  159. data/spec/extensions/eval_inspect_spec.rb +4 -3
  160. data/spec/extensions/force_encoding_spec.rb +12 -12
  161. data/spec/extensions/freeze_datasets_spec.rb +31 -0
  162. data/spec/extensions/graph_each_spec.rb +6 -18
  163. data/spec/extensions/hook_class_methods_spec.rb +7 -7
  164. data/spec/extensions/identifier_mangling_spec.rb +307 -0
  165. data/spec/extensions/instance_filters_spec.rb +5 -6
  166. data/spec/extensions/instance_hooks_spec.rb +12 -12
  167. data/spec/extensions/json_serializer_spec.rb +12 -15
  168. data/spec/extensions/lazy_attributes_spec.rb +4 -4
  169. data/spec/extensions/list_spec.rb +19 -21
  170. data/spec/extensions/many_through_many_spec.rb +108 -163
  171. data/spec/extensions/meta_def_spec.rb +7 -2
  172. data/spec/extensions/migration_spec.rb +10 -12
  173. data/spec/extensions/mssql_optimistic_locking_spec.rb +4 -3
  174. data/spec/extensions/named_timezones_spec.rb +4 -3
  175. data/spec/extensions/nested_attributes_spec.rb +2 -2
  176. data/spec/extensions/null_dataset_spec.rb +17 -12
  177. data/spec/extensions/optimistic_locking_spec.rb +4 -5
  178. data/spec/extensions/pagination_spec.rb +8 -10
  179. data/spec/extensions/pg_array_associations_spec.rb +28 -27
  180. data/spec/extensions/pg_array_ops_spec.rb +2 -1
  181. data/spec/extensions/pg_array_spec.rb +6 -2
  182. data/spec/extensions/pg_enum_spec.rb +5 -3
  183. data/spec/extensions/pg_hstore_ops_spec.rb +3 -1
  184. data/spec/extensions/pg_hstore_spec.rb +7 -6
  185. data/spec/extensions/pg_inet_ops_spec.rb +2 -1
  186. data/spec/extensions/pg_inet_spec.rb +2 -1
  187. data/spec/extensions/pg_interval_spec.rb +2 -1
  188. data/spec/extensions/pg_json_ops_spec.rb +2 -1
  189. data/spec/extensions/pg_json_spec.rb +6 -3
  190. data/spec/extensions/pg_loose_count_spec.rb +1 -0
  191. data/spec/extensions/pg_range_ops_spec.rb +3 -1
  192. data/spec/extensions/pg_range_spec.rb +9 -5
  193. data/spec/extensions/pg_row_ops_spec.rb +2 -1
  194. data/spec/extensions/pg_row_plugin_spec.rb +4 -6
  195. data/spec/extensions/pg_row_spec.rb +5 -3
  196. data/spec/extensions/pg_static_cache_updater_spec.rb +2 -1
  197. data/spec/extensions/pg_typecast_on_load_spec.rb +1 -1
  198. data/spec/extensions/prepared_statements_associations_spec.rb +1 -1
  199. data/spec/extensions/prepared_statements_spec.rb +12 -11
  200. data/spec/extensions/pretty_table_spec.rb +1 -1
  201. data/spec/extensions/query_spec.rb +8 -5
  202. data/spec/extensions/rcte_tree_spec.rb +39 -39
  203. data/spec/extensions/round_timestamps_spec.rb +2 -2
  204. data/spec/extensions/schema_dumper_spec.rb +3 -2
  205. data/spec/extensions/schema_spec.rb +2 -2
  206. data/spec/extensions/scissors_spec.rb +1 -2
  207. data/spec/extensions/sequel_3_dataset_methods_spec.rb +30 -17
  208. data/spec/extensions/serialization_modification_detection_spec.rb +2 -2
  209. data/spec/extensions/serialization_spec.rb +15 -13
  210. data/spec/extensions/set_overrides_spec.rb +14 -8
  211. data/spec/extensions/sharding_spec.rb +9 -18
  212. data/spec/extensions/shared_caching_spec.rb +3 -4
  213. data/spec/extensions/single_table_inheritance_spec.rb +11 -11
  214. data/spec/extensions/skip_create_refresh_spec.rb +2 -1
  215. data/spec/extensions/spec_helper.rb +1 -1
  216. data/spec/extensions/split_values_spec.rb +2 -2
  217. data/spec/extensions/sql_comments_spec.rb +6 -0
  218. data/spec/extensions/static_cache_spec.rb +7 -9
  219. data/spec/extensions/string_agg_spec.rb +30 -29
  220. data/spec/extensions/tactical_eager_loading_spec.rb +4 -5
  221. data/spec/extensions/thread_local_timezones_spec.rb +2 -2
  222. data/spec/extensions/timestamps_spec.rb +28 -3
  223. data/spec/extensions/to_dot_spec.rb +1 -2
  224. data/spec/extensions/tree_spec.rb +33 -29
  225. data/spec/extensions/typecast_on_load_spec.rb +1 -1
  226. data/spec/extensions/unlimited_update_spec.rb +1 -0
  227. data/spec/extensions/update_primary_key_spec.rb +11 -7
  228. data/spec/extensions/update_refresh_spec.rb +1 -1
  229. data/spec/extensions/uuid_spec.rb +0 -1
  230. data/spec/extensions/validate_associated_spec.rb +1 -1
  231. data/spec/extensions/validation_class_methods_spec.rb +10 -10
  232. data/spec/extensions/validation_helpers_spec.rb +10 -10
  233. data/spec/extensions/xml_serializer_spec.rb +7 -3
  234. data/spec/integration/associations_test.rb +31 -31
  235. data/spec/integration/dataset_test.rb +17 -19
  236. data/spec/integration/eager_loader_test.rb +24 -24
  237. data/spec/integration/model_test.rb +6 -6
  238. data/spec/integration/plugin_test.rb +43 -43
  239. data/spec/integration/prepared_statement_test.rb +6 -6
  240. data/spec/integration/schema_test.rb +63 -52
  241. data/spec/integration/spec_helper.rb +6 -1
  242. data/spec/integration/transaction_test.rb +13 -13
  243. data/spec/model/association_reflection_spec.rb +17 -17
  244. data/spec/model/associations_spec.rb +101 -96
  245. data/spec/model/base_spec.rb +175 -49
  246. data/spec/model/class_dataset_methods_spec.rb +5 -9
  247. data/spec/model/dataset_methods_spec.rb +5 -5
  248. data/spec/model/eager_loading_spec.rb +209 -235
  249. data/spec/model/hooks_spec.rb +15 -15
  250. data/spec/model/model_spec.rb +28 -21
  251. data/spec/model/plugins_spec.rb +4 -5
  252. data/spec/model/record_spec.rb +59 -57
  253. data/spec/model/spec_helper.rb +1 -1
  254. data/spec/model/validations_spec.rb +6 -6
  255. data/spec/spec_config.rb +1 -1
  256. metadata +10 -2
@@ -3,24 +3,24 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
3
3
  mod = shared_description do
4
4
  it "should take action depending on :on_duplicate_columns if 2 or more columns have the same name" do
5
5
  check(nil, @cols)
6
- @warned.must_equal nil
6
+ @warned.must_be_nil
7
7
 
8
8
  check(:ignore, @cols)
9
- @warned.must_equal nil
9
+ @warned.must_be_nil
10
10
 
11
11
  check(:warn, @cols)
12
- @warned.must_equal("One or more duplicate columns present in #{@cols.inspect}")
12
+ @warned.must_include("One or more duplicate columns present in #{@cols.inspect}")
13
13
 
14
14
  proc{check(:raise, @cols)}.must_raise(Sequel::DuplicateColumnError)
15
15
 
16
16
  cols = nil
17
17
  check(proc{|cs| cols = cs; nil}, @cols)
18
- @warned.must_equal nil
18
+ @warned.must_be_nil
19
19
  cols.must_equal @cols
20
20
 
21
21
  cols = nil
22
22
  check(proc{|cs| cols = cs; :ignore}, @cols)
23
- @warned.must_equal nil
23
+ @warned.must_be_nil
24
24
  cols.must_equal @cols
25
25
 
26
26
  cols = nil
@@ -29,17 +29,17 @@ mod = shared_description do
29
29
 
30
30
  cols = nil
31
31
  check(proc{|cs| cols = cs; :warn}, @cols)
32
- @warned.must_equal("One or more duplicate columns present in #{@cols.inspect}")
32
+ @warned.must_include("One or more duplicate columns present in #{@cols.inspect}")
33
33
  cols.must_equal @cols
34
34
 
35
35
  check(:raise, nil)
36
- @warned.must_equal nil
36
+ @warned.must_be_nil
37
37
  end
38
38
 
39
39
  it "should not raise error or warning if no columns have the same name" do
40
40
  [nil, :ignore, :raise, :warn, proc{|cs| :raise}].each do |handler|
41
41
  check(handler, @cols.uniq)
42
- @warned.must_equal nil
42
+ @warned.must_be_nil
43
43
  end
44
44
  end
45
45
  end
@@ -48,13 +48,10 @@ describe "Sequel::DuplicateColumnsHandler Database configuration" do
48
48
  before do
49
49
  @db = Sequel.mock
50
50
  @db.extension(:duplicate_columns_handler)
51
- @ds = @db[:things]
52
51
  @cols = [:id, :name, :id]
53
52
  @warned = nil
54
53
  set_warned = @set_warned = proc{|m| @warned = m}
55
- @ds.meta_def(:warn) do |message|
56
- set_warned.call(message)
57
- end
54
+ @ds = @db[:things].with_extend{define_method(:warn){|message| set_warned.call(message)}}
58
55
  end
59
56
 
60
57
  def check(handler, cols)
@@ -68,13 +65,10 @@ end
68
65
 
69
66
  describe "Sequel::DuplicateColumnsHandler Dataset configuration" do
70
67
  before do
71
- @ds = Sequel.mock[:things].extension!(:duplicate_columns_handler)
72
68
  @cols = [:id, :name, :id]
73
69
  @warned = nil
74
70
  set_warned = @set_warned = proc{|m| @warned = m}
75
- @ds.meta_def(:warn) do |message|
76
- set_warned.call(message)
77
- end
71
+ @ds = Sequel.mock[:things].extension(:duplicate_columns_handler).with_extend{define_method(:warn){|message| set_warned.call(message)}}
78
72
  end
79
73
 
80
74
  def check(handler, cols)
@@ -98,13 +92,13 @@ describe "Sequel::DuplicateColumnsHandler Dataset configuration" do
98
92
 
99
93
  it "should warn by defaul if there is no database or dataset handler" do
100
94
  @ds.send(:columns=, @cols)
101
- @warned.must_equal("One or more duplicate columns present in #{@cols.inspect}")
95
+ @warned.must_include("One or more duplicate columns present in #{@cols.inspect}")
102
96
  end
103
97
 
104
98
  it "should fallback to database setting if there is no dataset-level handler" do
105
99
  @ds.db.opts[:on_duplicate_columns] = :raise
106
100
  proc{@ds.send(:columns=, @cols)}.must_raise(Sequel::DuplicateColumnError)
107
101
  check(:ignore, @cols)
108
- @warned.must_equal nil
102
+ @warned.must_be_nil
109
103
  end
110
104
  end
@@ -11,9 +11,8 @@ describe "Sequel::Plugins::EagerEach" do
11
11
 
12
12
  it "should make #each on an eager dataset do eager loading" do
13
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}]
14
+ ds = @c.eager(:children).with_fetch([{:id=>1, :parent_id=>nil}, {:id=>2, :parent_id=>nil}])
15
+ @c.dataset = @c.dataset.with_fetch([{:id=>3, :parent_id=>1}, {:id=>4, :parent_id=>1}, {:id=>5, :parent_id=>2}, {:id=>6, :parent_id=>2}])
17
16
  ds.each{|c| a << c}
18
17
  a.must_equal [@c.load(:id=>1, :parent_id=>nil), @c.load(:id=>2, :parent_id=>nil)]
19
18
  a.map{|c| c.associations[:children]}.must_equal [[@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)]]
@@ -25,8 +24,7 @@ describe "Sequel::Plugins::EagerEach" do
25
24
 
26
25
  it "should make #each on an eager_graph dataset do eager loading" do
27
26
  a = []
28
- ds = @c.eager_graph(:children)
29
- 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}]
27
+ ds = @c.eager_graph(:children).with_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}])
30
28
  ds.each{|c| a << c}
31
29
  a.must_equal [@c.load(:id=>1, :parent_id=>nil), @c.load(:id=>2, :parent_id=>nil)]
32
30
  a.map{|c| c.associations[:children]}.must_equal [[@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)]]
@@ -34,9 +32,8 @@ describe "Sequel::Plugins::EagerEach" do
34
32
  end
35
33
 
36
34
  it "should make #first on an eager dataset do eager loading" do
37
- ds = @c.eager(:children)
38
- ds._fetch = [{:id=>1, :parent_id=>nil}]
39
- @c.dataset._fetch = [{:id=>3, :parent_id=>1}, {:id=>4, :parent_id=>1}]
35
+ ds = @c.eager(:children).with_fetch([{:id=>1, :parent_id=>nil}])
36
+ @c.dataset = @c.dataset.with_fetch([{:id=>3, :parent_id=>1}, {:id=>4, :parent_id=>1}])
40
37
  a = ds.first
41
38
  a.values.must_equal(:id=>1, :parent_id=>nil)
42
39
  a.associations[:children].must_equal [@c.load(:id=>3, :parent_id=>1), @c.load(:id=>4, :parent_id=>1)]
@@ -44,9 +41,7 @@ describe "Sequel::Plugins::EagerEach" do
44
41
  end
45
42
 
46
43
  it "should make #first on an eager_graph dataset do eager loading" do
47
- ds = @c.eager_graph(:children)
48
- ds._fetch = [[{:id=>1, :parent_id=>nil, :children_id=>3, :children_parent_id=>1}], [{:id=>1, :parent_id=>nil, :children_id=>3, :children_parent_id=>1}, {:id=>1, :parent_id=>nil, :children_id=>4, :children_parent_id=>1}]]
49
- a = ds.first
44
+ a = @c.eager_graph(:children).with_fetch([[{:id=>1, :parent_id=>nil, :children_id=>3, :children_parent_id=>1}], [{:id=>1, :parent_id=>nil, :children_id=>3, :children_parent_id=>1}, {:id=>1, :parent_id=>nil, :children_id=>4, :children_parent_id=>1}]]).first
50
45
  a.values.must_equal(:id=>1, :parent_id=>nil)
51
46
  a.associations[:children].must_equal [@c.load(:id=>3, :parent_id=>1), @c.load(:id=>4, :parent_id=>1)]
52
47
  @c.db.sqls.must_equal ['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) LIMIT 1',
@@ -54,13 +49,14 @@ describe "Sequel::Plugins::EagerEach" do
54
49
  end
55
50
 
56
51
  it "should make #first on a non-eager dataset work correctly" do
57
- @c.dataset._fetch = [{:id=>1, :parent_id=>nil}]
58
- @c.first.must_equal @c.load(:id=>1, :parent_id=>nil)
52
+ @c.dataset.with_fetch([{:id=>1, :parent_id=>nil}]).first.must_equal @c.load(:id=>1, :parent_id=>nil)
53
+ end
54
+
55
+ it "should get columns normally columns" do
56
+ @c.dataset.columns!.must_equal [:id, :parent_id]
59
57
  end
60
58
 
61
59
  it "should not attempt to eager load when getting the columns" do
62
- ds = @c.eager(:children)
63
- def ds.all; raise; end
64
- ds.columns!
60
+ ds = @c.eager(:children).with_extend{def all; raise; end}.columns!.must_equal [:id, :parent_id]
65
61
  end
66
62
  end
@@ -13,9 +13,9 @@ describe "filter_having extension" do
13
13
  end
14
14
 
15
15
  it "should handle IN/NOT IN queries with multiple columns and an empty dataset where the database doesn't support it" do
16
- @dataset.meta_def(:supports_multiple_column_in?){false}
17
16
  db = Sequel.mock
18
17
  d1 = db[:test].select(:id1, :id2).filter(:region=>'Asia').columns(:id1, :id2)
18
+ @dataset = @dataset.with_extend{def supports_multiple_column_in?; false end}
19
19
  @dataset.filter([:id1, :id2] => d1).sql.must_equal "SELECT * FROM test WHERE ((id1 != id1) AND (id2 != id2))"
20
20
  db.sqls.must_equal ["SELECT id1, id2 FROM test WHERE (region = 'Asia')"]
21
21
  @dataset.exclude([:id1, :id2] => d1).sql.must_equal "SELECT * FROM test WHERE ((id1 = id1) AND (id2 = id2))"
@@ -4,9 +4,10 @@ Sequel.extension :eval_inspect
4
4
 
5
5
  describe "eval_inspect extension" do
6
6
  before do
7
- @ds = Sequel.mock.dataset
8
- @ds.meta_def(:supports_window_functions?){true}
9
- @ds.meta_def(:literal_blob_append){|sql, s| sql << "X'#{s}'"}
7
+ @ds = Sequel.mock.dataset.with_extend do
8
+ def supports_window_functions?; true end
9
+ def literal_blob_append(sql, s) sql << "X'#{s}'" end
10
+ end
10
11
  end
11
12
 
12
13
  it "should make eval(obj.inspect) == obj for all Sequel::SQL::Expression subclasses" do
@@ -83,13 +83,13 @@ describe "force_encoding plugin" do
83
83
 
84
84
  it "should work when saving new model instances" do
85
85
  o = @c.new
86
- ds = DB[:a]
87
- def ds.first
88
- s = 'blah'.dup
89
- s.force_encoding('US-ASCII')
90
- {:id=>1, :x=>s}
86
+ @c.dataset = DB[:a].with_extend do
87
+ def first
88
+ s = 'blah'.dup
89
+ s.force_encoding('US-ASCII')
90
+ {:id=>1, :x=>s}
91
+ end
91
92
  end
92
- @c.dataset = ds
93
93
  o.save
94
94
  o.x.must_equal 'blah'
95
95
  o.x.encoding.must_equal @e1
@@ -97,13 +97,13 @@ describe "force_encoding plugin" do
97
97
 
98
98
  it "should work when refreshing model instances" do
99
99
  o = @c.load(:id=>1, :x=>'as'.dup)
100
- ds = DB[:a]
101
- def ds.first
102
- s = 'blah'.dup
103
- s.force_encoding('US-ASCII')
104
- {:id=>1, :x=>s}
100
+ @c.dataset = DB[:a].with_extend do
101
+ def first
102
+ s = 'blah'.dup
103
+ s.force_encoding('US-ASCII')
104
+ {:id=>1, :x=>s}
105
+ end
105
106
  end
106
- @c.dataset = ds
107
107
  o.refresh
108
108
  o.x.must_equal 'blah'
109
109
  o.x.encoding.must_equal @e1
@@ -0,0 +1,31 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "freeze_datasets extension" do
4
+ before do
5
+ @db = Sequel.mock.extension(:freeze_datasets)
6
+ end
7
+
8
+ it "should freeze datasets by default" do
9
+ @db.dataset.frozen?.must_equal true
10
+ @db.fetch('SQL').frozen?.must_equal true
11
+ @db.from(:table).frozen?.must_equal true
12
+ @db[:table].frozen?.must_equal true
13
+ end
14
+
15
+ it "should have dataset#dup return frozen dataset" do
16
+ @db.dataset.dup.frozen?.must_equal true
17
+ end
18
+
19
+ it "should cache Database#from calls with single symbol tables" do
20
+ @db.from(:foo).must_be_same_as @db.from(:foo)
21
+ @db.from(Sequel[:foo]).wont_be_same_as @db.from(Sequel[:foo])
22
+ end
23
+
24
+ it "should clear Database#from cache when modifying the schema" do
25
+ ds = @db.from(:foo)
26
+ ds.columns(:foo, :bar)
27
+ @db[:foo].columns.must_equal [:foo, :bar]
28
+ @db.create_table!(:foo){Integer :x}
29
+ @db[:foo].columns.wont_equal [:foo, :bar]
30
+ end
31
+ end
@@ -20,25 +20,15 @@ describe Sequel::Dataset, " graphing" do
20
20
  end
21
21
 
22
22
  it "#graph_each should handle graph using currently selected columns as the basis for the selected columns in a new graph" do
23
- ds = @ds1.select(:id).graph(@ds2, :x=>:id)
24
- ds._fetch = {:id=>1, :lines_id=>2, :x=>3, :y=>4, :graph_id=>5}
25
- ds.all.must_equal [{:points=>{:id=>1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
23
+ @ds1.select(:id).graph(@ds2, :x=>:id).with_fetch(:id=>1, :lines_id=>2, :x=>3, :y=>4, :graph_id=>5).all.must_equal [{:points=>{:id=>1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
26
24
 
27
- ds = @ds1.select(:id, :x).graph(@ds2, :x=>:id)
28
- ds._fetch = {:id=>1, :x=>-1, :lines_id=>2, :lines_x=>3, :y=>4, :graph_id=>5}
29
- ds.all.must_equal [{:points=>{:id=>1, :x=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
25
+ @ds1.select(:id, :x).graph(@ds2, :x=>:id).with_fetch(:id=>1, :x=>-1, :lines_id=>2, :lines_x=>3, :y=>4, :graph_id=>5).all.must_equal [{:points=>{:id=>1, :x=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
30
26
 
31
- ds = @ds1.select(Sequel.identifier(:id), Sequel.qualify(:points, :x)).graph(@ds2, :x=>:id)
32
- ds._fetch = {:id=>1, :x=>-1, :lines_id=>2, :lines_x=>3, :y=>4, :graph_id=>5}
33
- ds.all.must_equal [{:points=>{:id=>1, :x=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
27
+ @ds1.select(Sequel.identifier(:id), Sequel.qualify(:points, :x)).graph(@ds2, :x=>:id).with_fetch(:id=>1, :x=>-1, :lines_id=>2, :lines_x=>3, :y=>4, :graph_id=>5).all.must_equal [{:points=>{:id=>1, :x=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
34
28
 
35
- ds = @ds1.select(Sequel.identifier(:id).qualify(:points), Sequel.identifier(:x).as(:y)).graph(@ds2, :x=>:id)
36
- ds._fetch = {:id=>1, :y=>-1, :lines_id=>2, :x=>3, :lines_y=>4, :graph_id=>5}
37
- ds.all.must_equal [{:points=>{:id=>1, :y=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
29
+ @ds1.select(Sequel.identifier(:id).qualify(:points), Sequel.identifier(:x).as(:y)).graph(@ds2, :x=>:id).with_fetch(:id=>1, :y=>-1, :lines_id=>2, :x=>3, :lines_y=>4, :graph_id=>5).all.must_equal [{:points=>{:id=>1, :y=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
38
30
 
39
- ds = @ds1.select(:id, Sequel.identifier(:x).qualify(Sequel.identifier(:points)).as(Sequel.identifier(:y))).graph(@ds2, :x=>:id)
40
- ds._fetch = {:id=>1, :y=>-1, :lines_id=>2, :x=>3, :lines_y=>4, :graph_id=>5}
41
- ds.all.must_equal [{:points=>{:id=>1, :y=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
31
+ @ds1.select(:id, Sequel.identifier(:x).qualify(Sequel.identifier(:points)).as(Sequel.identifier(:y))).graph(@ds2, :x=>:id).with_fetch(:id=>1, :y=>-1, :lines_id=>2, :x=>3, :lines_y=>4, :graph_id=>5).all.must_equal [{:points=>{:id=>1, :y=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
42
32
  end
43
33
 
44
34
  it "#graph_each should split the result set into component tables" do
@@ -111,10 +101,8 @@ describe Sequel::Dataset, " graphing" do
111
101
  end
112
102
 
113
103
  it "#graph_each should run the row_proc for graphed datasets" do
114
- @ds1.row_proc = proc{|h| h.keys.each{|k| h[k] *= 2}; h}
115
- @ds2.row_proc = proc{|h| h.keys.each{|k| h[k] *= 3}; h}
116
104
  @db.fetch = {:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7}
117
- @ds1.graph(@ds2, :x=>:id).all.must_equal [{:points=>{:id=>2, :x=>4, :y=>6}, :lines=>{:id=>12, :x=>15, :y=>18, :graph_id=>21}}]
105
+ @ds1.with_row_proc(proc{|h| h.keys.each{|k| h[k] *= 2}; h}).graph(@ds2.with_row_proc(proc{|h| h.keys.each{|k| h[k] *= 3}; h}), :x=>:id).all.must_equal [{:points=>{:id=>2, :x=>4, :y=>6}, :lines=>{:id=>12, :x=>15, :y=>18, :graph_id=>21}}]
118
106
  end
119
107
 
120
108
  it "#with_sql_each should work normally if the dataset is not graphed" do
@@ -197,14 +197,14 @@ describe "Model#before_create && Model#after_create" do
197
197
  it ".create should cancel the save and return nil if before_create returns false and raise_on_save_failure is false" do
198
198
  @c.before_create{false}
199
199
  @c.raise_on_save_failure = false
200
- @c.create(:x => 2).must_equal nil
200
+ @c.create(:x => 2).must_be_nil
201
201
  DB.sqls.must_equal []
202
202
  end
203
203
 
204
204
  it ".create should cancel the save and return nil if before_create calls cancel_action and raise_on_save_failure is false" do
205
205
  @c.before_create{cancel_action}
206
206
  @c.raise_on_save_failure = false
207
- @c.create(:x => 2).must_equal nil
207
+ @c.create(:x => 2).must_be_nil
208
208
  DB.sqls.must_equal []
209
209
  end
210
210
  end
@@ -234,7 +234,7 @@ describe "Model#before_update && Model#after_update" do
234
234
  it "#save should cancel the save and return nil if before_update returns false and raise_on_save_failure is false" do
235
235
  @c.before_update{false}
236
236
  @c.raise_on_save_failure = false
237
- @c.load(:id => 2233).save.must_equal nil
237
+ @c.load(:id => 2233).save.must_be_nil
238
238
  DB.sqls.must_equal []
239
239
  end
240
240
  end
@@ -272,7 +272,7 @@ describe "Model#before_save && Model#after_save" do
272
272
  it "#save should cancel the save and return nil if before_save returns false and raise_on_save_failure is false" do
273
273
  @c.before_save{false}
274
274
  @c.raise_on_save_failure = false
275
- @c.load(:id => 2233).save.must_equal nil
275
+ @c.load(:id => 2233).save.must_be_nil
276
276
  DB.sqls.must_equal []
277
277
  end
278
278
  end
@@ -302,7 +302,7 @@ describe "Model#before_destroy && Model#after_destroy" do
302
302
  it "#destroy should cancel the destroy and return nil if before_destroy returns false and raise_on_save_failure is false" do
303
303
  @c.before_destroy{false}
304
304
  @c.raise_on_save_failure = false
305
- @c.load(:id => 2233).destroy.must_equal nil
305
+ @c.load(:id => 2233).destroy.must_be_nil
306
306
  DB.sqls.must_equal []
307
307
  end
308
308
  end
@@ -343,7 +343,7 @@ describe "Model#before_validation && Model#after_validation" do
343
343
  DB.sqls.clear
344
344
  m = @c.load(:id => 22)
345
345
  m.raise_on_save_failure = false
346
- m.save.must_equal nil
346
+ m.save.must_be_nil
347
347
  DB.sqls.must_equal ['BLAH before', 'BLAH after']
348
348
  end
349
349
 
@@ -356,7 +356,7 @@ describe "Model#before_validation && Model#after_validation" do
356
356
  it "#save should cancel the save and return nil if before_validation returns false and raise_on_save_failure is false" do
357
357
  @c.before_validation{false}
358
358
  @c.raise_on_save_failure = false
359
- @c.load(:id => 2233).save.must_equal nil
359
+ @c.load(:id => 2233).save.must_be_nil
360
360
  DB.sqls.must_equal []
361
361
  end
362
362
  end
@@ -0,0 +1,307 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "identifier_mangling extension" do
4
+ after do
5
+ Sequel.quote_identifiers = false
6
+ Sequel.identifier_input_method = nil
7
+ Sequel.identifier_output_method = nil
8
+ end
9
+
10
+ it "should respect the :quote_identifiers option" do
11
+ db = Sequel::Database.new(:quote_identifiers=>false, :identifier_mangling=>true)
12
+ db.quote_identifiers?.must_equal false
13
+ db = Sequel::Database.new(:quote_identifiers=>true, :identifier_mangling=>true)
14
+ db.quote_identifiers?.must_equal true
15
+ end
16
+
17
+ it "should upcase on input and downcase on output by default" do
18
+ db = Sequel::Database.new(:identifier_mangling=>true)
19
+ db.send(:identifier_input_method_default).must_equal :upcase
20
+ db.send(:identifier_output_method_default).must_equal :downcase
21
+ end
22
+
23
+ it "should respect the :identifier_input_method option" do
24
+ Sequel.identifier_input_method = nil
25
+ Sequel::Database.identifier_input_method.must_equal false
26
+ db = Sequel::Database.new(:identifier_input_method=>nil, :identifier_mangling=>true)
27
+ db.identifier_input_method.must_be_nil
28
+ db.identifier_input_method = :downcase
29
+ db.identifier_input_method.must_equal :downcase
30
+ db = Sequel::Database.new(:identifier_input_method=>:upcase, :identifier_mangling=>true)
31
+ db.identifier_input_method.must_equal :upcase
32
+ db.identifier_input_method = nil
33
+ db.identifier_input_method.must_be_nil
34
+ Sequel.identifier_input_method = :downcase
35
+ Sequel::Database.identifier_input_method.must_equal :downcase
36
+ db = Sequel::Database.new(:identifier_input_method=>nil, :identifier_mangling=>true)
37
+ db.identifier_input_method.must_be_nil
38
+ db.identifier_input_method = :upcase
39
+ db.identifier_input_method.must_equal :upcase
40
+ db = Sequel::Database.new(:identifier_input_method=>:upcase, :identifier_mangling=>true)
41
+ db.identifier_input_method.must_equal :upcase
42
+ db.identifier_input_method = nil
43
+ db.identifier_input_method.must_be_nil
44
+ end
45
+
46
+ it "should respect the :identifier_output_method option" do
47
+ Sequel.identifier_output_method = nil
48
+ Sequel::Database.identifier_output_method.must_equal false
49
+ db = Sequel::Database.new(:identifier_output_method=>nil, :identifier_mangling=>true)
50
+ db.identifier_output_method.must_be_nil
51
+ db.identifier_output_method = :downcase
52
+ db.identifier_output_method.must_equal :downcase
53
+ db = Sequel::Database.new(:identifier_output_method=>:upcase, :identifier_mangling=>true)
54
+ db.identifier_output_method.must_equal :upcase
55
+ db.identifier_output_method = nil
56
+ db.identifier_output_method.must_be_nil
57
+ Sequel.identifier_output_method = :downcase
58
+ Sequel::Database.identifier_output_method.must_equal :downcase
59
+ db = Sequel::Database.new(:identifier_output_method=>nil, :identifier_mangling=>true)
60
+ db.identifier_output_method.must_be_nil
61
+ db.identifier_output_method = :upcase
62
+ db.identifier_output_method.must_equal :upcase
63
+ db = Sequel::Database.new(:identifier_output_method=>:upcase, :identifier_mangling=>true)
64
+ db.identifier_output_method.must_equal :upcase
65
+ db.identifier_output_method = nil
66
+ db.identifier_output_method.must_be_nil
67
+ end
68
+
69
+ it "should use the default Sequel.quote_identifiers value" do
70
+ Sequel.quote_identifiers = true
71
+ Sequel::Database.new(:identifier_mangling=>true).quote_identifiers?.must_equal true
72
+ Sequel.quote_identifiers = false
73
+ Sequel::Database.new(:identifier_mangling=>true).quote_identifiers?.must_equal false
74
+ Sequel::Database.quote_identifiers = true
75
+ Sequel::Database.new(:identifier_mangling=>true).quote_identifiers?.must_equal true
76
+ Sequel::Database.quote_identifiers = false
77
+ Sequel::Database.new(:identifier_mangling=>true).quote_identifiers?.must_equal false
78
+ end
79
+
80
+ it "should use the default Sequel.identifier_input_method value" do
81
+ Sequel.identifier_input_method = :downcase
82
+ Sequel::Database.new(:identifier_mangling=>true).identifier_input_method.must_equal :downcase
83
+ Sequel.identifier_input_method = :upcase
84
+ Sequel::Database.new(:identifier_mangling=>true).identifier_input_method.must_equal :upcase
85
+ Sequel::Database.identifier_input_method = :downcase
86
+ Sequel::Database.new(:identifier_mangling=>true).identifier_input_method.must_equal :downcase
87
+ Sequel::Database.identifier_input_method = :upcase
88
+ Sequel::Database.new(:identifier_mangling=>true).identifier_input_method.must_equal :upcase
89
+ end
90
+
91
+ it "should use the default Sequel.identifier_output_method value" do
92
+ Sequel.identifier_output_method = :downcase
93
+ Sequel::Database.new(:identifier_mangling=>true).identifier_output_method.must_equal :downcase
94
+ Sequel.identifier_output_method = :upcase
95
+ Sequel::Database.new(:identifier_mangling=>true).identifier_output_method.must_equal :upcase
96
+ Sequel::Database.identifier_output_method = :downcase
97
+ Sequel::Database.new(:identifier_mangling=>true).identifier_output_method.must_equal :downcase
98
+ Sequel::Database.identifier_output_method = :upcase
99
+ Sequel::Database.new(:identifier_mangling=>true).identifier_output_method.must_equal :upcase
100
+ end
101
+
102
+ it "should respect the quote_indentifiers_default method if Sequel.quote_identifiers = nil" do
103
+ Sequel.quote_identifiers = nil
104
+ Sequel::Database.new(:identifier_mangling=>true).quote_identifiers?.must_equal true
105
+ x = Class.new(Sequel::Database){def quote_identifiers_default; false end}
106
+ x.new(:identifier_mangling=>true).quote_identifiers?.must_equal false
107
+ y = Class.new(Sequel::Database){def quote_identifiers_default; true end}
108
+ y.new(:identifier_mangling=>true).quote_identifiers?.must_equal true
109
+ end
110
+
111
+ it "should respect the identifier_input_method_default method if Sequel.identifier_input_method is not called" do
112
+ class Sequel::Database
113
+ @identifier_input_method = nil
114
+ end
115
+ x = Class.new(Sequel::Database){def identifier_input_method_default; :downcase end}
116
+ x.new(:identifier_mangling=>true).identifier_input_method.must_equal :downcase
117
+ y = Class.new(Sequel::Database){def identifier_input_method_default; :camelize end}
118
+ y.new(:identifier_mangling=>true).identifier_input_method.must_equal :camelize
119
+ end
120
+
121
+ it "should respect the identifier_output_method_default method if Sequel.identifier_output_method is not called" do
122
+ class Sequel::Database
123
+ @identifier_output_method = nil
124
+ end
125
+ x = Class.new(Sequel::Database){def identifier_output_method_default; :upcase end}
126
+ x.new(:identifier_mangling=>true).identifier_output_method.must_equal :upcase
127
+ y = Class.new(Sequel::Database){def identifier_output_method_default; :underscore end}
128
+ y.new(:identifier_mangling=>true).identifier_output_method.must_equal :underscore
129
+ end
130
+ end
131
+
132
+ describe "Database#input_identifier_meth" do
133
+ it "should be the input_identifer method of a default dataset for this database" do
134
+ db = Sequel::Database.new(:identifier_mangling=>true)
135
+ db.send(:input_identifier_meth).call(:a).must_equal 'a'
136
+ db.identifier_input_method = :upcase
137
+ db.send(:input_identifier_meth).call(:a).must_equal 'A'
138
+ end
139
+ end
140
+
141
+ describe "Database#output_identifier_meth" do
142
+ it "should be the output_identifer method of a default dataset for this database" do
143
+ db = Sequel::Database.new(:identifier_mangling=>true)
144
+ db.send(:output_identifier_meth).call('A').must_equal :A
145
+ db.identifier_output_method = :downcase
146
+ db.send(:output_identifier_meth).call('A').must_equal :a
147
+ end
148
+ end
149
+
150
+ describe "Database#metadata_dataset" do
151
+ it "should be a dataset with the default settings for identifier_mangling" do
152
+ ds = Sequel::Database.new(:identifier_mangling=>true).send(:metadata_dataset)
153
+ ds.literal(:a).must_equal 'A'
154
+ ds.send(:output_identifier, 'A').must_equal :a
155
+ end
156
+ end
157
+
158
+ describe "Dataset" do
159
+ before do
160
+ @dataset = Sequel.mock(:identifier_mangling=>true).dataset
161
+ end
162
+
163
+ it "should get quote_identifiers default from database" do
164
+ db = Sequel::Database.new(:quote_identifiers=>true, :identifier_mangling=>true)
165
+ db[:a].quote_identifiers?.must_equal true
166
+ db = Sequel::Database.new(:quote_identifiers=>false, :identifier_mangling=>true)
167
+ db[:a].quote_identifiers?.must_equal false
168
+ end
169
+
170
+ it "should get identifier_input_method default from database" do
171
+ db = Sequel::Database.new(:identifier_input_method=>:upcase, :identifier_mangling=>true)
172
+ db[:a].identifier_input_method.must_equal :upcase
173
+ db = Sequel::Database.new(:identifier_input_method=>:downcase, :identifier_mangling=>true)
174
+ db[:a].identifier_input_method.must_equal :downcase
175
+ end
176
+
177
+ it "should get identifier_output_method default from database" do
178
+ db = Sequel::Database.new(:identifier_output_method=>:upcase, :identifier_mangling=>true)
179
+ db[:a].identifier_output_method.must_equal :upcase
180
+ db = Sequel::Database.new(:identifier_output_method=>:downcase, :identifier_mangling=>true)
181
+ db[:a].identifier_output_method.must_equal :downcase
182
+ end
183
+
184
+ # SEQUEL5: Remove
185
+ unless Sequel.mock(:identifier_mangling=>true).dataset.frozen?
186
+ it "should have quote_identifiers= method which changes literalization of identifiers" do
187
+ @dataset.quote_identifiers = true
188
+ @dataset.literal(:a).must_equal '"a"'
189
+ @dataset.quote_identifiers = false
190
+ @dataset.literal(:a).must_equal 'a'
191
+ end
192
+
193
+ it "should have identifier_input_method= method which changes literalization of identifiers" do
194
+ @dataset.identifier_input_method = :upcase
195
+ @dataset.literal(:a).must_equal 'A'
196
+ @dataset.identifier_input_method = :downcase
197
+ @dataset.literal(:A).must_equal 'a'
198
+ @dataset.identifier_input_method = :reverse
199
+ @dataset.literal(:at_b).must_equal 'b_ta'
200
+ end
201
+
202
+ it "should have identifier_output_method= method which changes identifiers returned from the database" do
203
+ @dataset.send(:output_identifier, "at_b_C").must_equal :at_b_C
204
+ @dataset.identifier_output_method = :upcase
205
+ @dataset.send(:output_identifier, "at_b_C").must_equal :AT_B_C
206
+ @dataset.identifier_output_method = :downcase
207
+ @dataset.send(:output_identifier, "at_b_C").must_equal :at_b_c
208
+ @dataset.identifier_output_method = :reverse
209
+ @dataset.send(:output_identifier, "at_b_C").must_equal :C_b_ta
210
+ end
211
+ end
212
+
213
+ it "should have with_quote_identifiers method which returns cloned dataset with changed literalization of identifiers" do
214
+ @dataset.with_quote_identifiers(true).literal(:a).must_equal '"a"'
215
+ @dataset.with_quote_identifiers(false).literal(:a).must_equal 'a'
216
+ ds = @dataset.freeze.with_quote_identifiers(false)
217
+ ds.literal(:a).must_equal 'a'
218
+ ds.frozen?.must_equal true
219
+ end
220
+
221
+ it "should have with_identifier_input_method method which returns cloned dataset with changed literalization of identifiers" do
222
+ @dataset.with_identifier_input_method(:upcase).literal(:a).must_equal 'A'
223
+ @dataset.with_identifier_input_method(:downcase).literal(:A).must_equal 'a'
224
+ @dataset.with_identifier_input_method(:reverse).literal(:at_b).must_equal 'b_ta'
225
+ ds = @dataset.freeze.with_identifier_input_method(:reverse)
226
+ ds.frozen?.must_equal true
227
+ ds.literal(:at_b).must_equal 'b_ta'
228
+ end
229
+
230
+ it "should have with_identifier_output_method method which returns cloned dataset with changed identifiers returned from the database" do
231
+ @dataset.send(:output_identifier, "at_b_C").must_equal :at_b_C
232
+ @dataset.with_identifier_output_method(:upcase).send(:output_identifier, "at_b_C").must_equal :AT_B_C
233
+ @dataset.with_identifier_output_method(:downcase).send(:output_identifier, "at_b_C").must_equal :at_b_c
234
+ @dataset.with_identifier_output_method(:reverse).send(:output_identifier, "at_b_C").must_equal :C_b_ta
235
+ ds = @dataset.freeze.with_identifier_output_method(:reverse)
236
+ ds.send(:output_identifier, "at_b_C").must_equal :C_b_ta
237
+ ds.frozen?.must_equal true
238
+ end
239
+
240
+ it "should have output_identifier handle empty identifiers" do
241
+ @dataset.send(:output_identifier, "").must_equal :untitled
242
+ @dataset.with_identifier_output_method(:upcase).send(:output_identifier, "").must_equal :UNTITLED
243
+ @dataset.with_identifier_output_method(:downcase).send(:output_identifier, "").must_equal :untitled
244
+ @dataset.with_identifier_output_method(:reverse).send(:output_identifier, "").must_equal :deltitnu
245
+ end
246
+ end
247
+
248
+ describe "Frozen Datasets" do
249
+ before do
250
+ @ds = Sequel.mock(:identifier_mangling=>true)[:test].freeze
251
+ end
252
+
253
+ it "should raise an error when calling mutation methods" do
254
+ proc{@ds.identifier_input_method = :a}.must_raise RuntimeError
255
+ proc{@ds.identifier_output_method = :a}.must_raise RuntimeError
256
+ proc{@ds.quote_identifiers = false}.must_raise RuntimeError
257
+ end
258
+ end
259
+
260
+ describe "identifier_mangling extension" do
261
+ it "should be able to load dialects based on the database name" do
262
+ begin
263
+ qi = class Sequel::Database; @quote_identifiers; end
264
+ ii = class Sequel::Database; @identifier_input_method; end
265
+ io = class Sequel::Database; @identifier_output_method; end
266
+ Sequel.quote_identifiers = nil
267
+ class Sequel::Database; @identifier_input_method=nil; end
268
+ class Sequel::Database; @identifier_output_method=nil; end
269
+ Sequel.mock(:host=>'access').select(Date.new(2011, 12, 13)).sql.must_equal 'SELECT #2011-12-13#'
270
+ Sequel.mock(:host=>'cubrid').from(:a).offset(1).sql.must_equal 'SELECT * FROM "a" LIMIT 1,4294967295'
271
+ Sequel.mock(:host=>'db2').select(1).sql.must_equal 'SELECT 1 FROM "SYSIBM"."SYSDUMMY1"'
272
+ Sequel.mock(:host=>'firebird')[:a].distinct.limit(1, 2).sql.must_equal 'SELECT DISTINCT FIRST 1 SKIP 2 * FROM "A"'
273
+ Sequel.mock(:host=>'informix')[:a].distinct.limit(1, 2).sql.must_equal 'SELECT SKIP 2 FIRST 1 DISTINCT * FROM A'
274
+ Sequel.mock(:host=>'mssql')[:a].full_text_search(:b, 'c').sql.must_equal "SELECT * FROM [A] WHERE (CONTAINS ([B], 'c'))"
275
+ Sequel.mock(:host=>'mysql')[:a].full_text_search(:b, 'c').sql.must_equal "SELECT * FROM `a` WHERE (MATCH (`b`) AGAINST ('c'))"
276
+ Sequel.mock(:host=>'oracle')[:a].limit(1).sql.must_equal 'SELECT * FROM (SELECT * FROM "A") "T1" WHERE (ROWNUM <= 1)'
277
+ Sequel.mock(:host=>'postgres')[:a].full_text_search(:b, 'c').sql.must_equal "SELECT * FROM \"a\" WHERE (to_tsvector(CAST('simple' AS regconfig), (COALESCE(\"b\", ''))) @@ to_tsquery(CAST('simple' AS regconfig), 'c'))"
278
+ Sequel.mock(:host=>'sqlanywhere').from(:a).offset(1).sql.must_equal 'SELECT TOP 2147483647 START AT (1 + 1) * FROM "A"'
279
+ Sequel.mock(:host=>'sqlite')[:a___b].sql.must_equal "SELECT * FROM `a` AS 'b'"
280
+ ensure
281
+ Sequel.quote_identifiers = qi
282
+ Sequel::Database.send(:instance_variable_set, :@identifier_input_method, ii)
283
+ Sequel::Database.send(:instance_variable_set, :@identifier_output_method, io)
284
+ end
285
+ end
286
+ end
287
+
288
+ describe Sequel::Model, ".[] optimization" do
289
+ before do
290
+ @db = Sequel.mock(:identifier_mangling=>true, :quote_identifiers=>true)
291
+ def @db.schema(*) [[:id, {:primary_key=>true}]] end
292
+ def @db.supports_schema_parsing?() true end
293
+ @c = Class.new(Sequel::Model(@db))
294
+ @ds = @db.dataset.with_quote_identifiers(true)
295
+ end
296
+
297
+ it "should have simple_pk and simple_table respect dataset's identifier input methods" do
298
+ ds = @db.from(:ab).with_identifier_input_method(:reverse)
299
+ @c.set_dataset ds
300
+ @c.simple_table.must_equal '"ba"'
301
+ @c.set_primary_key :cd
302
+ @c.simple_pk.must_equal '"dc"'
303
+
304
+ @c.set_dataset ds.from(:ef__gh)
305
+ @c.simple_table.must_equal '"fe"."hg"'
306
+ end
307
+ end