sequel 4.24.0 → 4.25.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 +40 -0
- data/doc/association_basics.rdoc +2 -5
- data/doc/dataset_basics.rdoc +1 -1
- data/doc/postgresql.rdoc +47 -0
- data/doc/querying.rdoc +5 -0
- data/doc/release_notes/4.25.0.txt +181 -0
- data/lib/sequel/adapters/ibmdb.rb +0 -28
- data/lib/sequel/adapters/shared/db2.rb +31 -2
- data/lib/sequel/adapters/shared/mssql.rb +12 -12
- data/lib/sequel/adapters/shared/postgres.rb +102 -3
- data/lib/sequel/adapters/shared/sqlite.rb +1 -0
- data/lib/sequel/adapters/swift/sqlite.rb +12 -0
- data/lib/sequel/database/schema_generator.rb +4 -0
- data/lib/sequel/database/schema_methods.rb +3 -1
- data/lib/sequel/dataset/actions.rb +1 -1
- data/lib/sequel/dataset/prepared_statements.rb +15 -7
- data/lib/sequel/dataset/query.rb +16 -2
- data/lib/sequel/dataset/sql.rb +19 -16
- data/lib/sequel/extensions/empty_array_consider_nulls.rb +35 -0
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -34
- data/lib/sequel/extensions/pg_json_ops.rb +9 -1
- data/lib/sequel/extensions/query_literals.rb +1 -1
- data/lib/sequel/model/base.rb +7 -11
- data/lib/sequel/model/dataset_module.rb +1 -1
- data/lib/sequel/plugins/association_pks.rb +6 -0
- data/lib/sequel/plugins/dirty.rb +6 -1
- data/lib/sequel/plugins/inverted_subsets.rb +48 -0
- data/lib/sequel/plugins/serialization.rb +2 -0
- data/lib/sequel/plugins/singular_table_names.rb +31 -0
- data/lib/sequel/plugins/static_cache.rb +17 -0
- data/lib/sequel/sql.rb +1 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +12 -0
- data/spec/adapters/mysql_spec.rb +1 -0
- data/spec/adapters/postgres_spec.rb +41 -1
- data/spec/core/database_spec.rb +1 -0
- data/spec/core/dataset_spec.rb +55 -7
- data/spec/core/expression_filters_spec.rb +18 -0
- data/spec/core/schema_spec.rb +10 -2
- data/spec/extensions/association_pks_spec.rb +12 -0
- data/spec/extensions/{empty_array_ignore_nulls_spec.rb → empty_array_consider_nulls_spec.rb} +7 -7
- data/spec/extensions/inverted_subsets_spec.rb +33 -0
- data/spec/extensions/query_literals_spec.rb +16 -0
- data/spec/extensions/serialization_spec.rb +21 -0
- data/spec/extensions/singular_table_names_spec.rb +22 -0
- data/spec/integration/dataset_test.rb +2 -1
- data/spec/integration/prepared_statement_test.rb +35 -1
- data/spec/model/associations_spec.rb +2 -2
- data/spec/model/base_spec.rb +13 -8
- data/spec/model/class_dataset_methods_spec.rb +1 -0
- metadata +10 -5
- data/lib/sequel/adapters/firebird.rb +0 -105
- data/lib/sequel/adapters/informix.rb +0 -68
@@ -45,7 +45,7 @@ module Sequel
|
|
45
45
|
# Note that if you pass a block to these methods, it will use the default
|
46
46
|
# implementation without the special literal handling.
|
47
47
|
module QueryLiterals
|
48
|
-
%w'select select_append select_group select_more group group_and_count order order_append order_more'.each do |m|
|
48
|
+
%w'select select_append select_group select_more group group_and_count group_append order order_append order_more'.each do |m|
|
49
49
|
class_eval(<<-END, __FILE__, __LINE__ + 1)
|
50
50
|
def #{m}(*args)
|
51
51
|
if !block_given? && (l = query_literal(args))
|
data/lib/sequel/model/base.rb
CHANGED
@@ -508,16 +508,12 @@ module Sequel
|
|
508
508
|
end
|
509
509
|
subclass.instance_variable_set(iv, sup_class_value)
|
510
510
|
end
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
end
|
518
|
-
elsif @dataset
|
519
|
-
subclass.set_dataset(@dataset.clone, :inherited=>true) rescue nil
|
520
|
-
end
|
511
|
+
|
512
|
+
if @dataset && self != Model
|
513
|
+
subclass.set_dataset(@dataset.clone, :inherited=>true) rescue nil
|
514
|
+
elsif (n = subclass.name) && !n.to_s.empty?
|
515
|
+
db
|
516
|
+
subclass.set_dataset(subclass.implicit_table_name) rescue nil
|
521
517
|
end
|
522
518
|
end
|
523
519
|
|
@@ -756,7 +752,7 @@ module Sequel
|
|
756
752
|
# dataset methods that accept arguments, you should use define a
|
757
753
|
# method directly inside a #dataset_module block.
|
758
754
|
def subset(name, *args, &block)
|
759
|
-
|
755
|
+
def_dataset_method(name){filter(*args, &block)}
|
760
756
|
end
|
761
757
|
|
762
758
|
# Returns name of primary table for the dataset. If the table for the dataset
|
data/lib/sequel/plugins/dirty.rb
CHANGED
@@ -38,7 +38,12 @@ module Sequel
|
|
38
38
|
# artist.update(:name=>'Bar')
|
39
39
|
# artist.column_changes # => {}
|
40
40
|
# artist.previous_changes # => {:name=>['Foo', 'Bar']}
|
41
|
-
#
|
41
|
+
#
|
42
|
+
# There is one caveat; when used with a column that also uses the
|
43
|
+
# serialization plugin, setting the column back to its original value
|
44
|
+
# after changing it is not correctly detected and will leave an entry
|
45
|
+
# in changed_columns.
|
46
|
+
#
|
42
47
|
# Usage:
|
43
48
|
#
|
44
49
|
# # Make all model subclass instances record previous values (called before loading subclasses)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Sequel
|
2
|
+
module Plugins
|
3
|
+
# The inverted_subsets plugin adds another method for each defined
|
4
|
+
# subset, which inverts the condition supplied. By default, inverted
|
5
|
+
# subset method names are prefixed with not_.
|
6
|
+
#
|
7
|
+
# You can change the prefix, or indeed entirely customise the inverted names,
|
8
|
+
# by passing a block to the plugin configuration:
|
9
|
+
#
|
10
|
+
# # Use an exclude_ prefix for inverted subsets instead of not_
|
11
|
+
# Album.plugin(:inverted_subsets){|name| "exclude_#{name}"}
|
12
|
+
#
|
13
|
+
# Usage:
|
14
|
+
#
|
15
|
+
# # Add inverted subsets in the Album class
|
16
|
+
# Album.plugin :inverted_subsets
|
17
|
+
#
|
18
|
+
# # This will now create two methods, published and not_published
|
19
|
+
# Album.subset :published, :published => true
|
20
|
+
#
|
21
|
+
# Album.published.sql
|
22
|
+
# # SELECT * FROM albums WHERE (published IS TRUE)
|
23
|
+
#
|
24
|
+
# Album.not_published.sql
|
25
|
+
# # SELECT * FROM albums WHERE (published IS NOT TRUE)
|
26
|
+
#
|
27
|
+
module InvertedSubsets
|
28
|
+
# Default naming for inverted subsets
|
29
|
+
DEFAULT_NAME_BLOCK = lambda{|name| "not_#{name}"}
|
30
|
+
|
31
|
+
# Store the supplied block for calling later when subsets are defined, or
|
32
|
+
# create a default one if we need to.
|
33
|
+
def self.configure(model, &block)
|
34
|
+
model.instance_variable_set(:@inverted_subsets_name_block, block || DEFAULT_NAME_BLOCK)
|
35
|
+
end
|
36
|
+
|
37
|
+
module ClassMethods
|
38
|
+
Plugins.inherited_instance_variables(self, :@inverted_subsets_name_block => nil)
|
39
|
+
|
40
|
+
# Define a not_ prefixed subset which inverts the subset condition.
|
41
|
+
def subset(name, *args, &block)
|
42
|
+
super
|
43
|
+
def_dataset_method(@inverted_subsets_name_block.call(name)){exclude(*args, &block)}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -165,6 +165,8 @@ module Sequel
|
|
165
165
|
define_method("#{column}=") do |v|
|
166
166
|
if !changed_columns.include?(column) && (new? || get_column_value(column) != v)
|
167
167
|
changed_columns << column
|
168
|
+
|
169
|
+
will_change_column(column) if respond_to?(:will_change_column)
|
168
170
|
end
|
169
171
|
|
170
172
|
deserialized_values[column] = v
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Sequel
|
2
|
+
module Plugins
|
3
|
+
# The singular_table_names plugin changes the default
|
4
|
+
# table names for subclasses to not assume a plural version.
|
5
|
+
# By default, Sequel assumes table names for models use
|
6
|
+
# the plural versions.
|
7
|
+
#
|
8
|
+
# Note that this plugin only affects subclasses of the
|
9
|
+
# class it is loaded into, it does not affect the
|
10
|
+
# current class. So it only makes sense to load this
|
11
|
+
# into Sequel::Model itself, or a subclass of Sequel::Model
|
12
|
+
# that is created via Class.new.
|
13
|
+
#
|
14
|
+
# Usage:
|
15
|
+
#
|
16
|
+
# # Don't assume pluralized table names
|
17
|
+
# Sequel::Model.plugin :singular_table_names
|
18
|
+
module SingularTableNames
|
19
|
+
module ClassMethods
|
20
|
+
# Returns the implicit table name for the model class, which is the demodulized,
|
21
|
+
# underscored, name of the class.
|
22
|
+
#
|
23
|
+
# Artist.implicit_table_name # => :artist
|
24
|
+
# Foo::ArtistAlias.implicit_table_name # => :artist_alias
|
25
|
+
def implicit_table_name
|
26
|
+
underscore(demodulize(name)).to_sym
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -35,6 +35,23 @@ module Sequel
|
|
35
35
|
# # Cache the AlbumType class statically, but return unfrozen instances
|
36
36
|
# # that can be modified.
|
37
37
|
# AlbumType.plugin :static_cache, :frozen=>false
|
38
|
+
#
|
39
|
+
# If you would like the speed benefits of keeping :frozen=>true but still need
|
40
|
+
# to occasionally update objects, you can side-step the before_ hooks by
|
41
|
+
# overriding the class method +static_cache_allow_modifications?+ to return true:
|
42
|
+
#
|
43
|
+
# class Model
|
44
|
+
# plugin :static_cache
|
45
|
+
#
|
46
|
+
# def self.static_cache_allow_modifications?
|
47
|
+
# true
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# Now if you +#dup+ a Model object (the resulting object is not frozen), you
|
52
|
+
# will be able to update and save the duplicate.
|
53
|
+
# Note the caveats around your responsibility to update the cache still applies.
|
54
|
+
#
|
38
55
|
module StaticCache
|
39
56
|
# Populate the static caches when loading the plugin. Options:
|
40
57
|
# :frozen :: Whether retrieved model objects are frozen. The default is true,
|
data/lib/sequel/sql.rb
CHANGED
data/lib/sequel/version.rb
CHANGED
@@ -3,7 +3,7 @@ module Sequel
|
|
3
3
|
MAJOR = 4
|
4
4
|
# The minor version of Sequel. Bumped for every non-patch level
|
5
5
|
# release, generally around once a month.
|
6
|
-
MINOR =
|
6
|
+
MINOR = 25
|
7
7
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
8
8
|
# releases that fix regressions from previous versions.
|
9
9
|
TINY = 0
|
data/spec/adapters/db2_spec.rb
CHANGED
@@ -66,6 +66,7 @@ describe Sequel::Database do
|
|
66
66
|
after do
|
67
67
|
@db.drop_table(:items)
|
68
68
|
end
|
69
|
+
|
69
70
|
it "should parse primary keys from the schema properly" do
|
70
71
|
@db.create_table!(:items){Integer :number}
|
71
72
|
@db.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.must_equal []
|
@@ -74,6 +75,17 @@ describe Sequel::Database do
|
|
74
75
|
@db.create_table!(:items){Integer :number1, :null => false; Integer :number2, :null => false; primary_key [:number1, :number2]}
|
75
76
|
@db.schema(:items).collect{|k,v| k if v[:primary_key]}.compact.must_equal [:number1, :number2]
|
76
77
|
end
|
78
|
+
|
79
|
+
it "should not error on alter_table operations that need REORG" do
|
80
|
+
@db.create_table!(:items) do
|
81
|
+
varchar :a
|
82
|
+
end
|
83
|
+
@db.alter_table(:items) do
|
84
|
+
add_column :b, :varchar, :null => true
|
85
|
+
set_column_allow_null :a, false
|
86
|
+
add_index :a, :unique => true
|
87
|
+
end
|
88
|
+
end
|
77
89
|
end
|
78
90
|
|
79
91
|
describe "Sequel::IBMDB.convert_smallint_to_bool" do
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -11,7 +11,11 @@ def logger.method_missing(m, msg)
|
|
11
11
|
end
|
12
12
|
DB.loggers << logger
|
13
13
|
|
14
|
-
DB.extension :pg_array, :pg_hstore, :pg_range, :
|
14
|
+
DB.extension :pg_array, :pg_hstore, :pg_range, :pg_row, :pg_inet, :pg_json, :pg_enum
|
15
|
+
begin
|
16
|
+
DB.extension :pg_interval
|
17
|
+
rescue LoadError
|
18
|
+
end
|
15
19
|
|
16
20
|
describe "PostgreSQL", '#create_table' do
|
17
21
|
before do
|
@@ -168,6 +172,42 @@ describe "PostgreSQL views" do
|
|
168
172
|
end
|
169
173
|
end
|
170
174
|
|
175
|
+
describe "PostgreSQL", 'INSERT ON CONFLICT' do
|
176
|
+
before(:all) do
|
177
|
+
@db = DB
|
178
|
+
@db.create_table!(:ic_test){Integer :a; Integer :b; unique :a, :name=>:ic_test_a_uidx}
|
179
|
+
@ds = @db[:ic_test]
|
180
|
+
end
|
181
|
+
before do
|
182
|
+
@ds.delete
|
183
|
+
end
|
184
|
+
after(:all) do
|
185
|
+
@db.drop_table?(:ic_test)
|
186
|
+
end
|
187
|
+
|
188
|
+
it "Dataset#insert_ignore and insert_constraint should ignore uniqueness violations" do
|
189
|
+
@ds.insert(1, 2)
|
190
|
+
proc{@ds.insert(1, 3)}.must_raise Sequel::UniqueConstraintViolation
|
191
|
+
@ds.insert_ignore.insert(1, 3).must_equal nil
|
192
|
+
@ds.insert_conflict.insert(1, 3).must_equal nil
|
193
|
+
@ds.insert_conflict(:target=>:a).insert(1, 3).must_equal nil
|
194
|
+
@ds.insert_conflict(:constraint=>:ic_test_a_uidx).insert(1, 3).must_equal nil
|
195
|
+
@ds.all.must_equal [{:a=>1, :b=>2}]
|
196
|
+
end
|
197
|
+
|
198
|
+
it "Dataset#insert_constraint should handle upserts" do
|
199
|
+
@ds.insert(1, 2)
|
200
|
+
@ds.insert_conflict(:target=>:a, :update=>{:b=>3}).insert(1, 3).must_equal nil
|
201
|
+
@ds.all.must_equal [{:a=>1, :b=>3}]
|
202
|
+
@ds.insert_conflict(:constraint=>:ic_test_a_uidx, :update=>{:b=>4}).insert(1, 3).must_equal nil
|
203
|
+
@ds.all.must_equal [{:a=>1, :b=>4}]
|
204
|
+
@ds.insert_conflict(:constraint=>:ic_test_a_uidx, :update=>{:b=>5}, :update_where=>{:ic_test__b=>4}).insert(1, 3).must_equal nil
|
205
|
+
@ds.all.must_equal [{:a=>1, :b=>5}]
|
206
|
+
@ds.insert_conflict(:constraint=>:ic_test_a_uidx, :update=>{:b=>6}, :update_where=>{:ic_test__b=>4}).insert(1, 3).must_equal nil
|
207
|
+
@ds.all.must_equal [{:a=>1, :b=>5}]
|
208
|
+
end
|
209
|
+
end if DB.server_version >= 90500
|
210
|
+
|
171
211
|
describe "A PostgreSQL database" do
|
172
212
|
before(:all) do
|
173
213
|
@db = DB
|
data/spec/core/database_spec.rb
CHANGED
@@ -1683,6 +1683,7 @@ end
|
|
1683
1683
|
|
1684
1684
|
describe "Database#each_server with do/jdbc adapter connection string without :adapter option" do
|
1685
1685
|
it "should yield a separate database object for each server" do
|
1686
|
+
require 'sequel/adapters/mock'
|
1686
1687
|
klass = Class.new(Sequel::Database)
|
1687
1688
|
def klass.adapter_class(v)
|
1688
1689
|
raise unless v == :jdbc
|
data/spec/core/dataset_spec.rb
CHANGED
@@ -475,10 +475,10 @@ describe "Dataset#where" do
|
|
475
475
|
end
|
476
476
|
|
477
477
|
it "should handle all types of IN/NOT IN queries with empty arrays" do
|
478
|
-
@dataset.filter(:id => []).sql.must_equal "SELECT * FROM test WHERE (
|
479
|
-
@dataset.filter([:id1, :id2] => []).sql.must_equal "SELECT * FROM test WHERE (
|
480
|
-
@dataset.exclude(:id => []).sql.must_equal "SELECT * FROM test WHERE (
|
481
|
-
@dataset.exclude([:id1, :id2] => []).sql.must_equal "SELECT * FROM test WHERE (
|
478
|
+
@dataset.filter(:id => []).sql.must_equal "SELECT * FROM test WHERE (1 = 0)"
|
479
|
+
@dataset.filter([:id1, :id2] => []).sql.must_equal "SELECT * FROM test WHERE (1 = 0)"
|
480
|
+
@dataset.exclude(:id => []).sql.must_equal "SELECT * FROM test WHERE (1 = 1)"
|
481
|
+
@dataset.exclude([:id1, :id2] => []).sql.must_equal "SELECT * FROM test WHERE (1 = 1)"
|
482
482
|
end
|
483
483
|
|
484
484
|
it "should handle all types of IN/NOT IN queries" do
|
@@ -517,9 +517,9 @@ describe "Dataset#where" do
|
|
517
517
|
meta_def(@dataset, :supports_multiple_column_in?){false}
|
518
518
|
db = Sequel.mock
|
519
519
|
d1 = db[:test].select(:id1, :id2).filter(:region=>'Asia').columns(:id1, :id2)
|
520
|
-
@dataset.filter([:id1, :id2] => d1).sql.must_equal "SELECT * FROM test WHERE (
|
520
|
+
@dataset.filter([:id1, :id2] => d1).sql.must_equal "SELECT * FROM test WHERE (1 = 0)"
|
521
521
|
db.sqls.must_equal ["SELECT id1, id2 FROM test WHERE (region = 'Asia')"]
|
522
|
-
@dataset.exclude([:id1, :id2] => d1).sql.must_equal "SELECT * FROM test WHERE (
|
522
|
+
@dataset.exclude([:id1, :id2] => d1).sql.must_equal "SELECT * FROM test WHERE (1 = 1)"
|
523
523
|
db.sqls.must_equal ["SELECT id1, id2 FROM test WHERE (region = 'Asia')"]
|
524
524
|
end
|
525
525
|
|
@@ -875,6 +875,25 @@ describe "Dataset#group_by" do
|
|
875
875
|
end
|
876
876
|
end
|
877
877
|
|
878
|
+
describe "Dataset#group_append" do
|
879
|
+
before do
|
880
|
+
@d = Sequel.mock.dataset.from(:test)
|
881
|
+
end
|
882
|
+
|
883
|
+
it "should group by the given columns if no existing columns are present" do
|
884
|
+
@d.group_append(:a).sql.must_equal 'SELECT * FROM test GROUP BY a'
|
885
|
+
end
|
886
|
+
|
887
|
+
it "should add to the currently grouped columns" do
|
888
|
+
@d.group(:a).group_append(:b).sql.must_equal 'SELECT * FROM test GROUP BY a, b'
|
889
|
+
end
|
890
|
+
|
891
|
+
it "should accept a block that yields a virtual row" do
|
892
|
+
@d.group(:a).group_append{:b}.sql.must_equal 'SELECT * FROM test GROUP BY a, b'
|
893
|
+
@d.group(:a).group_append(:c){b}.sql.must_equal 'SELECT * FROM test GROUP BY a, c, b'
|
894
|
+
end
|
895
|
+
end
|
896
|
+
|
878
897
|
describe "Dataset#as" do
|
879
898
|
it "should set up an alias" do
|
880
899
|
dataset = Sequel.mock.dataset.from(:test)
|
@@ -3405,10 +3424,15 @@ describe "Dataset default #fetch_rows, #insert, #update, #delete, #truncate, #ex
|
|
3405
3424
|
proc{@ds.having(:a=>1).truncate}.must_raise(Sequel::InvalidOperation)
|
3406
3425
|
end
|
3407
3426
|
|
3408
|
-
it "#execute should execute the SQL on the database" do
|
3427
|
+
it "#execute should execute the SQL on the read_only database" do
|
3409
3428
|
@ds.send(:execute, 'SELECT 1')
|
3410
3429
|
@db.sqls.must_equal ["SELECT 1 -- read_only"]
|
3411
3430
|
end
|
3431
|
+
|
3432
|
+
it "#execute should execute the SQL on the default database if locking is used" do
|
3433
|
+
@ds.for_update.send(:execute, 'SELECT 1')
|
3434
|
+
@db.sqls.must_equal ["SELECT 1"]
|
3435
|
+
end
|
3412
3436
|
end
|
3413
3437
|
|
3414
3438
|
describe "Dataset#with_sql_*" do
|
@@ -3542,6 +3566,30 @@ describe "Dataset prepared statements and bound variables " do
|
|
3542
3566
|
'INSERT INTO items (num) VALUES (1) RETURNING *']
|
3543
3567
|
end
|
3544
3568
|
|
3569
|
+
it "#call and #prepare should handle returning" do
|
3570
|
+
meta_def(@ds, :supports_returning?){|_| true}
|
3571
|
+
meta_def(@ds, :insert_sql){|*v| "#{super(*v)} RETURNING *" }
|
3572
|
+
meta_def(@ds, :update_sql){|*v| "#{super(*v)} RETURNING *" }
|
3573
|
+
meta_def(@ds, :delete_sql){"#{super()} RETURNING *" }
|
3574
|
+
@ds = @ds.returning
|
3575
|
+
@ds.call(:insert, {:n=>1}, :num=>:$n)
|
3576
|
+
@ds.filter(:num=>:$n).call(:update, {:n=>1, :n2=>2}, :num=>:$n2)
|
3577
|
+
@ds.filter(:num=>:$n).call(:delete, :n=>1)
|
3578
|
+
@ds.prepare(:insert, :insert_rn, :num=>:$n).call(:n=>1)
|
3579
|
+
@ds.filter(:num=>:$n).prepare(:update, :update_rn, :num=>:$n2).call(:n=>1, :n2=>2)
|
3580
|
+
@ds.filter(:num=>:$n).prepare(:delete, :delete_rn).call(:n=>1)
|
3581
|
+
@db.sqls.must_equal([
|
3582
|
+
'INSERT INTO items (num) VALUES (1) RETURNING *',
|
3583
|
+
'UPDATE items SET num = 2 WHERE (num = 1) RETURNING *',
|
3584
|
+
'DELETE FROM items WHERE (num = 1) RETURNING *',
|
3585
|
+
]*2)
|
3586
|
+
end
|
3587
|
+
|
3588
|
+
it "PreparedStatement#prepare should raise an error" do
|
3589
|
+
ps = @ds.prepare(:select, :select_n)
|
3590
|
+
proc{ps.prepare(:select, :select_n2)}.must_raise Sequel::Error
|
3591
|
+
end
|
3592
|
+
|
3545
3593
|
it "#call should default to using :all if an invalid type is given" do
|
3546
3594
|
@ds.filter(:num=>:$n).call(:select_all, :n=>1)
|
3547
3595
|
@db.sqls.must_equal ['SELECT * FROM items WHERE (num = 1)']
|
@@ -68,8 +68,17 @@ describe "Blockless Ruby Filters" do
|
|
68
68
|
@d.l{x =~ (1...5)}.must_equal '((x >= 1) AND (x < 5))'
|
69
69
|
@d.l{x =~ [1,2,3]}.must_equal '(x IN (1, 2, 3))'
|
70
70
|
|
71
|
+
@d.l{(x + y) =~ 100}.must_equal '((x + y) = 100)'
|
72
|
+
@d.l{(x + y) =~ 'a'}.must_equal '((x + y) = \'a\')'
|
73
|
+
@d.l{(x + y) =~ true}.must_equal '((x + y) IS TRUE)'
|
74
|
+
@d.l{(x + y) =~ false}.must_equal '((x + y) IS FALSE)'
|
75
|
+
@d.l{(x + y) =~ nil}.must_equal '((x + y) IS NULL)'
|
76
|
+
@d.l{(x + y) =~ (1...5)}.must_equal '(((x + y) >= 1) AND ((x + y) < 5))'
|
77
|
+
@d.l{(x + y) =~ [1,2,3]}.must_equal '((x + y) IN (1, 2, 3))'
|
78
|
+
|
71
79
|
def @d.supports_regexp?; true end
|
72
80
|
@d.l{x =~ /blah/}.must_equal '(x ~ \'blah\')'
|
81
|
+
@d.l{(x + y) =~ /blah/}.must_equal '((x + y) ~ \'blah\')'
|
73
82
|
end
|
74
83
|
|
75
84
|
if RUBY_VERSION >= '1.9'
|
@@ -82,8 +91,17 @@ describe "Blockless Ruby Filters" do
|
|
82
91
|
@d.l{x !~ (1...5)}.must_equal '((x < 1) OR (x >= 5))'
|
83
92
|
@d.l{x !~ [1,2,3]}.must_equal '(x NOT IN (1, 2, 3))'
|
84
93
|
|
94
|
+
@d.l{(x + y) !~ 100}.must_equal '((x + y) != 100)'
|
95
|
+
@d.l{(x + y) !~ 'a'}.must_equal '((x + y) != \'a\')'
|
96
|
+
@d.l{(x + y) !~ true}.must_equal '((x + y) IS NOT TRUE)'
|
97
|
+
@d.l{(x + y) !~ false}.must_equal '((x + y) IS NOT FALSE)'
|
98
|
+
@d.l{(x + y) !~ nil}.must_equal '((x + y) IS NOT NULL)'
|
99
|
+
@d.l{(x + y) !~ (1...5)}.must_equal '(((x + y) < 1) OR ((x + y) >= 5))'
|
100
|
+
@d.l{(x + y) !~ [1,2,3]}.must_equal '((x + y) NOT IN (1, 2, 3))'
|
101
|
+
|
85
102
|
def @d.supports_regexp?; true end
|
86
103
|
@d.l{x !~ /blah/}.must_equal '(x !~ \'blah\')'
|
104
|
+
@d.l{(x + y) !~ /blah/}.must_equal '((x + y) !~ \'blah\')'
|
87
105
|
end
|
88
106
|
end
|
89
107
|
|