sequel 4.40.0 → 4.41.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +30 -0
- data/Rakefile +6 -3
- data/doc/association_basics.rdoc +3 -3
- data/doc/opening_databases.rdoc +3 -3
- data/doc/release_notes/4.41.0.txt +77 -0
- data/doc/schema_modification.rdoc +11 -11
- data/lib/sequel/adapters/ado.rb +137 -9
- data/lib/sequel/adapters/ado/mssql.rb +1 -1
- data/lib/sequel/adapters/jdbc.rb +1 -1
- data/lib/sequel/adapters/mysql2.rb +0 -1
- data/lib/sequel/adapters/shared/db2.rb +30 -10
- data/lib/sequel/adapters/shared/mssql.rb +11 -6
- data/lib/sequel/database/query.rb +3 -6
- data/lib/sequel/database/schema_generator.rb +7 -1
- data/lib/sequel/database/schema_methods.rb +0 -6
- data/lib/sequel/dataset/actions.rb +4 -4
- data/lib/sequel/dataset/graph.rb +3 -2
- data/lib/sequel/dataset/misc.rb +23 -0
- data/lib/sequel/dataset/mutation.rb +15 -14
- data/lib/sequel/dataset/query.rb +25 -5
- data/lib/sequel/extensions/constraint_validations.rb +1 -3
- data/lib/sequel/extensions/sql_comments.rb +6 -1
- data/lib/sequel/model/associations.rb +7 -1
- data/lib/sequel/model/base.rb +1 -1
- data/lib/sequel/plugins/class_table_inheritance.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +2 -2
- data/lib/sequel/plugins/json_serializer.rb +29 -7
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/firebird_spec.rb +2 -8
- data/spec/adapters/mssql_spec.rb +12 -12
- data/spec/adapters/mysql_spec.rb +11 -11
- data/spec/adapters/postgres_spec.rb +8 -9
- data/spec/adapters/spec_helper.rb +1 -0
- data/spec/adapters/sqlite_spec.rb +1 -3
- data/spec/core/database_spec.rb +3 -2
- data/spec/core/dataset_spec.rb +66 -22
- data/spec/core/expression_filters_spec.rb +4 -0
- data/spec/core/mock_adapter_spec.rb +1 -1
- data/spec/core/schema_generator_spec.rb +1 -1
- data/spec/core/schema_spec.rb +10 -1
- data/spec/core/spec_helper.rb +1 -0
- data/spec/extensions/class_table_inheritance_spec.rb +3 -0
- data/spec/extensions/connection_expiration_spec.rb +1 -1
- data/spec/extensions/graph_each_spec.rb +6 -0
- data/spec/extensions/hook_class_methods_spec.rb +46 -0
- data/spec/extensions/json_serializer_spec.rb +8 -3
- data/spec/extensions/set_overrides_spec.rb +4 -0
- data/spec/extensions/single_table_inheritance_spec.rb +2 -2
- data/spec/extensions/spec_helper.rb +1 -0
- data/spec/extensions/string_agg_spec.rb +4 -0
- data/spec/extensions/uuid_spec.rb +1 -2
- data/spec/integration/associations_test.rb +14 -0
- data/spec/integration/dataset_test.rb +17 -22
- data/spec/integration/schema_test.rb +3 -3
- data/spec/integration/spec_helper.rb +1 -0
- data/spec/integration/type_test.rb +1 -7
- data/spec/model/associations_spec.rb +26 -1
- data/spec/model/model_spec.rb +7 -1
- data/spec/model/spec_helper.rb +2 -0
- data/spec/sequel_warning.rb +4 -0
- metadata +6 -3
@@ -13,7 +13,7 @@ module Sequel
|
|
13
13
|
#
|
14
14
|
# album = Album[1]
|
15
15
|
# album.to_json
|
16
|
-
# # => '{"
|
16
|
+
# # => '{"id"=>1,"name"=>"RF","artist_id"=>2}'
|
17
17
|
#
|
18
18
|
# In addition, you can provide options to control the JSON output:
|
19
19
|
#
|
@@ -22,16 +22,23 @@ module Sequel
|
|
22
22
|
# # => '{"json_class"="Album","name"=>"RF"}'
|
23
23
|
#
|
24
24
|
# album.to_json(:include=>:artist)
|
25
|
-
# # => '{"
|
26
|
-
# # "artist":{"
|
25
|
+
# # => '{"id":1,"name":"RF","artist_id":2,
|
26
|
+
# # "artist":{"id":2,"name":"YJM"}}'
|
27
27
|
#
|
28
28
|
# You can use a hash value with <tt>:include</tt> to pass options
|
29
29
|
# to associations:
|
30
30
|
#
|
31
31
|
# album.to_json(:include=>{:artist=>{:only=>:name}})
|
32
|
-
# # => '{"
|
33
|
-
# # "artist":{"
|
32
|
+
# # => '{"id":1,"name":"RF","artist_id":2,
|
33
|
+
# # "artist":{"name":"YJM"}}'
|
34
34
|
#
|
35
|
+
# You can specify a name for a given association by passing <tt>:name</tt>
|
36
|
+
# to the <tt>:include</tt> hash
|
37
|
+
#
|
38
|
+
# album.to_json(:include=>{Sequel.as(:artist, :singer)=>{:only=>:name}})
|
39
|
+
# # => '{"id":1,"name":"RF","artist_id":2,
|
40
|
+
# # "singer":{"name":"YJM"}}'
|
41
|
+
#
|
35
42
|
# You can specify the <tt>:root</tt> option to nest the JSON under the
|
36
43
|
# name of the model:
|
37
44
|
#
|
@@ -299,6 +306,13 @@ module Sequel
|
|
299
306
|
if inc = opts[:include]
|
300
307
|
if inc.is_a?(Hash)
|
301
308
|
inc.each do |k, v|
|
309
|
+
if k.is_a?(Sequel::SQL::AliasedExpression)
|
310
|
+
key_name = k.aliaz.to_s
|
311
|
+
k = k.expression
|
312
|
+
else
|
313
|
+
key_name = k.to_s
|
314
|
+
end
|
315
|
+
|
302
316
|
v = v.empty? ? [] : [v]
|
303
317
|
|
304
318
|
objs = send(k)
|
@@ -309,14 +323,22 @@ module Sequel
|
|
309
323
|
objs.is_a?(Array)
|
310
324
|
end
|
311
325
|
|
312
|
-
h[
|
326
|
+
h[key_name] = if is_array
|
313
327
|
objs.map{|obj| Literal.new(Sequel.object_to_json(obj, *v))}
|
314
328
|
else
|
315
329
|
Literal.new(Sequel.object_to_json(objs, *v))
|
316
330
|
end
|
317
331
|
end
|
318
332
|
else
|
319
|
-
Array(inc).each
|
333
|
+
Array(inc).each do |c|
|
334
|
+
if c.is_a?(Sequel::SQL::AliasedExpression)
|
335
|
+
key_name = c.aliaz.to_s
|
336
|
+
c = c.expression
|
337
|
+
else
|
338
|
+
key_name = c.to_s
|
339
|
+
end
|
340
|
+
h[key_name] = send(c)
|
341
|
+
end
|
320
342
|
end
|
321
343
|
end
|
322
344
|
|
data/lib/sequel/version.rb
CHANGED
@@ -5,7 +5,7 @@ module Sequel
|
|
5
5
|
MAJOR = 4
|
6
6
|
# The minor version of Sequel. Bumped for every non-patch level
|
7
7
|
# release, generally around once a month.
|
8
|
-
MINOR =
|
8
|
+
MINOR = 41
|
9
9
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
10
10
|
# releases that fix regressions from previous versions.
|
11
11
|
TINY = 0
|
@@ -58,9 +58,8 @@ end
|
|
58
58
|
|
59
59
|
describe "A Firebird dataset" do
|
60
60
|
before do
|
61
|
-
@d = DB[:test]
|
62
|
-
@d.delete
|
63
|
-
@d.quote_identifiers = true
|
61
|
+
@d = DB[:test].with_quote_identifiers(true)
|
62
|
+
@d.delete
|
64
63
|
end
|
65
64
|
|
66
65
|
it "should return the correct record count" do
|
@@ -90,8 +89,6 @@ describe "A Firebird dataset" do
|
|
90
89
|
@d << {:name => 'def', :val => 789}
|
91
90
|
@d.filter(:name => 'abc').update(:val => 530)
|
92
91
|
|
93
|
-
# the third record should stay the same
|
94
|
-
# floating-point precision bullshit
|
95
92
|
@d[:name => 'def'][:val].must_equal 789
|
96
93
|
@d.filter(:val => 530).count.must_equal 2
|
97
94
|
end
|
@@ -112,7 +109,6 @@ describe "A Firebird dataset" do
|
|
112
109
|
end
|
113
110
|
|
114
111
|
it "should quote columns and tables using double quotes if quoting identifiers" do
|
115
|
-
@d.quote_identifiers = true
|
116
112
|
@d.select(:name).sql.must_equal \
|
117
113
|
'SELECT "NAME" FROM "TEST"'
|
118
114
|
|
@@ -157,7 +153,6 @@ describe "A Firebird dataset" do
|
|
157
153
|
end
|
158
154
|
|
159
155
|
it "should quote fields correctly when reversing the order if quoting identifiers" do
|
160
|
-
@d.quote_identifiers = true
|
161
156
|
@d.reverse_order(:name).sql.must_equal \
|
162
157
|
'SELECT * FROM "TEST" ORDER BY "NAME" DESC'
|
163
158
|
|
@@ -220,7 +215,6 @@ describe "A Firebird dataset" do
|
|
220
215
|
|
221
216
|
it "should quote and upcase reserved keywords" do
|
222
217
|
@d = DB[:testing]
|
223
|
-
@d.quote_identifiers = true
|
224
218
|
@d.select(:select).sql.must_equal \
|
225
219
|
'SELECT "SELECT" FROM "TESTING"'
|
226
220
|
end
|
data/spec/adapters/mssql_spec.rb
CHANGED
@@ -247,7 +247,7 @@ describe "Offset support" do
|
|
247
247
|
@db.create_table!(:i){Integer :id; Integer :parent_id}
|
248
248
|
@ds = @db[:i].order(:id)
|
249
249
|
@hs = []
|
250
|
-
@ds
|
250
|
+
@ds = @ds.with_row_proc(proc{|r| @hs << r.dup; r[:id] *= 2; r[:parent_id] *= 3; r})
|
251
251
|
@ds.import [:id, :parent_id], [[1,nil],[2,nil],[3,1],[4,1],[5,3],[6,5]]
|
252
252
|
end
|
253
253
|
after do
|
@@ -356,7 +356,9 @@ describe "MSSSQL::Dataset#insert" do
|
|
356
356
|
end
|
357
357
|
|
358
358
|
it "should have insert_select return nil if the server version is not 2005+" do
|
359
|
-
|
359
|
+
@ds = @ds.with_extend(Module.new do
|
360
|
+
def server_version() 8000760 end
|
361
|
+
end)
|
360
362
|
@ds.insert_select(:value=>10).must_equal nil
|
361
363
|
end
|
362
364
|
|
@@ -424,20 +426,16 @@ describe "A MSSQL database" do
|
|
424
426
|
end
|
425
427
|
|
426
428
|
describe "MSSQL::Database#rename_table" do
|
427
|
-
after do
|
428
|
-
DB.drop_table?(:foo)
|
429
|
-
end
|
430
|
-
|
431
429
|
it "should work on non-schema bound tables which need escaping" do
|
432
430
|
DB.quote_identifiers = true
|
433
431
|
DB.create_table! :'foo bar' do
|
434
432
|
text :name
|
435
433
|
end
|
436
|
-
DB.drop_table? :foo
|
437
434
|
DB.rename_table 'foo bar', 'foo'
|
435
|
+
DB.drop_table :foo
|
438
436
|
end
|
439
437
|
|
440
|
-
it "should work on schema bound tables" do
|
438
|
+
it "should work on schema bound tables within the same schema" do
|
441
439
|
DB.execute(<<-SQL)
|
442
440
|
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'MY')
|
443
441
|
EXECUTE sp_executesql N'create schema MY'
|
@@ -447,6 +445,7 @@ describe "MSSQL::Database#rename_table" do
|
|
447
445
|
end
|
448
446
|
DB.rename_table Sequel[:MY][:foo], Sequel[:MY][:bar]
|
449
447
|
DB.rename_table Sequel[:MY][:bar], :foo
|
448
|
+
DB.drop_table Sequel[:MY][:foo]
|
450
449
|
end
|
451
450
|
end
|
452
451
|
|
@@ -488,10 +487,11 @@ describe "MSSQL::Database#mssql_unicode_strings = false" do
|
|
488
487
|
DB.create_table!(:items){String :name}
|
489
488
|
ds = DB[:items]
|
490
489
|
ds.mssql_unicode_strings.must_equal false
|
491
|
-
|
492
|
-
ds.mssql_unicode_strings.must_equal
|
493
|
-
|
494
|
-
|
490
|
+
ds1 = ds.with_mssql_unicode_strings(true)
|
491
|
+
ds.mssql_unicode_strings.must_equal false
|
492
|
+
ds1.mssql_unicode_strings.must_equal true
|
493
|
+
ds1.insert(:name=>'foo')
|
494
|
+
ds1.select_map(:name).must_equal ['foo']
|
495
495
|
end
|
496
496
|
end
|
497
497
|
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -150,9 +150,10 @@ if [:mysql, :mysql2].include?(DB.adapter_scheme)
|
|
150
150
|
|
151
151
|
it "should allow disabling the conversion on a per-dataset basis" do
|
152
152
|
@db.convert_tinyint_to_bool = true
|
153
|
-
ds = @ds.
|
154
|
-
|
155
|
-
|
153
|
+
ds = @ds.with_extend(Module.new do
|
154
|
+
def cast_tinyint_integer?(f) true end #mysql
|
155
|
+
def convert_tinyint_to_bool?() false end #mysql2
|
156
|
+
end)
|
156
157
|
ds.delete
|
157
158
|
ds << {:b=>true, :i=>10}
|
158
159
|
ds.all.must_equal [{:b=>1, :i=>10}]
|
@@ -172,7 +173,7 @@ describe "A MySQL dataset" do
|
|
172
173
|
end
|
173
174
|
|
174
175
|
it "should quote columns and tables using back-ticks if quoting identifiers" do
|
175
|
-
@d
|
176
|
+
@d = @d.with_quote_identifiers(true)
|
176
177
|
@d.select(:name).sql.must_equal 'SELECT `name` FROM `items`'
|
177
178
|
@d.select(Sequel.lit('COUNT(*)')).sql.must_equal 'SELECT COUNT(*) FROM `items`'
|
178
179
|
@d.select(Sequel.function(:max, :value)).sql.must_equal 'SELECT max(`value`) FROM `items`'
|
@@ -190,7 +191,7 @@ describe "A MySQL dataset" do
|
|
190
191
|
end
|
191
192
|
|
192
193
|
it "should quote fields correctly when reversing the order" do
|
193
|
-
@d
|
194
|
+
@d = @d.with_quote_identifiers(true)
|
194
195
|
@d.reverse_order(:name).sql.must_equal 'SELECT * FROM `items` ORDER BY `name` DESC'
|
195
196
|
@d.reverse_order(Sequel.desc(:name)).sql.must_equal 'SELECT * FROM `items` ORDER BY `name` ASC'
|
196
197
|
@d.reverse_order(:name, Sequel.desc(:test)).sql.must_equal 'SELECT * FROM `items` ORDER BY `name` DESC, `test` ASC'
|
@@ -242,7 +243,7 @@ describe "MySQL datasets" do
|
|
242
243
|
end
|
243
244
|
|
244
245
|
it "should correctly quote column references" do
|
245
|
-
@d
|
246
|
+
@d = @d.with_quote_identifiers(true)
|
246
247
|
market = 'ICE'
|
247
248
|
ack_stamp = Time.now - 15 * 60 # 15 minutes ago
|
248
249
|
@d.select(:market, Sequel.function(:minute, Sequel.function(:from_unixtime, :ack)).as(:minute)).
|
@@ -321,8 +322,7 @@ describe "Joined MySQL dataset" do
|
|
321
322
|
end
|
322
323
|
|
323
324
|
it "should quote fields correctly" do
|
324
|
-
@ds.
|
325
|
-
@ds.join(:attributes, :node_id => :id).sql.must_equal "SELECT * FROM `nodes` INNER JOIN `attributes` ON (`attributes`.`node_id` = `nodes`.`id`)"
|
325
|
+
@ds.with_quote_identifiers(true).join(:attributes, :node_id => :id).sql.must_equal "SELECT * FROM `nodes` INNER JOIN `attributes` ON (`attributes`.`node_id` = `nodes`.`id`)"
|
326
326
|
end
|
327
327
|
|
328
328
|
it "should put a having clause before an order by clause" do
|
@@ -1168,7 +1168,7 @@ if DB.adapter_scheme == :mysql or DB.adapter_scheme == :jdbc or DB.adapter_schem
|
|
1168
1168
|
@d.call_sproc(:select, :test_sproc, 3).must_equal []
|
1169
1169
|
@d.insert(:value=>1)
|
1170
1170
|
@d.call_sproc(:select, :test_sproc, 4).must_equal [{:id=>nil, :value=>1, :b=>4}]
|
1171
|
-
@d
|
1171
|
+
@d = @d.with_row_proc(proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r})
|
1172
1172
|
@d.call_sproc(:select, :test_sproc, 3).must_equal [{:id=>nil, :value=>2, :b=>6}]
|
1173
1173
|
end
|
1174
1174
|
|
@@ -1179,7 +1179,7 @@ if DB.adapter_scheme == :mysql or DB.adapter_scheme == :jdbc or DB.adapter_schem
|
|
1179
1179
|
@d.call_sproc(:select, :test_sproc, 3, 4).must_equal []
|
1180
1180
|
@d.insert(:value=>1)
|
1181
1181
|
@d.call_sproc(:select, :test_sproc, 4, 5).must_equal [{:id=>nil, :value=>1, :b=>4, :d=>5}]
|
1182
|
-
@d
|
1182
|
+
@d = @d.with_row_proc(proc{|r| r.keys.each{|k| r[k] *= 2 if r[k].is_a?(Integer)}; r})
|
1183
1183
|
@d.call_sproc(:select, :test_sproc, 3, 4).must_equal [{:id=>nil, :value=>2, :b=>6, :d => 8}]
|
1184
1184
|
end
|
1185
1185
|
end
|
@@ -1259,7 +1259,7 @@ if DB.adapter_scheme == :mysql
|
|
1259
1259
|
end
|
1260
1260
|
|
1261
1261
|
it "should have regular row_procs work when splitting multiple result sets" do
|
1262
|
-
@ds
|
1262
|
+
@ds = @ds.with_row_proc(proc{|x| x[x.keys.first] *= 2; x})
|
1263
1263
|
@ds.split_multiple_result_sets.all.must_equal [[{:a=>20}, {:a=>30}], [{:b=>40}, {:b=>50}]]
|
1264
1264
|
end
|
1265
1265
|
|
@@ -964,13 +964,10 @@ describe "A PostgreSQL database" do
|
|
964
964
|
@db[:posts].order(:a).map(:a).must_equal [1, 2, 10, 20, 21]
|
965
965
|
end
|
966
966
|
|
967
|
-
it "should support specifying Integer/Bignum
|
967
|
+
it "should support specifying Integer/Bignum types in primary keys and have them be auto incrementing" do
|
968
968
|
@db.create_table(:posts){primary_key :a, :type=>Integer}
|
969
969
|
@db[:posts].insert.must_equal 1
|
970
970
|
@db[:posts].insert.must_equal 2
|
971
|
-
@db.create_table!(:posts){primary_key :a, :type=>Fixnum}
|
972
|
-
@db[:posts].insert.must_equal 1
|
973
|
-
@db[:posts].insert.must_equal 2
|
974
971
|
@db.create_table!(:posts){primary_key :a, :type=>:Bignum}
|
975
972
|
@db[:posts].insert.must_equal 1
|
976
973
|
@db[:posts].insert.must_equal 2
|
@@ -1730,11 +1727,13 @@ if DB.adapter_scheme == :postgres
|
|
1730
1727
|
end
|
1731
1728
|
|
1732
1729
|
it "should handle returning inside block" do
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1730
|
+
ds = @ds.with_extend(Module.new do
|
1731
|
+
def check_return
|
1732
|
+
use_cursor.each{|r| return}
|
1733
|
+
end
|
1734
|
+
end)
|
1735
|
+
ds.check_return
|
1736
|
+
ds.all.must_equal ds.use_cursor.all
|
1738
1737
|
end
|
1739
1738
|
end
|
1740
1739
|
|
@@ -457,9 +457,7 @@ describe "SQLite dataset" do
|
|
457
457
|
end
|
458
458
|
|
459
459
|
it "should have #explain work when identifier_output_method is modified" do
|
460
|
-
|
461
|
-
ds.identifier_output_method = :upcase
|
462
|
-
ds.explain.must_be_kind_of(String)
|
460
|
+
DB[:test].with_identifier_output_method(:upcase).explain.must_be_kind_of(String)
|
463
461
|
end
|
464
462
|
end
|
465
463
|
|
data/spec/core/database_spec.rb
CHANGED
@@ -1899,8 +1899,9 @@ describe "Database#raise_error" do
|
|
1899
1899
|
def @db.database_error_regexps
|
1900
1900
|
{/foo/ => Sequel::DatabaseDisconnectError, /bar/ => Sequel::ConstraintViolation}
|
1901
1901
|
end
|
1902
|
-
|
1903
|
-
proc{@db.send(:raise_error,
|
1902
|
+
e = Class.new(StandardError)
|
1903
|
+
proc{@db.send(:raise_error, e.new('foo'))}.must_raise(Sequel::DatabaseDisconnectError)
|
1904
|
+
proc{@db.send(:raise_error, e.new('bar'))}.must_raise(Sequel::ConstraintViolation)
|
1904
1905
|
end
|
1905
1906
|
end
|
1906
1907
|
|
data/spec/core/dataset_spec.rb
CHANGED
@@ -89,6 +89,33 @@ describe "Dataset" do
|
|
89
89
|
@dataset.send(:output_identifier, "at_b_C").must_equal :C_b_ta
|
90
90
|
end
|
91
91
|
|
92
|
+
it "should have with_quote_identifiers method which returns cloned dataset with changed literalization of identifiers" do
|
93
|
+
@dataset.with_quote_identifiers(true).literal(:a).must_equal '"a"'
|
94
|
+
@dataset.with_quote_identifiers(false).literal(:a).must_equal 'a'
|
95
|
+
ds = @dataset.freeze.with_quote_identifiers(false)
|
96
|
+
ds.literal(:a).must_equal 'a'
|
97
|
+
ds.frozen?.must_equal true
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should have with_identifier_input_method method which returns cloned dataset with changed literalization of identifiers" do
|
101
|
+
@dataset.with_identifier_input_method(:upcase).literal(:a).must_equal 'A'
|
102
|
+
@dataset.with_identifier_input_method(:downcase).literal(:A).must_equal 'a'
|
103
|
+
@dataset.with_identifier_input_method(:reverse).literal(:at_b).must_equal 'b_ta'
|
104
|
+
ds = @dataset.freeze.with_identifier_input_method(:reverse)
|
105
|
+
ds.frozen?.must_equal true
|
106
|
+
ds.literal(:at_b).must_equal 'b_ta'
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should have with_identifier_output_method method which returns cloned dataset with changed identifiers returned from the database" do
|
110
|
+
@dataset.send(:output_identifier, "at_b_C").must_equal :at_b_C
|
111
|
+
@dataset.with_identifier_output_method(:upcase).send(:output_identifier, "at_b_C").must_equal :AT_B_C
|
112
|
+
@dataset.with_identifier_output_method(:downcase).send(:output_identifier, "at_b_C").must_equal :at_b_c
|
113
|
+
@dataset.with_identifier_output_method(:reverse).send(:output_identifier, "at_b_C").must_equal :C_b_ta
|
114
|
+
ds = @dataset.freeze.with_identifier_output_method(:reverse)
|
115
|
+
ds.send(:output_identifier, "at_b_C").must_equal :C_b_ta
|
116
|
+
ds.frozen?.must_equal true
|
117
|
+
end
|
118
|
+
|
92
119
|
it "should have output_identifier handle empty identifiers" do
|
93
120
|
@dataset.send(:output_identifier, "").must_equal :untitled
|
94
121
|
@dataset.identifier_output_method = :upcase
|
@@ -167,8 +194,7 @@ describe "Dataset#==" do
|
|
167
194
|
|
168
195
|
it "should be different for datasets with different SQL" do
|
169
196
|
ds = @db[:t]
|
170
|
-
ds.
|
171
|
-
ds.wont_equal @db[:t]
|
197
|
+
ds.with_quote_identifiers(true).wont_equal ds
|
172
198
|
end
|
173
199
|
end
|
174
200
|
|
@@ -194,8 +220,7 @@ describe "Dataset#hash" do
|
|
194
220
|
|
195
221
|
it "should be different for datasets with different SQL" do
|
196
222
|
ds = @db[:t]
|
197
|
-
ds.
|
198
|
-
ds.hash.wont_equal @db[:t].hash
|
223
|
+
ds.with_quote_identifiers(true).hash.wont_equal ds.hash
|
199
224
|
end
|
200
225
|
end
|
201
226
|
|
@@ -937,7 +962,7 @@ describe "Dataset#literal" do
|
|
937
962
|
end
|
938
963
|
|
939
964
|
it "should support spaces inside column names" do
|
940
|
-
@ds
|
965
|
+
@ds = @ds.with_quote_identifiers(true)
|
941
966
|
@ds.literal(:"AB C").must_equal '"AB C"'
|
942
967
|
@ds.literal(:"Zvas htoy__aB cD").must_equal '"Zvas htoy"."aB cD"'
|
943
968
|
@ds.literal(:"aB cD___XX XX").must_equal '"aB cD" AS "XX XX"'
|
@@ -1061,7 +1086,7 @@ describe "Dataset#literal" do
|
|
1061
1086
|
end
|
1062
1087
|
|
1063
1088
|
it "should not modify literal strings" do
|
1064
|
-
@dataset
|
1089
|
+
@dataset = @dataset.with_quote_identifiers(true)
|
1065
1090
|
@dataset.literal(Sequel.lit('col1 + 2')).must_equal 'col1 + 2'
|
1066
1091
|
@dataset.update_sql(Sequel::SQL::Identifier.new(Sequel.lit('a')) => Sequel.lit('a + 2')).must_equal 'UPDATE "test" SET a = a + 2'
|
1067
1092
|
end
|
@@ -1115,12 +1140,11 @@ describe "Dataset#from" do
|
|
1115
1140
|
end
|
1116
1141
|
|
1117
1142
|
it "should treat string arguments as identifiers" do
|
1118
|
-
@dataset.
|
1119
|
-
@dataset.from('a').select_sql.must_equal "SELECT * FROM \"a\""
|
1143
|
+
@dataset.with_quote_identifiers(true).from('a').select_sql.must_equal "SELECT * FROM \"a\""
|
1120
1144
|
end
|
1121
1145
|
|
1122
1146
|
it "should not treat literal strings or blobs as identifiers" do
|
1123
|
-
@dataset
|
1147
|
+
@dataset = @dataset.with_quote_identifiers(true)
|
1124
1148
|
@dataset.from(Sequel.lit('a')).select_sql.must_equal "SELECT * FROM a"
|
1125
1149
|
@dataset.from(Sequel.blob('a')).select_sql.must_equal "SELECT * FROM 'a'"
|
1126
1150
|
end
|
@@ -1671,6 +1695,31 @@ describe "Dataset#offset" do
|
|
1671
1695
|
end
|
1672
1696
|
end
|
1673
1697
|
|
1698
|
+
describe "Dataset#with_extend" do
|
1699
|
+
it "should returned clone dataset extended with given modules" do
|
1700
|
+
d = Sequel.mock.dataset
|
1701
|
+
m1 = Module.new{def a; 1; end}
|
1702
|
+
m2 = Module.new{def b; a+2; end}
|
1703
|
+
d.with_extend(m1, m2).b.must_equal 3
|
1704
|
+
d.respond_to?(:b).must_equal false
|
1705
|
+
ds = d.freeze.with_extend(m1, m2)
|
1706
|
+
ds.b.must_equal 3
|
1707
|
+
ds.frozen?.must_equal true
|
1708
|
+
end
|
1709
|
+
end
|
1710
|
+
|
1711
|
+
describe "Dataset#with_row_proc" do
|
1712
|
+
it "should returned clone dataset with the given row_proc" do
|
1713
|
+
d = Sequel.mock.dataset
|
1714
|
+
l = lambda{|r| r}
|
1715
|
+
d.with_row_proc(l).row_proc.must_equal l
|
1716
|
+
assert_equal nil, d.row_proc
|
1717
|
+
ds = d.freeze.with_row_proc(l)
|
1718
|
+
ds.frozen?.must_equal true
|
1719
|
+
ds.row_proc.must_equal l
|
1720
|
+
end
|
1721
|
+
end
|
1722
|
+
|
1674
1723
|
describe "Dataset#naked" do
|
1675
1724
|
it "should returned clone dataset without row_proc" do
|
1676
1725
|
d = Sequel.mock.dataset
|
@@ -2126,8 +2175,7 @@ end
|
|
2126
2175
|
|
2127
2176
|
describe "Dataset#join_table" do
|
2128
2177
|
before do
|
2129
|
-
@d = Sequel.mock.dataset.from(:items)
|
2130
|
-
@d.quote_identifiers = true
|
2178
|
+
@d = Sequel.mock.dataset.from(:items).with_quote_identifiers(true)
|
2131
2179
|
end
|
2132
2180
|
|
2133
2181
|
it "should format the JOIN clause properly" do
|
@@ -2791,7 +2839,7 @@ describe "Dataset#single_value!" do
|
|
2791
2839
|
|
2792
2840
|
it "should call each and return the first value of the first record" do
|
2793
2841
|
@db.fetch = [{:a=>1, :b=>2}, {:a=>3, :b=>4}]
|
2794
|
-
@db[:test].single_value!.to_s.must_match
|
2842
|
+
@db[:test].single_value!.to_s.must_match(/\A(1|2)\z/)
|
2795
2843
|
@db.sqls.must_equal ['SELECT * FROM test']
|
2796
2844
|
end
|
2797
2845
|
|
@@ -3302,8 +3350,7 @@ describe "Dataset#insert_sql" do
|
|
3302
3350
|
end
|
3303
3351
|
|
3304
3352
|
it "should quote string keys" do
|
3305
|
-
@ds.
|
3306
|
-
@ds.insert_sql('c' => 'd').must_equal "INSERT INTO \"items\" (\"c\") VALUES ('d')"
|
3353
|
+
@ds.with_quote_identifiers(true).insert_sql('c' => 'd').must_equal "INSERT INTO \"items\" (\"c\") VALUES ('d')"
|
3307
3354
|
end
|
3308
3355
|
|
3309
3356
|
it "should accept array subscript references" do
|
@@ -3712,7 +3759,6 @@ describe "Dataset prepared statements and bound variables " do
|
|
3712
3759
|
end
|
3713
3760
|
|
3714
3761
|
it "should handle usage with Dataset.prepared_statements_module" do
|
3715
|
-
m = Module.new
|
3716
3762
|
@ds.extend(Sequel::Dataset.send(:prepared_statements_module, :prepare_bind, [Sequel::Dataset::ArgumentMapper, Sequel::Dataset::PreparedStatementMethods]){def foo; :bar; end})
|
3717
3763
|
@ds.foo.must_equal :bar
|
3718
3764
|
@ds.prepared_statement_name = 'foo'
|
@@ -4016,7 +4062,7 @@ describe "Sequel::Dataset #with and #with_recursive" do
|
|
4016
4062
|
end
|
4017
4063
|
|
4018
4064
|
it "#with and #with_recursive should quote the columns in the :args option" do
|
4019
|
-
@ds
|
4065
|
+
@ds = @ds.with_quote_identifiers(true)
|
4020
4066
|
@ds.with(:t, @db[:x], :args=>[:b]).sql.must_equal 'WITH "t"("b") AS (SELECT * FROM x) SELECT * FROM "t"'
|
4021
4067
|
@ds.with_recursive(:t, @db[:x], @db[:t], :args=>[:b, :c]).sql.must_equal 'WITH "t"("b", "c") AS (SELECT * FROM x UNION ALL SELECT * FROM t) SELECT * FROM "t"'
|
4022
4068
|
end
|
@@ -4631,8 +4677,7 @@ end
|
|
4631
4677
|
|
4632
4678
|
describe "Dataset emulating bitwise operator support" do
|
4633
4679
|
before do
|
4634
|
-
@ds = Sequel::Database.new.dataset
|
4635
|
-
@ds.quote_identifiers = true
|
4680
|
+
@ds = Sequel::Database.new.dataset.with_quote_identifiers(true)
|
4636
4681
|
def @ds.complex_expression_sql_append(sql, op, args)
|
4637
4682
|
complex_expression_arg_pairs_append(sql, args){|a, b| Sequel.function(:bitand, a, b)}
|
4638
4683
|
end
|
@@ -4681,20 +4726,19 @@ describe "Dataset extensions" do
|
|
4681
4726
|
end
|
4682
4727
|
|
4683
4728
|
it "should be able to register an extension with a block and Database#extension call the block" do
|
4684
|
-
@ds
|
4729
|
+
@ds = @ds.with_quote_identifiers(false)
|
4685
4730
|
Sequel::Dataset.register_extension(:foo){|db| db.quote_identifiers = true}
|
4686
4731
|
@ds.extension(:foo).quote_identifiers?.must_equal true
|
4687
4732
|
end
|
4688
4733
|
|
4689
4734
|
it "should be able to register an extension with a callable and Database#extension call the callable" do
|
4690
|
-
@ds
|
4735
|
+
@ds = @ds.with_quote_identifiers(false)
|
4691
4736
|
Sequel::Dataset.register_extension(:foo, proc{|db| db.quote_identifiers = true})
|
4692
4737
|
@ds.extension(:foo).quote_identifiers?.must_equal true
|
4693
4738
|
end
|
4694
4739
|
|
4695
4740
|
it "should be able to load multiple extensions in the same call" do
|
4696
|
-
@ds
|
4697
|
-
@ds.identifier_input_method = :downcase
|
4741
|
+
@ds = @ds.with_quote_identifiers(false).with_identifier_input_method(:downcase)
|
4698
4742
|
Sequel::Dataset.register_extension(:foo, proc{|ds| ds.quote_identifiers = true})
|
4699
4743
|
Sequel::Dataset.register_extension(:bar, proc{|ds| ds.identifier_input_method = nil})
|
4700
4744
|
ds = @ds.extension(:foo, :bar)
|