sequel 3.47.0 → 3.48.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 (243) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +230 -0
  3. data/README.rdoc +31 -40
  4. data/Rakefile +1 -14
  5. data/doc/active_record.rdoc +29 -29
  6. data/doc/association_basics.rdoc +4 -13
  7. data/doc/cheat_sheet.rdoc +8 -6
  8. data/doc/code_order.rdoc +89 -0
  9. data/doc/core_extensions.rdoc +3 -3
  10. data/doc/dataset_basics.rdoc +7 -8
  11. data/doc/dataset_filtering.rdoc +7 -2
  12. data/doc/mass_assignment.rdoc +2 -3
  13. data/doc/migration.rdoc +8 -8
  14. data/doc/model_hooks.rdoc +11 -7
  15. data/doc/object_model.rdoc +2 -2
  16. data/doc/opening_databases.rdoc +5 -14
  17. data/doc/prepared_statements.rdoc +5 -9
  18. data/doc/querying.rdoc +23 -28
  19. data/doc/reflection.rdoc +11 -0
  20. data/doc/release_notes/3.48.0.txt +477 -0
  21. data/doc/schema_modification.rdoc +12 -5
  22. data/doc/security.rdoc +2 -2
  23. data/doc/sharding.rdoc +1 -2
  24. data/doc/sql.rdoc +10 -13
  25. data/doc/testing.rdoc +8 -4
  26. data/doc/transactions.rdoc +2 -2
  27. data/doc/validations.rdoc +40 -17
  28. data/doc/virtual_rows.rdoc +2 -2
  29. data/lib/sequel/adapters/ado.rb +25 -20
  30. data/lib/sequel/adapters/ado/access.rb +1 -0
  31. data/lib/sequel/adapters/ado/mssql.rb +1 -0
  32. data/lib/sequel/adapters/db2.rb +9 -7
  33. data/lib/sequel/adapters/dbi.rb +16 -16
  34. data/lib/sequel/adapters/do.rb +17 -18
  35. data/lib/sequel/adapters/do/mysql.rb +1 -0
  36. data/lib/sequel/adapters/do/postgres.rb +2 -0
  37. data/lib/sequel/adapters/do/sqlite.rb +1 -0
  38. data/lib/sequel/adapters/firebird.rb +5 -7
  39. data/lib/sequel/adapters/ibmdb.rb +23 -20
  40. data/lib/sequel/adapters/informix.rb +8 -2
  41. data/lib/sequel/adapters/jdbc.rb +39 -35
  42. data/lib/sequel/adapters/jdbc/as400.rb +1 -0
  43. data/lib/sequel/adapters/jdbc/cubrid.rb +1 -0
  44. data/lib/sequel/adapters/jdbc/db2.rb +1 -0
  45. data/lib/sequel/adapters/jdbc/derby.rb +1 -0
  46. data/lib/sequel/adapters/jdbc/firebird.rb +1 -0
  47. data/lib/sequel/adapters/jdbc/h2.rb +1 -0
  48. data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -0
  49. data/lib/sequel/adapters/jdbc/informix.rb +1 -0
  50. data/lib/sequel/adapters/jdbc/jtds.rb +1 -0
  51. data/lib/sequel/adapters/jdbc/mssql.rb +1 -0
  52. data/lib/sequel/adapters/jdbc/mysql.rb +1 -0
  53. data/lib/sequel/adapters/jdbc/oracle.rb +1 -0
  54. data/lib/sequel/adapters/jdbc/postgresql.rb +2 -0
  55. data/lib/sequel/adapters/jdbc/progress.rb +1 -0
  56. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -0
  57. data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -0
  58. data/lib/sequel/adapters/mock.rb +30 -31
  59. data/lib/sequel/adapters/mysql.rb +6 -7
  60. data/lib/sequel/adapters/mysql2.rb +5 -6
  61. data/lib/sequel/adapters/odbc.rb +22 -20
  62. data/lib/sequel/adapters/odbc/mssql.rb +1 -0
  63. data/lib/sequel/adapters/openbase.rb +4 -1
  64. data/lib/sequel/adapters/oracle.rb +10 -8
  65. data/lib/sequel/adapters/postgres.rb +12 -10
  66. data/lib/sequel/adapters/shared/access.rb +6 -0
  67. data/lib/sequel/adapters/shared/cubrid.rb +2 -0
  68. data/lib/sequel/adapters/shared/db2.rb +2 -0
  69. data/lib/sequel/adapters/shared/firebird.rb +2 -0
  70. data/lib/sequel/adapters/shared/informix.rb +2 -0
  71. data/lib/sequel/adapters/shared/mssql.rb +14 -8
  72. data/lib/sequel/adapters/shared/mysql.rb +6 -0
  73. data/lib/sequel/adapters/shared/oracle.rb +2 -0
  74. data/lib/sequel/adapters/shared/postgres.rb +14 -4
  75. data/lib/sequel/adapters/shared/progress.rb +1 -0
  76. data/lib/sequel/adapters/shared/sqlite.rb +4 -3
  77. data/lib/sequel/adapters/sqlite.rb +6 -7
  78. data/lib/sequel/adapters/swift.rb +20 -21
  79. data/lib/sequel/adapters/swift/mysql.rb +1 -0
  80. data/lib/sequel/adapters/swift/postgres.rb +2 -0
  81. data/lib/sequel/adapters/swift/sqlite.rb +1 -0
  82. data/lib/sequel/adapters/tinytds.rb +5 -6
  83. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +68 -0
  84. data/lib/sequel/connection_pool.rb +1 -1
  85. data/lib/sequel/core.rb +57 -50
  86. data/lib/sequel/database/connecting.rb +9 -10
  87. data/lib/sequel/database/dataset.rb +11 -6
  88. data/lib/sequel/database/dataset_defaults.rb +61 -69
  89. data/lib/sequel/database/features.rb +21 -0
  90. data/lib/sequel/database/misc.rb +23 -3
  91. data/lib/sequel/database/query.rb +13 -7
  92. data/lib/sequel/database/schema_methods.rb +6 -6
  93. data/lib/sequel/database/transactions.rb +1 -0
  94. data/lib/sequel/dataset/actions.rb +51 -38
  95. data/lib/sequel/dataset/features.rb +1 -0
  96. data/lib/sequel/dataset/graph.rb +9 -33
  97. data/lib/sequel/dataset/misc.rb +30 -5
  98. data/lib/sequel/dataset/mutation.rb +2 -3
  99. data/lib/sequel/dataset/prepared_statements.rb +1 -1
  100. data/lib/sequel/dataset/query.rb +91 -27
  101. data/lib/sequel/dataset/sql.rb +40 -6
  102. data/lib/sequel/deprecated.rb +74 -0
  103. data/lib/sequel/deprecated_core_extensions.rb +135 -0
  104. data/lib/sequel/extensions/columns_introspection.rb +1 -5
  105. data/lib/sequel/extensions/core_extensions.rb +10 -3
  106. data/lib/sequel/extensions/date_arithmetic.rb +1 -0
  107. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +33 -0
  108. data/lib/sequel/extensions/filter_having.rb +58 -0
  109. data/lib/sequel/extensions/graph_each.rb +63 -0
  110. data/lib/sequel/extensions/hash_aliases.rb +44 -0
  111. data/lib/sequel/extensions/looser_typecasting.rb +14 -3
  112. data/lib/sequel/extensions/migration.rb +2 -3
  113. data/lib/sequel/extensions/named_timezones.rb +14 -1
  114. data/lib/sequel/extensions/null_dataset.rb +7 -1
  115. data/lib/sequel/extensions/pagination.rb +15 -5
  116. data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -0
  117. data/lib/sequel/extensions/pg_hstore_ops.rb +48 -14
  118. data/lib/sequel/extensions/pg_json.rb +7 -7
  119. data/lib/sequel/extensions/pg_range_ops.rb +8 -2
  120. data/lib/sequel/extensions/pg_statement_cache.rb +1 -0
  121. data/lib/sequel/extensions/pretty_table.rb +13 -4
  122. data/lib/sequel/extensions/query.rb +21 -4
  123. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +22 -0
  124. data/lib/sequel/extensions/schema_caching.rb +10 -7
  125. data/lib/sequel/extensions/schema_dumper.rb +35 -48
  126. data/lib/sequel/extensions/select_remove.rb +13 -4
  127. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +117 -0
  128. data/lib/sequel/extensions/set_overrides.rb +43 -0
  129. data/lib/sequel/extensions/to_dot.rb +6 -0
  130. data/lib/sequel/model.rb +12 -6
  131. data/lib/sequel/model/associations.rb +80 -38
  132. data/lib/sequel/model/base.rb +137 -52
  133. data/lib/sequel/model/errors.rb +7 -2
  134. data/lib/sequel/plugins/active_model.rb +13 -0
  135. data/lib/sequel/plugins/after_initialize.rb +43 -0
  136. data/lib/sequel/plugins/association_proxies.rb +63 -7
  137. data/lib/sequel/plugins/auto_validations.rb +56 -16
  138. data/lib/sequel/plugins/blacklist_security.rb +63 -0
  139. data/lib/sequel/plugins/class_table_inheritance.rb +9 -0
  140. data/lib/sequel/plugins/constraint_validations.rb +50 -8
  141. data/lib/sequel/plugins/dataset_associations.rb +2 -0
  142. data/lib/sequel/plugins/hook_class_methods.rb +7 -1
  143. data/lib/sequel/plugins/identity_map.rb +4 -0
  144. data/lib/sequel/plugins/json_serializer.rb +32 -13
  145. data/lib/sequel/plugins/optimistic_locking.rb +1 -1
  146. data/lib/sequel/plugins/rcte_tree.rb +4 -4
  147. data/lib/sequel/plugins/scissors.rb +33 -0
  148. data/lib/sequel/plugins/serialization.rb +1 -1
  149. data/lib/sequel/plugins/single_table_inheritance.rb +6 -0
  150. data/lib/sequel/plugins/tree.rb +5 -1
  151. data/lib/sequel/plugins/validation_class_methods.rb +2 -1
  152. data/lib/sequel/plugins/validation_helpers.rb +15 -11
  153. data/lib/sequel/plugins/xml_serializer.rb +12 -3
  154. data/lib/sequel/sql.rb +12 -2
  155. data/lib/sequel/timezones.rb +1 -1
  156. data/lib/sequel/version.rb +1 -1
  157. data/lib/sequel_core.rb +1 -0
  158. data/lib/sequel_model.rb +1 -0
  159. data/spec/adapters/mssql_spec.rb +24 -57
  160. data/spec/adapters/postgres_spec.rb +27 -55
  161. data/spec/adapters/spec_helper.rb +1 -1
  162. data/spec/adapters/sqlite_spec.rb +1 -1
  163. data/spec/bin_spec.rb +251 -0
  164. data/spec/core/database_spec.rb +46 -32
  165. data/spec/core/dataset_spec.rb +233 -181
  166. data/spec/core/deprecated_spec.rb +78 -0
  167. data/spec/core/expression_filters_spec.rb +3 -4
  168. data/spec/core/mock_adapter_spec.rb +9 -9
  169. data/spec/core/object_graph_spec.rb +9 -19
  170. data/spec/core/schema_spec.rb +3 -1
  171. data/spec/core/spec_helper.rb +19 -0
  172. data/spec/core_extensions_spec.rb +80 -30
  173. data/spec/extensions/after_initialize_spec.rb +24 -0
  174. data/spec/extensions/association_proxies_spec.rb +37 -1
  175. data/spec/extensions/auto_validations_spec.rb +20 -4
  176. data/spec/extensions/blacklist_security_spec.rb +87 -0
  177. data/spec/extensions/boolean_readers_spec.rb +2 -1
  178. data/spec/extensions/class_table_inheritance_spec.rb +7 -0
  179. data/spec/extensions/columns_introspection_spec.rb +3 -3
  180. data/spec/extensions/constraint_validations_plugin_spec.rb +83 -5
  181. data/spec/extensions/core_refinements_spec.rb +7 -7
  182. data/spec/extensions/dataset_associations_spec.rb +2 -2
  183. data/spec/extensions/date_arithmetic_spec.rb +1 -1
  184. data/spec/extensions/defaults_setter_spec.rb +2 -1
  185. data/spec/extensions/empty_array_ignore_nulls_spec.rb +24 -0
  186. data/spec/extensions/filter_having_spec.rb +40 -0
  187. data/spec/extensions/graph_each_spec.rb +109 -0
  188. data/spec/extensions/hash_aliases_spec.rb +16 -0
  189. data/spec/extensions/hook_class_methods_spec.rb +2 -2
  190. data/spec/extensions/identity_map_spec.rb +3 -3
  191. data/spec/extensions/json_serializer_spec.rb +19 -19
  192. data/spec/extensions/lazy_attributes_spec.rb +1 -0
  193. data/spec/extensions/list_spec.rb +13 -13
  194. data/spec/extensions/looser_typecasting_spec.rb +10 -3
  195. data/spec/extensions/many_through_many_spec.rb +1 -1
  196. data/spec/extensions/migration_spec.rb +7 -7
  197. data/spec/extensions/named_timezones_spec.rb +6 -0
  198. data/spec/extensions/nested_attributes_spec.rb +2 -2
  199. data/spec/extensions/null_dataset_spec.rb +1 -1
  200. data/spec/extensions/pagination_spec.rb +2 -2
  201. data/spec/extensions/pg_hstore_ops_spec.rb +75 -0
  202. data/spec/extensions/pg_range_ops_spec.rb +4 -2
  203. data/spec/extensions/pg_row_plugin_spec.rb +1 -1
  204. data/spec/extensions/pretty_table_spec.rb +1 -1
  205. data/spec/extensions/query_literals_spec.rb +1 -1
  206. data/spec/extensions/query_spec.rb +3 -3
  207. data/spec/extensions/schema_caching_spec.rb +3 -3
  208. data/spec/extensions/schema_dumper_spec.rb +27 -2
  209. data/spec/extensions/schema_spec.rb +2 -2
  210. data/spec/extensions/scissors_spec.rb +26 -0
  211. data/spec/extensions/select_remove_spec.rb +1 -1
  212. data/spec/extensions/sequel_3_dataset_methods_spec.rb +102 -0
  213. data/spec/extensions/set_overrides_spec.rb +45 -0
  214. data/spec/extensions/single_table_inheritance_spec.rb +10 -0
  215. data/spec/extensions/spec_helper.rb +24 -1
  216. data/spec/extensions/static_cache_spec.rb +1 -1
  217. data/spec/extensions/string_stripper_spec.rb +2 -1
  218. data/spec/extensions/to_dot_spec.rb +1 -1
  219. data/spec/extensions/typecast_on_load_spec.rb +3 -2
  220. data/spec/extensions/update_primary_key_spec.rb +2 -2
  221. data/spec/extensions/validation_class_methods_spec.rb +19 -19
  222. data/spec/extensions/validation_helpers_spec.rb +30 -21
  223. data/spec/extensions/xml_serializer_spec.rb +5 -5
  224. data/spec/integration/associations_test.rb +10 -30
  225. data/spec/integration/dataset_test.rb +20 -24
  226. data/spec/integration/eager_loader_test.rb +5 -5
  227. data/spec/integration/model_test.rb +3 -3
  228. data/spec/integration/plugin_test.rb +7 -39
  229. data/spec/integration/schema_test.rb +4 -38
  230. data/spec/integration/spec_helper.rb +2 -1
  231. data/spec/model/association_reflection_spec.rb +70 -5
  232. data/spec/model/associations_spec.rb +11 -11
  233. data/spec/model/base_spec.rb +25 -8
  234. data/spec/model/class_dataset_methods_spec.rb +143 -0
  235. data/spec/model/dataset_methods_spec.rb +1 -1
  236. data/spec/model/eager_loading_spec.rb +25 -25
  237. data/spec/model/hooks_spec.rb +1 -1
  238. data/spec/model/model_spec.rb +22 -7
  239. data/spec/model/plugins_spec.rb +1 -6
  240. data/spec/model/record_spec.rb +37 -29
  241. data/spec/model/spec_helper.rb +23 -1
  242. data/spec/model/validations_spec.rb +15 -17
  243. metadata +32 -3
@@ -134,7 +134,7 @@ end
134
134
 
135
135
  describe "Array#case and Hash#case" do
136
136
  before do
137
- @d = Sequel::Dataset.new(nil)
137
+ @d = Sequel.mock.dataset
138
138
  end
139
139
 
140
140
  specify "should return SQL CASE expression" do
@@ -166,7 +166,7 @@ end
166
166
 
167
167
  describe "Array#sql_value_list and #sql_array" do
168
168
  before do
169
- @d = Sequel::Dataset.new(nil)
169
+ @d = Sequel.mock.dataset
170
170
  end
171
171
 
172
172
  specify "should treat the array as an SQL value list instead of conditions when used as a placeholder value" do
@@ -231,7 +231,7 @@ end
231
231
 
232
232
  describe "#desc" do
233
233
  before do
234
- @ds = Sequel::Dataset.new(nil)
234
+ @ds = Sequel.mock.dataset
235
235
  end
236
236
 
237
237
  specify "should format a DESC clause for a column ref" do
@@ -247,7 +247,7 @@ end
247
247
 
248
248
  describe "#asc" do
249
249
  before do
250
- @ds = Sequel::Dataset.new(nil)
250
+ @ds = Sequel.mock.dataset
251
251
  end
252
252
 
253
253
  specify "should format a ASC clause for a column ref" do
@@ -263,7 +263,7 @@ end
263
263
 
264
264
  describe "#as" do
265
265
  before do
266
- @ds = Sequel::Dataset.new(nil)
266
+ @ds = Sequel.mock.dataset
267
267
  end
268
268
 
269
269
  specify "should format a AS clause for a column ref" do
@@ -327,7 +327,7 @@ end
327
327
 
328
328
  describe "Symbol#*" do
329
329
  before do
330
- @ds = Sequel::Dataset.new(nil)
330
+ @ds = Sequel.mock.dataset
331
331
  end
332
332
 
333
333
  specify "should format a qualified wildcard if no argument" do
@@ -347,7 +347,7 @@ end
347
347
 
348
348
  describe "Symbol" do
349
349
  before do
350
- @ds = Sequel::Dataset.new(nil)
350
+ @ds = Sequel.mock.dataset
351
351
  @ds.quote_identifiers = true
352
352
  @ds.identifier_input_method = :upcase
353
353
  end
@@ -2,7 +2,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe "Sequel::Plugins::DatasetAssociations" do
4
4
  before do
5
- @db = Sequel::Database.new
5
+ @db = Sequel.mock
6
6
  @Base = Class.new(Sequel::Model)
7
7
  @Base.plugin :dataset_associations
8
8
 
@@ -140,7 +140,7 @@ end
140
140
 
141
141
  describe "Sequel::Plugins::DatasetAssociations with composite keys" do
142
142
  before do
143
- @db = Sequel::Database.new
143
+ @db = Sequel.mock
144
144
  @Base = Class.new(Sequel::Model)
145
145
  @Base.plugin :dataset_associations
146
146
 
@@ -142,7 +142,7 @@ describe "date_arithmetic extension" do
142
142
  db.literal(Sequel.date_add(:a, @h2)).should == "(CAST(a AS timestamp) + 1 years + 1 months + 1 days + 1 hours + 1 minutes + 1 seconds)"
143
143
  end
144
144
 
145
- it "should raise error if literalizing on an unsupported database" do
145
+ qspecify "should raise error if literalizing on an unsupported database" do
146
146
  db = Sequel.mock
147
147
  db.extension :date_arithmetic
148
148
  lambda{db.literal(Sequel.date_add(:a, @h0))}.should raise_error(Sequel::NotImplemented)
@@ -2,7 +2,8 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe "Sequel::Plugins::DefaultsSetter" do
4
4
  before do
5
- @db = db = Sequel::Database.new
5
+ @db = db = Sequel.mock
6
+ def db.supports_schema_parsing?() true end
6
7
  @c = c = Class.new(Sequel::Model(db[:foo]))
7
8
  @c.instance_variable_set(:@db_schema, {:a=>{}})
8
9
  @c.plugin :defaults_setter
@@ -0,0 +1,24 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "filter_having extension" do
4
+ before do
5
+ @dataset = Sequel.mock[:test].extension(:empty_array_ignore_nulls)
6
+ end
7
+
8
+ specify "should handle all types of IN/NOT IN queries with empty arrays" do
9
+ @dataset.filter(:id => []).sql.should == "SELECT * FROM test WHERE (1 = 0)"
10
+ @dataset.filter([:id1, :id2] => []).sql.should == "SELECT * FROM test WHERE (1 = 0)"
11
+ @dataset.exclude(:id => []).sql.should == "SELECT * FROM test WHERE (1 = 1)"
12
+ @dataset.exclude([:id1, :id2] => []).sql.should == "SELECT * FROM test WHERE (1 = 1)"
13
+ end
14
+
15
+ specify "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
+ db = Sequel.mock
18
+ d1 = db[:test].select(:id1, :id2).filter(:region=>'Asia').columns(:id1, :id2)
19
+ @dataset.filter([:id1, :id2] => d1).sql.should == "SELECT * FROM test WHERE (1 = 0)"
20
+ db.sqls.should == ["SELECT id1, id2 FROM test WHERE (region = 'Asia')"]
21
+ @dataset.exclude([:id1, :id2] => d1).sql.should == "SELECT * FROM test WHERE (1 = 1)"
22
+ db.sqls.should == ["SELECT id1, id2 FROM test WHERE (region = 'Asia')"]
23
+ end
24
+ end
@@ -0,0 +1,40 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "filter_having extension" do
4
+ before do
5
+ @ds = Sequel.mock[:t].extension(:filter_having)
6
+ @dsh = @ds.having(:a)
7
+ end
8
+
9
+ it "should make filter operate on HAVING clause if dataset has a HAVING clause" do
10
+ @dsh.filter(:b).sql.should == 'SELECT * FROM t HAVING (a AND b)'
11
+ end
12
+
13
+ it "should make filter operate on WHERE clause if dataset does not have a HAVING clause" do
14
+ @ds.filter(:b).sql.should == 'SELECT * FROM t WHERE b'
15
+ end
16
+
17
+ it "should make and operate on HAVING clause if dataset has a HAVING clause" do
18
+ @dsh.and(:b).sql.should == 'SELECT * FROM t HAVING (a AND b)'
19
+ end
20
+
21
+ it "should make and operate on WHERE clause if dataset does not have a HAVING clause" do
22
+ @ds.where(:a).and(:b).sql.should == 'SELECT * FROM t WHERE (a AND b)'
23
+ end
24
+
25
+ it "should make or operate on HAVING clause if dataset has a HAVING clause" do
26
+ @dsh.or(:b).sql.should == 'SELECT * FROM t HAVING (a OR b)'
27
+ end
28
+
29
+ it "should make or operate on WHERE clause if dataset does not have a HAVING clause" do
30
+ @ds.where(:a).or(:b).sql.should == 'SELECT * FROM t WHERE (a OR b)'
31
+ end
32
+
33
+ it "should make exclude operate on HAVING clause if dataset has a HAVING clause" do
34
+ @dsh.exclude(:b).sql.should == 'SELECT * FROM t HAVING (a AND NOT b)'
35
+ end
36
+
37
+ it "should make exclude operate on WHERE clause if dataset does not have a HAVING clause" do
38
+ @ds.exclude(:b).sql.should == 'SELECT * FROM t WHERE NOT b'
39
+ end
40
+ end
@@ -0,0 +1,109 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe Sequel::Dataset, " graphing" do
4
+ before do
5
+ @db = Sequel.mock(:columns=>proc do |sql|
6
+ case sql
7
+ when /points/
8
+ [:id, :x, :y]
9
+ when /lines/
10
+ [:id, :x, :y, :graph_id]
11
+ else
12
+ [:id, :name, :x, :y, :lines_x]
13
+ end
14
+ end).extension(:graph_each)
15
+ @ds1 = @db.from(:points)
16
+ @ds2 = @db.from(:lines)
17
+ @ds3 = @db.from(:graphs)
18
+ [@ds1, @ds2, @ds3].each{|ds| ds.columns}
19
+ @db.sqls
20
+ end
21
+
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.should == [{:points=>{:id=>1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
26
+
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.should == [{:points=>{:id=>1, :x=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
30
+
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.should == [{:points=>{:id=>1, :x=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
34
+
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.should == [{:points=>{:id=>1, :y=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
38
+
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.should == [{:points=>{:id=>1, :y=>-1}, :lines=>{:id=>2, :x=>3, :y=>4, :graph_id=>5}}]
42
+ end
43
+
44
+ it "#graph_each should split the result set into component tables" do
45
+ @db.fetch = [[{:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7}],
46
+ [{:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graphs_id=>8, :name=>9, :graphs_x=>10, :graphs_y=>11, :graphs_lines_x=>12}],
47
+ [{:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graph_id_0=>8, :graph_x=>9, :graph_y=>10, :graph_graph_id=>11}]]
48
+
49
+ @ds1.graph(@ds2, :x=>:id).all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}}]
50
+ @ds1.graph(@ds2, :x=>:id).graph(@ds3, :id=>:graph_id).all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>{:id=>8, :name=>9, :x=>10, :y=>11, :lines_x=>12}}]
51
+ @ds1.graph(@ds2, :x=>:id).graph(@ds2, {:y=>:points__id}, :table_alias=>:graph).all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graph=>{:id=>8, :x=>9, :y=>10, :graph_id=>11}}]
52
+ end
53
+
54
+ it "#graph_each should give a nil value instead of a hash when all values for a table are nil" do
55
+ @db.fetch = [[{:id=>1,:x=>2,:y=>3,:lines_id=>nil,:lines_x=>nil,:lines_y=>nil,:graph_id=>nil}],
56
+ [{:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graphs_id=>nil, :name=>nil, :graphs_x=>nil, :graphs_y=>nil, :graphs_lines_x=>nil},
57
+ {:id=>2,:x=>4,:y=>5,:lines_id=>nil,:lines_x=>nil,:lines_y=>nil,:graph_id=>nil, :graphs_id=>nil, :name=>nil, :graphs_x=>nil, :graphs_y=>nil, :graphs_lines_x=>nil},
58
+ {:id=>3,:x=>5,:y=>6,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7, :graphs_id=>7, :name=>8, :graphs_x=>9, :graphs_y=>10, :graphs_lines_x=>11},
59
+ {:id=>3,:x=>5,:y=>6,:lines_id=>7,:lines_x=>5,:lines_y=>8,:graph_id=>9, :graphs_id=>9, :name=>10, :graphs_x=>10, :graphs_y=>11, :graphs_lines_x=>12}]]
60
+
61
+ @ds1.graph(@ds2, :x=>:id).all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>nil}]
62
+ @ds1.graph(@ds2, :x=>:id).graph(@ds3, :id=>:graph_id).all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>nil},
63
+ {:points=>{:id=>2, :x=>4, :y=>5}, :lines=>nil, :graphs=>nil},
64
+ {:points=>{:id=>3, :x=>5, :y=>6}, :lines=>{:id=>4, :x=>5, :y=>6, :graph_id=>7}, :graphs=>{:id=>7, :name=>8, :x=>9, :y=>10, :lines_x=>11}},
65
+ {:points=>{:id=>3, :x=>5, :y=>6}, :lines=>{:id=>7, :x=>5, :y=>8, :graph_id=>9}, :graphs=>{:id=>9, :name=>10, :x=>10, :y=>11, :lines_x=>12}}]
66
+ end
67
+
68
+ it "#graph_each should not give a nil value instead of a hash when any value for a table is false" do
69
+ @db.fetch = {:id=>1,:x=>2,:y=>3,:lines_id=>nil,:lines_x=>false,:lines_y=>nil,:graph_id=>nil}
70
+ @ds1.graph(@ds2, :x=>:id).all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :lines=>{:id=>nil, :x=>false, :y=>nil, :graph_id=>nil}}]
71
+ end
72
+
73
+ it "#graph_each should not included tables graphed with the :select => false option in the result set" do
74
+ @db.fetch = {:id=>1,:x=>2,:y=>3,:graphs_id=>8, :name=>9, :graphs_x=>10, :graphs_y=>11, :lines_x=>12}
75
+ @ds1.graph(:lines, {:x=>:id}, :select=>false).graph(:graphs, :id=>:graph_id).all.should == [{:points=>{:id=>1, :x=>2, :y=>3}, :graphs=>{:id=>8, :name=>9, :x=>10, :y=>11, :lines_x=>12}}]
76
+ end
77
+
78
+ it "#graph_each should only include the columns selected with #set_graph_aliases and #add_graph_aliases, if called" do
79
+ @db.fetch = [nil, [{:x=>2,:y=>3}], nil, [{:x=>2}], [{:x=>2, :q=>18}]]
80
+
81
+ @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x], :y=>[:lines, :y]).all.should == [{:points=>{:x=>2}, :lines=>{:y=>3}}]
82
+ ds = @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :x])
83
+ ds.all.should == [{:points=>{:x=>2}, :lines=>nil}]
84
+ ds = ds.add_graph_aliases(:q=>[:points, :r, 18])
85
+ ds.all.should == [{:points=>{:x=>2, :r=>18}, :lines=>nil}]
86
+ end
87
+
88
+ it "#graph_each should correctly map values when #set_graph_aliases is used with a third argument for each entry" do
89
+ @db.fetch = [nil, {:x=>2,:y=>3}]
90
+ @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points, :z1, 2], :y=>[:lines, :z2, Sequel.function(:random)]).all.should == [{:points=>{:z1=>2}, :lines=>{:z2=>3}}]
91
+ end
92
+
93
+ it "#graph_each should correctly map values when #set_graph_aliases is used with a single argument for each entry" do
94
+ @db.fetch = [nil, {:x=>2,:y=>3}]
95
+ @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>[:points], :y=>[:lines]).all.should == [{:points=>{:x=>2}, :lines=>{:y=>3}}]
96
+ end
97
+
98
+ it "#graph_each should correctly map values when #set_graph_aliases is used with a symbol for each entry" do
99
+ @db.fetch = [nil, {:x=>2,:y=>3}]
100
+ @ds1.graph(:lines, :x=>:id).set_graph_aliases(:x=>:points, :y=>:lines).all.should == [{:points=>{:x=>2}, :lines=>{:y=>3}}]
101
+ end
102
+
103
+ it "#graph_each should run the row_proc for graphed datasets" do
104
+ @ds1.row_proc = proc{|h| h.keys.each{|k| h[k] *= 2}; h}
105
+ @ds2.row_proc = proc{|h| h.keys.each{|k| h[k] *= 3}; h}
106
+ @db.fetch = {:id=>1,:x=>2,:y=>3,:lines_id=>4,:lines_x=>5,:lines_y=>6,:graph_id=>7}
107
+ @ds1.graph(@ds2, :x=>:id).all.should == [{:points=>{:id=>2, :x=>4, :y=>6}, :lines=>{:id=>12, :x=>15, :y=>18, :graph_id=>21}}]
108
+ end
109
+ end
@@ -0,0 +1,16 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "hash_aliases extension" do
4
+ before do
5
+ @ds = Sequel.mock.dataset.extension(:hash_aliases)
6
+ end
7
+
8
+ it "should make from treat hash arguments as alias specifiers" do
9
+ @ds.from(:a=>:b).sql.should == "SELECT * FROM a AS b"
10
+ end
11
+
12
+ it "should make select treat hash arguments as alias specifiers" do
13
+ @ds.select(:a=>:b).sql.should == "SELECT a AS b"
14
+ @ds.select{{:a=>:b}}.sql.should == "SELECT a AS b"
15
+ end
16
+ end
@@ -165,7 +165,7 @@ describe Sequel::Model, "hook_class_methods plugin" do
165
165
  end
166
166
 
167
167
  describe "Model#after_initialize" do
168
- specify "should be called after initialization" do
168
+ qspecify "should be called after initialization" do
169
169
  values1 = nil
170
170
  reached_after_initialized = false
171
171
 
@@ -325,7 +325,7 @@ describe "Model#before_validation && Model#after_validation" do
325
325
  after_validation{MODEL_DB << "BLAH after"}
326
326
 
327
327
  def self.validate(o)
328
- o.errors[:id] << 'not valid' unless o[:id] == 2233
328
+ o.errors.add(:id, 'not valid') unless o[:id] == 2233
329
329
  end
330
330
  columns :id
331
331
  end
@@ -282,8 +282,8 @@ describe "Sequel::Plugins::IdentityMap" do
282
282
  it "should work correctly when eagerly loading many_to_many associations with composite keys" do
283
283
  @c1.columns :id, :id2
284
284
  @c2.columns :id, :id2
285
- @c1.set_primary_key :id, :id2
286
- @c2.set_primary_key :id, :id2
285
+ @c1.set_primary_key [:id, :id2]
286
+ @c2.set_primary_key [:id, :id2]
287
287
  @c1.many_to_many :artists, :class=>@c2, :left_key=>[:album_id1, :album_id2], :right_key=>[:artist_id1, :artist_id2], :join_table=>:aa
288
288
  @c1.dataset._fetch = [{:id=>1, :id2=>4}, {:id=>2, :id2=>5}, {:id=>3, :id2=>6}]
289
289
  @c2.dataset._fetch = [ {:id=>1, :x_foreign_key_0_x=>1, :x_foreign_key_1_x=>4}, {:id=>1, :x_foreign_key_0_x=>2, :x_foreign_key_1_x=>5}, {:id=>2, :x_foreign_key_0_x=>1, :x_foreign_key_1_x=>4}, {:id=>2, :x_foreign_key_0_x=>2, :x_foreign_key_1_x=>5}, {:id=>3, :x_foreign_key_0_x=>1, :x_foreign_key_1_x=>4}, {:id=>3, :x_foreign_key_0_x=>1, :x_foreign_key_1_x=>4}]
@@ -319,7 +319,7 @@ describe "Sequel::Plugins::IdentityMap" do
319
319
  it "should work correctly when eagerly loading many_to_many associations with composite keys" do
320
320
  @c1.columns :id, :id2
321
321
  @c2.columns :id
322
- @c1.set_primary_key :id, :id2
322
+ @c1.set_primary_key [:id, :id2]
323
323
  @c1.plugin :many_through_many
324
324
  @c1.many_through_many :artists, [[:aa, [:album_id1, :album_id2], :artist_id]], :class=>@c2
325
325
  @c1.dataset._fetch = [{:id=>1, :id2=>4}, {:id=>2, :id2=>5}, {:id=>3, :id2=>6}]
@@ -4,7 +4,7 @@ describe "Sequel::Plugins::JsonSerializer" do
4
4
  before do
5
5
  class ::Artist < Sequel::Model
6
6
  unrestrict_primary_key
7
- plugin :json_serializer
7
+ plugin :json_serializer, :naked=>true
8
8
  columns :id, :name
9
9
  def_column_accessor :id, :name
10
10
  @db_schema = {:id=>{:type=>:integer}}
@@ -13,7 +13,7 @@ describe "Sequel::Plugins::JsonSerializer" do
13
13
  class ::Album < Sequel::Model
14
14
  unrestrict_primary_key
15
15
  attr_accessor :blah
16
- plugin :json_serializer
16
+ plugin :json_serializer, :naked=>true
17
17
  columns :id, :name, :artist_id
18
18
  def_column_accessor :id, :name, :artist_id
19
19
  many_to_one :artist
@@ -43,12 +43,12 @@ describe "Sequel::Plugins::JsonSerializer" do
43
43
  Artist.from_json(Artist.load(:name=>Date.today).to_json).should == Artist.load(:name=>Date.today)
44
44
  end
45
45
 
46
- it "should have .json_create method for creating an instance from a hash parsed from JSON" do
47
- JSON.parse(@artist.to_json, :create_additions=>true).should == @artist
48
- JSON.parse(@artist.to_json(:include=>{:albums=>{:include=>{:artist=>{:include=>:albums}}}}), :create_additions=>true).albums.map{|a| a.artist.albums}.should == [[@album]]
46
+ qspecify "should have .json_create method for creating an instance from a hash parsed from JSON" do
47
+ JSON.parse(@artist.to_json(:naked=>false), :create_additions=>true).should == @artist
48
+ JSON.parse(@artist.to_json(:naked=>false, :include=>{:albums=>{:include=>{:artist=>{:include=>:albums}}}}), :create_additions=>true).albums.map{|a| a.artist.albums}.should == [[@album]]
49
49
  end
50
50
 
51
- it "should have .json_create method raise error if not given a hash" do
51
+ qspecify "should have .json_create method raise error if not given a hash" do
52
52
  proc{Artist.json_create([])}.should raise_error(Sequel::Error)
53
53
  end
54
54
 
@@ -68,8 +68,8 @@ describe "Sequel::Plugins::JsonSerializer" do
68
68
  end
69
69
 
70
70
  it "should raise an error if attempting to parse json when providing array to non-array association or vice-versa" do
71
- proc{Artist.from_json('{"albums":{"id":1,"name":"RF","artist_id":2,"json_class":"Album"},"id":2,"name":"YJM","json_class":"Artist"}', :associations=>:albums)}.should raise_error(Sequel::Error)
72
- proc{Album.from_json('{"artist":[{"id":2,"name":"YJM","json_class":"Artist"}],"id":1,"name":"RF","json_class":"Album","artist_id":2}', :associations=>:artist)}.should raise_error(Sequel::Error)
71
+ proc{Artist.from_json('{"albums":{"id":1,"name":"RF","artist_id":2,"json_class":"Album"},"id":2,"name":"YJM"}', :associations=>:albums)}.should raise_error(Sequel::Error)
72
+ proc{Album.from_json('{"artist":[{"id":2,"name":"YJM","json_class":"Artist"}],"id":1,"name":"RF","artist_id":2}', :associations=>:artist)}.should raise_error(Sequel::Error)
73
73
  end
74
74
 
75
75
  it "should raise an error if attempting to parse an array containing non-hashes" do
@@ -129,7 +129,7 @@ describe "Sequel::Plugins::JsonSerializer" do
129
129
  Album.from_json(@album.to_json(:include=>{:artist=>{:include=>{:albums=>{:only=>:name}}}}), :associations=>{:artist=>{:associations=>:albums}}).artist.albums.should == [Album.load(:name=>@album.name)]
130
130
  end
131
131
 
132
- it "should automatically cascade parsing for all associations if :all_associations is used" do
132
+ qspecify "should automatically cascade parsing for all associations if :all_associations is used" do
133
133
  Artist.from_json(@artist.to_json(:include=>{:albums=>{:include=>:artist}}), :all_associations=>true).albums.map{|a| a.artist}.should == [@artist]
134
134
  end
135
135
 
@@ -222,7 +222,7 @@ describe "Sequel::Plugins::JsonSerializer" do
222
222
 
223
223
  it "should handle the :root=>:both option to qualify a dataset of records" do
224
224
  Album.dataset._fetch = [{:id=>1, :name=>'RF'}, {:id=>1, :name=>'RF'}]
225
- Album.dataset.to_json(:root=>true, :only => :id).to_s.should == '{"albums":[{"album":{"id":1}},{"album":{"id":1}}]}'
225
+ Album.dataset.to_json(:root=>:both, :only => :id).to_s.should == '{"albums":[{"album":{"id":1}},{"album":{"id":1}}]}'
226
226
  end
227
227
 
228
228
  it "should handle the :root=>:collection option to qualify just the collection" do
@@ -235,16 +235,16 @@ describe "Sequel::Plugins::JsonSerializer" do
235
235
  Album.dataset.to_json(:root=>:instance, :only => :id).to_s.should == '[{"album":{"id":1}},{"album":{"id":1}}]'
236
236
  end
237
237
 
238
- it "should handle the :root=>true option be the same as :root=>:both for backwards compatibility" do
238
+ qspecify "should handle the :root=>true option be the same as :root=>:both for backwards compatibility" do
239
239
  Album.dataset._fetch = [{:id=>1, :name=>'RF'}, {:id=>1, :name=>'RF'}]
240
240
  Album.dataset.to_json(:root=>true, :only => :id).to_s.should == '{"albums":[{"album":{"id":1}},{"album":{"id":1}}]}'
241
241
  end
242
242
 
243
243
  it "should store the default options in json_serializer_opts" do
244
- Album.json_serializer_opts.should == {}
244
+ Album.json_serializer_opts.should == {:naked=>true}
245
245
  c = Class.new(Album)
246
- c.plugin :json_serializer, :naked=>true
247
- c.json_serializer_opts.should == {:naked=>true}
246
+ c.plugin :json_serializer, :naked=>false
247
+ c.json_serializer_opts.should == {:naked=>false}
248
248
  end
249
249
 
250
250
  it "should work correctly when subclassing" do
@@ -260,26 +260,26 @@ describe "Sequel::Plugins::JsonSerializer" do
260
260
  Object.send(:remove_const, :Artist3)
261
261
  end
262
262
 
263
- it "should have :associations option take precedence over :all_assocations" do
263
+ qspecify "should have :associations option take precedence over :all_assocations" do
264
264
  Artist.from_json(@artist.to_json(:include=>:albums), :associations=>[], :all_associations=>true, :fields=>[]).associations.should == {}
265
265
  end
266
266
 
267
- it "should allow overriding of :all_columns options in associated objects" do
267
+ qspecify "should allow overriding of :all_columns options in associated objects" do
268
268
  Album.restrict_primary_key
269
269
  Artist.from_json(@artist.to_json(:include=>:albums), :associations=>{:albums=>{:fields=>[:id, :name, :artist_id], :missing=>:raise}}, :all_columns=>true).albums.should == [@album]
270
270
  end
271
271
 
272
- it "should handle typecasting if setter columns exist when using :all_columns" do
272
+ qspecify "should handle typecasting if setter columns exist when using :all_columns" do
273
273
  Artist.restrict_primary_key
274
274
  Artist.from_json('{"id":"2","name":"YJM","json_class":"Artist"}', :all_columns=>true).should == @artist
275
275
  end
276
276
 
277
- it "should allow setting columns that are restricted if :all_columns is used" do
277
+ qspecify "should allow setting columns that are restricted if :all_columns is used" do
278
278
  Artist.restrict_primary_key
279
279
  Artist.from_json(@artist.to_json, :all_columns=>true).should == @artist
280
280
  end
281
281
 
282
- it "should raise an error if using :all_columns and non-column is in the JSON" do
282
+ qspecify "should raise an error if using :all_columns and non-column is in the JSON" do
283
283
  proc{Artist.from_json('{"foo":"bar"}', :all_columns=>true)}.should raise_error(Sequel::Error)
284
284
  end
285
285
 
@@ -4,6 +4,7 @@ require 'yaml'
4
4
  describe "Sequel::Plugins::LazyAttributes" do
5
5
  before do
6
6
  @db = Sequel.mock
7
+ def @db.supports_schema_parsing?() true end
7
8
  @db.meta_def(:schema){|*a| [[:id, {:type=>:integer}], [:name,{:type=>:string}]]}
8
9
  class ::LazyAttributesModel < Sequel::Model(@db[:la])
9
10
  plugin :lazy_attributes