sequel 4.10.0 → 4.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +58 -0
  3. data/doc/association_basics.rdoc +1 -1
  4. data/doc/cheat_sheet.rdoc +0 -1
  5. data/doc/core_extensions.rdoc +2 -2
  6. data/doc/dataset_filtering.rdoc +5 -5
  7. data/doc/model_hooks.rdoc +9 -0
  8. data/doc/object_model.rdoc +7 -13
  9. data/doc/opening_databases.rdoc +3 -1
  10. data/doc/querying.rdoc +8 -8
  11. data/doc/release_notes/4.11.0.txt +147 -0
  12. data/doc/sql.rdoc +11 -7
  13. data/doc/virtual_rows.rdoc +4 -5
  14. data/lib/sequel/adapters/ibmdb.rb +24 -16
  15. data/lib/sequel/adapters/jdbc/h2.rb +5 -0
  16. data/lib/sequel/adapters/jdbc/hsqldb.rb +5 -0
  17. data/lib/sequel/adapters/mock.rb +14 -2
  18. data/lib/sequel/adapters/shared/access.rb +6 -9
  19. data/lib/sequel/adapters/shared/cubrid.rb +5 -0
  20. data/lib/sequel/adapters/shared/db2.rb +5 -0
  21. data/lib/sequel/adapters/shared/firebird.rb +5 -0
  22. data/lib/sequel/adapters/shared/mssql.rb +23 -16
  23. data/lib/sequel/adapters/shared/mysql.rb +12 -2
  24. data/lib/sequel/adapters/shared/oracle.rb +31 -15
  25. data/lib/sequel/adapters/shared/postgres.rb +28 -4
  26. data/lib/sequel/adapters/shared/sqlanywhere.rb +5 -0
  27. data/lib/sequel/adapters/shared/sqlite.rb +12 -1
  28. data/lib/sequel/ast_transformer.rb +9 -7
  29. data/lib/sequel/connection_pool.rb +10 -4
  30. data/lib/sequel/database/features.rb +15 -0
  31. data/lib/sequel/database/schema_generator.rb +2 -2
  32. data/lib/sequel/database/schema_methods.rb +21 -3
  33. data/lib/sequel/database/transactions.rb +8 -4
  34. data/lib/sequel/dataset/actions.rb +13 -7
  35. data/lib/sequel/dataset/features.rb +7 -0
  36. data/lib/sequel/dataset/query.rb +28 -11
  37. data/lib/sequel/dataset/sql.rb +90 -14
  38. data/lib/sequel/extensions/constraint_validations.rb +2 -2
  39. data/lib/sequel/extensions/date_arithmetic.rb +1 -1
  40. data/lib/sequel/extensions/eval_inspect.rb +12 -6
  41. data/lib/sequel/extensions/pg_array_ops.rb +11 -2
  42. data/lib/sequel/extensions/pg_json.rb +130 -23
  43. data/lib/sequel/extensions/pg_json_ops.rb +196 -28
  44. data/lib/sequel/extensions/to_dot.rb +5 -7
  45. data/lib/sequel/model/associations.rb +0 -50
  46. data/lib/sequel/plugins/class_table_inheritance.rb +49 -21
  47. data/lib/sequel/plugins/many_through_many.rb +10 -11
  48. data/lib/sequel/plugins/serialization.rb +4 -1
  49. data/lib/sequel/plugins/sharding.rb +0 -9
  50. data/lib/sequel/plugins/single_table_inheritance.rb +4 -2
  51. data/lib/sequel/plugins/timestamps.rb +2 -2
  52. data/lib/sequel/sql.rb +166 -44
  53. data/lib/sequel/version.rb +1 -1
  54. data/spec/adapters/postgres_spec.rb +199 -133
  55. data/spec/core/connection_pool_spec.rb +6 -0
  56. data/spec/core/database_spec.rb +12 -0
  57. data/spec/core/dataset_spec.rb +58 -3
  58. data/spec/core/expression_filters_spec.rb +67 -5
  59. data/spec/core/mock_adapter_spec.rb +8 -4
  60. data/spec/core/schema_spec.rb +7 -0
  61. data/spec/core_extensions_spec.rb +14 -0
  62. data/spec/extensions/class_table_inheritance_spec.rb +23 -3
  63. data/spec/extensions/core_refinements_spec.rb +14 -0
  64. data/spec/extensions/eval_inspect_spec.rb +8 -4
  65. data/spec/extensions/pg_array_ops_spec.rb +6 -0
  66. data/spec/extensions/pg_json_ops_spec.rb +99 -0
  67. data/spec/extensions/pg_json_spec.rb +104 -4
  68. data/spec/extensions/serialization_spec.rb +19 -0
  69. data/spec/extensions/single_table_inheritance_spec.rb +11 -3
  70. data/spec/extensions/timestamps_spec.rb +10 -0
  71. data/spec/extensions/to_dot_spec.rb +8 -4
  72. data/spec/integration/database_test.rb +1 -1
  73. data/spec/integration/dataset_test.rb +9 -0
  74. data/spec/integration/schema_test.rb +27 -0
  75. metadata +4 -2
@@ -8,6 +8,8 @@ describe "pg_json extension" do
8
8
  @m = m::JSONDatabaseMethods
9
9
  @hc = m::JSONHash
10
10
  @ac = m::JSONArray
11
+ @bhc = m::JSONBHash
12
+ @bac = m::JSONBArray
11
13
 
12
14
  # Create subclass in correct namespace for easily overriding methods
13
15
  j = m::JSON = JSON.dup
@@ -46,6 +48,14 @@ describe "pg_json extension" do
46
48
  @m.db_parse_json('1.1').should == 1.1
47
49
  end
48
50
 
51
+ it "should parse json and non-json plain strings, integers, and floats correctly in db_parse_jsonb" do
52
+ @m.db_parse_jsonb('{"a": "b", "c": {"d": "e"}}').to_hash.should == {'a'=>'b', 'c'=>{'d'=>'e'}}
53
+ @m.db_parse_jsonb('[1, [2], {"a": "b"}]').to_a.should == [1, [2], {'a'=>'b'}]
54
+ @m.db_parse_jsonb('1').should == 1
55
+ @m.db_parse_jsonb('"b"').should == 'b'
56
+ @m.db_parse_jsonb('1.1').should == 1.1
57
+ end
58
+
49
59
  it "should raise an error when attempting to parse invalid json" do
50
60
  proc{@m.parse_json('')}.should raise_error(Sequel::InvalidValue)
51
61
  proc{@m.parse_json('1')}.should raise_error(Sequel::InvalidValue)
@@ -72,6 +82,13 @@ describe "pg_json extension" do
72
82
  @db.literal(Sequel.pg_json('a'=>'b')).should == "'{\"a\":\"b\"}'::json"
73
83
  end
74
84
 
85
+ it "should literalize JSONHash and JSONArray to strings correctly" do
86
+ @db.literal(Sequel.pg_jsonb([])).should == "'[]'::jsonb"
87
+ @db.literal(Sequel.pg_jsonb([1, [2], {'a'=>'b'}])).should == "'[1,[2],{\"a\":\"b\"}]'::jsonb"
88
+ @db.literal(Sequel.pg_jsonb({})).should == "'{}'::jsonb"
89
+ @db.literal(Sequel.pg_jsonb('a'=>'b')).should == "'{\"a\":\"b\"}'::jsonb"
90
+ end
91
+
75
92
  it "should have Sequel.pg_json return JSONHash and JSONArray as is" do
76
93
  a = Sequel.pg_json({})
77
94
  Sequel.pg_json(a).should equal(a)
@@ -79,22 +96,72 @@ describe "pg_json extension" do
79
96
  Sequel.pg_json(a).should equal(a)
80
97
  end
81
98
 
82
- it "should have JSONHash#to_hash method for getting underlying hash" do
99
+ it "should have Sequel.pg_json convert jsonb values" do
100
+ a = {}
101
+ v = Sequel.pg_json(Sequel.pg_jsonb(a))
102
+ v.to_hash.should equal(a)
103
+ v.should be_a_kind_of(@hc)
104
+
105
+ a = []
106
+ v = Sequel.pg_json(Sequel.pg_jsonb(a))
107
+ v.to_a.should equal(a)
108
+ v.should be_a_kind_of(@ac)
109
+ end
110
+
111
+ it "should have Sequel.pg_jsonb return JSONBHash and JSONBArray as is" do
112
+ a = Sequel.pg_jsonb({})
113
+ Sequel.pg_jsonb(a).should equal(a)
114
+ a = Sequel.pg_jsonb([])
115
+ Sequel.pg_jsonb(a).should equal(a)
116
+ end
117
+
118
+ it "should have Sequel.pg_jsonb convert json values" do
119
+ a = {}
120
+ v = Sequel.pg_jsonb(Sequel.pg_json(a))
121
+ v.to_hash.should equal(a)
122
+ v.should be_a_kind_of(@bhc)
123
+
124
+ a = []
125
+ v = Sequel.pg_jsonb(Sequel.pg_json(a))
126
+ v.to_a.should equal(a)
127
+ v.should be_a_kind_of(@bac)
128
+ end
129
+
130
+ it "should have JSONHashBase#to_hash method for getting underlying hash" do
83
131
  Sequel.pg_json({}).to_hash.should be_a_kind_of(Hash)
132
+ Sequel.pg_jsonb({}).to_hash.should be_a_kind_of(Hash)
133
+ end
134
+
135
+ it "should allow aliasing json objects" do
136
+ @db.literal(Sequel.pg_json({}).as(:a)).should == "'{}'::json AS a"
137
+ @db.literal(Sequel.pg_json([]).as(:a)).should == "'[]'::json AS a"
138
+ @db.literal(Sequel.pg_jsonb({}).as(:a)).should == "'{}'::jsonb AS a"
139
+ @db.literal(Sequel.pg_jsonb([]).as(:a)).should == "'[]'::jsonb AS a"
140
+ end
141
+
142
+ it "should allow casting json objects" do
143
+ @db.literal(Sequel.pg_json({}).cast(String)).should == "CAST('{}'::json AS text)"
144
+ @db.literal(Sequel.pg_json([]).cast(String)).should == "CAST('[]'::json AS text)"
145
+ @db.literal(Sequel.pg_jsonb({}).cast(String)).should == "CAST('{}'::jsonb AS text)"
146
+ @db.literal(Sequel.pg_jsonb([]).cast(String)).should == "CAST('[]'::jsonb AS text)"
84
147
  end
85
148
 
86
- it "should have JSONArray#to_a method for getting underlying array" do
149
+ it "should have JSONArrayBase#to_a method for getting underlying array" do
87
150
  Sequel.pg_json([]).to_a.should be_a_kind_of(Array)
151
+ Sequel.pg_jsonb([]).to_a.should be_a_kind_of(Array)
88
152
  end
89
153
 
90
- it "should support using JSONHash and JSONArray as bound variables" do
154
+ it "should support using JSONHashBase and JSONArrayBase as bound variables" do
91
155
  @db.bound_variable_arg(1, nil).should == 1
92
156
  @db.bound_variable_arg(Sequel.pg_json([1]), nil).should == '[1]'
93
157
  @db.bound_variable_arg(Sequel.pg_json('a'=>'b'), nil).should == '{"a":"b"}'
158
+ @db.bound_variable_arg(Sequel.pg_jsonb([1]), nil).should == '[1]'
159
+ @db.bound_variable_arg(Sequel.pg_jsonb('a'=>'b'), nil).should == '{"a":"b"}'
94
160
  end
95
161
 
96
- it "should support using json[] types in bound variables" do
162
+ it "should support using json[] and jsonb[] types in bound variables" do
97
163
  @db.bound_variable_arg(Sequel.pg_array([Sequel.pg_json([{"a"=>1}]), Sequel.pg_json("b"=>[1, 2])]), nil).should == '{"[{\\"a\\":1}]","{\\"b\\":[1,2]}"}'
164
+ @db.bound_variable_arg(Sequel.pg_array([Sequel.pg_jsonb([{"a"=>1}]), Sequel.pg_jsonb("b"=>[1, 2])]), nil).should == '{"[{\\"a\\":1}]","{\\"b\\":[1,2]}"}'
98
165
  end
99
166
 
100
167
  it "should parse json type from the schema correctly" do
@@ -102,23 +169,56 @@ describe "pg_json extension" do
102
169
  @db.schema(:items).map{|e| e[1][:type]}.should == [:integer, :json]
103
170
  end
104
171
 
172
+ it "should parse json type from the schema correctly" do
173
+ @db.fetch = [{:name=>'id', :db_type=>'integer'}, {:name=>'i', :db_type=>'jsonb'}]
174
+ @db.schema(:items).map{|e| e[1][:type]}.should == [:integer, :jsonb]
175
+ end
176
+
105
177
  it "should support typecasting for the json type" do
106
178
  h = Sequel.pg_json(1=>2)
107
179
  a = Sequel.pg_json([1])
108
180
  @db.typecast_value(:json, h).should equal(h)
109
181
  @db.typecast_value(:json, h.to_hash).should == h
110
182
  @db.typecast_value(:json, h.to_hash).should be_a_kind_of(@hc)
183
+ @db.typecast_value(:json, Sequel.pg_jsonb(h)).should == h
184
+ @db.typecast_value(:json, Sequel.pg_jsonb(h)).should be_a_kind_of(@hc)
111
185
  @db.typecast_value(:json, a).should equal(a)
112
186
  @db.typecast_value(:json, a.to_a).should == a
113
187
  @db.typecast_value(:json, a.to_a).should be_a_kind_of(@ac)
188
+ @db.typecast_value(:json, Sequel.pg_jsonb(a)).should == a
189
+ @db.typecast_value(:json, Sequel.pg_jsonb(a)).should be_a_kind_of(@ac)
114
190
  @db.typecast_value(:json, '[]').should == Sequel.pg_json([])
191
+ @db.typecast_value(:json, '[]').should be_a_kind_of(@ac)
115
192
  @db.typecast_value(:json, '{"a": "b"}').should == Sequel.pg_json("a"=>"b")
193
+ @db.typecast_value(:json, '{"a": "b"}').should be_a_kind_of(@hc)
116
194
  proc{@db.typecast_value(:json, '')}.should raise_error(Sequel::InvalidValue)
117
195
  proc{@db.typecast_value(:json, 1)}.should raise_error(Sequel::InvalidValue)
118
196
  end
119
197
 
198
+ it "should support typecasting for the jsonb type" do
199
+ h = Sequel.pg_jsonb(1=>2)
200
+ a = Sequel.pg_jsonb([1])
201
+ @db.typecast_value(:jsonb, h).should equal(h)
202
+ @db.typecast_value(:jsonb, h.to_hash).should == h
203
+ @db.typecast_value(:jsonb, h.to_hash).should be_a_kind_of(@bhc)
204
+ @db.typecast_value(:jsonb, Sequel.pg_json(h)).should == h
205
+ @db.typecast_value(:jsonb, Sequel.pg_json(h)).should be_a_kind_of(@bhc)
206
+ @db.typecast_value(:jsonb, a).should equal(a)
207
+ @db.typecast_value(:jsonb, a.to_a).should == a
208
+ @db.typecast_value(:jsonb, a.to_a).should be_a_kind_of(@bac)
209
+ @db.typecast_value(:jsonb, Sequel.pg_json(a)).should == a
210
+ @db.typecast_value(:jsonb, Sequel.pg_json(a)).should be_a_kind_of(@bac)
211
+ @db.typecast_value(:jsonb, '[]').should == Sequel.pg_jsonb([])
212
+ @db.typecast_value(:jsonb, '[]').should be_a_kind_of(@bac)
213
+ @db.typecast_value(:jsonb, '{"a": "b"}').should == Sequel.pg_jsonb("a"=>"b")
214
+ @db.typecast_value(:jsonb, '{"a": "b"}').should be_a_kind_of(@bhc)
215
+ proc{@db.typecast_value(:jsonb, '')}.should raise_error(Sequel::InvalidValue)
216
+ proc{@db.typecast_value(:jsonb, 1)}.should raise_error(Sequel::InvalidValue)
217
+ end
218
+
120
219
  it "should return correct results for Database#schema_type_class" do
121
220
  @db.schema_type_class(:json).should == [Sequel::Postgres::JSONHash, Sequel::Postgres::JSONArray]
221
+ @db.schema_type_class(:jsonb).should == [Sequel::Postgres::JSONBHash, Sequel::Postgres::JSONBArray]
122
222
  @db.schema_type_class(:integer).should == Integer
123
223
  end
124
224
  end
@@ -300,4 +300,23 @@ describe "Serialization plugin" do
300
300
  o.dup.deserialized_values.should == o.deserialized_values
301
301
  o.dup.deserialized_values.should_not equal(o.deserialized_values)
302
302
  end
303
+
304
+ it "should have changed_columns include serialized columns if those columns have changed" do
305
+ @c.plugin :serialization, :yaml, :abc, :def
306
+ @c.dataset._fetch = {:id => 1, :abc => "--- 1\n", :def => "--- hello\n"}
307
+ o = @c.first
308
+ o.changed_columns.should == []
309
+ o.abc = 1
310
+ o.changed_columns.should == []
311
+ o.abc = 1
312
+ o.changed_columns.should == []
313
+ o.abc = 2
314
+ o.changed_columns.should == [:abc]
315
+ o.def = 'hello'
316
+ o.changed_columns.should == [:abc]
317
+ o.def = 'hello'
318
+ o.changed_columns.should == [:abc]
319
+ o.def = 'hello2'
320
+ o.changed_columns.should == [:abc, :def]
321
+ end
303
322
  end
@@ -70,19 +70,27 @@ describe Sequel::Model, "single table inheritance plugin" do
70
70
  called.should == false
71
71
  end
72
72
 
73
- it "should add a before_create hook that sets the model class name for the key" do
73
+ it "should set the model class name when saving" do
74
74
  StiTest.new.save
75
75
  StiTestSub1.new.save
76
76
  StiTestSub2.new.save
77
77
  DB.sqls.should == ["INSERT INTO sti_tests (kind) VALUES ('StiTest')", "SELECT * FROM sti_tests WHERE (id = 10) LIMIT 1", "INSERT INTO sti_tests (kind) VALUES ('StiTestSub1')", "SELECT * FROM sti_tests WHERE ((sti_tests.kind IN ('StiTestSub1')) AND (id = 10)) LIMIT 1", "INSERT INTO sti_tests (kind) VALUES ('StiTestSub2')", "SELECT * FROM sti_tests WHERE ((sti_tests.kind IN ('StiTestSub2')) AND (id = 10)) LIMIT 1"]
78
78
  end
79
79
 
80
- it "should have the before_create hook not override an existing value" do
80
+ it "should handle validations on the type column field" do
81
+ o = StiTestSub1.new
82
+ def o.validate
83
+ errors.add(:kind, 'not present') unless kind
84
+ end
85
+ o.valid?.should == true
86
+ end
87
+
88
+ it "should override an existing value in the class name field" do
81
89
  StiTest.create(:kind=>'StiTestSub1')
82
90
  DB.sqls.should == ["INSERT INTO sti_tests (kind) VALUES ('StiTestSub1')", "SELECT * FROM sti_tests WHERE (id = 10) LIMIT 1"]
83
91
  end
84
92
 
85
- it "should have the before_create hook handle columns with the same name as existing method names" do
93
+ it "should handle type column with the same name as existing method names" do
86
94
  StiTest.plugin :single_table_inheritance, :type
87
95
  StiTest.columns :id, :type
88
96
  StiTest.create
@@ -22,6 +22,16 @@ describe "Sequel::Plugins::Timestamps" do
22
22
  Sequel.datetime_class = Time
23
23
  end
24
24
 
25
+ it "should handle validations on the timestamp fields for new objects" do
26
+ @c.plugin :timestamps, :update_on_create=>true
27
+ o = @c.new
28
+ def o.validate
29
+ errors.add(model.create_timestamp_field, 'not present') unless send(model.create_timestamp_field)
30
+ errors.add(model.update_timestamp_field, 'not present') unless send(model.update_timestamp_field)
31
+ end
32
+ o.valid?.should == true
33
+ end
34
+
25
35
  it "should set the create timestamp field on creation" do
26
36
  o = @c.create
27
37
  @c.db.sqls.should == ["INSERT INTO t (created_at) VALUES ('2009-08-01')"]
@@ -108,6 +108,10 @@ END
108
108
  dot(@ds.from(Sequel.as(:a, :b))).should == ["1 -> 2 [label=\"from\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"AliasedExpression\"];", "3 -> 4 [label=\"expression\"];", "4 [label=\":a\"];", "3 -> 5 [label=\"alias\"];", "5 [label=\":b\"];"]
109
109
  end
110
110
 
111
+ it "should handle SQL::AliasedExpressions with column aliases" do
112
+ dot(@ds.from(Sequel.as(:a, :b, [:c, :d]))).should == ["1 -> 2 [label=\"from\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"AliasedExpression\"];", "3 -> 4 [label=\"expression\"];", "4 [label=\":a\"];", "3 -> 5 [label=\"alias\"];", "5 [label=\":b\"];", "3 -> 6 [label=\"columns\"];", "6 [label=\"Array\"];", "6 -> 7 [label=\"0\"];", "7 [label=\":c\"];", "6 -> 8 [label=\"1\"];", "8 [label=\":d\"];"]
113
+ end
114
+
111
115
  it "should handle SQL::CaseExpressions" do
112
116
  dot(@ds.select(Sequel.case({:a=>:b}, :c, :d))).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"CaseExpression\"];", "3 -> 4 [label=\"expression\"];", "4 [label=\":d\"];", "3 -> 5 [label=\"conditions\"];", "5 [label=\"Array\"];", "5 -> 6 [label=\"0\"];", "6 [label=\"Array\"];", "6 -> 7 [label=\"0\"];", "7 [label=\":a\"];", "6 -> 8 [label=\"1\"];", "8 [label=\":b\"];", "3 -> 9 [label=\"default\"];", "9 [label=\":c\"];"]
113
117
  end
@@ -117,15 +121,15 @@ END
117
121
  end
118
122
 
119
123
  it "should handle SQL::Function" do
120
- dot(@ds.select{a(b)}).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"Function: a\"];", "3 -> 4 [label=\"0\"];", "4 [label=\"Identifier\"];", "4 -> 5 [label=\"value\"];", "5 [label=\":b\"];"]
124
+ dot(@ds.select{a(b)}).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"Function: a\"];", "3 -> 4 [label=\"0\"];", "4 [label=\"Identifier\"];", "4 -> 5 [label=\"value\"];", "5 [label=\":b\"];", "3 -> 6 [label=\"args\"];", "6 [label=\"Array\"];", "6 -> 7 [label=\"0\"];", "7 [label=\"Identifier\"];", "7 -> 8 [label=\"value\"];", "8 [label=\":b\"];", "3 -> 9 [label=\"opts\"];", "9 [label=\"Hash\"];"]
121
125
  end
122
126
 
123
127
  it "should handle SQL::Subscript" do
124
128
  dot(@ds.select(Sequel.subscript(:a, 1))).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"Subscript\"];", "3 -> 4 [label=\"f\"];", "4 [label=\":a\"];", "3 -> 5 [label=\"sub\"];", "5 [label=\"Array\"];", "5 -> 6 [label=\"0\"];", "6 [label=\"1\"];"]
125
129
  end
126
130
 
127
- it "should handle SQL::WindowFunction" do
128
- dot(@ds.select{sum{}.over(:partition=>:a)}).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"WindowFunction\"];", "3 -> 4 [label=\"function\"];", "4 [label=\"Function: sum\"];", "3 -> 5 [label=\"window\"];", "5 [label=\"Window\"];", "5 -> 6 [label=\"opts\"];", "6 [label=\"Hash\"];", "6 -> 7 [label=\"partition\"];", "7 [label=\":a\"];"]
131
+ it "should handle SQL::Function with a window" do
132
+ dot(@ds.select{sum{}.over(:partition=>:a)}).should == ["1 -> 2 [label=\"select\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\"Function: sum\"];", "3 -> 4 [label=\"args\"];", "4 [label=\"Array\"];", "3 -> 5 [label=\"opts\"];", "5 [label=\"Hash\"];", "5 -> 6 [label=\"over\"];", "6 [label=\"Window\"];", "6 -> 7 [label=\"opts\"];", "7 [label=\"Hash\"];", "7 -> 8 [label=\"partition\"];", "8 [label=\":a\"];"]
129
133
  end
130
134
 
131
135
  it "should handle SQL::PlaceholderLiteralString" do
@@ -137,7 +141,7 @@ END
137
141
  end
138
142
 
139
143
  it "should handle JOIN USING" do
140
- dot(@ds.from(:a).join(:d, [:c], :table_alias=>:c)).should == ["1 -> 2 [label=\"from\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\":a\"];", "1 -> 4 [label=\"join\"];", "4 [label=\"Array\"];", "4 -> 5 [label=\"0\"];", "5 [label=\"INNER JOIN USING\"];", "5 -> 6 [label=\"table\"];", "6 [label=\":d\"];", "5 -> 7 [label=\"alias\"];", "7 [label=\":c\"];", "5 -> 8 [label=\"using\"];", "8 [label=\"Array\"];", "8 -> 9 [label=\"0\"];", "9 [label=\":c\"];"]
144
+ dot(@ds.from(:a).join(:d, [:c], :table_alias=>:c)).should == ["1 -> 2 [label=\"from\"];", "2 [label=\"Array\"];", "2 -> 3 [label=\"0\"];", "3 [label=\":a\"];", "1 -> 4 [label=\"join\"];", "4 [label=\"Array\"];", "4 -> 5 [label=\"0\"];", "5 [label=\"INNER JOIN USING\"];", "5 -> 6 [label=\"table\"];", "6 [label=\"AliasedExpression\"];", "6 -> 7 [label=\"expression\"];", "7 [label=\":d\"];", "6 -> 8 [label=\"alias\"];", "8 [label=\":c\"];", "5 -> 9 [label=\"using\"];", "9 [label=\"Array\"];", "9 -> 10 [label=\"0\"];", "10 [label=\":c\"];"]
141
145
  end
142
146
 
143
147
  it "should handle other types" do
@@ -21,7 +21,7 @@ describe Sequel::Database do
21
21
  end
22
22
 
23
23
  specify "should raise Sequel::DatabaseError on invalid SQL" do
24
- proc{@db << "SELECT"}.should raise_error(Sequel::DatabaseError)
24
+ proc{@db << "S"}.should raise_error(Sequel::DatabaseError)
25
25
  end
26
26
 
27
27
  specify "should have Sequel::DatabaseError#sql give the SQL causing the error" do
@@ -293,6 +293,10 @@ describe "Simple Dataset operations" do
293
293
  @ds.select(:id___x, :number___n).first.should == {:x=>1, :n=>10}
294
294
  end
295
295
 
296
+ specify "should support table aliases with column aliases" do
297
+ DB.from(@ds.as(:i, [:x, :n])).first.should == {:x=>1, :n=>10}
298
+ end if DB.dataset.supports_derived_column_lists?
299
+
296
300
  specify "should handle true/false properly" do
297
301
  @ds.filter(Sequel::TRUE).select_map(:number).should == [10]
298
302
  @ds.filter(Sequel::FALSE).select_map(:number).should == []
@@ -907,6 +911,11 @@ describe "Sequel::Dataset#import and #multi_insert" do
907
911
  @ids.import([:i], [[10], [20], [30]], :slice_size=>3)
908
912
  @ids.all.should == [{:i=>10}, {:i=>20}, {:i=>30}]
909
913
  end
914
+
915
+ it "should import many rows at once" do
916
+ @ids.import([:i], (1..1000).to_a.map{|x| [x]})
917
+ @ids.select_order_map(:i).should == (1..1000).to_a
918
+ end
910
919
  end
911
920
 
912
921
  describe "Sequel::Dataset#import and #multi_insert :return=>:primary_key " do
@@ -272,12 +272,14 @@ describe "Database schema modifiers" do
272
272
 
273
273
  describe "views" do
274
274
  before do
275
+ @db.drop_view(:items_view2) rescue nil
275
276
  @db.drop_view(:items_view) rescue nil
276
277
  @db.create_table(:items){Integer :number}
277
278
  @ds.insert(:number=>1)
278
279
  @ds.insert(:number=>2)
279
280
  end
280
281
  after do
282
+ @db.drop_view(:items_view2) rescue nil
281
283
  @db.drop_view(:items_view) rescue nil
282
284
  end
283
285
 
@@ -286,6 +288,31 @@ describe "Database schema modifiers" do
286
288
  @db[:items_view].map(:number).should == [1]
287
289
  end
288
290
 
291
+ specify "should create views with check options correctly" do
292
+ @db.create_view(:items_view, @ds.where{number > 2}, :check=>true)
293
+ proc{@db[:items_view].insert(1)}.should raise_error(Sequel::DatabaseError)
294
+ @db[:items_view].insert(3)
295
+ @db[:items_view].select_order_map(:number).should == [3]
296
+ @db.create_view(:items_view2, @db[:items_view].where{number > 1}, :check=>true)
297
+ proc{@db[:items_view2].insert(1)}.should raise_error(Sequel::DatabaseError)
298
+ proc{@db[:items_view2].insert(2)}.should raise_error(Sequel::DatabaseError)
299
+ @db[:items_view2].insert(4)
300
+ @db[:items_view2].select_order_map(:number).should == [3, 4]
301
+ @ds.select_order_map(:number).should == [1, 2, 3, 4]
302
+ end if DB.supports_views_with_check_option?
303
+
304
+ specify "should create views with local check options correctly" do
305
+ @db.create_view(:items_view, @ds.where{number > 2})
306
+ @db[:items_view].insert(3)
307
+ @db[:items_view].select_order_map(:number).should == [3]
308
+ @db.create_view(:items_view2, @db[:items_view].where{number > 1}, :check=>:local)
309
+ proc{@db[:items_view2].insert(1)}.should raise_error(Sequel::DatabaseError)
310
+ @db[:items_view2].insert(2)
311
+ @db[:items_view2].insert(4)
312
+ @db[:items_view2].select_order_map(:number).should == [3, 4]
313
+ @ds.select_order_map(:number).should == [1, 2, 2, 3, 4]
314
+ end if DB.supports_views_with_local_check_option?
315
+
289
316
  cspecify "should create views with explicit columns correctly", :sqlite do
290
317
  @db.create_view(:items_view, @ds.where(:number=>1), :columns=>[:n])
291
318
  @db[:items_view].map(:n).should == [1]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.10.0
4
+ version: 4.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-01 00:00:00.000000000 Z
11
+ date: 2014-06-03 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: The Database Toolkit for Ruby
14
14
  email: code@jeremyevans.net
@@ -127,6 +127,7 @@ extra_rdoc_files:
127
127
  - doc/release_notes/4.8.0.txt
128
128
  - doc/release_notes/4.9.0.txt
129
129
  - doc/release_notes/4.10.0.txt
130
+ - doc/release_notes/4.11.0.txt
130
131
  files:
131
132
  - CHANGELOG
132
133
  - MIT-LICENSE
@@ -224,6 +225,7 @@ files:
224
225
  - doc/release_notes/4.0.0.txt
225
226
  - doc/release_notes/4.1.0.txt
226
227
  - doc/release_notes/4.10.0.txt
228
+ - doc/release_notes/4.11.0.txt
227
229
  - doc/release_notes/4.2.0.txt
228
230
  - doc/release_notes/4.3.0.txt
229
231
  - doc/release_notes/4.4.0.txt