sequel 4.24.0 → 4.25.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|