sequel 3.28.0 → 3.29.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +119 -3
- data/Rakefile +5 -3
- data/bin/sequel +1 -5
- data/doc/model_hooks.rdoc +9 -1
- data/doc/opening_databases.rdoc +49 -40
- data/doc/prepared_statements.rdoc +27 -6
- data/doc/release_notes/3.28.0.txt +2 -2
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +18 -9
- data/doc/transactions.rdoc +41 -1
- data/lib/sequel/adapters/ado.rb +28 -17
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/amalgalite.rb +11 -7
- data/lib/sequel/adapters/db2.rb +122 -70
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do.rb +5 -36
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/firebird.rb +3 -6
- data/lib/sequel/adapters/ibmdb.rb +24 -16
- data/lib/sequel/adapters/informix.rb +2 -4
- data/lib/sequel/adapters/jdbc.rb +47 -11
- data/lib/sequel/adapters/jdbc/as400.rb +5 -24
- data/lib/sequel/adapters/jdbc/db2.rb +0 -5
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
- data/lib/sequel/adapters/jdbc/h2.rb +10 -12
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +0 -5
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
- data/lib/sequel/adapters/jdbc/mysql.rb +0 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +70 -3
- data/lib/sequel/adapters/jdbc/postgresql.rb +0 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
- data/lib/sequel/adapters/jdbc/transactions.rb +56 -7
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +64 -51
- data/lib/sequel/adapters/mysql2.rb +15 -9
- data/lib/sequel/adapters/odbc.rb +13 -6
- data/lib/sequel/adapters/odbc/db2.rb +0 -4
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +333 -51
- data/lib/sequel/adapters/postgres.rb +80 -27
- data/lib/sequel/adapters/shared/access.rb +0 -6
- data/lib/sequel/adapters/shared/db2.rb +13 -15
- data/lib/sequel/adapters/shared/firebird.rb +6 -6
- data/lib/sequel/adapters/shared/mssql.rb +23 -18
- data/lib/sequel/adapters/shared/mysql.rb +6 -6
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -30
- data/lib/sequel/adapters/shared/postgres.rb +35 -18
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +116 -37
- data/lib/sequel/adapters/sqlite.rb +16 -8
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/swift/mysql.rb +0 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/tinytds.rb +13 -10
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -0
- data/lib/sequel/core.rb +40 -0
- data/lib/sequel/database/connecting.rb +1 -2
- data/lib/sequel/database/dataset.rb +3 -3
- data/lib/sequel/database/dataset_defaults.rb +58 -0
- data/lib/sequel/database/misc.rb +62 -2
- data/lib/sequel/database/query.rb +113 -49
- data/lib/sequel/database/schema_methods.rb +7 -2
- data/lib/sequel/dataset/actions.rb +37 -19
- data/lib/sequel/dataset/features.rb +24 -0
- data/lib/sequel/dataset/graph.rb +7 -6
- data/lib/sequel/dataset/misc.rb +11 -3
- data/lib/sequel/dataset/mutation.rb +2 -3
- data/lib/sequel/dataset/prepared_statements.rb +6 -4
- data/lib/sequel/dataset/query.rb +46 -15
- data/lib/sequel/dataset/sql.rb +28 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/model.rb +2 -1
- data/lib/sequel/model/associations.rb +115 -33
- data/lib/sequel/model/base.rb +91 -31
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +6 -10
- data/lib/sequel/plugins/prepared_statements.rb +12 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/sharding.rb +0 -5
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/timezones.rb +42 -42
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +29 -29
- data/spec/adapters/mysql_spec.rb +86 -104
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +98 -33
- data/spec/adapters/spec_helper.rb +0 -5
- data/spec/adapters/sqlite_spec.rb +24 -21
- data/spec/core/connection_pool_spec.rb +9 -15
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +491 -227
- data/spec/core/dataset_spec.rb +638 -1051
- data/spec/core/expression_filters_spec.rb +0 -1
- data/spec/core/mock_adapter_spec.rb +378 -0
- data/spec/core/object_graph_spec.rb +48 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +51 -114
- data/spec/core/spec_helper.rb +3 -90
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +3 -0
- data/spec/extensions/schema_spec.rb +1 -1
- data/spec/extensions/serialization_modification_detection_spec.rb +1 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/spec_helper.rb +4 -0
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/integration/associations_test.rb +123 -12
- data/spec/integration/dataset_test.rb +140 -47
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +179 -128
- data/spec/integration/prepared_statement_test.rb +92 -91
- data/spec/integration/schema_test.rb +42 -23
- data/spec/integration/spec_helper.rb +25 -31
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +161 -34
- data/spec/integration/type_test.rb +3 -3
- data/spec/model/association_reflection_spec.rb +83 -7
- data/spec/model/associations_spec.rb +393 -676
- data/spec/model/base_spec.rb +186 -116
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +343 -867
- data/spec/model/hooks_spec.rb +160 -79
- data/spec/model/model_spec.rb +118 -165
- data/spec/model/plugins_spec.rb +7 -13
- data/spec/model/record_spec.rb +138 -207
- data/spec/model/spec_helper.rb +10 -73
- metadata +14 -8
data/spec/core/dataset_spec.rb
CHANGED
@@ -60,12 +60,6 @@ describe "Dataset" do
|
|
60
60
|
db = Sequel::Database.new(:identifier_output_method=>:downcase)
|
61
61
|
db[:a].identifier_output_method.should == :downcase
|
62
62
|
end
|
63
|
-
end
|
64
|
-
|
65
|
-
describe "Dataset" do
|
66
|
-
before do
|
67
|
-
@dataset = Sequel::Dataset.new("db")
|
68
|
-
end
|
69
63
|
|
70
64
|
specify "should have quote_identifiers= method which changes literalization of identifiers" do
|
71
65
|
@dataset.quote_identifiers = true
|
@@ -111,27 +105,25 @@ describe "Dataset#clone" do
|
|
111
105
|
|
112
106
|
specify "should create an exact copy of the dataset" do
|
113
107
|
@dataset.row_proc = Proc.new{|r| r}
|
114
|
-
|
108
|
+
clone = @dataset.clone
|
115
109
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
110
|
+
clone.object_id.should_not === @dataset.object_id
|
111
|
+
clone.class.should == @dataset.class
|
112
|
+
clone.db.should == @dataset.db
|
113
|
+
clone.opts.should == @dataset.opts
|
114
|
+
clone.row_proc.should == @dataset.row_proc
|
120
115
|
end
|
121
116
|
|
122
117
|
specify "should deep-copy the dataset opts" do
|
123
|
-
|
118
|
+
clone = @dataset.clone
|
124
119
|
|
125
|
-
|
120
|
+
clone.opts.should_not equal(@dataset.opts)
|
126
121
|
@dataset.filter!(:a => 'b')
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
clone
|
132
|
-
clone.class.should == @dataset.class
|
133
|
-
clone.db.should == @dataset.db
|
134
|
-
clone.opts.should == @dataset.opts
|
122
|
+
clone.opts[:filter].should be_nil
|
123
|
+
|
124
|
+
clone = @dataset.clone(:from => [:other])
|
125
|
+
@dataset.opts[:from].should == [:items]
|
126
|
+
clone.opts[:from].should == [:other]
|
135
127
|
end
|
136
128
|
|
137
129
|
specify "should merge the specified options" do
|
@@ -144,12 +136,6 @@ describe "Dataset#clone" do
|
|
144
136
|
clone.opts.should == {:from => [:other]}
|
145
137
|
end
|
146
138
|
|
147
|
-
specify "should create a clone with a deep copy of options" do
|
148
|
-
clone = @dataset.clone(:from => [:other])
|
149
|
-
@dataset.opts[:from].should == [:items]
|
150
|
-
clone.opts[:from].should == [:other]
|
151
|
-
end
|
152
|
-
|
153
139
|
specify "should return an object with the same modules included" do
|
154
140
|
m = Module.new do
|
155
141
|
def __xyz__; "xyz"; end
|
@@ -161,7 +147,7 @@ end
|
|
161
147
|
|
162
148
|
describe "Dataset#==" do
|
163
149
|
before do
|
164
|
-
@db =
|
150
|
+
@db = Sequel.mock
|
165
151
|
@h = {}
|
166
152
|
end
|
167
153
|
|
@@ -170,7 +156,7 @@ describe "Dataset#==" do
|
|
170
156
|
end
|
171
157
|
|
172
158
|
specify "should be different for datasets with different dbs" do
|
173
|
-
@db[:t].should_not ==
|
159
|
+
@db[:t].should_not == Sequel.mock[:t]
|
174
160
|
end
|
175
161
|
|
176
162
|
specify "should be different for datasets with different opts" do
|
@@ -186,7 +172,7 @@ end
|
|
186
172
|
|
187
173
|
describe "Dataset#hash" do
|
188
174
|
before do
|
189
|
-
@db =
|
175
|
+
@db = Sequel.mock
|
190
176
|
@h = {}
|
191
177
|
end
|
192
178
|
|
@@ -197,7 +183,7 @@ describe "Dataset#hash" do
|
|
197
183
|
end
|
198
184
|
|
199
185
|
specify "should be different for datasets with different dbs" do
|
200
|
-
@db[:t].hash.should_not ==
|
186
|
+
@db[:t].hash.should_not == Sequel.mock[:t].hash
|
201
187
|
end
|
202
188
|
|
203
189
|
specify "should be different for datasets with different opts" do
|
@@ -232,6 +218,12 @@ describe "A simple dataset" do
|
|
232
218
|
@dataset.insert_sql.should == 'INSERT INTO test DEFAULT VALUES'
|
233
219
|
end
|
234
220
|
|
221
|
+
specify "should use a single column with a default value when the dataset doesn't support using insert statement with default values" do
|
222
|
+
@dataset.meta_def(:insert_supports_empty_values?){false}
|
223
|
+
@dataset.meta_def(:columns){[:a, :b]}
|
224
|
+
@dataset.insert_sql.should == 'INSERT INTO test (b) VALUES (DEFAULT)'
|
225
|
+
end
|
226
|
+
|
235
227
|
specify "should format an insert statement with hash" do
|
236
228
|
@dataset.insert_sql(:name => 'wxyz', :price => 342).
|
237
229
|
should match(/INSERT INTO test \(name, price\) VALUES \('wxyz', 342\)|INSERT INTO test \(price, name\) VALUES \(342, 'wxyz'\)/)
|
@@ -245,8 +237,6 @@ describe "A simple dataset" do
|
|
245
237
|
end
|
246
238
|
|
247
239
|
specify "should format an insert statement with an object that respond_to? :values" do
|
248
|
-
dbb = Sequel::Database.new
|
249
|
-
|
250
240
|
v = Object.new
|
251
241
|
def v.values; {:a => 1}; end
|
252
242
|
|
@@ -261,29 +251,24 @@ describe "A simple dataset" do
|
|
261
251
|
end
|
262
252
|
|
263
253
|
specify "should format an insert statement with sub-query" do
|
264
|
-
@
|
265
|
-
@dataset.insert_sql(@sub).should == \
|
266
|
-
"INSERT INTO test SELECT * FROM something WHERE (x = 2)"
|
254
|
+
@dataset.insert_sql(@dataset.from(:something).filter(:x => 2)).should == "INSERT INTO test SELECT * FROM something WHERE (x = 2)"
|
267
255
|
end
|
268
256
|
|
269
257
|
specify "should format an insert statement with array" do
|
270
|
-
@dataset.insert_sql('a', 2, 6.5).should ==
|
271
|
-
"INSERT INTO test VALUES ('a', 2, 6.5)"
|
258
|
+
@dataset.insert_sql('a', 2, 6.5).should == "INSERT INTO test VALUES ('a', 2, 6.5)"
|
272
259
|
end
|
273
260
|
|
274
261
|
specify "should format an update statement" do
|
275
|
-
@dataset.update_sql(:name => 'abc').should ==
|
276
|
-
"UPDATE test SET name = 'abc'"
|
262
|
+
@dataset.update_sql(:name => 'abc').should == "UPDATE test SET name = 'abc'"
|
277
263
|
end
|
278
264
|
|
279
265
|
specify "should be able to return rows for arbitrary SQL" do
|
280
|
-
@dataset.clone(:sql => 'xxx yyy zzz').select_sql.should ==
|
281
|
-
"xxx yyy zzz"
|
266
|
+
@dataset.clone(:sql => 'xxx yyy zzz').select_sql.should == "xxx yyy zzz"
|
282
267
|
end
|
283
268
|
|
284
269
|
specify "should use the :sql option for all sql methods" do
|
285
270
|
sql = "X"
|
286
|
-
ds =
|
271
|
+
ds = @dataset.clone(:sql=>sql)
|
287
272
|
ds.sql.should == sql
|
288
273
|
ds.select_sql.should == sql
|
289
274
|
ds.insert_sql.should == sql
|
@@ -418,7 +403,7 @@ describe "Dataset#where" do
|
|
418
403
|
b.should == a
|
419
404
|
end
|
420
405
|
|
421
|
-
specify "should not replace named placeholders that don't
|
406
|
+
specify "should not replace named placeholders that don't exist in the hash" do
|
422
407
|
@dataset.where('price < :price AND id in :ids', :price=>100).select_sql.should ==
|
423
408
|
"SELECT * FROM test WHERE (price < 100 AND id in :ids)"
|
424
409
|
end
|
@@ -538,53 +523,31 @@ describe "Dataset#where" do
|
|
538
523
|
|
539
524
|
specify "should handle IN/NOT IN queries with multiple columns and a dataset where the database doesn't support it" do
|
540
525
|
@dataset.meta_def(:supports_multiple_column_in?){false}
|
541
|
-
db =
|
542
|
-
d1 = db[:test].select(:id1, :id2).filter(:region=>'Asia')
|
543
|
-
d1.instance_variable_set(:@columns, [:id1, :id2])
|
544
|
-
def d1.fetch_rows(sql)
|
545
|
-
db << sql
|
546
|
-
@columns = [:id1, :id2]
|
547
|
-
yield(:id1=>1, :id2=>2)
|
548
|
-
yield(:id1=>3, :id2=>4)
|
549
|
-
end
|
526
|
+
db = Sequel.mock(:fetch=>[{:id1=>1, :id2=>2}, {:id1=>3, :id2=>4}])
|
527
|
+
d1 = db[:test].select(:id1, :id2).filter(:region=>'Asia').columns(:id1, :id2)
|
550
528
|
@dataset.filter([:id1, :id2] => d1).sql.should == "SELECT * FROM test WHERE (((id1 = 1) AND (id2 = 2)) OR ((id1 = 3) AND (id2 = 4)))"
|
551
529
|
db.sqls.should == ["SELECT id1, id2 FROM test WHERE (region = 'Asia')"]
|
552
|
-
db.sqls.clear
|
553
530
|
@dataset.exclude([:id1, :id2] => d1).sql.should == "SELECT * FROM test WHERE (((id1 != 1) OR (id2 != 2)) AND ((id1 != 3) OR (id2 != 4)))"
|
554
531
|
db.sqls.should == ["SELECT id1, id2 FROM test WHERE (region = 'Asia')"]
|
555
532
|
end
|
556
533
|
|
557
534
|
specify "should handle IN/NOT IN queries with multiple columns and an empty dataset where the database doesn't support it" do
|
558
535
|
@dataset.meta_def(:supports_multiple_column_in?){false}
|
559
|
-
db =
|
560
|
-
d1 = db[:test].select(:id1, :id2).filter(:region=>'Asia')
|
561
|
-
d1.instance_variable_set(:@columns, [:id1, :id2])
|
562
|
-
def d1.fetch_rows(sql)
|
563
|
-
db << sql
|
564
|
-
@columns = [:id1, :id2]
|
565
|
-
end
|
536
|
+
db = Sequel.mock
|
537
|
+
d1 = db[:test].select(:id1, :id2).filter(:region=>'Asia').columns(:id1, :id2)
|
566
538
|
@dataset.filter([:id1, :id2] => d1).sql.should == "SELECT * FROM test WHERE ((id1 != id1) AND (id2 != id2))"
|
567
539
|
db.sqls.should == ["SELECT id1, id2 FROM test WHERE (region = 'Asia')"]
|
568
|
-
db.sqls.clear
|
569
540
|
@dataset.exclude([:id1, :id2] => d1).sql.should == "SELECT * FROM test WHERE (1 = 1)"
|
570
541
|
db.sqls.should == ["SELECT id1, id2 FROM test WHERE (region = 'Asia')"]
|
571
542
|
end
|
572
543
|
|
573
544
|
specify "should handle IN/NOT IN queries for datasets with row_procs" do
|
574
545
|
@dataset.meta_def(:supports_multiple_column_in?){false}
|
575
|
-
db =
|
576
|
-
d1 = db[:test].select(:id1, :id2).filter(:region=>'Asia')
|
546
|
+
db = Sequel.mock(:fetch=>[{:id1=>1, :id2=>2}, {:id1=>3, :id2=>4}])
|
547
|
+
d1 = db[:test].select(:id1, :id2).filter(:region=>'Asia').columns(:id1, :id2)
|
577
548
|
d1.row_proc = proc{|h| Object.new}
|
578
|
-
d1.instance_variable_set(:@columns, [:id1, :id2])
|
579
|
-
def d1.fetch_rows(sql)
|
580
|
-
db << sql
|
581
|
-
@columns = [:id1, :id2]
|
582
|
-
yield(:id1=>1, :id2=>2)
|
583
|
-
yield(:id1=>3, :id2=>4)
|
584
|
-
end
|
585
549
|
@dataset.filter([:id1, :id2] => d1).sql.should == "SELECT * FROM test WHERE (((id1 = 1) AND (id2 = 2)) OR ((id1 = 3) AND (id2 = 4)))"
|
586
550
|
db.sqls.should == ["SELECT id1, id2 FROM test WHERE (region = 'Asia')"]
|
587
|
-
db.sqls.clear
|
588
551
|
@dataset.exclude([:id1, :id2] => d1).sql.should == "SELECT * FROM test WHERE (((id1 != 1) OR (id2 != 2)) AND ((id1 != 3) OR (id2 != 4)))"
|
589
552
|
db.sqls.should == ["SELECT id1, id2 FROM test WHERE (region = 'Asia')"]
|
590
553
|
end
|
@@ -687,33 +650,25 @@ describe "Dataset#or" do
|
|
687
650
|
end
|
688
651
|
|
689
652
|
specify "should add an alternative expression to the where clause" do
|
690
|
-
@d1.or(:y => 2).sql.should ==
|
691
|
-
'SELECT * FROM test WHERE ((x = 1) OR (y = 2))'
|
653
|
+
@d1.or(:y => 2).sql.should == 'SELECT * FROM test WHERE ((x = 1) OR (y = 2))'
|
692
654
|
end
|
693
655
|
|
694
656
|
specify "should accept all forms of filters" do
|
695
|
-
@d1.or('y > ?', 2).sql.should ==
|
696
|
-
|
697
|
-
@d1.or(:yy.sql_number > 3).sql.should ==
|
698
|
-
'SELECT * FROM test WHERE ((x = 1) OR (yy > 3))'
|
657
|
+
@d1.or('y > ?', 2).sql.should == 'SELECT * FROM test WHERE ((x = 1) OR (y > 2))'
|
658
|
+
@d1.or(:yy.sql_number > 3).sql.should == 'SELECT * FROM test WHERE ((x = 1) OR (yy > 3))'
|
699
659
|
end
|
700
660
|
|
701
661
|
specify "should accept blocks passed to filter" do
|
702
|
-
@d1.or{:yy.sql_number > 3}.sql.should ==
|
703
|
-
'SELECT * FROM test WHERE ((x = 1) OR (yy > 3))'
|
662
|
+
@d1.or{:yy.sql_number > 3}.sql.should == 'SELECT * FROM test WHERE ((x = 1) OR (yy > 3))'
|
704
663
|
end
|
705
664
|
|
706
665
|
specify "should correctly add parens to give predictable results" do
|
707
|
-
@d1.filter(:y => 2).or(:z => 3).sql.should ==
|
708
|
-
|
709
|
-
|
710
|
-
@d1.or(:y => 2).filter(:z => 3).sql.should ==
|
711
|
-
'SELECT * FROM test WHERE (((x = 1) OR (y = 2)) AND (z = 3))'
|
666
|
+
@d1.filter(:y => 2).or(:z => 3).sql.should == 'SELECT * FROM test WHERE (((x = 1) AND (y = 2)) OR (z = 3))'
|
667
|
+
@d1.or(:y => 2).filter(:z => 3).sql.should == 'SELECT * FROM test WHERE (((x = 1) OR (y = 2)) AND (z = 3))'
|
712
668
|
end
|
713
669
|
|
714
670
|
specify "should allow the use of blocks and arguments simultaneously" do
|
715
|
-
@d1.or(:zz.sql_number < 3){:yy.sql_number > 3}.sql.should ==
|
716
|
-
'SELECT * FROM test WHERE ((x = 1) OR ((zz < 3) AND (yy > 3)))'
|
671
|
+
@d1.or(:zz.sql_number < 3){:yy.sql_number > 3}.sql.should == 'SELECT * FROM test WHERE ((x = 1) OR ((zz < 3) AND (yy > 3)))'
|
717
672
|
end
|
718
673
|
end
|
719
674
|
|
@@ -726,34 +681,25 @@ describe "Dataset#and" do
|
|
726
681
|
specify "should raise if no filter exists" do
|
727
682
|
proc {@dataset.and(:a => 1)}.should raise_error(Sequel::Error)
|
728
683
|
proc {@dataset.where(:a => 1).group(:t).and(:b => 2)}.should_not raise_error(Sequel::Error)
|
729
|
-
@dataset.where(:a => 1).group(:t).and(:b => 2).sql ==
|
730
|
-
"SELECT * FROM test WHERE (a = 1) AND (b = 2) GROUP BY t"
|
684
|
+
@dataset.where(:a => 1).group(:t).and(:b => 2).sql == "SELECT * FROM test WHERE (a = 1) AND (b = 2) GROUP BY t"
|
731
685
|
end
|
732
686
|
|
733
687
|
specify "should add an alternative expression to the where clause" do
|
734
|
-
@d1.and(:y => 2).sql.should ==
|
735
|
-
'SELECT * FROM test WHERE ((x = 1) AND (y = 2))'
|
688
|
+
@d1.and(:y => 2).sql.should == 'SELECT * FROM test WHERE ((x = 1) AND (y = 2))'
|
736
689
|
end
|
737
690
|
|
738
|
-
specify "should accept
|
739
|
-
|
740
|
-
@d1.and(
|
741
|
-
'SELECT * FROM test WHERE ((x = 1) AND (y > 2))'
|
742
|
-
@d1.and(:yy.sql_number > 3).sql.should ==
|
743
|
-
'SELECT * FROM test WHERE ((x = 1) AND (yy > 3))'
|
691
|
+
specify "should accept different types of filters" do
|
692
|
+
@d1.and('y > ?', 2).sql.should == 'SELECT * FROM test WHERE ((x = 1) AND (y > 2))'
|
693
|
+
@d1.and(:yy.sql_number > 3).sql.should == 'SELECT * FROM test WHERE ((x = 1) AND (yy > 3))'
|
744
694
|
end
|
745
695
|
|
746
696
|
specify "should accept blocks passed to filter" do
|
747
|
-
@d1.and {:yy.sql_number > 3}.sql.should ==
|
748
|
-
'SELECT * FROM test WHERE ((x = 1) AND (yy > 3))'
|
697
|
+
@d1.and {:yy.sql_number > 3}.sql.should == 'SELECT * FROM test WHERE ((x = 1) AND (yy > 3))'
|
749
698
|
end
|
750
699
|
|
751
700
|
specify "should correctly add parens to give predictable results" do
|
752
|
-
@d1.or(:y => 2).and(:z => 3).sql.should ==
|
753
|
-
|
754
|
-
|
755
|
-
@d1.and(:y => 2).or(:z => 3).sql.should ==
|
756
|
-
'SELECT * FROM test WHERE (((x = 1) AND (y = 2)) OR (z = 3))'
|
701
|
+
@d1.or(:y => 2).and(:z => 3).sql.should == 'SELECT * FROM test WHERE (((x = 1) OR (y = 2)) AND (z = 3))'
|
702
|
+
@d1.and(:y => 2).or(:z => 3).sql.should == 'SELECT * FROM test WHERE (((x = 1) AND (y = 2)) OR (z = 3))'
|
757
703
|
end
|
758
704
|
end
|
759
705
|
|
@@ -763,13 +709,11 @@ describe "Dataset#exclude" do
|
|
763
709
|
end
|
764
710
|
|
765
711
|
specify "should correctly negate the expression when one condition is given" do
|
766
|
-
@dataset.exclude(:region=>'Asia').select_sql.should ==
|
767
|
-
"SELECT * FROM test WHERE (region != 'Asia')"
|
712
|
+
@dataset.exclude(:region=>'Asia').select_sql.should == "SELECT * FROM test WHERE (region != 'Asia')"
|
768
713
|
end
|
769
714
|
|
770
715
|
specify "should affect the having clause if having clause is already used" do
|
771
|
-
@dataset.group_and_count(:name).having{count > 2}.exclude{count > 5}.sql.should ==
|
772
|
-
"SELECT name, count(*) AS count FROM test GROUP BY name HAVING ((count > 2) AND (count <= 5))"
|
716
|
+
@dataset.group_and_count(:name).having{count > 2}.exclude{count > 5}.sql.should == "SELECT name, count(*) AS count FROM test GROUP BY name HAVING ((count > 2) AND (count <= 5))"
|
773
717
|
end
|
774
718
|
|
775
719
|
specify "should take multiple conditions as a hash and express the logic correctly in SQL" do
|
@@ -779,30 +723,24 @@ describe "Dataset#exclude" do
|
|
779
723
|
end
|
780
724
|
|
781
725
|
specify "should parenthesize a single string condition correctly" do
|
782
|
-
@dataset.exclude("region = 'Asia' AND name = 'Japan'").select_sql.should ==
|
783
|
-
"SELECT * FROM test WHERE NOT (region = 'Asia' AND name = 'Japan')"
|
726
|
+
@dataset.exclude("region = 'Asia' AND name = 'Japan'").select_sql.should == "SELECT * FROM test WHERE NOT (region = 'Asia' AND name = 'Japan')"
|
784
727
|
end
|
785
728
|
|
786
729
|
specify "should parenthesize an array condition correctly" do
|
787
|
-
@dataset.exclude('region = ? AND name = ?', 'Asia', 'Japan').select_sql.should ==
|
788
|
-
"SELECT * FROM test WHERE NOT (region = 'Asia' AND name = 'Japan')"
|
730
|
+
@dataset.exclude('region = ? AND name = ?', 'Asia', 'Japan').select_sql.should == "SELECT * FROM test WHERE NOT (region = 'Asia' AND name = 'Japan')"
|
789
731
|
end
|
790
732
|
|
791
733
|
specify "should correctly parenthesize when it is used twice" do
|
792
|
-
@dataset.exclude(:region => 'Asia').exclude(:name => 'Japan').select_sql.should ==
|
793
|
-
"SELECT * FROM test WHERE ((region != 'Asia') AND (name != 'Japan'))"
|
734
|
+
@dataset.exclude(:region => 'Asia').exclude(:name => 'Japan').select_sql.should == "SELECT * FROM test WHERE ((region != 'Asia') AND (name != 'Japan'))"
|
794
735
|
end
|
795
736
|
|
796
737
|
specify "should support proc expressions" do
|
797
|
-
@dataset.exclude{:id.sql_number < 6}.sql.should ==
|
798
|
-
'SELECT * FROM test WHERE (id >= 6)'
|
738
|
+
@dataset.exclude{:id.sql_number < 6}.sql.should == 'SELECT * FROM test WHERE (id >= 6)'
|
799
739
|
end
|
800
740
|
|
801
741
|
specify "should allow the use of blocks and arguments simultaneously" do
|
802
|
-
@dataset.exclude(:id => (7..11)){:id.sql_number < 6}.sql.should ==
|
803
|
-
|
804
|
-
@dataset.exclude([:id, 1], [:x, 3]){:id.sql_number < 6}.sql.should ==
|
805
|
-
'SELECT * FROM test WHERE ((id != 1) OR (x != 3) OR (id >= 6))'
|
742
|
+
@dataset.exclude(:id => (7..11)){:id.sql_number < 6}.sql.should == 'SELECT * FROM test WHERE ((id < 7) OR (id > 11) OR (id >= 6))'
|
743
|
+
@dataset.exclude([:id, 1], [:x, 3]){:id.sql_number < 6}.sql.should == 'SELECT * FROM test WHERE ((id != 1) OR (x != 3) OR (id >= 6))'
|
806
744
|
end
|
807
745
|
end
|
808
746
|
|
@@ -850,9 +788,6 @@ describe "Dataset#having" do
|
|
850
788
|
before do
|
851
789
|
@dataset = Sequel::Dataset.new(nil).from(:test)
|
852
790
|
@grouped = @dataset.group(:region).select(:region, :sum.sql_function(:population), :avg.sql_function(:gdp))
|
853
|
-
@d1 = @grouped.having('sum(population) > 10')
|
854
|
-
@d2 = @grouped.having(:region => 'Asia')
|
855
|
-
@columns = "region, sum(population), avg(gdp)"
|
856
791
|
end
|
857
792
|
|
858
793
|
specify "should just clone if given an empty argument" do
|
@@ -862,18 +797,15 @@ describe "Dataset#having" do
|
|
862
797
|
end
|
863
798
|
|
864
799
|
specify "should affect select statements" do
|
865
|
-
@
|
866
|
-
"SELECT #{@columns} FROM test GROUP BY region HAVING (sum(population) > 10)"
|
800
|
+
@grouped.having('sum(population) > 10').select_sql.should == "SELECT region, sum(population), avg(gdp) FROM test GROUP BY region HAVING (sum(population) > 10)"
|
867
801
|
end
|
868
802
|
|
869
803
|
specify "should support proc expressions" do
|
870
|
-
@grouped.having {:sum.sql_function(:population) > 10}.sql.should ==
|
871
|
-
"SELECT #{@columns} FROM test GROUP BY region HAVING (sum(population) > 10)"
|
804
|
+
@grouped.having {:sum.sql_function(:population) > 10}.sql.should == "SELECT region, sum(population), avg(gdp) FROM test GROUP BY region HAVING (sum(population) > 10)"
|
872
805
|
end
|
873
806
|
|
874
807
|
specify "should work with and on the having clause" do
|
875
|
-
@grouped.having( :a.sql_number > 1 ).and( :b.sql_number < 2 ).sql.should ==
|
876
|
-
"SELECT #{@columns} FROM test GROUP BY region HAVING ((a > 1) AND (b < 2))"
|
808
|
+
@grouped.having( :a.sql_number > 1 ).and( :b.sql_number < 2 ).sql.should == "SELECT region, sum(population), avg(gdp) FROM test GROUP BY region HAVING ((a > 1) AND (b < 2))"
|
877
809
|
end
|
878
810
|
end
|
879
811
|
|
@@ -904,7 +836,7 @@ describe "a grouped dataset" do
|
|
904
836
|
end
|
905
837
|
|
906
838
|
specify "should format the right statement for counting (as a subquery)" do
|
907
|
-
db =
|
839
|
+
db = Sequel.mock
|
908
840
|
db[:test].select(:name).group(:name).count
|
909
841
|
db.sqls.should == ["SELECT COUNT(*) AS count FROM (SELECT name FROM test GROUP BY name) AS t1 LIMIT 1"]
|
910
842
|
end
|
@@ -924,31 +856,23 @@ describe "Dataset#group_by" do
|
|
924
856
|
end
|
925
857
|
|
926
858
|
specify "should specify the grouping in generated select statement" do
|
927
|
-
@dataset.select_sql.should ==
|
928
|
-
|
929
|
-
@dataset.group_by(:
|
930
|
-
"SELECT * FROM test GROUP BY a, b"
|
931
|
-
@dataset.group_by(:type_id=>nil).select_sql.should ==
|
932
|
-
"SELECT * FROM test GROUP BY (type_id IS NULL)"
|
859
|
+
@dataset.select_sql.should == "SELECT * FROM test GROUP BY type_id"
|
860
|
+
@dataset.group_by(:a, :b).select_sql.should == "SELECT * FROM test GROUP BY a, b"
|
861
|
+
@dataset.group_by(:type_id=>nil).select_sql.should == "SELECT * FROM test GROUP BY (type_id IS NULL)"
|
933
862
|
end
|
934
863
|
|
935
864
|
specify "should ungroup when passed nil or no arguments" do
|
936
|
-
@dataset.group_by.select_sql.should ==
|
937
|
-
|
938
|
-
@dataset.group_by(nil).select_sql.should ==
|
939
|
-
"SELECT * FROM test"
|
865
|
+
@dataset.group_by.select_sql.should == "SELECT * FROM test"
|
866
|
+
@dataset.group_by(nil).select_sql.should == "SELECT * FROM test"
|
940
867
|
end
|
941
868
|
|
942
869
|
specify "should undo previous grouping" do
|
943
|
-
@dataset.group_by(:a).group_by(:b).select_sql.should ==
|
944
|
-
|
945
|
-
@dataset.group_by(:a, :b).group_by.select_sql.should ==
|
946
|
-
"SELECT * FROM test"
|
870
|
+
@dataset.group_by(:a).group_by(:b).select_sql.should == "SELECT * FROM test GROUP BY b"
|
871
|
+
@dataset.group_by(:a, :b).group_by.select_sql.should == "SELECT * FROM test"
|
947
872
|
end
|
948
873
|
|
949
874
|
specify "should be aliased as #group" do
|
950
|
-
@dataset.group(:type_id=>nil).select_sql.should ==
|
951
|
-
"SELECT * FROM test GROUP BY (type_id IS NULL)"
|
875
|
+
@dataset.group(:type_id=>nil).select_sql.should == "SELECT * FROM test GROUP BY (type_id IS NULL)"
|
952
876
|
end
|
953
877
|
|
954
878
|
specify "should take a virtual row block" do
|
@@ -962,14 +886,13 @@ end
|
|
962
886
|
describe "Dataset#as" do
|
963
887
|
specify "should set up an alias" do
|
964
888
|
dataset = Sequel::Dataset.new(nil).from(:test)
|
965
|
-
dataset.select(dataset.limit(1).select(:name).as(:n)).sql.should ==
|
966
|
-
'SELECT (SELECT name FROM test LIMIT 1) AS n FROM test'
|
889
|
+
dataset.select(dataset.limit(1).select(:name).as(:n)).sql.should == 'SELECT (SELECT name FROM test LIMIT 1) AS n FROM test'
|
967
890
|
end
|
968
891
|
end
|
969
892
|
|
970
893
|
describe "Dataset#literal" do
|
971
894
|
before do
|
972
|
-
@dataset = Sequel::
|
895
|
+
@dataset = Sequel::Database.new.from(:test)
|
973
896
|
end
|
974
897
|
|
975
898
|
specify "should escape strings properly" do
|
@@ -1138,35 +1061,25 @@ describe "Dataset#from" do
|
|
1138
1061
|
end
|
1139
1062
|
|
1140
1063
|
specify "should format a Dataset as a subquery if it has had options set" do
|
1141
|
-
@dataset.from(@dataset.from(:a).where(:a=>1)).select_sql.should ==
|
1142
|
-
"SELECT * FROM (SELECT * FROM a WHERE (a = 1)) AS t1"
|
1064
|
+
@dataset.from(@dataset.from(:a).where(:a=>1)).select_sql.should == "SELECT * FROM (SELECT * FROM a WHERE (a = 1)) AS t1"
|
1143
1065
|
end
|
1144
1066
|
|
1145
1067
|
specify "should automatically alias sub-queries" do
|
1146
|
-
@dataset.from(@dataset.from(:a).group(:b)).select_sql.should ==
|
1147
|
-
"SELECT * FROM (SELECT * FROM a GROUP BY b) AS t1"
|
1068
|
+
@dataset.from(@dataset.from(:a).group(:b)).select_sql.should == "SELECT * FROM (SELECT * FROM a GROUP BY b) AS t1"
|
1148
1069
|
|
1149
1070
|
d1 = @dataset.from(:a).group(:b)
|
1150
1071
|
d2 = @dataset.from(:c).group(:d)
|
1151
|
-
|
1152
|
-
@dataset.from(d1, d2).sql.should ==
|
1153
|
-
"SELECT * FROM (SELECT * FROM a GROUP BY b) AS t1, (SELECT * FROM c GROUP BY d) AS t2"
|
1072
|
+
@dataset.from(d1, d2).sql.should == "SELECT * FROM (SELECT * FROM a GROUP BY b) AS t1, (SELECT * FROM c GROUP BY d) AS t2"
|
1154
1073
|
end
|
1155
1074
|
|
1156
1075
|
specify "should accept a hash for aliasing" do
|
1157
|
-
@dataset.from(:a => :b).sql.should ==
|
1158
|
-
|
1159
|
-
|
1160
|
-
@dataset.from(:a => 'b').sql.should ==
|
1161
|
-
"SELECT * FROM a AS b"
|
1162
|
-
|
1163
|
-
@dataset.from(@dataset.from(:a).group(:b) => :c).sql.should ==
|
1164
|
-
"SELECT * FROM (SELECT * FROM a GROUP BY b) AS c"
|
1076
|
+
@dataset.from(:a => :b).sql.should == "SELECT * FROM a AS b"
|
1077
|
+
@dataset.from(:a => 'b').sql.should == "SELECT * FROM a AS b"
|
1078
|
+
@dataset.from(@dataset.from(:a).group(:b) => :c).sql.should == "SELECT * FROM (SELECT * FROM a GROUP BY b) AS c"
|
1165
1079
|
end
|
1166
1080
|
|
1167
1081
|
specify "should always use a subquery if given a dataset" do
|
1168
|
-
@dataset.from(@dataset.from(:a)).select_sql.should ==
|
1169
|
-
"SELECT * FROM (SELECT * FROM a) AS t1"
|
1082
|
+
@dataset.from(@dataset.from(:a)).select_sql.should == "SELECT * FROM (SELECT * FROM a) AS t1"
|
1170
1083
|
end
|
1171
1084
|
|
1172
1085
|
specify "should remove all FROM tables if called with no arguments" do
|
@@ -1174,32 +1087,27 @@ describe "Dataset#from" do
|
|
1174
1087
|
end
|
1175
1088
|
|
1176
1089
|
specify "should accept sql functions" do
|
1177
|
-
@dataset.from(:abc.sql_function(:def)).select_sql.should ==
|
1178
|
-
|
1179
|
-
|
1180
|
-
@dataset.from(:a.sql_function(:i)).select_sql.should ==
|
1181
|
-
"SELECT * FROM a(i)"
|
1090
|
+
@dataset.from(:abc.sql_function(:def)).select_sql.should == "SELECT * FROM abc(def)"
|
1091
|
+
@dataset.from(:a.sql_function(:i)).select_sql.should == "SELECT * FROM a(i)"
|
1182
1092
|
end
|
1183
1093
|
|
1184
1094
|
specify "should accept :schema__table___alias symbol format" do
|
1185
|
-
@dataset.from(:abc__def).select_sql.should ==
|
1186
|
-
|
1187
|
-
@dataset.from(:
|
1188
|
-
|
1189
|
-
@dataset.from(:
|
1190
|
-
|
1191
|
-
@dataset.from(:
|
1192
|
-
|
1193
|
-
@dataset.from(:
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
@dataset.
|
1198
|
-
|
1199
|
-
@dataset.from(:
|
1200
|
-
|
1201
|
-
@dataset.from(:'#___#').select_sql.should ==
|
1202
|
-
'SELECT * FROM # AS #'
|
1095
|
+
@dataset.from(:abc__def).select_sql.should == "SELECT * FROM abc.def"
|
1096
|
+
@dataset.from(:a_b__c).select_sql.should == "SELECT * FROM a_b.c"
|
1097
|
+
@dataset.from(:'#__#').select_sql.should == 'SELECT * FROM #.#'
|
1098
|
+
@dataset.from(:abc__def___d).select_sql.should == "SELECT * FROM abc.def AS d"
|
1099
|
+
@dataset.from(:a_b__d_e___f_g).select_sql.should == "SELECT * FROM a_b.d_e AS f_g"
|
1100
|
+
@dataset.from(:'#__#___#').select_sql.should == 'SELECT * FROM #.# AS #'
|
1101
|
+
@dataset.from(:abc___def).select_sql.should == "SELECT * FROM abc AS def"
|
1102
|
+
@dataset.from(:a_b___c_d).select_sql.should == "SELECT * FROM a_b AS c_d"
|
1103
|
+
@dataset.from(:'#___#').select_sql.should == 'SELECT * FROM # AS #'
|
1104
|
+
end
|
1105
|
+
|
1106
|
+
specify "should hoist WITH clauses from subqueries if the dataset doesn't support CTEs in subselects" do
|
1107
|
+
@dataset.meta_def(:supports_cte?){true}
|
1108
|
+
@dataset.meta_def(:supports_cte_in_subselect?){false}
|
1109
|
+
@dataset.from(@dataset.from(:a).with(:a, @dataset.from(:b))).sql.should == 'WITH a AS (SELECT * FROM b) SELECT * FROM (SELECT * FROM a) AS t1'
|
1110
|
+
@dataset.from(@dataset.from(:a).with(:a, @dataset.from(:b)), @dataset.from(:c).with(:c, @dataset.from(:d))).sql.should == 'WITH a AS (SELECT * FROM b), c AS (SELECT * FROM d) SELECT * FROM (SELECT * FROM a) AS t1, (SELECT * FROM c) AS t2'
|
1203
1111
|
end
|
1204
1112
|
end
|
1205
1113
|
|
@@ -1216,18 +1124,17 @@ describe "Dataset#select" do
|
|
1216
1124
|
specify "should accept symbols and literal strings" do
|
1217
1125
|
@d.select('aaa'.lit).sql.should == 'SELECT aaa FROM test'
|
1218
1126
|
@d.select(:a, 'b'.lit).sql.should == 'SELECT a, b FROM test'
|
1219
|
-
@d.select(:test__cc, 'test.d AS e'.lit).sql.should ==
|
1220
|
-
|
1221
|
-
@d.select(
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
@d.select(:test.*).sql.should ==
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
@d.select(:
|
1230
|
-
'SELECT test.name AS n FROM test'
|
1127
|
+
@d.select(:test__cc, 'test.d AS e'.lit).sql.should == 'SELECT test.cc, test.d AS e FROM test'
|
1128
|
+
@d.select('test.d AS e'.lit, :test__cc).sql.should == 'SELECT test.d AS e, test.cc FROM test'
|
1129
|
+
@d.select(:test__name___n).sql.should == 'SELECT test.name AS n FROM test'
|
1130
|
+
end
|
1131
|
+
|
1132
|
+
specify "should accept ColumnAlls" do
|
1133
|
+
@d.select(:test.*).sql.should == 'SELECT test.* FROM test'
|
1134
|
+
end
|
1135
|
+
|
1136
|
+
specify "should accept QualifiedIdentifiers" do
|
1137
|
+
@d.select(:test__name.as(:n)).sql.should == 'SELECT test.name AS n FROM test'
|
1231
1138
|
end
|
1232
1139
|
|
1233
1140
|
specify "should use the wildcard if no arguments are given" do
|
@@ -1235,20 +1142,17 @@ describe "Dataset#select" do
|
|
1235
1142
|
end
|
1236
1143
|
|
1237
1144
|
specify "should accept a hash for AS values" do
|
1238
|
-
@d.select(:name => 'n', :__ggh => 'age').sql.should =~
|
1239
|
-
/SELECT ((name AS n, __ggh AS age)|(__ggh AS age, name AS n)) FROM test/
|
1145
|
+
@d.select(:name => 'n', :__ggh => 'age').sql.should =~ /SELECT ((name AS n, __ggh AS age)|(__ggh AS age, name AS n)) FROM test/
|
1240
1146
|
end
|
1241
1147
|
|
1242
|
-
specify "should
|
1148
|
+
specify "should override the previous select option" do
|
1243
1149
|
@d.select!(:a, :b, :c).select.sql.should == 'SELECT * FROM test'
|
1244
1150
|
@d.select!(:price).select(:name).sql.should == 'SELECT name FROM test'
|
1245
1151
|
end
|
1246
1152
|
|
1247
1153
|
specify "should accept arbitrary objects and literalize them correctly" do
|
1248
1154
|
@d.select(1, :a, 't').sql.should == "SELECT 1, a, 't' FROM test"
|
1249
|
-
|
1250
1155
|
@d.select(nil, :sum.sql_function(:t), :x___y).sql.should == "SELECT NULL, sum(t), x AS y FROM test"
|
1251
|
-
|
1252
1156
|
@d.select(nil, 1, :x => :y).sql.should == "SELECT NULL, 1, x AS y FROM test"
|
1253
1157
|
end
|
1254
1158
|
|
@@ -1297,7 +1201,7 @@ describe "Dataset#select_all" do
|
|
1297
1201
|
@d.select_all.sql.should == 'SELECT * FROM test'
|
1298
1202
|
end
|
1299
1203
|
|
1300
|
-
specify "should
|
1204
|
+
specify "should override the previous select option" do
|
1301
1205
|
@d.select!(:a, :b, :c).select_all.sql.should == 'SELECT * FROM test'
|
1302
1206
|
end
|
1303
1207
|
|
@@ -1394,38 +1298,31 @@ describe "Dataset#order" do
|
|
1394
1298
|
end
|
1395
1299
|
|
1396
1300
|
specify "should include an ORDER BY clause in the select statement" do
|
1397
|
-
@dataset.order(:name).sql.should ==
|
1398
|
-
'SELECT * FROM test ORDER BY name'
|
1301
|
+
@dataset.order(:name).sql.should == 'SELECT * FROM test ORDER BY name'
|
1399
1302
|
end
|
1400
1303
|
|
1401
1304
|
specify "should accept multiple arguments" do
|
1402
|
-
@dataset.order(:name, :price.desc).sql.should ==
|
1403
|
-
'SELECT * FROM test ORDER BY name, price DESC'
|
1305
|
+
@dataset.order(:name, :price.desc).sql.should == 'SELECT * FROM test ORDER BY name, price DESC'
|
1404
1306
|
end
|
1405
1307
|
|
1406
1308
|
specify "should accept :nulls options for asc and desc" do
|
1407
|
-
@dataset.order(:name.asc(:nulls=>:last), :price.desc(:nulls=>:first)).sql.should ==
|
1408
|
-
'SELECT * FROM test ORDER BY name ASC NULLS LAST, price DESC NULLS FIRST'
|
1309
|
+
@dataset.order(:name.asc(:nulls=>:last), :price.desc(:nulls=>:first)).sql.should == 'SELECT * FROM test ORDER BY name ASC NULLS LAST, price DESC NULLS FIRST'
|
1409
1310
|
end
|
1410
1311
|
|
1411
|
-
specify "should
|
1412
|
-
@dataset.order(:name).order(:stamp).sql.should ==
|
1413
|
-
'SELECT * FROM test ORDER BY stamp'
|
1312
|
+
specify "should override a previous ordering" do
|
1313
|
+
@dataset.order(:name).order(:stamp).sql.should == 'SELECT * FROM test ORDER BY stamp'
|
1414
1314
|
end
|
1415
1315
|
|
1416
1316
|
specify "should accept a literal string" do
|
1417
|
-
@dataset.order('dada ASC'.lit).sql.should ==
|
1418
|
-
'SELECT * FROM test ORDER BY dada ASC'
|
1317
|
+
@dataset.order('dada ASC'.lit).sql.should == 'SELECT * FROM test ORDER BY dada ASC'
|
1419
1318
|
end
|
1420
1319
|
|
1421
1320
|
specify "should accept a hash as an expression" do
|
1422
|
-
@dataset.order(:name=>nil).sql.should ==
|
1423
|
-
'SELECT * FROM test ORDER BY (name IS NULL)'
|
1321
|
+
@dataset.order(:name=>nil).sql.should == 'SELECT * FROM test ORDER BY (name IS NULL)'
|
1424
1322
|
end
|
1425
1323
|
|
1426
1324
|
specify "should accept a nil to remove ordering" do
|
1427
|
-
@dataset.order(:bah).order(nil).sql.should ==
|
1428
|
-
'SELECT * FROM test'
|
1325
|
+
@dataset.order(:bah).order(nil).sql.should == 'SELECT * FROM test'
|
1429
1326
|
end
|
1430
1327
|
|
1431
1328
|
specify "should accept a block that yields a virtual row" do
|
@@ -1502,28 +1399,23 @@ describe "Dataset#order_by" do
|
|
1502
1399
|
end
|
1503
1400
|
|
1504
1401
|
specify "should include an ORDER BY clause in the select statement" do
|
1505
|
-
@dataset.order_by(:name).sql.should ==
|
1506
|
-
'SELECT * FROM test ORDER BY name'
|
1402
|
+
@dataset.order_by(:name).sql.should == 'SELECT * FROM test ORDER BY name'
|
1507
1403
|
end
|
1508
1404
|
|
1509
1405
|
specify "should accept multiple arguments" do
|
1510
|
-
@dataset.order_by(:name, :price.desc).sql.should ==
|
1511
|
-
'SELECT * FROM test ORDER BY name, price DESC'
|
1406
|
+
@dataset.order_by(:name, :price.desc).sql.should == 'SELECT * FROM test ORDER BY name, price DESC'
|
1512
1407
|
end
|
1513
1408
|
|
1514
|
-
specify "should
|
1515
|
-
@dataset.order_by(:name).order(:stamp).sql.should ==
|
1516
|
-
'SELECT * FROM test ORDER BY stamp'
|
1409
|
+
specify "should override a previous ordering" do
|
1410
|
+
@dataset.order_by(:name).order(:stamp).sql.should == 'SELECT * FROM test ORDER BY stamp'
|
1517
1411
|
end
|
1518
1412
|
|
1519
1413
|
specify "should accept a string" do
|
1520
|
-
@dataset.order_by('dada ASC'.lit).sql.should ==
|
1521
|
-
'SELECT * FROM test ORDER BY dada ASC'
|
1414
|
+
@dataset.order_by('dada ASC'.lit).sql.should == 'SELECT * FROM test ORDER BY dada ASC'
|
1522
1415
|
end
|
1523
1416
|
|
1524
1417
|
specify "should accept a nil to remove ordering" do
|
1525
|
-
@dataset.order_by(:bah).order_by(nil).sql.should ==
|
1526
|
-
'SELECT * FROM test'
|
1418
|
+
@dataset.order_by(:bah).order_by(nil).sql.should == 'SELECT * FROM test'
|
1527
1419
|
end
|
1528
1420
|
end
|
1529
1421
|
|
@@ -1556,13 +1448,11 @@ describe "Dataset#order_prepend" do
|
|
1556
1448
|
end
|
1557
1449
|
|
1558
1450
|
specify "should include an ORDER BY clause in the select statement" do
|
1559
|
-
@dataset.order_prepend(:name).sql.should ==
|
1560
|
-
'SELECT * FROM test ORDER BY name'
|
1451
|
+
@dataset.order_prepend(:name).sql.should == 'SELECT * FROM test ORDER BY name'
|
1561
1452
|
end
|
1562
1453
|
|
1563
1454
|
specify "should add to the beginning of a previous ordering" do
|
1564
|
-
@dataset.order(:name).order_prepend(:stamp.desc).sql.should ==
|
1565
|
-
'SELECT * FROM test ORDER BY stamp DESC, name'
|
1455
|
+
@dataset.order(:name).order_prepend(:stamp.desc).sql.should == 'SELECT * FROM test ORDER BY stamp DESC, name'
|
1566
1456
|
end
|
1567
1457
|
|
1568
1458
|
specify "should accept a block that yields a virtual row" do
|
@@ -1577,45 +1467,36 @@ describe "Dataset#reverse_order" do
|
|
1577
1467
|
end
|
1578
1468
|
|
1579
1469
|
specify "should use DESC as default order" do
|
1580
|
-
@dataset.reverse_order(:name).sql.should ==
|
1581
|
-
'SELECT * FROM test ORDER BY name DESC'
|
1470
|
+
@dataset.reverse_order(:name).sql.should == 'SELECT * FROM test ORDER BY name DESC'
|
1582
1471
|
end
|
1583
1472
|
|
1584
1473
|
specify "should invert the order given" do
|
1585
|
-
@dataset.reverse_order(:name.desc).sql.should ==
|
1586
|
-
'SELECT * FROM test ORDER BY name ASC'
|
1474
|
+
@dataset.reverse_order(:name.desc).sql.should == 'SELECT * FROM test ORDER BY name ASC'
|
1587
1475
|
end
|
1588
1476
|
|
1589
1477
|
specify "should invert the order for ASC expressions" do
|
1590
|
-
@dataset.reverse_order(:name.asc).sql.should ==
|
1591
|
-
'SELECT * FROM test ORDER BY name DESC'
|
1478
|
+
@dataset.reverse_order(:name.asc).sql.should == 'SELECT * FROM test ORDER BY name DESC'
|
1592
1479
|
end
|
1593
1480
|
|
1594
1481
|
specify "should accept multiple arguments" do
|
1595
|
-
@dataset.reverse_order(:name, :price.desc).sql.should ==
|
1596
|
-
'SELECT * FROM test ORDER BY name DESC, price ASC'
|
1482
|
+
@dataset.reverse_order(:name, :price.desc).sql.should == 'SELECT * FROM test ORDER BY name DESC, price ASC'
|
1597
1483
|
end
|
1598
1484
|
|
1599
1485
|
specify "should handles NULLS ordering correctly when reversing" do
|
1600
|
-
@dataset.reverse_order(:name.asc(:nulls=>:first), :price.desc(:nulls=>:last)).sql.should ==
|
1601
|
-
'SELECT * FROM test ORDER BY name DESC NULLS LAST, price ASC NULLS FIRST'
|
1486
|
+
@dataset.reverse_order(:name.asc(:nulls=>:first), :price.desc(:nulls=>:last)).sql.should == 'SELECT * FROM test ORDER BY name DESC NULLS LAST, price ASC NULLS FIRST'
|
1602
1487
|
end
|
1603
1488
|
|
1604
1489
|
specify "should reverse a previous ordering if no arguments are given" do
|
1605
|
-
@dataset.order(:name).reverse_order.sql.should ==
|
1606
|
-
|
1607
|
-
@dataset.order(:clumsy.desc, :fool).reverse_order.sql.should ==
|
1608
|
-
'SELECT * FROM test ORDER BY clumsy ASC, fool DESC'
|
1490
|
+
@dataset.order(:name).reverse_order.sql.should == 'SELECT * FROM test ORDER BY name DESC'
|
1491
|
+
@dataset.order(:clumsy.desc, :fool).reverse_order.sql.should == 'SELECT * FROM test ORDER BY clumsy ASC, fool DESC'
|
1609
1492
|
end
|
1610
1493
|
|
1611
1494
|
specify "should return an unordered dataset for a dataset with no order" do
|
1612
|
-
@dataset.unordered.reverse_order.sql.should ==
|
1613
|
-
'SELECT * FROM test'
|
1495
|
+
@dataset.unordered.reverse_order.sql.should == 'SELECT * FROM test'
|
1614
1496
|
end
|
1615
1497
|
|
1616
1498
|
specify "should have #reverse alias" do
|
1617
|
-
@dataset.order(:name).reverse.sql.should ==
|
1618
|
-
'SELECT * FROM test ORDER BY name DESC'
|
1499
|
+
@dataset.order(:name).reverse.sql.should == 'SELECT * FROM test ORDER BY name DESC'
|
1619
1500
|
end
|
1620
1501
|
end
|
1621
1502
|
|
@@ -1625,42 +1506,33 @@ describe "Dataset#limit" do
|
|
1625
1506
|
end
|
1626
1507
|
|
1627
1508
|
specify "should include a LIMIT clause in the select statement" do
|
1628
|
-
@dataset.limit(10).sql.should ==
|
1629
|
-
'SELECT * FROM test LIMIT 10'
|
1509
|
+
@dataset.limit(10).sql.should == 'SELECT * FROM test LIMIT 10'
|
1630
1510
|
end
|
1631
1511
|
|
1632
1512
|
specify "should accept ranges" do
|
1633
|
-
@dataset.limit(3..7).sql.should ==
|
1634
|
-
|
1635
|
-
|
1636
|
-
@dataset.limit(3...7).sql.should ==
|
1637
|
-
'SELECT * FROM test LIMIT 4 OFFSET 3'
|
1513
|
+
@dataset.limit(3..7).sql.should == 'SELECT * FROM test LIMIT 5 OFFSET 3'
|
1514
|
+
@dataset.limit(3...7).sql.should == 'SELECT * FROM test LIMIT 4 OFFSET 3'
|
1638
1515
|
end
|
1639
1516
|
|
1640
1517
|
specify "should include an offset if a second argument is given" do
|
1641
|
-
@dataset.limit(6, 10).sql.should ==
|
1642
|
-
|
1643
|
-
end
|
1518
|
+
@dataset.limit(6, 10).sql.should == 'SELECT * FROM test LIMIT 6 OFFSET 10'
|
1519
|
+
end
|
1644
1520
|
|
1645
1521
|
specify "should convert regular strings to integers" do
|
1646
|
-
@dataset.limit('6', 'a() - 1').sql.should ==
|
1647
|
-
'SELECT * FROM test LIMIT 6 OFFSET 0'
|
1522
|
+
@dataset.limit('6', 'a() - 1').sql.should == 'SELECT * FROM test LIMIT 6 OFFSET 0'
|
1648
1523
|
end
|
1649
1524
|
|
1650
1525
|
specify "should not convert literal strings to integers" do
|
1651
|
-
@dataset.limit('6'.lit, 'a() - 1'.lit).sql.should ==
|
1652
|
-
'SELECT * FROM test LIMIT 6 OFFSET a() - 1'
|
1526
|
+
@dataset.limit('6'.lit, 'a() - 1'.lit).sql.should == 'SELECT * FROM test LIMIT 6 OFFSET a() - 1'
|
1653
1527
|
end
|
1654
1528
|
|
1655
1529
|
specify "should not convert other objects" do
|
1656
|
-
@dataset.limit(6, :a.sql_function - 1).sql.should ==
|
1657
|
-
'SELECT * FROM test LIMIT 6 OFFSET (a() - 1)'
|
1530
|
+
@dataset.limit(6, :a.sql_function - 1).sql.should == 'SELECT * FROM test LIMIT 6 OFFSET (a() - 1)'
|
1658
1531
|
end
|
1659
1532
|
|
1660
1533
|
specify "should work with fixed sql datasets" do
|
1661
1534
|
@dataset.opts[:sql] = 'select * from cccc'
|
1662
|
-
@dataset.limit(6, 10).sql.should ==
|
1663
|
-
'SELECT * FROM (select * from cccc) AS t1 LIMIT 6 OFFSET 10'
|
1535
|
+
@dataset.limit(6, 10).sql.should == 'SELECT * FROM (select * from cccc) AS t1 LIMIT 6 OFFSET 10'
|
1664
1536
|
end
|
1665
1537
|
|
1666
1538
|
specify "should raise an error if an invalid limit or offset is used" do
|
@@ -1674,15 +1546,10 @@ describe "Dataset#limit" do
|
|
1674
1546
|
end
|
1675
1547
|
|
1676
1548
|
describe "Dataset#naked" do
|
1677
|
-
before do
|
1678
|
-
@d1 = Sequel::Dataset.new(nil, {1 => 2, 3 => 4})
|
1679
|
-
@d2 = @d1.clone
|
1680
|
-
@d2.row_proc = Proc.new{|r| r}
|
1681
|
-
end
|
1682
|
-
|
1683
1549
|
specify "should remove any existing row_proc" do
|
1684
|
-
|
1685
|
-
|
1550
|
+
d = Sequel::Dataset.new(nil)
|
1551
|
+
d.row_proc = Proc.new{|r| r}
|
1552
|
+
d.naked.row_proc.should be_nil
|
1686
1553
|
end
|
1687
1554
|
end
|
1688
1555
|
|
@@ -1712,11 +1579,11 @@ end
|
|
1712
1579
|
|
1713
1580
|
describe "Dataset#map" do
|
1714
1581
|
before do
|
1715
|
-
@d =
|
1582
|
+
@d = Sequel.mock(:fetch=>[{:a => 1, :b => 2}, {:a => 3, :b => 4}, {:a => 5, :b => 6}])[:items]
|
1716
1583
|
end
|
1717
1584
|
|
1718
1585
|
specify "should provide the usual functionality if no argument is given" do
|
1719
|
-
@d.map
|
1586
|
+
@d.map{|n| n[:a] + n[:b]}.should == [3, 7, 11]
|
1720
1587
|
end
|
1721
1588
|
|
1722
1589
|
specify "should map using #[column name] if column name is given" do
|
@@ -1727,14 +1594,25 @@ describe "Dataset#map" do
|
|
1727
1594
|
@d.map([:a, :b]).should == [[1, 2], [3, 4], [5, 6]]
|
1728
1595
|
end
|
1729
1596
|
|
1597
|
+
specify "should not call the row_proc if an argument is given" do
|
1598
|
+
@d.row_proc = proc{|r| h = {}; r.keys.each{|k| h[k] = r[k] * 2}; h}
|
1599
|
+
@d.map(:a).should == [1, 3, 5]
|
1600
|
+
@d.map([:a, :b]).should == [[1, 2], [3, 4], [5, 6]]
|
1601
|
+
end
|
1602
|
+
|
1603
|
+
specify "should call the row_proc if no argument is given" do
|
1604
|
+
@d.row_proc = proc{|r| h = {}; r.keys.each{|k| h[k] = r[k] * 2}; h}
|
1605
|
+
@d.map{|n| n[:a] + n[:b]}.should == [6, 14, 22]
|
1606
|
+
end
|
1607
|
+
|
1730
1608
|
specify "should return the complete dataset values if nothing is given" do
|
1731
|
-
@d.map.to_a.should ==
|
1609
|
+
@d.map.to_a.should == [{:a => 1, :b => 2}, {:a => 3, :b => 4}, {:a => 5, :b => 6}]
|
1732
1610
|
end
|
1733
1611
|
end
|
1734
1612
|
|
1735
1613
|
describe "Dataset#to_hash" do
|
1736
1614
|
before do
|
1737
|
-
@d =
|
1615
|
+
@d = Sequel.mock(:fetch=>[{:a => 1, :b => 2}, {:a => 3, :b => 4}, {:a => 5, :b => 6}])[:items]
|
1738
1616
|
end
|
1739
1617
|
|
1740
1618
|
specify "should provide a hash with the first column as key and the second as value" do
|
@@ -1753,11 +1631,28 @@ describe "Dataset#to_hash" do
|
|
1753
1631
|
@d.to_hash([:b, :a], [:a, :b]).should == {[2, 1] => [1, 2], [4, 3] => [3, 4], [6, 5] => [5, 6]}
|
1754
1632
|
@d.to_hash([:a, :b]).should == {[1, 2] => {:a => 1, :b => 2}, [3, 4] => {:a => 3, :b => 4}, [5, 6] => {:a => 5, :b => 6}}
|
1755
1633
|
end
|
1634
|
+
|
1635
|
+
specify "should not call the row_proc if two arguments are given" do
|
1636
|
+
@d.row_proc = proc{|r| h = {}; r.keys.each{|k| h[k] = r[k] * 2}; h}
|
1637
|
+
@d.to_hash(:a, :b).should == {1 => 2, 3 => 4, 5 => 6}
|
1638
|
+
@d.to_hash(:b, :a).should == {2 => 1, 4 => 3, 6 => 5}
|
1639
|
+
@d.to_hash([:a, :b], :b).should == {[1, 2] => 2, [3, 4] => 4, [5, 6] => 6}
|
1640
|
+
@d.to_hash(:b, [:a, :b]).should == {2 => [1, 2], 4 => [3, 4], 6 => [5, 6]}
|
1641
|
+
@d.to_hash([:b, :a], [:a, :b]).should == {[2, 1] => [1, 2], [4, 3] => [3, 4], [6, 5] => [5, 6]}
|
1642
|
+
end
|
1643
|
+
|
1644
|
+
specify "should call the row_proc if only a single argument is given" do
|
1645
|
+
@d.row_proc = proc{|r| h = {}; r.keys.each{|k| h[k] = r[k] * 2}; h}
|
1646
|
+
@d.to_hash(:a).should == {2 => {:a => 2, :b => 4}, 6 => {:a => 6, :b => 8}, 10 => {:a => 10, :b => 12}}
|
1647
|
+
@d.to_hash(:b).should == {4 => {:a => 2, :b => 4}, 8 => {:a => 6, :b => 8}, 12 => {:a => 10, :b => 12}}
|
1648
|
+
@d.to_hash([:a, :b]).should == {[2, 4] => {:a => 2, :b => 4}, [6, 8] => {:a => 6, :b => 8}, [10, 12] => {:a => 10, :b => 12}}
|
1649
|
+
end
|
1650
|
+
|
1756
1651
|
end
|
1757
1652
|
|
1758
1653
|
describe "Dataset#distinct" do
|
1759
1654
|
before do
|
1760
|
-
@db =
|
1655
|
+
@db = Sequel.mock
|
1761
1656
|
@dataset = @db[:test].select(:name)
|
1762
1657
|
end
|
1763
1658
|
|
@@ -1784,113 +1679,84 @@ end
|
|
1784
1679
|
|
1785
1680
|
describe "Dataset#count" do
|
1786
1681
|
before do
|
1787
|
-
@
|
1788
|
-
|
1789
|
-
@@sql
|
1790
|
-
end
|
1791
|
-
|
1792
|
-
def fetch_rows(sql)
|
1793
|
-
@columns = [sql =~ /SELECT COUNT/i ? :count : :a]
|
1794
|
-
@@sql = sql
|
1795
|
-
yield({@columns.first=>1})
|
1796
|
-
end
|
1797
|
-
end
|
1798
|
-
@dataset = @c.new(nil).from(:test)
|
1682
|
+
@db = Sequel.mock(:fetch=>{:count=>1})
|
1683
|
+
@dataset = @db.from(:test).columns(:count)
|
1799
1684
|
end
|
1800
1685
|
|
1801
1686
|
specify "should format SQL properly" do
|
1802
1687
|
@dataset.count.should == 1
|
1803
|
-
@
|
1688
|
+
@db.sqls.should == ['SELECT COUNT(*) AS count FROM test LIMIT 1']
|
1804
1689
|
end
|
1805
1690
|
|
1806
1691
|
specify "should include the where clause if it's there" do
|
1807
1692
|
@dataset.filter(:abc.sql_number < 30).count.should == 1
|
1808
|
-
@
|
1693
|
+
@db.sqls.should == ['SELECT COUNT(*) AS count FROM test WHERE (abc < 30) LIMIT 1']
|
1809
1694
|
end
|
1810
1695
|
|
1811
1696
|
specify "should count properly for datasets with fixed sql" do
|
1812
1697
|
@dataset.opts[:sql] = "select abc from xyz"
|
1813
1698
|
@dataset.count.should == 1
|
1814
|
-
@
|
1699
|
+
@db.sqls.should == ["SELECT COUNT(*) AS count FROM (select abc from xyz) AS t1 LIMIT 1"]
|
1815
1700
|
end
|
1816
1701
|
|
1817
1702
|
specify "should count properly when using UNION, INTERSECT, or EXCEPT" do
|
1818
1703
|
@dataset.union(@dataset).count.should == 1
|
1819
|
-
@
|
1704
|
+
@db.sqls.should == ["SELECT COUNT(*) AS count FROM (SELECT * FROM test UNION SELECT * FROM test) AS t1 LIMIT 1"]
|
1820
1705
|
@dataset.intersect(@dataset).count.should == 1
|
1821
|
-
@
|
1706
|
+
@db.sqls.should == ["SELECT COUNT(*) AS count FROM (SELECT * FROM test INTERSECT SELECT * FROM test) AS t1 LIMIT 1"]
|
1822
1707
|
@dataset.except(@dataset).count.should == 1
|
1823
|
-
@
|
1708
|
+
@db.sqls.should == ["SELECT COUNT(*) AS count FROM (SELECT * FROM test EXCEPT SELECT * FROM test) AS t1 LIMIT 1"]
|
1824
1709
|
end
|
1825
1710
|
|
1826
1711
|
specify "should return limit if count is greater than it" do
|
1827
1712
|
@dataset.limit(5).count.should == 1
|
1828
|
-
@
|
1713
|
+
@db.sqls.should == ["SELECT COUNT(*) AS count FROM (SELECT * FROM test LIMIT 5) AS t1 LIMIT 1"]
|
1829
1714
|
end
|
1830
1715
|
|
1831
1716
|
it "should work on a graphed_dataset" do
|
1832
1717
|
@dataset.should_receive(:columns).twice.and_return([:a])
|
1833
1718
|
@dataset.graph(@dataset, [:a], :table_alias=>:test2).count.should == 1
|
1834
|
-
@
|
1719
|
+
@db.sqls.should == ['SELECT COUNT(*) AS count FROM test LEFT OUTER JOIN test AS test2 USING (a) LIMIT 1']
|
1835
1720
|
end
|
1836
1721
|
|
1837
1722
|
specify "should not cache the columns value" do
|
1838
|
-
ds = @dataset.from(:blah)
|
1723
|
+
ds = @dataset.from(:blah).columns(:a)
|
1839
1724
|
ds.columns.should == [:a]
|
1840
1725
|
ds.count.should == 1
|
1841
|
-
@
|
1726
|
+
@db.sqls.should == ['SELECT COUNT(*) AS count FROM blah LIMIT 1']
|
1842
1727
|
ds.columns.should == [:a]
|
1843
1728
|
end
|
1844
1729
|
end
|
1845
1730
|
|
1846
|
-
|
1847
1731
|
describe "Dataset#group_and_count" do
|
1848
1732
|
before do
|
1849
|
-
@
|
1850
|
-
def self.sql
|
1851
|
-
@@sql
|
1852
|
-
end
|
1853
|
-
|
1854
|
-
def fetch_rows(sql)
|
1855
|
-
@@sql = sql
|
1856
|
-
yield({1 => 1})
|
1857
|
-
end
|
1858
|
-
end
|
1859
|
-
@ds = @c.new(nil).from(:test)
|
1733
|
+
@ds = Sequel::Dataset.new(nil).from(:test)
|
1860
1734
|
end
|
1861
1735
|
|
1862
1736
|
specify "should format SQL properly" do
|
1863
|
-
@ds.group_and_count(:name).sql.should ==
|
1864
|
-
"SELECT name, count(*) AS count FROM test GROUP BY name"
|
1737
|
+
@ds.group_and_count(:name).sql.should == "SELECT name, count(*) AS count FROM test GROUP BY name"
|
1865
1738
|
end
|
1866
1739
|
|
1867
1740
|
specify "should accept multiple columns for grouping" do
|
1868
|
-
@ds.group_and_count(:a, :b).sql.should ==
|
1869
|
-
"SELECT a, b, count(*) AS count FROM test GROUP BY a, b"
|
1741
|
+
@ds.group_and_count(:a, :b).sql.should == "SELECT a, b, count(*) AS count FROM test GROUP BY a, b"
|
1870
1742
|
end
|
1871
1743
|
|
1872
1744
|
specify "should format column aliases in the select clause but not in the group clause" do
|
1873
|
-
@ds.group_and_count(:name___n).sql.should ==
|
1874
|
-
|
1875
|
-
@ds.group_and_count(:name__n).sql.should ==
|
1876
|
-
"SELECT name.n, count(*) AS count FROM test GROUP BY name.n"
|
1745
|
+
@ds.group_and_count(:name___n).sql.should == "SELECT name AS n, count(*) AS count FROM test GROUP BY name"
|
1746
|
+
@ds.group_and_count(:name__n).sql.should == "SELECT name.n, count(*) AS count FROM test GROUP BY name.n"
|
1877
1747
|
end
|
1878
1748
|
|
1879
1749
|
specify "should handle identifiers" do
|
1880
|
-
@ds.group_and_count(:name___n.identifier).sql.should ==
|
1881
|
-
"SELECT name___n, count(*) AS count FROM test GROUP BY name___n"
|
1750
|
+
@ds.group_and_count(:name___n.identifier).sql.should == "SELECT name___n, count(*) AS count FROM test GROUP BY name___n"
|
1882
1751
|
end
|
1883
1752
|
|
1884
1753
|
specify "should handle literal strings" do
|
1885
|
-
@ds.group_and_count("name".lit).sql.should ==
|
1886
|
-
"SELECT name, count(*) AS count FROM test GROUP BY name"
|
1754
|
+
@ds.group_and_count("name".lit).sql.should == "SELECT name, count(*) AS count FROM test GROUP BY name"
|
1887
1755
|
end
|
1888
1756
|
|
1889
1757
|
specify "should handle aliased expressions" do
|
1890
|
-
@ds.group_and_count(:name.as(:n)).sql.should ==
|
1891
|
-
|
1892
|
-
@ds.group_and_count(:name.identifier.as(:n)).sql.should ==
|
1893
|
-
"SELECT name AS n, count(*) AS count FROM test GROUP BY name"
|
1758
|
+
@ds.group_and_count(:name.as(:n)).sql.should == "SELECT name AS n, count(*) AS count FROM test GROUP BY name"
|
1759
|
+
@ds.group_and_count(:name.identifier.as(:n)).sql.should == "SELECT name AS n, count(*) AS count FROM test GROUP BY name"
|
1894
1760
|
end
|
1895
1761
|
|
1896
1762
|
specify "should take a virtual row block" do
|
@@ -1902,20 +1768,11 @@ end
|
|
1902
1768
|
|
1903
1769
|
describe "Dataset#empty?" do
|
1904
1770
|
specify "should return true if records exist in the dataset" do
|
1905
|
-
|
1906
|
-
|
1907
|
-
|
1908
|
-
|
1909
|
-
|
1910
|
-
def fetch_rows(sql)
|
1911
|
-
@@sql = sql
|
1912
|
-
yield({1 => 1}) unless sql =~ /WHERE 'f'/
|
1913
|
-
end
|
1914
|
-
end
|
1915
|
-
@c.new(nil).from(:test).should_not be_empty
|
1916
|
-
@c.sql.should == 'SELECT 1 FROM test LIMIT 1'
|
1917
|
-
@c.new(nil).from(:test).filter(false).should be_empty
|
1918
|
-
@c.sql.should == "SELECT 1 FROM test WHERE 'f' LIMIT 1"
|
1771
|
+
db = Sequel.mock(:fetch=>proc{|sql| {1=>1} unless sql =~ /WHERE 'f'/})
|
1772
|
+
db.from(:test).should_not be_empty
|
1773
|
+
db.sqls.should == ['SELECT 1 FROM test LIMIT 1']
|
1774
|
+
db.from(:test).filter(false).should be_empty
|
1775
|
+
db.sqls.should == ["SELECT 1 FROM test WHERE 'f' LIMIT 1"]
|
1919
1776
|
end
|
1920
1777
|
end
|
1921
1778
|
|
@@ -1994,25 +1851,31 @@ describe "Dataset#from_self" do
|
|
1994
1851
|
'SELECT * FROM (SELECT name FROM test LIMIT 1) AS some_name INNER JOIN posts ON (posts.alias = some_name.name)'
|
1995
1852
|
end
|
1996
1853
|
|
1997
|
-
specify "should not options such as server" do
|
1854
|
+
specify "should not remove non-SQL options such as :server" do
|
1998
1855
|
@ds.server(:blah).from_self(:alias=>:some_name).opts[:server].should == :blah
|
1999
1856
|
end
|
2000
1857
|
|
1858
|
+
specify "should hoist WITH clauses in current dataset if dataset doesn't support WITH in subselect" do
|
1859
|
+
ds = Sequel::Dataset.new(nil)
|
1860
|
+
ds.meta_def(:supports_cte?){true}
|
1861
|
+
ds.meta_def(:supports_cte_in_subselect?){false}
|
1862
|
+
ds.from(:a).with(:a, ds.from(:b)).from_self.sql.should == 'WITH a AS (SELECT * FROM b) SELECT * FROM (SELECT * FROM a) AS t1'
|
1863
|
+
ds.from(:a, :c).with(:a, ds.from(:b)).with(:c, ds.from(:d)).from_self.sql.should == 'WITH a AS (SELECT * FROM b), c AS (SELECT * FROM d) SELECT * FROM (SELECT * FROM a, c) AS t1'
|
1864
|
+
end
|
2001
1865
|
end
|
2002
1866
|
|
2003
1867
|
describe "Dataset#join_table" do
|
2004
1868
|
before do
|
2005
|
-
@d =
|
1869
|
+
@d = Sequel::Dataset.new(nil).from(:items)
|
2006
1870
|
@d.quote_identifiers = true
|
2007
1871
|
end
|
2008
1872
|
|
2009
1873
|
specify "should format the JOIN clause properly" do
|
2010
|
-
@d.join_table(:left_outer, :categories, :category_id => :id).sql.should ==
|
2011
|
-
'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1874
|
+
@d.join_table(:left_outer, :categories, :category_id => :id).sql.should == 'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
2012
1875
|
end
|
2013
1876
|
|
2014
1877
|
specify "should handle multiple conditions on the same join table column" do
|
2015
|
-
@d.join_table(:left_outer, :categories, [[:category_id, :id], [:category_id, 0..100]]).sql.should ==
|
1878
|
+
@d.join_table(:left_outer, :categories, [[:category_id, :id], [:category_id, 0..100]]).sql.should ==
|
2016
1879
|
'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON (("categories"."category_id" = "items"."id") AND ("categories"."category_id" >= 0) AND ("categories"."category_id" <= 100))'
|
2017
1880
|
end
|
2018
1881
|
|
@@ -2022,45 +1885,30 @@ describe "Dataset#join_table" do
|
|
2022
1885
|
end
|
2023
1886
|
|
2024
1887
|
specify "should include ORDER BY clause if applicable" do
|
2025
|
-
@d.order(:stamp).join_table(:full_outer, :categories, :category_id => :id).sql.should ==
|
2026
|
-
'SELECT * FROM "items" FULL OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id") ORDER BY "stamp"'
|
1888
|
+
@d.order(:stamp).join_table(:full_outer, :categories, :category_id => :id).sql.should == 'SELECT * FROM "items" FULL OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id") ORDER BY "stamp"'
|
2027
1889
|
end
|
2028
1890
|
|
2029
1891
|
specify "should support multiple joins" do
|
2030
|
-
@d.join_table(:inner, :b, :items_id=>:id).join_table(:left_outer, :c, :b_id => :b__id).sql.should ==
|
2031
|
-
'SELECT * FROM "items" INNER JOIN "b" ON ("b"."items_id" = "items"."id") LEFT OUTER JOIN "c" ON ("c"."b_id" = "b"."id")'
|
1892
|
+
@d.join_table(:inner, :b, :items_id=>:id).join_table(:left_outer, :c, :b_id => :b__id).sql.should == 'SELECT * FROM "items" INNER JOIN "b" ON ("b"."items_id" = "items"."id") LEFT OUTER JOIN "c" ON ("c"."b_id" = "b"."id")'
|
2032
1893
|
end
|
2033
1894
|
|
2034
1895
|
specify "should support arbitrary join types" do
|
2035
|
-
@d.join_table(:magic, :categories, :category_id=>:id).sql.should ==
|
2036
|
-
'SELECT * FROM "items" MAGIC JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1896
|
+
@d.join_table(:magic, :categories, :category_id=>:id).sql.should == 'SELECT * FROM "items" MAGIC JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
2037
1897
|
end
|
2038
1898
|
|
2039
1899
|
specify "should support many join methods" do
|
2040
|
-
@d.left_outer_join(:categories, :category_id=>:id).sql.should ==
|
2041
|
-
|
2042
|
-
@d.
|
2043
|
-
|
2044
|
-
@d.
|
2045
|
-
|
2046
|
-
@d.
|
2047
|
-
|
2048
|
-
@d.
|
2049
|
-
|
2050
|
-
@d.
|
2051
|
-
|
2052
|
-
@d.full_join(:categories, :category_id=>:id).sql.should ==
|
2053
|
-
'SELECT * FROM "items" FULL JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
2054
|
-
@d.natural_join(:categories).sql.should ==
|
2055
|
-
'SELECT * FROM "items" NATURAL JOIN "categories"'
|
2056
|
-
@d.natural_left_join(:categories).sql.should ==
|
2057
|
-
'SELECT * FROM "items" NATURAL LEFT JOIN "categories"'
|
2058
|
-
@d.natural_right_join(:categories).sql.should ==
|
2059
|
-
'SELECT * FROM "items" NATURAL RIGHT JOIN "categories"'
|
2060
|
-
@d.natural_full_join(:categories).sql.should ==
|
2061
|
-
'SELECT * FROM "items" NATURAL FULL JOIN "categories"'
|
2062
|
-
@d.cross_join(:categories).sql.should ==
|
2063
|
-
'SELECT * FROM "items" CROSS JOIN "categories"'
|
1900
|
+
@d.left_outer_join(:categories, :category_id=>:id).sql.should == 'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1901
|
+
@d.right_outer_join(:categories, :category_id=>:id).sql.should == 'SELECT * FROM "items" RIGHT OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1902
|
+
@d.full_outer_join(:categories, :category_id=>:id).sql.should == 'SELECT * FROM "items" FULL OUTER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1903
|
+
@d.inner_join(:categories, :category_id=>:id).sql.should == 'SELECT * FROM "items" INNER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1904
|
+
@d.left_join(:categories, :category_id=>:id).sql.should == 'SELECT * FROM "items" LEFT JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1905
|
+
@d.right_join(:categories, :category_id=>:id).sql.should == 'SELECT * FROM "items" RIGHT JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1906
|
+
@d.full_join(:categories, :category_id=>:id).sql.should == 'SELECT * FROM "items" FULL JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1907
|
+
@d.natural_join(:categories).sql.should == 'SELECT * FROM "items" NATURAL JOIN "categories"'
|
1908
|
+
@d.natural_left_join(:categories).sql.should == 'SELECT * FROM "items" NATURAL LEFT JOIN "categories"'
|
1909
|
+
@d.natural_right_join(:categories).sql.should == 'SELECT * FROM "items" NATURAL RIGHT JOIN "categories"'
|
1910
|
+
@d.natural_full_join(:categories).sql.should == 'SELECT * FROM "items" NATURAL FULL JOIN "categories"'
|
1911
|
+
@d.cross_join(:categories).sql.should == 'SELECT * FROM "items" CROSS JOIN "categories"'
|
2064
1912
|
end
|
2065
1913
|
|
2066
1914
|
specify "should raise an error if additional arguments are provided to join methods that don't take conditions" do
|
@@ -2080,95 +1928,68 @@ describe "Dataset#join_table" do
|
|
2080
1928
|
end
|
2081
1929
|
|
2082
1930
|
specify "should default to a plain join if nil is used for the type" do
|
2083
|
-
@d.join_table(nil, :categories, :category_id=>:id).sql.should ==
|
2084
|
-
'SELECT * FROM "items" JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1931
|
+
@d.join_table(nil, :categories, :category_id=>:id).sql.should == 'SELECT * FROM "items" JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
2085
1932
|
end
|
2086
1933
|
|
2087
1934
|
specify "should use an inner join for Dataset#join" do
|
2088
|
-
@d.join(:categories, :category_id=>:id).sql.should ==
|
2089
|
-
'SELECT * FROM "items" INNER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
1935
|
+
@d.join(:categories, :category_id=>:id).sql.should == 'SELECT * FROM "items" INNER JOIN "categories" ON ("categories"."category_id" = "items"."id")'
|
2090
1936
|
end
|
2091
1937
|
|
2092
1938
|
specify "should support aliased tables using the deprecated argument" do
|
2093
|
-
@d.from('stats').join('players', {:id => :player_id}, 'p').sql.should ==
|
2094
|
-
'SELECT * FROM "stats" INNER JOIN "players" AS "p" ON ("p"."id" = "stats"."player_id")'
|
1939
|
+
@d.from('stats').join('players', {:id => :player_id}, 'p').sql.should == 'SELECT * FROM "stats" INNER JOIN "players" AS "p" ON ("p"."id" = "stats"."player_id")'
|
2095
1940
|
end
|
2096
1941
|
|
2097
1942
|
specify "should support aliased tables using the :table_alias option" do
|
2098
|
-
@d.from('stats').join('players', {:id => :player_id}, :table_alias=>:p).sql.should ==
|
2099
|
-
'SELECT * FROM "stats" INNER JOIN "players" AS "p" ON ("p"."id" = "stats"."player_id")'
|
1943
|
+
@d.from('stats').join('players', {:id => :player_id}, :table_alias=>:p).sql.should == 'SELECT * FROM "stats" INNER JOIN "players" AS "p" ON ("p"."id" = "stats"."player_id")'
|
2100
1944
|
end
|
2101
1945
|
|
2102
1946
|
specify "should support aliased tables using an implicit alias" do
|
2103
|
-
@d.from('stats').join(:players.as(:p), {:id => :player_id}).sql.should ==
|
2104
|
-
'SELECT * FROM "stats" INNER JOIN "players" AS "p" ON ("p"."id" = "stats"."player_id")'
|
1947
|
+
@d.from('stats').join(:players.as(:p), {:id => :player_id}).sql.should == 'SELECT * FROM "stats" INNER JOIN "players" AS "p" ON ("p"."id" = "stats"."player_id")'
|
2105
1948
|
end
|
2106
1949
|
|
2107
1950
|
specify "should support using an alias for the FROM when doing the first join with unqualified condition columns" do
|
2108
|
-
|
2109
|
-
ds.quote_identifiers = true
|
2110
|
-
ds.join_table(:inner, :bar, :id => :bar_id).sql.should ==
|
2111
|
-
'SELECT * FROM "foo" AS "f" INNER JOIN "bar" ON ("bar"."id" = "f"."bar_id")'
|
1951
|
+
@d.from(:foo=>:f).join_table(:inner, :bar, :id => :bar_id).sql.should == 'SELECT * FROM "foo" AS "f" INNER JOIN "bar" ON ("bar"."id" = "f"."bar_id")'
|
2112
1952
|
end
|
2113
1953
|
|
2114
1954
|
specify "should support implicit schemas in from table symbols" do
|
2115
|
-
@d.from(:s__t).join(:u__v, {:id => :player_id}).sql.should ==
|
2116
|
-
'SELECT * FROM "s"."t" INNER JOIN "u"."v" ON ("u"."v"."id" = "s"."t"."player_id")'
|
1955
|
+
@d.from(:s__t).join(:u__v, {:id => :player_id}).sql.should == 'SELECT * FROM "s"."t" INNER JOIN "u"."v" ON ("u"."v"."id" = "s"."t"."player_id")'
|
2117
1956
|
end
|
2118
1957
|
|
2119
1958
|
specify "should support implicit aliases in from table symbols" do
|
2120
|
-
@d.from(:t___z).join(:v___y, {:id => :player_id}).sql.should ==
|
2121
|
-
|
2122
|
-
@d.from(:s__t___z).join(:u__v___y, {:id => :player_id}).sql.should ==
|
2123
|
-
'SELECT * FROM "s"."t" AS "z" INNER JOIN "u"."v" AS "y" ON ("y"."id" = "z"."player_id")'
|
1959
|
+
@d.from(:t___z).join(:v___y, {:id => :player_id}).sql.should == 'SELECT * FROM "t" AS "z" INNER JOIN "v" AS "y" ON ("y"."id" = "z"."player_id")'
|
1960
|
+
@d.from(:s__t___z).join(:u__v___y, {:id => :player_id}).sql.should == 'SELECT * FROM "s"."t" AS "z" INNER JOIN "u"."v" AS "y" ON ("y"."id" = "z"."player_id")'
|
2124
1961
|
end
|
2125
1962
|
|
2126
1963
|
specify "should support AliasedExpressions" do
|
2127
|
-
@d.from(:s.as(:t)).join(:u.as(:v), {:id => :player_id}).sql.should ==
|
2128
|
-
'SELECT * FROM "s" AS "t" INNER JOIN "u" AS "v" ON ("v"."id" = "t"."player_id")'
|
1964
|
+
@d.from(:s.as(:t)).join(:u.as(:v), {:id => :player_id}).sql.should == 'SELECT * FROM "s" AS "t" INNER JOIN "u" AS "v" ON ("v"."id" = "t"."player_id")'
|
2129
1965
|
end
|
2130
1966
|
|
2131
1967
|
specify "should support the :implicit_qualifier option" do
|
2132
|
-
@d.from('stats').join('players', {:id => :player_id}, :implicit_qualifier=>:p).sql.should ==
|
2133
|
-
'SELECT * FROM "stats" INNER JOIN "players" ON ("players"."id" = "p"."player_id")'
|
1968
|
+
@d.from('stats').join('players', {:id => :player_id}, :implicit_qualifier=>:p).sql.should == 'SELECT * FROM "stats" INNER JOIN "players" ON ("players"."id" = "p"."player_id")'
|
2134
1969
|
end
|
2135
1970
|
|
2136
1971
|
specify "should allow for arbitrary conditions in the JOIN clause" do
|
2137
|
-
@d.join_table(:left_outer, :categories, :status => 0).sql.should ==
|
2138
|
-
|
2139
|
-
@d.join_table(:left_outer, :categories, :
|
2140
|
-
|
2141
|
-
@d.join_table(:left_outer, :categories, :timestamp => "CURRENT_TIMESTAMP".lit).sql.should ==
|
2142
|
-
'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."timestamp" = CURRENT_TIMESTAMP)'
|
2143
|
-
@d.join_table(:left_outer, :categories, :status => [1, 2, 3]).sql.should ==
|
2144
|
-
'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."status" IN (1, 2, 3))'
|
1972
|
+
@d.join_table(:left_outer, :categories, :status => 0).sql.should == 'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."status" = 0)'
|
1973
|
+
@d.join_table(:left_outer, :categories, :categorizable_type => "Post").sql.should == 'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."categorizable_type" = \'Post\')'
|
1974
|
+
@d.join_table(:left_outer, :categories, :timestamp => "CURRENT_TIMESTAMP".lit).sql.should == 'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."timestamp" = CURRENT_TIMESTAMP)'
|
1975
|
+
@d.join_table(:left_outer, :categories, :status => [1, 2, 3]).sql.should == 'SELECT * FROM "items" LEFT OUTER JOIN "categories" ON ("categories"."status" IN (1, 2, 3))'
|
2145
1976
|
end
|
2146
1977
|
|
2147
1978
|
specify "should raise error for a table without a source" do
|
2148
|
-
proc {Sequel::Dataset.new(nil).join('players', :id => :player_id)}.
|
2149
|
-
should raise_error(Sequel::Error)
|
1979
|
+
proc {Sequel::Dataset.new(nil).join('players', :id => :player_id)}.should raise_error(Sequel::Error)
|
2150
1980
|
end
|
2151
1981
|
|
2152
1982
|
specify "should support joining datasets" do
|
2153
1983
|
ds = Sequel::Dataset.new(nil).from(:categories)
|
2154
|
-
|
2155
|
-
@d.join_table(:left_outer, ds, :item_id => :id).sql.should ==
|
2156
|
-
'SELECT * FROM "items" LEFT OUTER JOIN (SELECT * FROM categories) AS "t1" ON ("t1"."item_id" = "items"."id")'
|
2157
|
-
|
1984
|
+
@d.join_table(:left_outer, ds, :item_id => :id).sql.should == 'SELECT * FROM "items" LEFT OUTER JOIN (SELECT * FROM categories) AS "t1" ON ("t1"."item_id" = "items"."id")'
|
2158
1985
|
ds.filter!(:active => true)
|
2159
|
-
|
2160
|
-
@d.join_table(:left_outer, ds, :item_id => :id).sql.should ==
|
2161
|
-
'SELECT * FROM "items" LEFT OUTER JOIN (SELECT * FROM categories WHERE (active IS TRUE)) AS "t1" ON ("t1"."item_id" = "items"."id")'
|
2162
|
-
|
2163
|
-
@d.from_self.join_table(:left_outer, ds, :item_id => :id).sql.should ==
|
2164
|
-
'SELECT * FROM (SELECT * FROM "items") AS "t1" LEFT OUTER JOIN (SELECT * FROM categories WHERE (active IS TRUE)) AS "t2" ON ("t2"."item_id" = "t1"."id")'
|
1986
|
+
@d.join_table(:left_outer, ds, :item_id => :id).sql.should == 'SELECT * FROM "items" LEFT OUTER JOIN (SELECT * FROM categories WHERE (active IS TRUE)) AS "t1" ON ("t1"."item_id" = "items"."id")'
|
1987
|
+
@d.from_self.join_table(:left_outer, ds, :item_id => :id).sql.should == 'SELECT * FROM (SELECT * FROM "items") AS "t1" LEFT OUTER JOIN (SELECT * FROM categories WHERE (active IS TRUE)) AS "t2" ON ("t2"."item_id" = "t1"."id")'
|
2165
1988
|
end
|
2166
1989
|
|
2167
1990
|
specify "should support joining datasets and aliasing the join" do
|
2168
1991
|
ds = Sequel::Dataset.new(nil).from(:categories)
|
2169
|
-
|
2170
|
-
@d.join_table(:left_outer, ds, {:ds__item_id => :id}, :ds).sql.should ==
|
2171
|
-
'SELECT * FROM "items" LEFT OUTER JOIN (SELECT * FROM categories) AS "ds" ON ("ds"."item_id" = "items"."id")'
|
1992
|
+
@d.join_table(:left_outer, ds, {:ds__item_id => :id}, :ds).sql.should == 'SELECT * FROM "items" LEFT OUTER JOIN (SELECT * FROM categories) AS "ds" ON ("ds"."item_id" = "items"."id")'
|
2172
1993
|
end
|
2173
1994
|
|
2174
1995
|
specify "should support joining multiple datasets" do
|
@@ -2185,40 +2006,30 @@ describe "Dataset#join_table" do
|
|
2185
2006
|
specify "should support joining objects that respond to :table_name" do
|
2186
2007
|
ds = Object.new
|
2187
2008
|
def ds.table_name; :categories end
|
2188
|
-
|
2189
|
-
@d.join(ds, :item_id => :id).sql.should ==
|
2190
|
-
'SELECT * FROM "items" INNER JOIN "categories" ON ("categories"."item_id" = "items"."id")'
|
2009
|
+
@d.join(ds, :item_id => :id).sql.should == 'SELECT * FROM "items" INNER JOIN "categories" ON ("categories"."item_id" = "items"."id")'
|
2191
2010
|
end
|
2192
2011
|
|
2193
|
-
specify "should support using
|
2194
|
-
@d.join(:categories,
|
2195
|
-
'SELECT * FROM "items" INNER JOIN "categories" AS "c" ON (c.item_id = items.id)'
|
2012
|
+
specify "should support using an SQL String as the join condition" do
|
2013
|
+
@d.join(:categories, "c.item_id = items.id", :c).sql.should == 'SELECT * FROM "items" INNER JOIN "categories" AS "c" ON (c.item_id = items.id)'
|
2196
2014
|
end
|
2197
2015
|
|
2198
2016
|
specify "should support using a boolean column as the join condition" do
|
2199
|
-
@d.join(:categories, :active).sql.should ==
|
2200
|
-
'SELECT * FROM "items" INNER JOIN "categories" ON "active"'
|
2017
|
+
@d.join(:categories, :active).sql.should == 'SELECT * FROM "items" INNER JOIN "categories" ON "active"'
|
2201
2018
|
end
|
2202
2019
|
|
2203
2020
|
specify "should support using an expression as the join condition" do
|
2204
|
-
@d.join(:categories, :number.sql_number > 10).sql.should ==
|
2205
|
-
'SELECT * FROM "items" INNER JOIN "categories" ON ("number" > 10)'
|
2021
|
+
@d.join(:categories, :number.sql_number > 10).sql.should == 'SELECT * FROM "items" INNER JOIN "categories" ON ("number" > 10)'
|
2206
2022
|
end
|
2207
2023
|
|
2208
|
-
specify "should support natural and cross joins
|
2209
|
-
@d.join_table(:natural, :categories).sql.should ==
|
2210
|
-
|
2211
|
-
@d.join_table(:
|
2212
|
-
'SELECT * FROM "items" CROSS JOIN "categories"'
|
2213
|
-
@d.join_table(:natural, :categories, nil, :c).sql.should ==
|
2214
|
-
'SELECT * FROM "items" NATURAL JOIN "categories" AS "c"'
|
2024
|
+
specify "should support natural and cross joins" do
|
2025
|
+
@d.join_table(:natural, :categories).sql.should == 'SELECT * FROM "items" NATURAL JOIN "categories"'
|
2026
|
+
@d.join_table(:cross, :categories, nil).sql.should == 'SELECT * FROM "items" CROSS JOIN "categories"'
|
2027
|
+
@d.join_table(:natural, :categories, nil, :c).sql.should == 'SELECT * FROM "items" NATURAL JOIN "categories" AS "c"'
|
2215
2028
|
end
|
2216
2029
|
|
2217
2030
|
specify "should support joins with a USING clause if an array of symbols is used" do
|
2218
|
-
@d.join(:categories, [:id]).sql.should ==
|
2219
|
-
|
2220
|
-
@d.join(:categories, [:id1, :id2]).sql.should ==
|
2221
|
-
'SELECT * FROM "items" INNER JOIN "categories" USING ("id1", "id2")'
|
2031
|
+
@d.join(:categories, [:id]).sql.should == 'SELECT * FROM "items" INNER JOIN "categories" USING ("id")'
|
2032
|
+
@d.join(:categories, [:id1, :id2]).sql.should == 'SELECT * FROM "items" INNER JOIN "categories" USING ("id1", "id2")'
|
2222
2033
|
end
|
2223
2034
|
|
2224
2035
|
specify "should emulate JOIN USING (poorly) if the dataset doesn't support it" do
|
@@ -2286,22 +2097,17 @@ describe "Dataset#join_table" do
|
|
2286
2097
|
end
|
2287
2098
|
|
2288
2099
|
specify "should use the block result as the only condition if no condition is given" do
|
2289
|
-
@d.join(:categories){|j,lj,js| {:b.qualify(j)=>:c.qualify(lj)}}.sql.should ==
|
2290
|
-
|
2291
|
-
@d.join(:categories){|j,lj,js| :b.qualify(j) > :c.qualify(lj)}.sql.should ==
|
2292
|
-
'SELECT * FROM "items" INNER JOIN "categories" ON ("categories"."b" > "items"."c")'
|
2100
|
+
@d.join(:categories){|j,lj,js| {:b.qualify(j)=>:c.qualify(lj)}}.sql.should == 'SELECT * FROM "items" INNER JOIN "categories" ON ("categories"."b" = "items"."c")'
|
2101
|
+
@d.join(:categories){|j,lj,js| :b.qualify(j) > :c.qualify(lj)}.sql.should == 'SELECT * FROM "items" INNER JOIN "categories" ON ("categories"."b" > "items"."c")'
|
2293
2102
|
end
|
2294
2103
|
|
2295
2104
|
specify "should combine the block conditions and argument conditions if both given" do
|
2296
|
-
@d.join(:categories, :a=>:d){|j,lj,js| {:b.qualify(j)=>:c.qualify(lj)}}.sql.should ==
|
2297
|
-
|
2298
|
-
@d.join(:categories, :a=>:d){|j,lj,js| :b.qualify(j) > :c.qualify(lj)}.sql.should ==
|
2299
|
-
'SELECT * FROM "items" INNER JOIN "categories" ON (("categories"."a" = "items"."d") AND ("categories"."b" > "items"."c"))'
|
2105
|
+
@d.join(:categories, :a=>:d){|j,lj,js| {:b.qualify(j)=>:c.qualify(lj)}}.sql.should == 'SELECT * FROM "items" INNER JOIN "categories" ON (("categories"."a" = "items"."d") AND ("categories"."b" = "items"."c"))'
|
2106
|
+
@d.join(:categories, :a=>:d){|j,lj,js| :b.qualify(j) > :c.qualify(lj)}.sql.should == 'SELECT * FROM "items" INNER JOIN "categories" ON (("categories"."a" = "items"."d") AND ("categories"."b" > "items"."c"))'
|
2300
2107
|
end
|
2301
2108
|
|
2302
2109
|
specify "should prefer explicit aliases over implicit" do
|
2303
|
-
@d.from(:items___i).join(:categories___c, {:category_id => :id}, {:table_alias=>:c2, :implicit_qualifier=>:i2}).sql.should ==
|
2304
|
-
'SELECT * FROM "items" AS "i" INNER JOIN "categories" AS "c2" ON ("c2"."category_id" = "i2"."id")'
|
2110
|
+
@d.from(:items___i).join(:categories___c, {:category_id => :id}, {:table_alias=>:c2, :implicit_qualifier=>:i2}).sql.should == 'SELECT * FROM "items" AS "i" INNER JOIN "categories" AS "c2" ON ("c2"."category_id" = "i2"."id")'
|
2305
2111
|
@d.from(:items.as(:i)).join(:categories.as(:c), {:category_id => :id}, {:table_alias=>:c2, :implicit_qualifier=>:i2}).sql.should ==
|
2306
2112
|
'SELECT * FROM "items" AS "i" INNER JOIN "categories" AS "c2" ON ("c2"."category_id" = "i2"."id")'
|
2307
2113
|
end
|
@@ -2320,81 +2126,48 @@ describe "Dataset#join_table" do
|
|
2320
2126
|
end
|
2321
2127
|
|
2322
2128
|
describe "Dataset#[]=" do
|
2323
|
-
before do
|
2324
|
-
c = Class.new(Sequel::Dataset) do
|
2325
|
-
def last_sql
|
2326
|
-
@@last_sql
|
2327
|
-
end
|
2328
|
-
|
2329
|
-
def update(*args)
|
2330
|
-
@@last_sql = update_sql(*args)
|
2331
|
-
end
|
2332
|
-
end
|
2333
|
-
|
2334
|
-
@d = c.new(nil).from(:items)
|
2335
|
-
end
|
2336
|
-
|
2337
2129
|
specify "should perform an update on the specified filter" do
|
2338
|
-
|
2339
|
-
|
2130
|
+
db = Sequel.mock
|
2131
|
+
ds = db[:items]
|
2132
|
+
ds[:a => 1] = {:x => 3}
|
2133
|
+
db.sqls.should == ['UPDATE items SET x = 3 WHERE (a = 1)']
|
2340
2134
|
end
|
2341
2135
|
end
|
2342
2136
|
|
2343
2137
|
describe "Dataset#set" do
|
2344
|
-
before do
|
2345
|
-
c = Class.new(Sequel::Dataset) do
|
2346
|
-
def last_sql
|
2347
|
-
@@last_sql
|
2348
|
-
end
|
2349
|
-
|
2350
|
-
def update(*args, &block)
|
2351
|
-
@@last_sql = update_sql(*args, &block)
|
2352
|
-
end
|
2353
|
-
end
|
2354
|
-
|
2355
|
-
@d = c.new(nil).from(:items)
|
2356
|
-
end
|
2357
|
-
|
2358
2138
|
specify "should act as alias to #update" do
|
2359
|
-
|
2360
|
-
|
2139
|
+
db = Sequel.mock
|
2140
|
+
ds = db[:items]
|
2141
|
+
ds.set({:x => 3})
|
2142
|
+
db.sqls.should == ['UPDATE items SET x = 3']
|
2361
2143
|
end
|
2362
2144
|
end
|
2363
2145
|
|
2364
|
-
|
2365
2146
|
describe "Dataset#insert_multiple" do
|
2366
2147
|
before do
|
2367
|
-
|
2368
|
-
|
2369
|
-
def insert(arg)
|
2370
|
-
@inserts ||= []
|
2371
|
-
@inserts << arg
|
2372
|
-
end
|
2373
|
-
end
|
2374
|
-
|
2375
|
-
@d = c.new(nil)
|
2148
|
+
@db = Sequel.mock
|
2149
|
+
@ds = @db[:items]
|
2376
2150
|
end
|
2377
2151
|
|
2378
2152
|
specify "should insert all items in the supplied array" do
|
2379
|
-
@
|
2380
|
-
@
|
2153
|
+
@ds.insert_multiple(['aa', 5, 3, {:a => 2}])
|
2154
|
+
@db.sqls.should == ["INSERT INTO items VALUES ('aa')",
|
2155
|
+
"INSERT INTO items VALUES (5)",
|
2156
|
+
"INSERT INTO items VALUES (3)",
|
2157
|
+
"INSERT INTO items (a) VALUES (2)"]
|
2381
2158
|
end
|
2382
2159
|
|
2383
2160
|
specify "should pass array items through the supplied block if given" do
|
2384
|
-
|
2385
|
-
@
|
2386
|
-
|
2161
|
+
@ds.insert_multiple(["inevitable", "hello", "the ticking clock"]){|i| i.gsub('l', 'r')}
|
2162
|
+
@db.sqls.should == ["INSERT INTO items VALUES ('inevitabre')",
|
2163
|
+
"INSERT INTO items VALUES ('herro')",
|
2164
|
+
"INSERT INTO items VALUES ('the ticking crock')"]
|
2387
2165
|
end
|
2388
2166
|
end
|
2389
2167
|
|
2390
2168
|
describe "Dataset aggregate methods" do
|
2391
2169
|
before do
|
2392
|
-
|
2393
|
-
def fetch_rows(sql)
|
2394
|
-
yield({1 => sql})
|
2395
|
-
end
|
2396
|
-
end
|
2397
|
-
@d = c.new(nil).from(:test)
|
2170
|
+
@d = Sequel.mock(:fetch=>proc{|s| {1=>s}})[:test]
|
2398
2171
|
end
|
2399
2172
|
|
2400
2173
|
specify "should include min" do
|
@@ -2428,116 +2201,88 @@ end
|
|
2428
2201
|
|
2429
2202
|
describe "Dataset#range" do
|
2430
2203
|
before do
|
2431
|
-
|
2432
|
-
|
2433
|
-
|
2434
|
-
def last_sql; self.class.send(:class_variable_get, :@@sql); end
|
2435
|
-
|
2436
|
-
def fetch_rows(sql)
|
2437
|
-
self.class.send(:class_variable_set, :@@sql, sql)
|
2438
|
-
yield(:v1 => 1, :v2 => 10)
|
2439
|
-
end
|
2440
|
-
end
|
2441
|
-
@d = c.new(nil).from(:test)
|
2204
|
+
@db = Sequel.mock(:fetch=>{:v1 => 1, :v2 => 10})
|
2205
|
+
@ds = @db[:test]
|
2442
2206
|
end
|
2443
2207
|
|
2444
2208
|
specify "should generate a correct SQL statement" do
|
2445
|
-
@
|
2446
|
-
@
|
2209
|
+
@ds.range(:stamp)
|
2210
|
+
@db.sqls.should == ["SELECT min(stamp) AS v1, max(stamp) AS v2 FROM test LIMIT 1"]
|
2447
2211
|
|
2448
|
-
@
|
2449
|
-
@
|
2212
|
+
@ds.filter(:price.sql_number > 100).range(:stamp)
|
2213
|
+
@db.sqls.should == ["SELECT min(stamp) AS v1, max(stamp) AS v2 FROM test WHERE (price > 100) LIMIT 1"]
|
2450
2214
|
end
|
2451
2215
|
|
2452
2216
|
specify "should return a range object" do
|
2453
|
-
@
|
2217
|
+
@ds.range(:tryme).should == (1..10)
|
2454
2218
|
end
|
2455
2219
|
|
2456
2220
|
specify "should use a subselect for the same conditions as count" do
|
2457
|
-
@
|
2458
|
-
@
|
2221
|
+
@ds.order(:stamp).limit(5).range(:stamp).should == (1..10)
|
2222
|
+
@db.sqls.should == ['SELECT min(stamp) AS v1, max(stamp) AS v2 FROM (SELECT * FROM test ORDER BY stamp LIMIT 5) AS t1 LIMIT 1']
|
2459
2223
|
end
|
2460
2224
|
end
|
2461
2225
|
|
2462
2226
|
describe "Dataset#interval" do
|
2463
2227
|
before do
|
2464
|
-
|
2465
|
-
|
2466
|
-
|
2467
|
-
def last_sql; self.class.send(:class_variable_get, :@@sql); end
|
2468
|
-
|
2469
|
-
def fetch_rows(sql)
|
2470
|
-
self.class.send(:class_variable_set, :@@sql, sql)
|
2471
|
-
yield(:v => 1234)
|
2472
|
-
end
|
2473
|
-
end
|
2474
|
-
@d = c.new(nil).from(:test)
|
2228
|
+
@db = Sequel.mock(:fetch=>{:v => 1234})
|
2229
|
+
@ds = @db[:test]
|
2475
2230
|
end
|
2476
2231
|
|
2477
|
-
specify "should generate
|
2478
|
-
@
|
2479
|
-
@
|
2232
|
+
specify "should generate the correct SQL statement" do
|
2233
|
+
@ds.interval(:stamp)
|
2234
|
+
@db.sqls.should == ["SELECT (max(stamp) - min(stamp)) FROM test LIMIT 1"]
|
2480
2235
|
|
2481
|
-
@
|
2482
|
-
@
|
2483
|
-
end
|
2484
|
-
|
2485
|
-
specify "should return an integer" do
|
2486
|
-
@d.interval(:tryme).should == 1234
|
2236
|
+
@ds.filter(:price.sql_number > 100).interval(:stamp)
|
2237
|
+
@db.sqls.should == ["SELECT (max(stamp) - min(stamp)) FROM test WHERE (price > 100) LIMIT 1"]
|
2487
2238
|
end
|
2488
2239
|
|
2489
2240
|
specify "should use a subselect for the same conditions as count" do
|
2490
|
-
@
|
2491
|
-
@
|
2241
|
+
@ds.order(:stamp).limit(5).interval(:stamp).should == 1234
|
2242
|
+
@db.sqls.should == ['SELECT (max(stamp) - min(stamp)) FROM (SELECT * FROM test ORDER BY stamp LIMIT 5) AS t1 LIMIT 1']
|
2492
2243
|
end
|
2493
2244
|
end
|
2494
2245
|
|
2495
2246
|
describe "Dataset #first and #last" do
|
2496
2247
|
before do
|
2497
|
-
@
|
2498
|
-
|
2499
|
-
s = select_sql
|
2500
|
-
x = [:a,1,:b,2,s]
|
2501
|
-
i = /LIMIT (\d+)/.match(s)[1].to_i.times{yield x}
|
2502
|
-
end
|
2503
|
-
end
|
2504
|
-
@d = @c.new(nil).from(:test)
|
2248
|
+
@db = Sequel.mock(:fetch=>proc{|s| {:s=>s}})
|
2249
|
+
@d = @db[:test]
|
2505
2250
|
end
|
2506
2251
|
|
2507
2252
|
specify "should return a single record if no argument is given" do
|
2508
|
-
@d.order(:a).first.should ==
|
2509
|
-
@d.order(:a).last.should ==
|
2253
|
+
@d.order(:a).first.should == {:s=>'SELECT * FROM test ORDER BY a LIMIT 1'}
|
2254
|
+
@d.order(:a).last.should == {:s=>'SELECT * FROM test ORDER BY a DESC LIMIT 1'}
|
2510
2255
|
end
|
2511
2256
|
|
2512
2257
|
specify "should return the first/last matching record if argument is not an Integer" do
|
2513
|
-
@d.order(:a).first(:z => 26).should ==
|
2514
|
-
@d.order(:a).first('z = ?', 15).should ==
|
2515
|
-
@d.order(:a).last(:z => 26).should ==
|
2516
|
-
@d.order(:a).last('z = ?', 15).should ==
|
2258
|
+
@d.order(:a).first(:z => 26).should == {:s=>'SELECT * FROM test WHERE (z = 26) ORDER BY a LIMIT 1'}
|
2259
|
+
@d.order(:a).first('z = ?', 15).should == {:s=>'SELECT * FROM test WHERE (z = 15) ORDER BY a LIMIT 1'}
|
2260
|
+
@d.order(:a).last(:z => 26).should == {:s=>'SELECT * FROM test WHERE (z = 26) ORDER BY a DESC LIMIT 1'}
|
2261
|
+
@d.order(:a).last('z = ?', 15).should == {:s=>'SELECT * FROM test WHERE (z = 15) ORDER BY a DESC LIMIT 1'}
|
2517
2262
|
end
|
2518
2263
|
|
2519
2264
|
specify "should set the limit and return an array of records if the given number is > 1" do
|
2520
2265
|
i = rand(10) + 10
|
2521
|
-
r = @d.order(:a).first(i).should == [
|
2266
|
+
r = @d.order(:a).first(i).should == [{:s=>"SELECT * FROM test ORDER BY a LIMIT #{i}"}]
|
2522
2267
|
i = rand(10) + 10
|
2523
|
-
r = @d.order(:a).last(i).should == [
|
2268
|
+
r = @d.order(:a).last(i).should == [{:s=>"SELECT * FROM test ORDER BY a DESC LIMIT #{i}"}]
|
2524
2269
|
end
|
2525
2270
|
|
2526
2271
|
specify "should return the first matching record if a block is given without an argument" do
|
2527
|
-
@d.first{:z.sql_number > 26}.should ==
|
2528
|
-
@d.order(:name).last{:z.sql_number > 26}.should ==
|
2272
|
+
@d.first{:z.sql_number > 26}.should == {:s=>'SELECT * FROM test WHERE (z > 26) LIMIT 1'}
|
2273
|
+
@d.order(:name).last{:z.sql_number > 26}.should == {:s=>'SELECT * FROM test WHERE (z > 26) ORDER BY name DESC LIMIT 1'}
|
2529
2274
|
end
|
2530
2275
|
|
2531
2276
|
specify "should combine block and standard argument filters if argument is not an Integer" do
|
2532
|
-
@d.first(:y=>25){:z.sql_number > 26}.should ==
|
2533
|
-
@d.order(:name).last('y = ?', 16){:z.sql_number > 26}.should ==
|
2277
|
+
@d.first(:y=>25){:z.sql_number > 26}.should == {:s=>'SELECT * FROM test WHERE ((z > 26) AND (y = 25)) LIMIT 1'}
|
2278
|
+
@d.order(:name).last('y = ?', 16){:z.sql_number > 26}.should == {:s=>'SELECT * FROM test WHERE ((z > 26) AND (y = 16)) ORDER BY name DESC LIMIT 1'}
|
2534
2279
|
end
|
2535
2280
|
|
2536
2281
|
specify "should filter and return an array of records if an Integer argument is provided and a block is given" do
|
2537
2282
|
i = rand(10) + 10
|
2538
|
-
r = @d.order(:a).first(i){:z.sql_number > 26}.should == [
|
2283
|
+
r = @d.order(:a).first(i){:z.sql_number > 26}.should == [{:s=>"SELECT * FROM test WHERE (z > 26) ORDER BY a LIMIT #{i}"}]
|
2539
2284
|
i = rand(10) + 10
|
2540
|
-
r = @d.order(:a).last(i){:z.sql_number > 26}.should == [
|
2285
|
+
r = @d.order(:a).last(i){:z.sql_number > 26}.should == [{:s=>"SELECT * FROM test WHERE (z > 26) ORDER BY a DESC LIMIT #{i}"}]
|
2541
2286
|
end
|
2542
2287
|
|
2543
2288
|
specify "#last should raise if no order is given" do
|
@@ -2548,10 +2293,10 @@ describe "Dataset #first and #last" do
|
|
2548
2293
|
end
|
2549
2294
|
|
2550
2295
|
specify "#last should invert the order" do
|
2551
|
-
@d.order(:a).last.
|
2552
|
-
@d.order(:b.desc).last.
|
2553
|
-
@d.order(:c, :d).last.
|
2554
|
-
@d.order(:e.desc, :f).last.
|
2296
|
+
@d.order(:a).last.should == {:s=>'SELECT * FROM test ORDER BY a DESC LIMIT 1'}
|
2297
|
+
@d.order(:b.desc).last.should == {:s=>'SELECT * FROM test ORDER BY b ASC LIMIT 1'}
|
2298
|
+
@d.order(:c, :d).last.should == {:s=>'SELECT * FROM test ORDER BY c DESC, d DESC LIMIT 1'}
|
2299
|
+
@d.order(:e.desc, :f).last.should == {:s=>'SELECT * FROM test ORDER BY e ASC, f DESC LIMIT 1'}
|
2555
2300
|
end
|
2556
2301
|
end
|
2557
2302
|
|
@@ -2562,55 +2307,37 @@ describe "Dataset compound operations" do
|
|
2562
2307
|
end
|
2563
2308
|
|
2564
2309
|
specify "should support UNION and UNION ALL" do
|
2565
|
-
@a.union(@b).sql.should ==
|
2566
|
-
|
2567
|
-
@b.union(@a, true).sql.should ==
|
2568
|
-
"SELECT * FROM (SELECT * FROM b WHERE (z = 2) UNION ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2569
|
-
@b.union(@a, :all=>true).sql.should == \
|
2570
|
-
"SELECT * FROM (SELECT * FROM b WHERE (z = 2) UNION ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2310
|
+
@a.union(@b).sql.should == "SELECT * FROM (SELECT * FROM a WHERE (z = 1) UNION SELECT * FROM b WHERE (z = 2)) AS t1"
|
2311
|
+
@b.union(@a, true).sql.should == "SELECT * FROM (SELECT * FROM b WHERE (z = 2) UNION ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2312
|
+
@b.union(@a, :all=>true).sql.should == "SELECT * FROM (SELECT * FROM b WHERE (z = 2) UNION ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2571
2313
|
end
|
2572
2314
|
|
2573
2315
|
specify "should support INTERSECT and INTERSECT ALL" do
|
2574
|
-
@a.intersect(@b).sql.should ==
|
2575
|
-
|
2576
|
-
@b.intersect(@a, true).sql.should ==
|
2577
|
-
"SELECT * FROM (SELECT * FROM b WHERE (z = 2) INTERSECT ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2578
|
-
@b.intersect(@a, :all=>true).sql.should == \
|
2579
|
-
"SELECT * FROM (SELECT * FROM b WHERE (z = 2) INTERSECT ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2316
|
+
@a.intersect(@b).sql.should == "SELECT * FROM (SELECT * FROM a WHERE (z = 1) INTERSECT SELECT * FROM b WHERE (z = 2)) AS t1"
|
2317
|
+
@b.intersect(@a, true).sql.should == "SELECT * FROM (SELECT * FROM b WHERE (z = 2) INTERSECT ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2318
|
+
@b.intersect(@a, :all=>true).sql.should == "SELECT * FROM (SELECT * FROM b WHERE (z = 2) INTERSECT ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2580
2319
|
end
|
2581
2320
|
|
2582
2321
|
specify "should support EXCEPT and EXCEPT ALL" do
|
2583
|
-
@a.except(@b).sql.should ==
|
2584
|
-
|
2585
|
-
@b.except(@a, true).sql.should ==
|
2586
|
-
"SELECT * FROM (SELECT * FROM b WHERE (z = 2) EXCEPT ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2587
|
-
@b.except(@a, :all=>true).sql.should == \
|
2588
|
-
"SELECT * FROM (SELECT * FROM b WHERE (z = 2) EXCEPT ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2322
|
+
@a.except(@b).sql.should == "SELECT * FROM (SELECT * FROM a WHERE (z = 1) EXCEPT SELECT * FROM b WHERE (z = 2)) AS t1"
|
2323
|
+
@b.except(@a, true).sql.should == "SELECT * FROM (SELECT * FROM b WHERE (z = 2) EXCEPT ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2324
|
+
@b.except(@a, :all=>true).sql.should == "SELECT * FROM (SELECT * FROM b WHERE (z = 2) EXCEPT ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2589
2325
|
end
|
2590
2326
|
|
2591
2327
|
specify "should support :alias option for specifying identifier" do
|
2592
|
-
@a.union(@b, :alias=>:xx).sql.should ==
|
2593
|
-
|
2594
|
-
@a.
|
2595
|
-
"SELECT * FROM (SELECT * FROM a WHERE (z = 1) INTERSECT SELECT * FROM b WHERE (z = 2)) AS xx"
|
2596
|
-
@a.except(@b, :alias=>:xx).sql.should == \
|
2597
|
-
"SELECT * FROM (SELECT * FROM a WHERE (z = 1) EXCEPT SELECT * FROM b WHERE (z = 2)) AS xx"
|
2328
|
+
@a.union(@b, :alias=>:xx).sql.should == "SELECT * FROM (SELECT * FROM a WHERE (z = 1) UNION SELECT * FROM b WHERE (z = 2)) AS xx"
|
2329
|
+
@a.intersect(@b, :alias=>:xx).sql.should == "SELECT * FROM (SELECT * FROM a WHERE (z = 1) INTERSECT SELECT * FROM b WHERE (z = 2)) AS xx"
|
2330
|
+
@a.except(@b, :alias=>:xx).sql.should == "SELECT * FROM (SELECT * FROM a WHERE (z = 1) EXCEPT SELECT * FROM b WHERE (z = 2)) AS xx"
|
2598
2331
|
end
|
2599
2332
|
|
2600
2333
|
specify "should support :from_self=>false option to not wrap the compound in a SELECT * FROM (...)" do
|
2601
|
-
@b.union(@a, :from_self=>false).sql.should ==
|
2602
|
-
|
2603
|
-
@b.
|
2604
|
-
"SELECT * FROM b WHERE (z = 2) INTERSECT SELECT * FROM a WHERE (z = 1)"
|
2605
|
-
@b.except(@a, :from_self=>false).sql.should == \
|
2606
|
-
"SELECT * FROM b WHERE (z = 2) EXCEPT SELECT * FROM a WHERE (z = 1)"
|
2334
|
+
@b.union(@a, :from_self=>false).sql.should == "SELECT * FROM b WHERE (z = 2) UNION SELECT * FROM a WHERE (z = 1)"
|
2335
|
+
@b.intersect(@a, :from_self=>false).sql.should == "SELECT * FROM b WHERE (z = 2) INTERSECT SELECT * FROM a WHERE (z = 1)"
|
2336
|
+
@b.except(@a, :from_self=>false).sql.should == "SELECT * FROM b WHERE (z = 2) EXCEPT SELECT * FROM a WHERE (z = 1)"
|
2607
2337
|
|
2608
|
-
@b.union(@a, :from_self=>false, :all=>true).sql.should ==
|
2609
|
-
|
2610
|
-
@b.
|
2611
|
-
"SELECT * FROM b WHERE (z = 2) INTERSECT ALL SELECT * FROM a WHERE (z = 1)"
|
2612
|
-
@b.except(@a, :from_self=>false, :all=>true).sql.should == \
|
2613
|
-
"SELECT * FROM b WHERE (z = 2) EXCEPT ALL SELECT * FROM a WHERE (z = 1)"
|
2338
|
+
@b.union(@a, :from_self=>false, :all=>true).sql.should == "SELECT * FROM b WHERE (z = 2) UNION ALL SELECT * FROM a WHERE (z = 1)"
|
2339
|
+
@b.intersect(@a, :from_self=>false, :all=>true).sql.should == "SELECT * FROM b WHERE (z = 2) INTERSECT ALL SELECT * FROM a WHERE (z = 1)"
|
2340
|
+
@b.except(@a, :from_self=>false, :all=>true).sql.should == "SELECT * FROM b WHERE (z = 2) EXCEPT ALL SELECT * FROM a WHERE (z = 1)"
|
2614
2341
|
end
|
2615
2342
|
|
2616
2343
|
specify "should raise an InvalidOperation if INTERSECT or EXCEPT is used and they are not supported" do
|
@@ -2630,141 +2357,105 @@ describe "Dataset compound operations" do
|
|
2630
2357
|
end
|
2631
2358
|
|
2632
2359
|
specify "should handle chained compound operations" do
|
2633
|
-
@a.union(@b).union(@a, true).sql.should ==
|
2634
|
-
|
2635
|
-
@a.
|
2636
|
-
"SELECT * FROM (SELECT * FROM (SELECT * FROM a WHERE (z = 1) INTERSECT ALL SELECT * FROM b WHERE (z = 2)) AS t1 INTERSECT SELECT * FROM a WHERE (z = 1)) AS t1"
|
2637
|
-
@a.except(@b).except(@a, true).sql.should == \
|
2638
|
-
"SELECT * FROM (SELECT * FROM (SELECT * FROM a WHERE (z = 1) EXCEPT SELECT * FROM b WHERE (z = 2)) AS t1 EXCEPT ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2360
|
+
@a.union(@b).union(@a, true).sql.should == "SELECT * FROM (SELECT * FROM (SELECT * FROM a WHERE (z = 1) UNION SELECT * FROM b WHERE (z = 2)) AS t1 UNION ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2361
|
+
@a.intersect(@b, true).intersect(@a).sql.should == "SELECT * FROM (SELECT * FROM (SELECT * FROM a WHERE (z = 1) INTERSECT ALL SELECT * FROM b WHERE (z = 2)) AS t1 INTERSECT SELECT * FROM a WHERE (z = 1)) AS t1"
|
2362
|
+
@a.except(@b).except(@a, true).sql.should == "SELECT * FROM (SELECT * FROM (SELECT * FROM a WHERE (z = 1) EXCEPT SELECT * FROM b WHERE (z = 2)) AS t1 EXCEPT ALL SELECT * FROM a WHERE (z = 1)) AS t1"
|
2639
2363
|
end
|
2640
2364
|
|
2641
2365
|
specify "should use a subselect when using a compound operation with a dataset that already has a compound operation" do
|
2642
|
-
@a.union(@b.union(@a, true)).sql.should ==
|
2643
|
-
|
2644
|
-
@a.
|
2645
|
-
"SELECT * FROM (SELECT * FROM a WHERE (z = 1) INTERSECT ALL SELECT * FROM (SELECT * FROM b WHERE (z = 2) INTERSECT SELECT * FROM a WHERE (z = 1)) AS t1) AS t1"
|
2646
|
-
@a.except(@b.except(@a, true)).sql.should == \
|
2647
|
-
"SELECT * FROM (SELECT * FROM a WHERE (z = 1) EXCEPT SELECT * FROM (SELECT * FROM b WHERE (z = 2) EXCEPT ALL SELECT * FROM a WHERE (z = 1)) AS t1) AS t1"
|
2366
|
+
@a.union(@b.union(@a, true)).sql.should == "SELECT * FROM (SELECT * FROM a WHERE (z = 1) UNION SELECT * FROM (SELECT * FROM b WHERE (z = 2) UNION ALL SELECT * FROM a WHERE (z = 1)) AS t1) AS t1"
|
2367
|
+
@a.intersect(@b.intersect(@a), true).sql.should == "SELECT * FROM (SELECT * FROM a WHERE (z = 1) INTERSECT ALL SELECT * FROM (SELECT * FROM b WHERE (z = 2) INTERSECT SELECT * FROM a WHERE (z = 1)) AS t1) AS t1"
|
2368
|
+
@a.except(@b.except(@a, true)).sql.should == "SELECT * FROM (SELECT * FROM a WHERE (z = 1) EXCEPT SELECT * FROM (SELECT * FROM b WHERE (z = 2) EXCEPT ALL SELECT * FROM a WHERE (z = 1)) AS t1) AS t1"
|
2648
2369
|
end
|
2649
2370
|
|
2650
2371
|
specify "should order and limit properly when using UNION, INTERSECT, or EXCEPT" do
|
2651
2372
|
@dataset = Sequel::Dataset.new(nil).from(:test)
|
2652
|
-
@dataset.union(@dataset).limit(2).sql.should ==
|
2653
|
-
|
2654
|
-
@dataset.limit(2)
|
2655
|
-
|
2656
|
-
@dataset.
|
2657
|
-
|
2658
|
-
|
2659
|
-
@dataset.union(@dataset).order(:num).sql.should ==
|
2660
|
-
"SELECT * FROM (SELECT * FROM test UNION SELECT * FROM test) AS t1 ORDER BY num"
|
2661
|
-
@dataset.order(:num).intersect(@dataset).sql.should ==
|
2662
|
-
"SELECT * FROM (SELECT * FROM (SELECT * FROM test ORDER BY num) AS t1 INTERSECT SELECT * FROM test) AS t1"
|
2663
|
-
@dataset.except(@dataset.order(:num)).sql.should ==
|
2664
|
-
"SELECT * FROM (SELECT * FROM test EXCEPT SELECT * FROM (SELECT * FROM test ORDER BY num) AS t1) AS t1"
|
2373
|
+
@dataset.union(@dataset).limit(2).sql.should == "SELECT * FROM (SELECT * FROM test UNION SELECT * FROM test) AS t1 LIMIT 2"
|
2374
|
+
@dataset.limit(2).intersect(@dataset).sql.should == "SELECT * FROM (SELECT * FROM (SELECT * FROM test LIMIT 2) AS t1 INTERSECT SELECT * FROM test) AS t1"
|
2375
|
+
@dataset.except(@dataset.limit(2)).sql.should == "SELECT * FROM (SELECT * FROM test EXCEPT SELECT * FROM (SELECT * FROM test LIMIT 2) AS t1) AS t1"
|
2376
|
+
|
2377
|
+
@dataset.union(@dataset).order(:num).sql.should == "SELECT * FROM (SELECT * FROM test UNION SELECT * FROM test) AS t1 ORDER BY num"
|
2378
|
+
@dataset.order(:num).intersect(@dataset).sql.should == "SELECT * FROM (SELECT * FROM (SELECT * FROM test ORDER BY num) AS t1 INTERSECT SELECT * FROM test) AS t1"
|
2379
|
+
@dataset.except(@dataset.order(:num)).sql.should == "SELECT * FROM (SELECT * FROM test EXCEPT SELECT * FROM (SELECT * FROM test ORDER BY num) AS t1) AS t1"
|
2665
2380
|
|
2666
2381
|
@dataset.limit(2).order(:a).union(@dataset.limit(3).order(:b)).order(:c).limit(4).sql.should ==
|
2667
2382
|
"SELECT * FROM (SELECT * FROM (SELECT * FROM test ORDER BY a LIMIT 2) AS t1 UNION SELECT * FROM (SELECT * FROM test ORDER BY b LIMIT 3) AS t1) AS t1 ORDER BY c LIMIT 4"
|
2668
2383
|
end
|
2669
2384
|
|
2385
|
+
specify "should hoist WITH clauses in given dataset if dataset doesn't support WITH in subselect" do
|
2386
|
+
ds = Sequel::Dataset.new(nil)
|
2387
|
+
ds.meta_def(:supports_cte?){true}
|
2388
|
+
ds.meta_def(:supports_cte_in_subselect?){false}
|
2389
|
+
ds.from(:a).union(ds.from(:c).with(:c, ds.from(:d)), :from_self=>false).sql.should == 'WITH c AS (SELECT * FROM d) SELECT * FROM a UNION SELECT * FROM c'
|
2390
|
+
ds.from(:a).except(ds.from(:c).with(:c, ds.from(:d))).sql.should == 'WITH c AS (SELECT * FROM d) SELECT * FROM (SELECT * FROM a EXCEPT SELECT * FROM c) AS t1'
|
2391
|
+
ds.from(:a).with(:a, ds.from(:b)).intersect(ds.from(:c).with(:c, ds.from(:d)), :from_self=>false).sql.should == 'WITH a AS (SELECT * FROM b), c AS (SELECT * FROM d) SELECT * FROM a INTERSECT SELECT * FROM c'
|
2392
|
+
end
|
2670
2393
|
end
|
2671
2394
|
|
2672
2395
|
describe "Dataset#[]" do
|
2673
2396
|
before do
|
2674
|
-
@
|
2675
|
-
|
2676
|
-
|
2677
|
-
def self.last_dataset
|
2678
|
-
class_variable_get(:@@last_dataset)
|
2679
|
-
end
|
2680
|
-
|
2681
|
-
def single_record
|
2682
|
-
self.class.send(:class_variable_set, :@@last_dataset, opts ? clone(opts) : self)
|
2683
|
-
{1 => 2, 3 => 4}
|
2684
|
-
end
|
2685
|
-
end
|
2686
|
-
@d = @c.new(nil).from(:test)
|
2397
|
+
@db = Sequel.mock(:fetch=>{1 => 2, 3 => 4})
|
2398
|
+
@d = @db[:items]
|
2687
2399
|
end
|
2688
2400
|
|
2689
2401
|
specify "should return a single record filtered according to the given conditions" do
|
2690
2402
|
@d[:name => 'didi'].should == {1 => 2, 3 => 4}
|
2691
|
-
@
|
2403
|
+
@db.sqls.should == ["SELECT * FROM items WHERE (name = 'didi') LIMIT 1"]
|
2692
2404
|
|
2693
2405
|
@d[:id => 5..45].should == {1 => 2, 3 => 4}
|
2694
|
-
@
|
2406
|
+
@db.sqls.should == ["SELECT * FROM items WHERE ((id >= 5) AND (id <= 45)) LIMIT 1"]
|
2695
2407
|
end
|
2696
2408
|
end
|
2697
2409
|
|
2698
2410
|
describe "Dataset#single_record" do
|
2699
2411
|
before do
|
2700
|
-
@
|
2701
|
-
def fetch_rows(sql)
|
2702
|
-
yield sql
|
2703
|
-
end
|
2704
|
-
end
|
2705
|
-
@cc = Class.new(@c) do
|
2706
|
-
def fetch_rows(sql); end
|
2707
|
-
end
|
2708
|
-
|
2709
|
-
@d = @c.new(nil).from(:test)
|
2710
|
-
@e = @cc.new(nil).from(:test)
|
2412
|
+
@db = Sequel.mock
|
2711
2413
|
end
|
2712
2414
|
|
2713
2415
|
specify "should call each with a limit of 1 and return the record" do
|
2714
|
-
@
|
2416
|
+
@db.fetch = {:a=>1}
|
2417
|
+
@db[:test].single_record.should == {:a=>1}
|
2418
|
+
@db.sqls.should == ['SELECT * FROM test LIMIT 1']
|
2715
2419
|
end
|
2716
2420
|
|
2717
2421
|
specify "should return nil if no record is present" do
|
2718
|
-
@
|
2422
|
+
@db[:test].single_record.should be_nil
|
2423
|
+
@db.sqls.should == ['SELECT * FROM test LIMIT 1']
|
2719
2424
|
end
|
2720
2425
|
end
|
2721
2426
|
|
2722
2427
|
describe "Dataset#single_value" do
|
2723
2428
|
before do
|
2724
|
-
@
|
2725
|
-
def fetch_rows(sql)
|
2726
|
-
yield({1 => sql})
|
2727
|
-
end
|
2728
|
-
end
|
2729
|
-
@cc = Class.new(@c) do
|
2730
|
-
def fetch_rows(sql); end
|
2731
|
-
end
|
2732
|
-
|
2733
|
-
@d = @c.new(nil).from(:test)
|
2734
|
-
@e = @cc.new(nil).from(:test)
|
2429
|
+
@db = Sequel.mock
|
2735
2430
|
end
|
2736
2431
|
|
2737
2432
|
specify "should call each and return the first value of the first record" do
|
2738
|
-
@
|
2433
|
+
@db.fetch = {:a=>1}
|
2434
|
+
@db[:test].single_value.should == 1
|
2435
|
+
@db.sqls.should == ['SELECT * FROM test LIMIT 1']
|
2739
2436
|
end
|
2740
2437
|
|
2741
2438
|
specify "should return nil if no records" do
|
2742
|
-
@
|
2439
|
+
@db[:test].single_value.should be_nil
|
2440
|
+
@db.sqls.should == ['SELECT * FROM test LIMIT 1']
|
2743
2441
|
end
|
2744
2442
|
|
2745
2443
|
it "should work on a graphed_dataset" do
|
2746
|
-
@
|
2747
|
-
@
|
2444
|
+
@db.fetch = {:a=>1}
|
2445
|
+
ds = @db[:test].columns(:a)
|
2446
|
+
ds.graph(ds, [:a], :table_alias=>:test2).single_value.should == 1
|
2447
|
+
@db.sqls.should == ['SELECT test.a, test2.a AS test2_a FROM test LEFT OUTER JOIN test AS test2 USING (a) LIMIT 1']
|
2748
2448
|
end
|
2749
2449
|
end
|
2750
2450
|
|
2751
2451
|
describe "Dataset#get" do
|
2752
2452
|
before do
|
2753
|
-
@
|
2754
|
-
attr_reader :last_sql
|
2755
|
-
|
2756
|
-
def fetch_rows(sql)
|
2757
|
-
@last_sql = sql
|
2758
|
-
yield(:name => sql)
|
2759
|
-
end
|
2760
|
-
end
|
2761
|
-
|
2762
|
-
@d = @c.new(nil).from(:test)
|
2453
|
+
@d = Sequel.mock(:fetch=>proc{|s| {:name=>s}})[:test]
|
2763
2454
|
end
|
2764
2455
|
|
2765
2456
|
specify "should select the specified column and fetch its value" do
|
2766
2457
|
@d.get(:name).should == "SELECT name FROM test LIMIT 1"
|
2767
|
-
@d.get(:abc).should == "SELECT abc FROM test LIMIT 1"
|
2458
|
+
@d.get(:abc).should == "SELECT abc FROM test LIMIT 1"
|
2768
2459
|
end
|
2769
2460
|
|
2770
2461
|
specify "should work with filters" do
|
@@ -2787,239 +2478,206 @@ end
|
|
2787
2478
|
|
2788
2479
|
describe "Dataset#set_row_proc" do
|
2789
2480
|
before do
|
2790
|
-
@
|
2791
|
-
|
2792
|
-
|
2793
|
-
(1..10).each {|i| block.call({:kind => i[0]})}
|
2794
|
-
end
|
2795
|
-
end
|
2796
|
-
@dataset = @c.new(nil).from(:items)
|
2481
|
+
@db = Sequel.mock(:fetch=>[{:a=>1}, {:a=>2}])
|
2482
|
+
@dataset = @db[:items]
|
2483
|
+
@dataset.row_proc = proc{|h| h[:der] = h[:a] + 2; h}
|
2797
2484
|
end
|
2798
2485
|
|
2799
2486
|
specify "should cause dataset to pass all rows through the filter" do
|
2800
|
-
@dataset.row_proc = proc{|h| h[:der] = h[:kind] + 2; h}
|
2801
|
-
|
2802
2487
|
rows = @dataset.all
|
2803
|
-
rows.
|
2804
|
-
|
2805
|
-
rows.each {|r| r[:der].should == (r[:kind] + 2)}
|
2488
|
+
rows.map{|h| h[:der]}.should == [3, 4]
|
2489
|
+
@db.sqls.should == ['SELECT * FROM items']
|
2806
2490
|
end
|
2807
2491
|
|
2808
2492
|
specify "should be copied over when dataset is cloned" do
|
2809
|
-
@dataset.
|
2810
|
-
|
2811
|
-
@dataset.filter(:a => 1).first.should == {:kind => 1, :der => 3}
|
2493
|
+
@dataset.filter(:a => 1).all.should == [{:a=>1, :der=>3}, {:a=>2, :der=>4}]
|
2812
2494
|
end
|
2813
2495
|
end
|
2814
2496
|
|
2815
2497
|
describe "Dataset#<<" do
|
2816
2498
|
before do
|
2817
|
-
@
|
2818
|
-
@d.meta_def(:insert) do |*args|
|
2819
|
-
1234567890
|
2820
|
-
end
|
2499
|
+
@db = Sequel.mock
|
2821
2500
|
end
|
2822
|
-
|
2501
|
+
|
2823
2502
|
specify "should call #insert" do
|
2824
|
-
|
2503
|
+
@db[:items] << {:name => 1}
|
2504
|
+
@db.sqls.should == ['INSERT INTO items (name) VALUES (1)']
|
2505
|
+
end
|
2506
|
+
|
2507
|
+
specify "should be chainable" do
|
2508
|
+
@db[:items] << {:name => 1} << @db[:old_items].select(:name)
|
2509
|
+
@db.sqls.should == ['INSERT INTO items (name) VALUES (1)', 'INSERT INTO items SELECT name FROM old_items']
|
2825
2510
|
end
|
2826
2511
|
end
|
2827
2512
|
|
2828
2513
|
describe "Dataset#columns" do
|
2829
2514
|
before do
|
2830
|
-
@dataset =
|
2831
|
-
@dataset.meta_def(:columns=) {|c| @columns = c}
|
2832
|
-
i = 'a'
|
2833
|
-
@dataset.meta_def(:each){@columns = select_sql + i; i = i.next}
|
2515
|
+
@dataset = Sequel.mock[:items]
|
2834
2516
|
end
|
2835
2517
|
|
2836
2518
|
specify "should return the value of @columns if @columns is not nil" do
|
2837
|
-
@dataset.columns
|
2838
|
-
@dataset.
|
2519
|
+
@dataset.columns(:a, :b, :c).columns.should == [:a, :b, :c]
|
2520
|
+
@dataset.db.sqls.should == []
|
2839
2521
|
end
|
2840
2522
|
|
2841
2523
|
specify "should attempt to get a single record and return @columns if @columns is nil" do
|
2842
|
-
@dataset.columns =
|
2843
|
-
@dataset.columns.should ==
|
2844
|
-
@dataset.
|
2845
|
-
|
2524
|
+
@dataset.db.columns = [:a]
|
2525
|
+
@dataset.columns.should == [:a]
|
2526
|
+
@dataset.db.sqls.should == ['SELECT * FROM items LIMIT 1']
|
2527
|
+
end
|
2528
|
+
|
2529
|
+
specify "should be cleared if you change the selected columns" do
|
2530
|
+
@dataset.db.columns = [[:a], [:b]]
|
2531
|
+
@dataset.columns.should == [:a]
|
2532
|
+
@dataset.db.sqls.should == ['SELECT * FROM items LIMIT 1']
|
2533
|
+
@dataset.columns.should == [:a]
|
2534
|
+
@dataset.db.sqls.should == []
|
2535
|
+
ds = @dataset.select{foo{}}
|
2536
|
+
ds.columns.should == [:b]
|
2537
|
+
@dataset.db.sqls.should == ['SELECT foo() FROM items LIMIT 1']
|
2538
|
+
end
|
2539
|
+
|
2540
|
+
specify "should be cleared if you change the FROM table" do
|
2541
|
+
@dataset.db.columns = [[:a], [:b]]
|
2542
|
+
@dataset.columns.should == [:a]
|
2543
|
+
@dataset.db.sqls.should == ['SELECT * FROM items LIMIT 1']
|
2544
|
+
ds = @dataset.from(:foo)
|
2545
|
+
ds.columns.should == [:b]
|
2546
|
+
@dataset.db.sqls.should == ['SELECT * FROM foo LIMIT 1']
|
2547
|
+
end
|
2548
|
+
|
2549
|
+
specify "should be cleared if you join a table to the dataset" do
|
2550
|
+
@dataset.db.columns = [[:a], [:a, :b]]
|
2551
|
+
@dataset.columns.should == [:a]
|
2552
|
+
@dataset.db.sqls.should == ['SELECT * FROM items LIMIT 1']
|
2553
|
+
ds = @dataset.cross_join(:foo)
|
2554
|
+
ds.columns.should == [:a, :b]
|
2555
|
+
@dataset.db.sqls.should == ['SELECT * FROM items CROSS JOIN foo LIMIT 1']
|
2556
|
+
end
|
2557
|
+
|
2558
|
+
specify "should be cleared if you set custom SQL for the dataset" do
|
2559
|
+
@dataset.db.columns = [[:a], [:b]]
|
2560
|
+
@dataset.columns.should == [:a]
|
2561
|
+
@dataset.db.sqls.should == ['SELECT * FROM items LIMIT 1']
|
2562
|
+
ds = @dataset.with_sql('SELECT b FROM foo')
|
2563
|
+
ds.columns.should == [:b]
|
2564
|
+
@dataset.db.sqls.should == ['SELECT b FROM foo']
|
2846
2565
|
end
|
2847
2566
|
|
2848
2567
|
specify "should ignore any filters, orders, or DISTINCT clauses" do
|
2568
|
+
@dataset.db.columns = [:a]
|
2849
2569
|
@dataset.filter!(:b=>100).order!(:b).distinct!
|
2850
|
-
@dataset.columns
|
2851
|
-
@dataset.
|
2570
|
+
@dataset.columns.should == [:a]
|
2571
|
+
@dataset.db.sqls.should == ['SELECT * FROM items LIMIT 1']
|
2852
2572
|
end
|
2853
2573
|
end
|
2854
2574
|
|
2855
2575
|
describe "Dataset#columns!" do
|
2856
|
-
before do
|
2857
|
-
@dataset = DummyDataset.new(nil).from(:items)
|
2858
|
-
i = 'a'
|
2859
|
-
@dataset.meta_def(:each){@columns = select_sql + i; i = i.next}
|
2860
|
-
end
|
2861
|
-
|
2862
2576
|
specify "should always attempt to get a record and return @columns" do
|
2863
|
-
|
2864
|
-
|
2865
|
-
|
2866
|
-
|
2577
|
+
ds = Sequel.mock(:columns=>[[:a, :b, :c], [:d, :e, :f]])[:items]
|
2578
|
+
ds.columns!.should == [:a, :b, :c]
|
2579
|
+
ds.db.sqls.should == ['SELECT * FROM items LIMIT 1']
|
2580
|
+
ds.columns!.should == [:d, :e, :f]
|
2581
|
+
ds.db.sqls.should == ['SELECT * FROM items LIMIT 1']
|
2867
2582
|
end
|
2868
2583
|
end
|
2869
2584
|
|
2870
2585
|
describe "Dataset#import" do
|
2871
2586
|
before do
|
2872
|
-
@
|
2873
|
-
|
2874
|
-
|
2875
|
-
def execute(sql, opts={})
|
2876
|
-
@sqls ||= []
|
2877
|
-
@sqls << sql
|
2878
|
-
end
|
2879
|
-
alias execute_dui execute
|
2880
|
-
|
2881
|
-
def transaction(opts={})
|
2882
|
-
@sqls ||= []
|
2883
|
-
@sqls << 'BEGIN'
|
2884
|
-
yield
|
2885
|
-
@sqls << 'COMMIT'
|
2886
|
-
end
|
2887
|
-
end
|
2888
|
-
@db = @dbc.new
|
2889
|
-
|
2890
|
-
@ds = Sequel::Dataset.new(@db).from(:items)
|
2891
|
-
|
2892
|
-
@list = [{:name => 'abc'}, {:name => 'def'}, {:name => 'ghi'}]
|
2587
|
+
@db = Sequel.mock
|
2588
|
+
@ds = @db[:items]
|
2893
2589
|
end
|
2894
2590
|
|
2895
2591
|
specify "should accept string keys as column names" do
|
2896
2592
|
@ds.import(['x', 'y'], [[1, 2], [3, 4]])
|
2897
|
-
@db.sqls.should == [
|
2898
|
-
'BEGIN',
|
2593
|
+
@db.sqls.should == ['BEGIN',
|
2899
2594
|
"INSERT INTO items (x, y) VALUES (1, 2)",
|
2900
2595
|
"INSERT INTO items (x, y) VALUES (3, 4)",
|
2901
|
-
'COMMIT'
|
2902
|
-
]
|
2596
|
+
'COMMIT']
|
2903
2597
|
end
|
2904
2598
|
|
2905
2599
|
specify "should accept a columns array and a values array" do
|
2906
2600
|
@ds.import([:x, :y], [[1, 2], [3, 4]])
|
2907
|
-
@db.sqls.should == [
|
2908
|
-
'BEGIN',
|
2601
|
+
@db.sqls.should == ['BEGIN',
|
2909
2602
|
"INSERT INTO items (x, y) VALUES (1, 2)",
|
2910
2603
|
"INSERT INTO items (x, y) VALUES (3, 4)",
|
2911
|
-
'COMMIT'
|
2912
|
-
]
|
2604
|
+
'COMMIT']
|
2913
2605
|
end
|
2914
2606
|
|
2915
2607
|
specify "should accept a columns array and a dataset" do
|
2916
|
-
@ds2 =
|
2608
|
+
@ds2 = @ds.from(:cats).filter(:purr => true).select(:a, :b)
|
2917
2609
|
|
2918
2610
|
@ds.import([:x, :y], @ds2)
|
2919
|
-
@db.sqls.should == [
|
2920
|
-
'BEGIN',
|
2611
|
+
@db.sqls.should == ['BEGIN',
|
2921
2612
|
"INSERT INTO items (x, y) SELECT a, b FROM cats WHERE (purr IS TRUE)",
|
2922
|
-
'COMMIT'
|
2923
|
-
]
|
2613
|
+
'COMMIT']
|
2924
2614
|
end
|
2925
2615
|
|
2926
2616
|
specify "should accept a columns array and a values array with :commit_every option" do
|
2927
2617
|
@ds.import([:x, :y], [[1, 2], [3, 4], [5, 6]], :commit_every => 3)
|
2928
|
-
@db.sqls.should == [
|
2929
|
-
'BEGIN',
|
2618
|
+
@db.sqls.should == ['BEGIN',
|
2930
2619
|
"INSERT INTO items (x, y) VALUES (1, 2)",
|
2931
2620
|
"INSERT INTO items (x, y) VALUES (3, 4)",
|
2932
2621
|
"INSERT INTO items (x, y) VALUES (5, 6)",
|
2933
|
-
'COMMIT'
|
2934
|
-
]
|
2622
|
+
'COMMIT']
|
2935
2623
|
end
|
2936
|
-
specify "should accept a columns array and a values array with slice option" do
|
2624
|
+
specify "should accept a columns array and a values array with :slice option" do
|
2937
2625
|
@ds.import([:x, :y], [[1, 2], [3, 4], [5, 6]], :slice => 2)
|
2938
|
-
@db.sqls.should == [
|
2939
|
-
'BEGIN',
|
2626
|
+
@db.sqls.should == ['BEGIN',
|
2940
2627
|
"INSERT INTO items (x, y) VALUES (1, 2)",
|
2941
2628
|
"INSERT INTO items (x, y) VALUES (3, 4)",
|
2942
2629
|
'COMMIT',
|
2943
2630
|
'BEGIN',
|
2944
2631
|
"INSERT INTO items (x, y) VALUES (5, 6)",
|
2945
|
-
'COMMIT'
|
2946
|
-
]
|
2632
|
+
'COMMIT']
|
2947
2633
|
end
|
2948
2634
|
end
|
2949
2635
|
|
2950
2636
|
describe "Dataset#multi_insert" do
|
2951
2637
|
before do
|
2952
|
-
@
|
2953
|
-
|
2954
|
-
|
2955
|
-
def execute(sql, opts={})
|
2956
|
-
@sqls ||= []
|
2957
|
-
@sqls << sql
|
2958
|
-
end
|
2959
|
-
alias execute_dui execute
|
2960
|
-
|
2961
|
-
def transaction(opts={})
|
2962
|
-
@sqls ||= []
|
2963
|
-
@sqls << 'BEGIN'
|
2964
|
-
yield
|
2965
|
-
@sqls << 'COMMIT'
|
2966
|
-
end
|
2967
|
-
end
|
2968
|
-
@db = @dbc.new
|
2969
|
-
|
2970
|
-
@ds = Sequel::Dataset.new(@db).from(:items)
|
2971
|
-
|
2638
|
+
@db = Sequel.mock
|
2639
|
+
@ds = @db[:items]
|
2972
2640
|
@list = [{:name => 'abc'}, {:name => 'def'}, {:name => 'ghi'}]
|
2973
2641
|
end
|
2974
2642
|
|
2975
2643
|
specify "should issue multiple insert statements inside a transaction" do
|
2976
2644
|
@ds.multi_insert(@list)
|
2977
|
-
@db.sqls.should == [
|
2978
|
-
'BEGIN',
|
2645
|
+
@db.sqls.should == ['BEGIN',
|
2979
2646
|
"INSERT INTO items (name) VALUES ('abc')",
|
2980
2647
|
"INSERT INTO items (name) VALUES ('def')",
|
2981
2648
|
"INSERT INTO items (name) VALUES ('ghi')",
|
2982
|
-
'COMMIT'
|
2983
|
-
]
|
2649
|
+
'COMMIT']
|
2984
2650
|
end
|
2985
2651
|
|
2986
2652
|
specify "should handle different formats for tables" do
|
2987
2653
|
@ds = @ds.from(:sch__tab)
|
2988
2654
|
@ds.multi_insert(@list)
|
2989
|
-
@db.sqls.should == [
|
2990
|
-
'BEGIN',
|
2655
|
+
@db.sqls.should == ['BEGIN',
|
2991
2656
|
"INSERT INTO sch.tab (name) VALUES ('abc')",
|
2992
2657
|
"INSERT INTO sch.tab (name) VALUES ('def')",
|
2993
2658
|
"INSERT INTO sch.tab (name) VALUES ('ghi')",
|
2994
|
-
'COMMIT'
|
2995
|
-
]
|
2996
|
-
@db.sqls.clear
|
2659
|
+
'COMMIT']
|
2997
2660
|
|
2998
2661
|
@ds = @ds.from(:tab.qualify(:sch))
|
2999
2662
|
@ds.multi_insert(@list)
|
3000
|
-
@db.sqls.should == [
|
3001
|
-
'BEGIN',
|
2663
|
+
@db.sqls.should == ['BEGIN',
|
3002
2664
|
"INSERT INTO sch.tab (name) VALUES ('abc')",
|
3003
2665
|
"INSERT INTO sch.tab (name) VALUES ('def')",
|
3004
2666
|
"INSERT INTO sch.tab (name) VALUES ('ghi')",
|
3005
|
-
'COMMIT'
|
3006
|
-
|
3007
|
-
@db.sqls.clear
|
2667
|
+
'COMMIT']
|
2668
|
+
|
3008
2669
|
@ds = @ds.from(:sch__tab.identifier)
|
3009
2670
|
@ds.multi_insert(@list)
|
3010
|
-
@db.sqls.should == [
|
3011
|
-
'BEGIN',
|
2671
|
+
@db.sqls.should == ['BEGIN',
|
3012
2672
|
"INSERT INTO sch__tab (name) VALUES ('abc')",
|
3013
2673
|
"INSERT INTO sch__tab (name) VALUES ('def')",
|
3014
2674
|
"INSERT INTO sch__tab (name) VALUES ('ghi')",
|
3015
|
-
'COMMIT'
|
3016
|
-
]
|
2675
|
+
'COMMIT']
|
3017
2676
|
end
|
3018
2677
|
|
3019
2678
|
specify "should accept the :commit_every option for committing every x records" do
|
3020
2679
|
@ds.multi_insert(@list, :commit_every => 1)
|
3021
|
-
@db.sqls.should == [
|
3022
|
-
'BEGIN',
|
2680
|
+
@db.sqls.should == ['BEGIN',
|
3023
2681
|
"INSERT INTO items (name) VALUES ('abc')",
|
3024
2682
|
'COMMIT',
|
3025
2683
|
'BEGIN',
|
@@ -3027,36 +2685,31 @@ describe "Dataset#multi_insert" do
|
|
3027
2685
|
'COMMIT',
|
3028
2686
|
'BEGIN',
|
3029
2687
|
"INSERT INTO items (name) VALUES ('ghi')",
|
3030
|
-
'COMMIT'
|
3031
|
-
]
|
2688
|
+
'COMMIT']
|
3032
2689
|
end
|
3033
2690
|
|
3034
2691
|
specify "should accept the :slice option for committing every x records" do
|
3035
2692
|
@ds.multi_insert(@list, :slice => 2)
|
3036
|
-
@db.sqls.should == [
|
3037
|
-
'BEGIN',
|
2693
|
+
@db.sqls.should == ['BEGIN',
|
3038
2694
|
"INSERT INTO items (name) VALUES ('abc')",
|
3039
2695
|
"INSERT INTO items (name) VALUES ('def')",
|
3040
2696
|
'COMMIT',
|
3041
2697
|
'BEGIN',
|
3042
2698
|
"INSERT INTO items (name) VALUES ('ghi')",
|
3043
|
-
'COMMIT'
|
3044
|
-
]
|
2699
|
+
'COMMIT']
|
3045
2700
|
end
|
3046
2701
|
|
3047
2702
|
specify "should accept string keys as column names" do
|
3048
2703
|
@ds.multi_insert([{'x'=>1, 'y'=>2}, {'x'=>3, 'y'=>4}])
|
3049
|
-
@db.sqls.should == [
|
3050
|
-
'BEGIN',
|
2704
|
+
@db.sqls.should == ['BEGIN',
|
3051
2705
|
"INSERT INTO items (x, y) VALUES (1, 2)",
|
3052
2706
|
"INSERT INTO items (x, y) VALUES (3, 4)",
|
3053
|
-
'COMMIT'
|
3054
|
-
]
|
2707
|
+
'COMMIT']
|
3055
2708
|
end
|
3056
2709
|
|
3057
2710
|
specify "should not do anything if no hashes are provided" do
|
3058
2711
|
@ds.multi_insert([])
|
3059
|
-
@db.sqls.should
|
2712
|
+
@db.sqls.should == []
|
3060
2713
|
end
|
3061
2714
|
end
|
3062
2715
|
|
@@ -3101,41 +2754,21 @@ describe "Dataset" do
|
|
3101
2754
|
end
|
3102
2755
|
|
3103
2756
|
specify "should support chaining of bang methods" do
|
3104
|
-
@d.order!(:y)
|
3105
|
-
@d.filter!(:y => 1)
|
3106
|
-
@d.sql.should == "SELECT * FROM x WHERE (y = 1) ORDER BY y"
|
2757
|
+
@d.order!(:y).filter!(:y => 1).sql.should == "SELECT * FROM x WHERE (y = 1) ORDER BY y"
|
3107
2758
|
end
|
3108
2759
|
end
|
3109
2760
|
|
3110
2761
|
describe "Dataset#to_csv" do
|
3111
2762
|
before do
|
3112
|
-
@
|
3113
|
-
attr_accessor :data
|
3114
|
-
attr_accessor :columns
|
3115
|
-
|
3116
|
-
def fetch_rows(sql, &block)
|
3117
|
-
@data.each(&block)
|
3118
|
-
end
|
3119
|
-
|
3120
|
-
# naked should return self here because to_csv wants a naked result set.
|
3121
|
-
def naked
|
3122
|
-
self
|
3123
|
-
end
|
3124
|
-
end
|
3125
|
-
|
3126
|
-
@ds = @c.new(nil).from(:items)
|
3127
|
-
@ds.columns = [:a, :b, :c]
|
3128
|
-
@ds.data = [ {:a=>1, :b=>2, :c=>3}, {:a=>4, :b=>5, :c=>6}, {:a=>7, :b=>8, :c=>9} ]
|
2763
|
+
@ds = Sequel.mock(:fetch=>[{:a=>1, :b=>2, :c=>3}, {:a=>4, :b=>5, :c=>6}, {:a=>7, :b=>8, :c=>9}])[:items].columns(:a, :b, :c)
|
3129
2764
|
end
|
3130
2765
|
|
3131
2766
|
specify "should format a CSV representation of the records" do
|
3132
|
-
@ds.to_csv.should ==
|
3133
|
-
"a, b, c\r\n1, 2, 3\r\n4, 5, 6\r\n7, 8, 9\r\n"
|
2767
|
+
@ds.to_csv.should == "a, b, c\r\n1, 2, 3\r\n4, 5, 6\r\n7, 8, 9\r\n"
|
3134
2768
|
end
|
3135
2769
|
|
3136
2770
|
specify "should exclude column titles if so specified" do
|
3137
|
-
@ds.to_csv(false).should ==
|
3138
|
-
"1, 2, 3\r\n4, 5, 6\r\n7, 8, 9\r\n"
|
2771
|
+
@ds.to_csv(false).should == "1, 2, 3\r\n4, 5, 6\r\n7, 8, 9\r\n"
|
3139
2772
|
end
|
3140
2773
|
end
|
3141
2774
|
|
@@ -3233,66 +2866,40 @@ describe "Dataset#insert_sql" do
|
|
3233
2866
|
end
|
3234
2867
|
end
|
3235
2868
|
|
3236
|
-
|
3237
|
-
|
3238
|
-
|
3239
|
-
true
|
2869
|
+
describe "Dataset#inspect" do
|
2870
|
+
before do
|
2871
|
+
class ::InspectDataset < Sequel::Dataset; end
|
3240
2872
|
end
|
3241
|
-
|
3242
|
-
|
3243
|
-
class DummyMummyDatabase < Sequel::Database
|
3244
|
-
attr_reader :sqls
|
3245
|
-
|
3246
|
-
def execute(sql)
|
3247
|
-
@sqls ||= []
|
3248
|
-
@sqls << sql
|
2873
|
+
after do
|
2874
|
+
Object.send(:remove_const, :InspectDataset) if defined?(::InspectDataset)
|
3249
2875
|
end
|
3250
|
-
|
3251
|
-
def transaction; yield; end
|
3252
2876
|
|
3253
|
-
|
3254
|
-
|
2877
|
+
specify "should include the class name and the corresponding SQL statement" do
|
2878
|
+
Sequel::Dataset.new(nil).from(:blah).inspect.should == '#<Sequel::Dataset: "SELECT * FROM blah">'
|
2879
|
+
InspectDataset.new(nil).from(:blah).inspect.should == '#<InspectDataset: "SELECT * FROM blah">'
|
3255
2880
|
end
|
3256
|
-
end
|
3257
2881
|
|
3258
|
-
|
3259
|
-
|
3260
|
-
|
3261
|
-
end
|
3262
|
-
|
3263
|
-
specify "should include the class name and the corresponding SQL statement" do
|
3264
|
-
@ds.inspect.should == '#<%s: %s>' % [@ds.class.to_s, @ds.sql.inspect]
|
2882
|
+
specify "should skip anonymous classes" do
|
2883
|
+
Class.new(Class.new(Sequel::Dataset)).new(nil).from(:blah).inspect.should == '#<Sequel::Dataset: "SELECT * FROM blah">'
|
2884
|
+
Class.new(InspectDataset).new(nil).from(:blah).inspect.should == '#<InspectDataset: "SELECT * FROM blah">'
|
3265
2885
|
end
|
3266
2886
|
end
|
3267
2887
|
|
3268
2888
|
describe "Dataset#all" do
|
3269
2889
|
before do
|
3270
|
-
@
|
3271
|
-
def fetch_rows(sql, &block)
|
3272
|
-
block.call({:x => 1, :y => 2})
|
3273
|
-
block.call({:x => 3, :y => 4})
|
3274
|
-
block.call(sql)
|
3275
|
-
end
|
3276
|
-
end
|
3277
|
-
@dataset = @c.new(nil).from(:items)
|
2890
|
+
@dataset = Sequel.mock(:fetch=>[{:x => 1, :y => 2}, {:x => 3, :y => 4}])[:items]
|
3278
2891
|
end
|
3279
2892
|
|
3280
2893
|
specify "should return an array with all records" do
|
3281
|
-
@dataset.all.should == [
|
3282
|
-
|
3283
|
-
{:x => 3, :y => 4},
|
3284
|
-
"SELECT * FROM items"
|
3285
|
-
]
|
2894
|
+
@dataset.all.should == [{:x => 1, :y => 2}, {:x => 3, :y => 4}]
|
2895
|
+
@dataset.db.sqls.should == ["SELECT * FROM items"]
|
3286
2896
|
end
|
3287
2897
|
|
3288
2898
|
specify "should iterate over the array if a block is given" do
|
3289
2899
|
a = []
|
3290
|
-
|
3291
|
-
|
3292
|
-
|
3293
|
-
end
|
3294
|
-
|
3295
|
-
a.should == [1, 3, "SELECT * FROM items"]
|
2900
|
+
@dataset.all{|r| a << r.values_at(:x, :y)}.should == [{:x => 1, :y => 2}, {:x => 3, :y => 4}]
|
2901
|
+
a.should == [[1, 2], [3, 4]]
|
2902
|
+
@dataset.db.sqls.should == ["SELECT * FROM items"]
|
3296
2903
|
end
|
3297
2904
|
end
|
3298
2905
|
|
@@ -3302,71 +2909,56 @@ describe "Dataset#grep" do
|
|
3302
2909
|
end
|
3303
2910
|
|
3304
2911
|
specify "should format a SQL filter correctly" do
|
3305
|
-
@ds.grep(:title, 'ruby').sql.should ==
|
3306
|
-
"SELECT * FROM posts WHERE ((title LIKE 'ruby'))"
|
2912
|
+
@ds.grep(:title, 'ruby').sql.should == "SELECT * FROM posts WHERE ((title LIKE 'ruby'))"
|
3307
2913
|
end
|
3308
2914
|
|
3309
2915
|
specify "should support multiple columns" do
|
3310
|
-
@ds.grep([:title, :body], 'ruby').sql.should ==
|
3311
|
-
"SELECT * FROM posts WHERE ((title LIKE 'ruby') OR (body LIKE 'ruby'))"
|
2916
|
+
@ds.grep([:title, :body], 'ruby').sql.should == "SELECT * FROM posts WHERE ((title LIKE 'ruby') OR (body LIKE 'ruby'))"
|
3312
2917
|
end
|
3313
2918
|
|
3314
2919
|
specify "should support multiple search terms" do
|
3315
|
-
@ds.grep(:title, ['abc', 'def']).sql.should ==
|
3316
|
-
"SELECT * FROM posts WHERE ((title LIKE 'abc') OR (title LIKE 'def'))"
|
2920
|
+
@ds.grep(:title, ['abc', 'def']).sql.should == "SELECT * FROM posts WHERE ((title LIKE 'abc') OR (title LIKE 'def'))"
|
3317
2921
|
end
|
3318
2922
|
|
3319
2923
|
specify "should support multiple columns and search terms" do
|
3320
|
-
@ds.grep([:title, :body], ['abc', 'def']).sql.should ==
|
3321
|
-
"SELECT * FROM posts WHERE ((title LIKE 'abc') OR (title LIKE 'def') OR (body LIKE 'abc') OR (body LIKE 'def'))"
|
2924
|
+
@ds.grep([:title, :body], ['abc', 'def']).sql.should == "SELECT * FROM posts WHERE ((title LIKE 'abc') OR (title LIKE 'def') OR (body LIKE 'abc') OR (body LIKE 'def'))"
|
3322
2925
|
end
|
3323
2926
|
|
3324
2927
|
specify "should support the :all_patterns option" do
|
3325
|
-
@ds.grep([:title, :body], ['abc', 'def'], :all_patterns=>true).sql.should ==
|
3326
|
-
"SELECT * FROM posts WHERE (((title LIKE 'abc') OR (body LIKE 'abc')) AND ((title LIKE 'def') OR (body LIKE 'def')))"
|
2928
|
+
@ds.grep([:title, :body], ['abc', 'def'], :all_patterns=>true).sql.should == "SELECT * FROM posts WHERE (((title LIKE 'abc') OR (body LIKE 'abc')) AND ((title LIKE 'def') OR (body LIKE 'def')))"
|
3327
2929
|
end
|
3328
2930
|
|
3329
2931
|
specify "should support the :all_columns option" do
|
3330
|
-
@ds.grep([:title, :body], ['abc', 'def'], :all_columns=>true).sql.should ==
|
3331
|
-
"SELECT * FROM posts WHERE (((title LIKE 'abc') OR (title LIKE 'def')) AND ((body LIKE 'abc') OR (body LIKE 'def')))"
|
2932
|
+
@ds.grep([:title, :body], ['abc', 'def'], :all_columns=>true).sql.should == "SELECT * FROM posts WHERE (((title LIKE 'abc') OR (title LIKE 'def')) AND ((body LIKE 'abc') OR (body LIKE 'def')))"
|
3332
2933
|
end
|
3333
2934
|
|
3334
2935
|
specify "should support the :case_insensitive option" do
|
3335
|
-
@ds.grep([:title, :body], ['abc', 'def'], :case_insensitive=>true).sql.should ==
|
3336
|
-
"SELECT * FROM posts WHERE ((title ILIKE 'abc') OR (title ILIKE 'def') OR (body ILIKE 'abc') OR (body ILIKE 'def'))"
|
2936
|
+
@ds.grep([:title, :body], ['abc', 'def'], :case_insensitive=>true).sql.should == "SELECT * FROM posts WHERE ((title ILIKE 'abc') OR (title ILIKE 'def') OR (body ILIKE 'abc') OR (body ILIKE 'def'))"
|
3337
2937
|
end
|
3338
2938
|
|
3339
2939
|
specify "should support the :all_patterns and :all_columns options together" do
|
3340
|
-
@ds.grep([:title, :body], ['abc', 'def'], :all_patterns=>true, :all_columns=>true).sql.should ==
|
3341
|
-
"SELECT * FROM posts WHERE ((title LIKE 'abc') AND (body LIKE 'abc') AND (title LIKE 'def') AND (body LIKE 'def'))"
|
2940
|
+
@ds.grep([:title, :body], ['abc', 'def'], :all_patterns=>true, :all_columns=>true).sql.should == "SELECT * FROM posts WHERE ((title LIKE 'abc') AND (body LIKE 'abc') AND (title LIKE 'def') AND (body LIKE 'def'))"
|
3342
2941
|
end
|
3343
2942
|
|
3344
2943
|
specify "should support the :all_patterns and :case_insensitive options together" do
|
3345
|
-
@ds.grep([:title, :body], ['abc', 'def'], :all_patterns=>true, :case_insensitive=>true).sql.should ==
|
3346
|
-
"SELECT * FROM posts WHERE (((title ILIKE 'abc') OR (body ILIKE 'abc')) AND ((title ILIKE 'def') OR (body ILIKE 'def')))"
|
2944
|
+
@ds.grep([:title, :body], ['abc', 'def'], :all_patterns=>true, :case_insensitive=>true).sql.should == "SELECT * FROM posts WHERE (((title ILIKE 'abc') OR (body ILIKE 'abc')) AND ((title ILIKE 'def') OR (body ILIKE 'def')))"
|
3347
2945
|
end
|
3348
2946
|
|
3349
2947
|
specify "should support the :all_columns and :case_insensitive options together" do
|
3350
|
-
@ds.grep([:title, :body], ['abc', 'def'], :all_columns=>true, :case_insensitive=>true).sql.should ==
|
3351
|
-
"SELECT * FROM posts WHERE (((title ILIKE 'abc') OR (title ILIKE 'def')) AND ((body ILIKE 'abc') OR (body ILIKE 'def')))"
|
2948
|
+
@ds.grep([:title, :body], ['abc', 'def'], :all_columns=>true, :case_insensitive=>true).sql.should == "SELECT * FROM posts WHERE (((title ILIKE 'abc') OR (title ILIKE 'def')) AND ((body ILIKE 'abc') OR (body ILIKE 'def')))"
|
3352
2949
|
end
|
3353
2950
|
|
3354
2951
|
specify "should support the :all_patterns, :all_columns, and :case_insensitive options together" do
|
3355
|
-
@ds.grep([:title, :body], ['abc', 'def'], :all_patterns=>true, :all_columns=>true, :case_insensitive=>true).sql.should ==
|
3356
|
-
"SELECT * FROM posts WHERE ((title ILIKE 'abc') AND (body ILIKE 'abc') AND (title ILIKE 'def') AND (body ILIKE 'def'))"
|
2952
|
+
@ds.grep([:title, :body], ['abc', 'def'], :all_patterns=>true, :all_columns=>true, :case_insensitive=>true).sql.should == "SELECT * FROM posts WHERE ((title ILIKE 'abc') AND (body ILIKE 'abc') AND (title ILIKE 'def') AND (body ILIKE 'def'))"
|
3357
2953
|
end
|
3358
2954
|
|
3359
2955
|
specify "should support regexps though the database may not support it" do
|
3360
|
-
@ds.grep(:title, /ruby/).sql.should ==
|
3361
|
-
|
3362
|
-
|
3363
|
-
@ds.grep(:title, [/^ruby/, 'ruby']).sql.should ==
|
3364
|
-
"SELECT * FROM posts WHERE ((title ~ '^ruby') OR (title LIKE 'ruby'))"
|
2956
|
+
@ds.grep(:title, /ruby/).sql.should == "SELECT * FROM posts WHERE ((title ~ 'ruby'))"
|
2957
|
+
@ds.grep(:title, [/^ruby/, 'ruby']).sql.should == "SELECT * FROM posts WHERE ((title ~ '^ruby') OR (title LIKE 'ruby'))"
|
3365
2958
|
end
|
3366
2959
|
|
3367
2960
|
specify "should support searching against other columns" do
|
3368
|
-
@ds.grep(:title, :body).sql.should ==
|
3369
|
-
"SELECT * FROM posts WHERE ((title LIKE body))"
|
2961
|
+
@ds.grep(:title, :body).sql.should == "SELECT * FROM posts WHERE ((title LIKE body))"
|
3370
2962
|
end
|
3371
2963
|
end
|
3372
2964
|
|
@@ -3420,18 +3012,7 @@ end
|
|
3420
3012
|
|
3421
3013
|
describe "Dataset prepared statements and bound variables " do
|
3422
3014
|
before do
|
3423
|
-
@db = Sequel
|
3424
|
-
@db.meta_def(:sqls){@sqls||=[]}
|
3425
|
-
def @db.execute(sql, opts={})
|
3426
|
-
sqls << sql
|
3427
|
-
end
|
3428
|
-
def @db.dataset
|
3429
|
-
ds = super()
|
3430
|
-
def ds.fetch_rows(sql, &block)
|
3431
|
-
execute(sql)
|
3432
|
-
end
|
3433
|
-
ds
|
3434
|
-
end
|
3015
|
+
@db = Sequel.mock
|
3435
3016
|
@ds = @db[:items]
|
3436
3017
|
@ds.meta_def(:insert_sql){|*v| "#{super(*v)}#{' RETURNING *' if opts.has_key?(:returning)}" }
|
3437
3018
|
end
|
@@ -3477,7 +3058,7 @@ describe "Dataset prepared statements and bound variables " do
|
|
3477
3058
|
|
3478
3059
|
specify "#inspect should indicate it is a prepared statement with the prepared SQL" do
|
3479
3060
|
@ds.filter(:num=>:$n).prepare(:select, :sn).inspect.should == \
|
3480
|
-
'<Sequel::Dataset/PreparedStatement "SELECT * FROM items WHERE (num = $n)">'
|
3061
|
+
'<Sequel::Mock::Dataset/PreparedStatement "SELECT * FROM items WHERE (num = $n)">'
|
3481
3062
|
end
|
3482
3063
|
|
3483
3064
|
specify "should handle literal strings" do
|
@@ -3513,23 +3094,16 @@ end
|
|
3513
3094
|
|
3514
3095
|
describe Sequel::Dataset::UnnumberedArgumentMapper do
|
3515
3096
|
before do
|
3516
|
-
@db = Sequel
|
3517
|
-
@db.meta_def(:sqls){@sqls||=[]}
|
3518
|
-
def @db.execute(sql, opts={})
|
3519
|
-
sqls << [sql, *opts[:arguments]]
|
3520
|
-
end
|
3097
|
+
@db = Sequel.mock
|
3521
3098
|
@ds = @db[:items].filter(:num=>:$n)
|
3522
|
-
def @ds.fetch_rows(sql, &block)
|
3523
|
-
execute(sql)
|
3524
|
-
end
|
3525
3099
|
def @ds.execute(sql, opts={}, &block)
|
3526
|
-
|
3100
|
+
super(sql, opts.merge({:arguments=>bind_arguments}), &block)
|
3527
3101
|
end
|
3528
|
-
def @ds.execute_dui(
|
3529
|
-
|
3102
|
+
def @ds.execute_dui(sql, opts={}, &block)
|
3103
|
+
super(sql, opts.merge({:arguments=>bind_arguments}), &block)
|
3530
3104
|
end
|
3531
|
-
def @ds.execute_insert(
|
3532
|
-
|
3105
|
+
def @ds.execute_insert(sql, opts={}, &block)
|
3106
|
+
super(sql, opts.merge({:arguments=>bind_arguments}), &block)
|
3533
3107
|
end
|
3534
3108
|
@ps = []
|
3535
3109
|
@ps << @ds.prepare(:select, :s)
|
@@ -3542,64 +3116,43 @@ describe Sequel::Dataset::UnnumberedArgumentMapper do
|
|
3542
3116
|
end
|
3543
3117
|
|
3544
3118
|
specify "#inspect should show the actual SQL submitted to the database" do
|
3545
|
-
@ps.first.inspect.should == '<Sequel::Dataset/PreparedStatement "SELECT * FROM items WHERE (num = ?)">'
|
3119
|
+
@ps.first.inspect.should == '<Sequel::Mock::Dataset/PreparedStatement "SELECT * FROM items WHERE (num = ?)">'
|
3546
3120
|
end
|
3547
3121
|
|
3548
3122
|
specify "should submitted the SQL to the database with placeholders and bind variables" do
|
3549
3123
|
@ps.each{|p| p.prepared_sql; p.call(:n=>1)}
|
3550
|
-
@db.sqls.should == [
|
3551
|
-
|
3552
|
-
|
3553
|
-
|
3554
|
-
|
3555
|
-
|
3556
|
-
]
|
3124
|
+
@db.sqls.should == ["SELECT * FROM items WHERE (num = ?) -- args: [1]",
|
3125
|
+
"SELECT * FROM items WHERE (num = ?) -- args: [1]",
|
3126
|
+
"SELECT * FROM items WHERE (num = ?) LIMIT 1 -- args: [1]",
|
3127
|
+
"DELETE FROM items WHERE (num = ?) -- args: [1]",
|
3128
|
+
"INSERT INTO items (num) VALUES (?) -- args: [1]",
|
3129
|
+
"UPDATE items SET num = ? WHERE (num = ?) -- args: [1, 1]"]
|
3557
3130
|
end
|
3558
3131
|
end
|
3559
3132
|
|
3560
3133
|
describe "Sequel::Dataset#server" do
|
3561
3134
|
specify "should set the server to use for the dataset" do
|
3562
|
-
@db = Sequel
|
3135
|
+
@db = Sequel.mock(:servers=>{:s=>{}, :i=>{}, :d=>{}, :u=>{}})
|
3563
3136
|
@ds = @db[:items].server(:s)
|
3564
|
-
sqls = []
|
3565
|
-
@db.meta_def(:execute) do |sql, opts|
|
3566
|
-
sqls << [sql, opts[:server]]
|
3567
|
-
end
|
3568
|
-
def @ds.fetch_rows(sql, &block)
|
3569
|
-
execute(sql)
|
3570
|
-
end
|
3571
3137
|
@ds.all
|
3572
3138
|
@ds.server(:i).insert(:a=>1)
|
3573
3139
|
@ds.server(:d).delete
|
3574
3140
|
@ds.server(:u).update(:a=>:a+1)
|
3575
|
-
sqls.should == [
|
3576
|
-
['INSERT INTO items (a) VALUES (1)', :i],
|
3577
|
-
['DELETE FROM items', :d],
|
3578
|
-
['UPDATE items SET a = (a + 1)', :u]]
|
3141
|
+
@db.sqls.should == ['SELECT * FROM items -- s', 'INSERT INTO items (a) VALUES (1) -- i', 'DELETE FROM items -- d', 'UPDATE items SET a = (a + 1) -- u']
|
3579
3142
|
end
|
3580
3143
|
end
|
3581
3144
|
|
3582
3145
|
describe "Sequel::Dataset#each_server" do
|
3583
|
-
before do
|
3584
|
-
@db = Sequel::Database.new(:servers=>{:s=>{}, :i=>{}})
|
3585
|
-
@ds = @db[:items]
|
3586
|
-
sqls = @sqls = []
|
3587
|
-
@db.meta_def(:execute) do |sql, opts|
|
3588
|
-
sqls << [sql, opts[:server]]
|
3589
|
-
end
|
3590
|
-
def @ds.fetch_rows(sql, &block)
|
3591
|
-
execute(sql)
|
3592
|
-
end
|
3593
|
-
end
|
3594
|
-
|
3595
3146
|
specify "should yield a dataset for each server" do
|
3147
|
+
@db = Sequel.mock(:servers=>{:s=>{}, :i=>{}})
|
3148
|
+
@ds = @db[:items]
|
3596
3149
|
@ds.each_server do |ds|
|
3597
3150
|
ds.should be_a_kind_of(Sequel::Dataset)
|
3598
3151
|
ds.should_not == @ds
|
3599
3152
|
ds.sql.should == @ds.sql
|
3600
3153
|
ds.all
|
3601
3154
|
end
|
3602
|
-
@sqls.
|
3155
|
+
@db.sqls.sort.should == ['SELECT * FROM items', 'SELECT * FROM items -- i', 'SELECT * FROM items -- s']
|
3603
3156
|
end
|
3604
3157
|
end
|
3605
3158
|
|
@@ -3649,23 +3202,23 @@ end
|
|
3649
3202
|
|
3650
3203
|
describe "Sequel::Dataset#qualify" do
|
3651
3204
|
specify "should qualify to the given table" do
|
3652
|
-
|
3205
|
+
Sequel::Dataset.new(nil).from(:t).filter{a<b}.qualify(:e).sql.should == 'SELECT e.* FROM t WHERE (e.a < e.b)'
|
3653
3206
|
end
|
3654
3207
|
|
3655
3208
|
specify "should qualify to the first source if no table if given" do
|
3656
|
-
|
3209
|
+
Sequel::Dataset.new(nil).from(:t).filter{a<b}.qualify.sql.should == 'SELECT t.* FROM t WHERE (t.a < t.b)'
|
3657
3210
|
end
|
3658
3211
|
end
|
3659
3212
|
|
3660
3213
|
describe "Sequel::Dataset#qualify_to" do
|
3661
3214
|
specify "should qualify to the given table" do
|
3662
|
-
|
3215
|
+
Sequel::Dataset.new(nil).from(:t).filter{a<b}.qualify_to(:e).sql.should == 'SELECT e.* FROM t WHERE (e.a < e.b)'
|
3663
3216
|
end
|
3664
3217
|
end
|
3665
3218
|
|
3666
3219
|
describe "Sequel::Dataset#qualify_to_first_source" do
|
3667
3220
|
before do
|
3668
|
-
@ds =
|
3221
|
+
@ds = Sequel::Database.new[:t]
|
3669
3222
|
end
|
3670
3223
|
|
3671
3224
|
specify "should qualify_to the first source" do
|
@@ -3675,13 +3228,11 @@ describe "Sequel::Dataset#qualify_to_first_source" do
|
|
3675
3228
|
end
|
3676
3229
|
|
3677
3230
|
specify "should handle the select, order, where, having, and group options/clauses" do
|
3678
|
-
@ds.select(:a).filter(:a=>1).order(:a).group(:a).having(:a).qualify_to_first_source.sql.should ==
|
3679
|
-
'SELECT t.a FROM t WHERE (t.a = 1) GROUP BY t.a HAVING t.a ORDER BY t.a'
|
3231
|
+
@ds.select(:a).filter(:a=>1).order(:a).group(:a).having(:a).qualify_to_first_source.sql.should == 'SELECT t.a FROM t WHERE (t.a = 1) GROUP BY t.a HAVING t.a ORDER BY t.a'
|
3680
3232
|
end
|
3681
3233
|
|
3682
3234
|
specify "should handle the select using a table.* if all columns are currently selected" do
|
3683
|
-
@ds.filter(:a=>1).order(:a).group(:a).having(:a).qualify_to_first_source.sql.should ==
|
3684
|
-
'SELECT t.* FROM t WHERE (t.a = 1) GROUP BY t.a HAVING t.a ORDER BY t.a'
|
3235
|
+
@ds.filter(:a=>1).order(:a).group(:a).having(:a).qualify_to_first_source.sql.should == 'SELECT t.* FROM t WHERE (t.a = 1) GROUP BY t.a HAVING t.a ORDER BY t.a'
|
3685
3236
|
end
|
3686
3237
|
|
3687
3238
|
specify "should handle hashes in select option" do
|
@@ -3750,14 +3301,13 @@ describe "Sequel::Dataset#qualify_to_first_source" do
|
|
3750
3301
|
end
|
3751
3302
|
|
3752
3303
|
specify "should handle all other objects by returning them unchanged" do
|
3753
|
-
@ds.select("a").filter{a(3)}.filter('blah').order('true'.lit).group('a > ?'.lit(1)).having(false).qualify_to_first_source.sql.should ==
|
3754
|
-
"SELECT 'a' FROM t WHERE (a(3) AND (blah)) GROUP BY a > 1 HAVING 'f' ORDER BY true"
|
3304
|
+
@ds.select("a").filter{a(3)}.filter('blah').order('true'.lit).group('a > ?'.lit(1)).having(false).qualify_to_first_source.sql.should == "SELECT 'a' FROM t WHERE (a(3) AND (blah)) GROUP BY a > 1 HAVING 'f' ORDER BY true"
|
3755
3305
|
end
|
3756
3306
|
end
|
3757
3307
|
|
3758
3308
|
describe "Sequel::Dataset#unbind" do
|
3759
3309
|
before do
|
3760
|
-
@ds =
|
3310
|
+
@ds = Sequel::Database.new[:t]
|
3761
3311
|
@u = proc{|ds| ds, bv = ds.unbind; [ds.sql, bv]}
|
3762
3312
|
end
|
3763
3313
|
|
@@ -3827,7 +3377,7 @@ end
|
|
3827
3377
|
|
3828
3378
|
describe "Sequel::Dataset #with and #with_recursive" do
|
3829
3379
|
before do
|
3830
|
-
@db =
|
3380
|
+
@db = Sequel::Database.new
|
3831
3381
|
@ds = @db[:t]
|
3832
3382
|
end
|
3833
3383
|
|
@@ -3868,11 +3418,18 @@ describe "Sequel::Dataset #with and #with_recursive" do
|
|
3868
3418
|
@ds.with(:t, @db[:x]).update_sql(:foo=>1).should == 'WITH t AS (SELECT * FROM x) UPDATE t SET foo = 1'
|
3869
3419
|
@ds.with(:t, @db[:x]).delete_sql.should == 'WITH t AS (SELECT * FROM x) DELETE FROM t'
|
3870
3420
|
end
|
3421
|
+
|
3422
|
+
specify "should hoist WITH clauses in given dataset(s) if dataset doesn't support WITH in subselect" do
|
3423
|
+
@ds.meta_def(:supports_cte?){true}
|
3424
|
+
@ds.meta_def(:supports_cte_in_subselect?){false}
|
3425
|
+
@ds.with(:t, @ds.from(:s).with(:s, @ds.from(:r))).sql.should == 'WITH s AS (SELECT * FROM r), t AS (SELECT * FROM s) SELECT * FROM t'
|
3426
|
+
@ds.with_recursive(:t, @ds.from(:s).with(:s, @ds.from(:r)), @ds.from(:q).with(:q, @ds.from(:p))).sql.should == 'WITH s AS (SELECT * FROM r), q AS (SELECT * FROM p), t AS (SELECT * FROM s UNION ALL SELECT * FROM q) SELECT * FROM t'
|
3427
|
+
end
|
3871
3428
|
end
|
3872
3429
|
|
3873
3430
|
describe Sequel::SQL::Constants do
|
3874
3431
|
before do
|
3875
|
-
@db =
|
3432
|
+
@db = Sequel::Database.new
|
3876
3433
|
end
|
3877
3434
|
|
3878
3435
|
it "should have CURRENT_DATE" do
|
@@ -3917,7 +3474,7 @@ end
|
|
3917
3474
|
|
3918
3475
|
describe "Sequel timezone support" do
|
3919
3476
|
before do
|
3920
|
-
@db =
|
3477
|
+
@db = Sequel::Database.new
|
3921
3478
|
@dataset = @db.dataset
|
3922
3479
|
@dataset.meta_def(:supports_timestamp_timezones?){true}
|
3923
3480
|
@dataset.meta_def(:supports_timestamp_usecs?){false}
|
@@ -3952,6 +3509,30 @@ describe "Sequel timezone support" do
|
|
3952
3509
|
@dataset.literal(t).should == "#{s}#{@offset}'"
|
3953
3510
|
end
|
3954
3511
|
|
3512
|
+
specify "should have Database#timezone override Sequel.database_timezone" do
|
3513
|
+
Sequel.database_timezone = :local
|
3514
|
+
@db.timezone = :utc
|
3515
|
+
|
3516
|
+
t = Time.now
|
3517
|
+
s = t.getutc.strftime("'%Y-%m-%d %H:%M:%S")
|
3518
|
+
@dataset.literal(t).should == "#{s}+0000'"
|
3519
|
+
|
3520
|
+
t = DateTime.now
|
3521
|
+
s = t.new_offset(0).strftime("'%Y-%m-%d %H:%M:%S")
|
3522
|
+
@dataset.literal(t).should == "#{s}+0000'"
|
3523
|
+
|
3524
|
+
Sequel.database_timezone = :utc
|
3525
|
+
@db.timezone = :local
|
3526
|
+
|
3527
|
+
t = Time.now.utc
|
3528
|
+
s = t.getlocal.strftime("'%Y-%m-%d %H:%M:%S")
|
3529
|
+
@dataset.literal(t).should == "#{s}#{@offset}'"
|
3530
|
+
|
3531
|
+
t = DateTime.now.new_offset(0)
|
3532
|
+
s = t.new_offset(DateTime.now.offset).strftime("'%Y-%m-%d %H:%M:%S")
|
3533
|
+
@dataset.literal(t).should == "#{s}#{@offset}'"
|
3534
|
+
end
|
3535
|
+
|
3955
3536
|
specify "should handle converting database timestamps into application timestamps" do
|
3956
3537
|
Sequel.database_timezone = :utc
|
3957
3538
|
Sequel.application_timezone = :local
|
@@ -4062,13 +3643,7 @@ end
|
|
4062
3643
|
|
4063
3644
|
describe "Sequel::Dataset#select_map" do
|
4064
3645
|
before do
|
4065
|
-
@ds =
|
4066
|
-
def @ds.fetch_rows(sql)
|
4067
|
-
db << sql
|
4068
|
-
yield({:c=>1})
|
4069
|
-
yield({:c=>2})
|
4070
|
-
end
|
4071
|
-
@ds.db.reset
|
3646
|
+
@ds = Sequel.mock(:fetch=>[{:c=>1}, {:c=>2}])[:t]
|
4072
3647
|
end
|
4073
3648
|
|
4074
3649
|
specify "should do select and map in one step" do
|
@@ -4099,21 +3674,19 @@ describe "Sequel::Dataset#select_map" do
|
|
4099
3674
|
specify "should handle an array of columns" do
|
4100
3675
|
@ds.select_map([:c, :c]).should == [[1, 1], [2, 2]]
|
4101
3676
|
@ds.db.sqls.should == ['SELECT c, c FROM t']
|
4102
|
-
@ds.
|
4103
|
-
@ds.
|
4104
|
-
|
3677
|
+
@ds.select_map([:d.as(:c), :c.qualify(:b), :c.identifier, :c.identifier.qualify(:b), :a__c, :a__d___c]).should == [[1, 1, 1, 1, 1, 1], [2, 2, 2, 2, 2, 2]]
|
3678
|
+
@ds.db.sqls.should == ['SELECT d AS c, b.c, c, b.c, a.c, a.d AS c FROM t']
|
3679
|
+
end
|
3680
|
+
|
3681
|
+
specify "should handle an array with a single element" do
|
3682
|
+
@ds.select_map([:c]).should == [[1], [2]]
|
3683
|
+
@ds.db.sqls.should == ['SELECT c FROM t']
|
4105
3684
|
end
|
4106
3685
|
end
|
4107
3686
|
|
4108
3687
|
describe "Sequel::Dataset#select_order_map" do
|
4109
3688
|
before do
|
4110
|
-
@ds =
|
4111
|
-
def @ds.fetch_rows(sql)
|
4112
|
-
db << sql
|
4113
|
-
yield({:c=>1})
|
4114
|
-
yield({:c=>2})
|
4115
|
-
end
|
4116
|
-
@ds.db.reset
|
3689
|
+
@ds = Sequel.mock(:fetch=>[{:c=>1}, {:c=>2}])[:t]
|
4117
3690
|
end
|
4118
3691
|
|
4119
3692
|
specify "should do select and map in one step" do
|
@@ -4154,73 +3727,65 @@ describe "Sequel::Dataset#select_order_map" do
|
|
4154
3727
|
specify "should handle an array of columns" do
|
4155
3728
|
@ds.select_order_map([:c, :c]).should == [[1, 1], [2, 2]]
|
4156
3729
|
@ds.db.sqls.should == ['SELECT c, c FROM t ORDER BY c, c']
|
4157
|
-
@ds.db.reset
|
4158
3730
|
@ds.select_order_map([:d.as(:c), :c.qualify(:b), :c.identifier, :c.identifier.qualify(:b), :c.identifier.qualify(:b).desc, :a__c, :a__d___c.desc]).should == [[1, 1, 1, 1, 1, 1, 1], [2, 2, 2, 2, 2, 2, 2]]
|
4159
3731
|
@ds.db.sqls.should == ['SELECT d AS c, b.c, c, b.c, b.c, a.c, a.d AS c FROM t ORDER BY d, b.c, c, b.c, b.c DESC, a.c, a.d DESC']
|
4160
3732
|
end
|
3733
|
+
|
3734
|
+
specify "should handle an array with a single element" do
|
3735
|
+
@ds.select_order_map([:c]).should == [[1], [2]]
|
3736
|
+
@ds.db.sqls.should == ['SELECT c FROM t ORDER BY c']
|
3737
|
+
end
|
4161
3738
|
end
|
4162
3739
|
|
4163
3740
|
describe "Sequel::Dataset#select_hash" do
|
4164
3741
|
before do
|
4165
|
-
@
|
4166
|
-
|
4167
|
-
@hs = hs
|
4168
|
-
end
|
4169
|
-
def @ds.fetch_rows(sql)
|
4170
|
-
db << sql
|
4171
|
-
@hs.each{|h| yield h}
|
4172
|
-
end
|
4173
|
-
@ds.db.reset
|
3742
|
+
@db = Sequel.mock(:fetch=>[{:a=>1, :b=>2}, {:a=>3, :b=>4}])
|
3743
|
+
@ds = @db[:t]
|
4174
3744
|
end
|
4175
3745
|
|
4176
3746
|
specify "should do select and to_hash in one step" do
|
4177
|
-
@ds.set_fr_yield([{:a=>1, :b=>2}, {:a=>3, :b=>4}])
|
4178
3747
|
@ds.select_hash(:a, :b).should == {1=>2, 3=>4}
|
4179
3748
|
@ds.db.sqls.should == ['SELECT a, b FROM t']
|
4180
3749
|
end
|
4181
3750
|
|
4182
3751
|
specify "should handle implicit qualifiers in arguments" do
|
4183
|
-
@ds.set_fr_yield([{:a=>1, :b=>2}, {:a=>3, :b=>4}])
|
4184
3752
|
@ds.select_hash(:t__a, :t__b).should == {1=>2, 3=>4}
|
4185
3753
|
@ds.db.sqls.should == ['SELECT t.a, t.b FROM t']
|
4186
3754
|
end
|
4187
3755
|
|
4188
3756
|
specify "should handle implicit aliases in arguments" do
|
4189
|
-
@ds.set_fr_yield([{:a=>1, :b=>2}, {:a=>3, :b=>4}])
|
4190
3757
|
@ds.select_hash(:c___a, :d___b).should == {1=>2, 3=>4}
|
4191
3758
|
@ds.db.sqls.should == ['SELECT c AS a, d AS b FROM t']
|
4192
3759
|
end
|
4193
3760
|
|
4194
3761
|
specify "should handle implicit qualifiers and aliases in arguments" do
|
4195
|
-
@ds.set_fr_yield([{:a=>1, :b=>2}, {:a=>3, :b=>4}])
|
4196
3762
|
@ds.select_hash(:t__c___a, :t__d___b).should == {1=>2, 3=>4}
|
4197
3763
|
@ds.db.sqls.should == ['SELECT t.c AS a, t.d AS b FROM t']
|
4198
3764
|
end
|
4199
3765
|
|
4200
3766
|
specify "should handle SQL::Identifiers in arguments" do
|
4201
|
-
@ds.set_fr_yield([{:a=>1, :b=>2}, {:a=>3, :b=>4}])
|
4202
3767
|
@ds.select_hash(:a.identifier, :b.identifier).should == {1=>2, 3=>4}
|
4203
3768
|
@ds.db.sqls.should == ['SELECT a, b FROM t']
|
4204
3769
|
end
|
4205
3770
|
|
4206
3771
|
specify "should handle SQL::QualifiedIdentifiers in arguments" do
|
4207
|
-
@ds.set_fr_yield([{:a=>1, :b=>2}, {:a=>3, :b=>4}])
|
4208
3772
|
@ds.select_hash(:a.qualify(:t), :b.identifier.qualify(:t)).should == {1=>2, 3=>4}
|
4209
3773
|
@ds.db.sqls.should == ['SELECT t.a, t.b FROM t']
|
4210
3774
|
end
|
4211
3775
|
|
4212
3776
|
specify "should handle SQL::AliasedExpressions in arguments" do
|
4213
|
-
@ds.set_fr_yield([{:a=>1, :b=>2}, {:a=>3, :b=>4}])
|
4214
3777
|
@ds.select_hash(:c.as(:a), :t.as(:b)).should == {1=>2, 3=>4}
|
4215
3778
|
@ds.db.sqls.should == ['SELECT c AS a, t AS b FROM t']
|
4216
3779
|
end
|
4217
3780
|
|
4218
3781
|
specify "should work with arrays of columns" do
|
4219
|
-
@
|
3782
|
+
@db.fetch = [{:a=>1, :b=>2, :c=>3}, {:a=>4, :b=>5, :c=>6}]
|
4220
3783
|
@ds.select_hash([:a, :c], :b).should == {[1, 3]=>2, [4, 6]=>5}
|
4221
3784
|
@ds.db.sqls.should == ['SELECT a, c, b FROM t']
|
4222
3785
|
@ds.select_hash(:a, [:b, :c]).should == {1=>[2, 3], 4=>[5, 6]}
|
3786
|
+
@ds.db.sqls.should == ['SELECT a, b, c FROM t']
|
4223
3787
|
@ds.select_hash([:a, :b], [:b, :c]).should == {[1, 2]=>[2, 3], [4, 5]=>[5, 6]}
|
3788
|
+
@ds.db.sqls.should == ['SELECT a, b, b, c FROM t']
|
4224
3789
|
end
|
4225
3790
|
|
4226
3791
|
specify "should raise an error if the resulting symbol cannot be determined" do
|
@@ -4230,9 +3795,8 @@ end
|
|
4230
3795
|
|
4231
3796
|
describe "Modifying joined datasets" do
|
4232
3797
|
before do
|
4233
|
-
@ds =
|
3798
|
+
@ds = Sequel.mock.from(:b, :c).join(:d, [:id]).where(:id => 2)
|
4234
3799
|
@ds.meta_def(:supports_modifying_joins?){true}
|
4235
|
-
@ds.db.reset
|
4236
3800
|
end
|
4237
3801
|
|
4238
3802
|
specify "should allow deleting from joined datasets" do
|
@@ -4248,7 +3812,7 @@ end
|
|
4248
3812
|
|
4249
3813
|
describe "Dataset#lock_style and for_update" do
|
4250
3814
|
before do
|
4251
|
-
@ds =
|
3815
|
+
@ds = Sequel::Dataset.new(nil).from(:t)
|
4252
3816
|
end
|
4253
3817
|
|
4254
3818
|
specify "#for_update should use FOR UPDATE" do
|
@@ -4271,16 +3835,15 @@ describe "Custom ASTTransformer" do
|
|
4271
3835
|
(s.is_a?(Symbol) || s.is_a?(String)) ? :"#{s}#{s}" : super
|
4272
3836
|
end
|
4273
3837
|
end.new
|
4274
|
-
ds =
|
3838
|
+
ds = Sequel::Dataset.new(nil).from(:t).cross_join(:a___g).join(:b___h, [:c]).join(:d___i, :e=>:f)
|
4275
3839
|
ds.sql.should == 'SELECT * FROM t CROSS JOIN a AS g INNER JOIN b AS h USING (c) INNER JOIN d AS i ON (i.e = h.f)'
|
4276
|
-
ds.clone(:from=>c.transform(ds.opts[:from]), :join=>c.transform(ds.opts[:join])).sql.should ==
|
4277
|
-
'SELECT * FROM tt CROSS JOIN aa AS gg INNER JOIN bb AS hh USING (cc) INNER JOIN dd AS ii ON (ii.ee = hh.ff)'
|
3840
|
+
ds.clone(:from=>c.transform(ds.opts[:from]), :join=>c.transform(ds.opts[:join])).sql.should == 'SELECT * FROM tt CROSS JOIN aa AS gg INNER JOIN bb AS hh USING (cc) INNER JOIN dd AS ii ON (ii.ee = hh.ff)'
|
4278
3841
|
end
|
4279
3842
|
end
|
4280
3843
|
|
4281
3844
|
describe "Dataset#returning" do
|
4282
3845
|
before do
|
4283
|
-
@ds = Sequel
|
3846
|
+
@ds = Sequel.mock(:fetch=>proc{|s| {:foo=>s}})[:t].returning(:foo)
|
4284
3847
|
@pr = proc do
|
4285
3848
|
[:insert, :update, :delete].each do |m|
|
4286
3849
|
@ds.meta_def(:"#{m}_clause_methods"){super() + [:"#{m}_returning_sql"]}
|
@@ -4303,9 +3866,6 @@ describe "Dataset#returning" do
|
|
4303
3866
|
|
4304
3867
|
specify "should have insert, update, and delete yield to blocks if RETURNING is used" do
|
4305
3868
|
@pr.call
|
4306
|
-
def @ds.fetch_rows(sql)
|
4307
|
-
yield(:foo=>sql)
|
4308
|
-
end
|
4309
3869
|
h = {}
|
4310
3870
|
@ds.delete{|r| h = r}
|
4311
3871
|
h.should == {:foo=>"DELETE FROM t RETURNING foo"}
|
@@ -4317,12 +3877,39 @@ describe "Dataset#returning" do
|
|
4317
3877
|
|
4318
3878
|
specify "should have insert, update, and delete return arrays of hashes if RETURNING is used and a block is not given" do
|
4319
3879
|
@pr.call
|
4320
|
-
def @ds.fetch_rows(sql)
|
4321
|
-
yield(:foo=>sql)
|
4322
|
-
end
|
4323
3880
|
h = {}
|
4324
3881
|
@ds.delete.should == [{:foo=>"DELETE FROM t RETURNING foo"}]
|
4325
3882
|
@ds.insert(1).should == [{:foo=>"INSERT INTO t VALUES (1) RETURNING foo"}]
|
4326
3883
|
@ds.update(:foo=>1).should == [{:foo=>"UPDATE t SET foo = 1 RETURNING foo"}]
|
4327
3884
|
end
|
4328
3885
|
end
|
3886
|
+
|
3887
|
+
describe "Dataset emulating bitwise operator support" do
|
3888
|
+
before do
|
3889
|
+
@ds = Sequel::Database.new.dataset
|
3890
|
+
@ds.quote_identifiers = true
|
3891
|
+
def @ds.complex_expression_sql(op, args)
|
3892
|
+
complex_expression_arg_pairs(args){|a, b| "bitand(#{literal(a)}, #{literal(b)})"}
|
3893
|
+
end
|
3894
|
+
end
|
3895
|
+
|
3896
|
+
it "should work with any numbers of arguments for operators" do
|
3897
|
+
@ds.select(Sequel::SQL::ComplexExpression.new(:&, :x)).sql.should == 'SELECT "x"'
|
3898
|
+
@ds.select(:x & 1).sql.should == 'SELECT bitand("x", 1)'
|
3899
|
+
@ds.select(:x & 1 & 2).sql.should == 'SELECT bitand(bitand("x", 1), 2)'
|
3900
|
+
end
|
3901
|
+
end
|
3902
|
+
|
3903
|
+
describe "Dataset feature defaults" do
|
3904
|
+
it "should not require aliases for recursive CTEs by default" do
|
3905
|
+
Sequel::Database.new.dataset.recursive_cte_requires_column_aliases?.should be_false
|
3906
|
+
end
|
3907
|
+
|
3908
|
+
it "should not require placeholder type specifiers by default" do
|
3909
|
+
Sequel::Database.new.dataset.requires_placeholder_type_specifiers?.should be_false
|
3910
|
+
end
|
3911
|
+
|
3912
|
+
it "offset use should be returning a separate row number column by default" do
|
3913
|
+
Sequel::Database.new.dataset.send(:offset_returns_row_number_column?).should be_false
|
3914
|
+
end
|
3915
|
+
end
|