sequel 4.40.0 → 4.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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)
|