sequel 4.48.0 → 4.49.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +56 -0
- data/doc/advanced_associations.rdoc +1 -1
- data/doc/opening_databases.rdoc +3 -2
- data/doc/release_notes/4.49.0.txt +222 -0
- data/lib/sequel/adapters/ibmdb.rb +6 -1
- data/lib/sequel/adapters/jdbc.rb +3 -1
- data/lib/sequel/adapters/jdbc/h2.rb +10 -1
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -2
- data/lib/sequel/adapters/jdbc/sqlserver.rb +9 -2
- data/lib/sequel/adapters/mock.rb +3 -0
- data/lib/sequel/adapters/mysql2.rb +1 -1
- data/lib/sequel/adapters/postgres.rb +2 -1
- data/lib/sequel/adapters/shared/mysql.rb +4 -1
- data/lib/sequel/adapters/shared/oracle.rb +26 -3
- data/lib/sequel/connection_pool.rb +9 -2
- data/lib/sequel/connection_pool/sharded_single.rb +1 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +1 -1
- data/lib/sequel/connection_pool/single.rb +2 -2
- data/lib/sequel/connection_pool/threaded.rb +2 -2
- data/lib/sequel/database/connecting.rb +3 -3
- data/lib/sequel/database/dataset_defaults.rb +14 -1
- data/lib/sequel/dataset.rb +1 -1
- data/lib/sequel/dataset/actions.rb +54 -0
- data/lib/sequel/dataset/dataset_module.rb +58 -0
- data/lib/sequel/dataset/query.rb +3 -3
- data/lib/sequel/exceptions.rb +8 -0
- data/lib/sequel/extensions/_model_pg_row.rb +5 -2
- data/lib/sequel/extensions/current_datetime_timestamp.rb +2 -1
- data/lib/sequel/extensions/date_arithmetic.rb +1 -0
- data/lib/sequel/extensions/duplicate_columns_handler.rb +2 -2
- data/lib/sequel/extensions/migration.rb +5 -2
- data/lib/sequel/extensions/null_dataset.rb +1 -0
- data/lib/sequel/model/associations.rb +3 -0
- data/lib/sequel/model/base.rb +10 -55
- data/lib/sequel/model/dataset_module.rb +5 -43
- data/lib/sequel/model/errors.rb +2 -1
- data/lib/sequel/model/inflections.rb +17 -5
- data/lib/sequel/plugins/active_model.rb +2 -2
- data/lib/sequel/plugins/class_table_inheritance.rb +1 -0
- data/lib/sequel/plugins/composition.rb +2 -2
- data/lib/sequel/plugins/dataset_associations.rb +25 -13
- data/lib/sequel/plugins/json_serializer.rb +2 -2
- data/lib/sequel/plugins/pg_row.rb +4 -2
- data/lib/sequel/plugins/serialization.rb +1 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +6 -1
- data/lib/sequel/plugins/touch.rb +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +10 -2
- data/lib/sequel/sql.rb +16 -7
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +4 -4
- data/spec/adapters/mysql_spec.rb +5 -1
- data/spec/adapters/oracle_spec.rb +4 -0
- data/spec/bin_spec.rb +7 -1
- data/spec/core/connection_pool_spec.rb +28 -14
- data/spec/core/database_spec.rb +149 -0
- data/spec/core/dataset_spec.rb +173 -0
- data/spec/extensions/class_table_inheritance_spec.rb +58 -17
- data/spec/extensions/composition_spec.rb +13 -0
- data/spec/extensions/dataset_associations_spec.rb +12 -0
- data/spec/extensions/many_through_many_spec.rb +4 -4
- data/spec/extensions/null_dataset_spec.rb +1 -1
- data/spec/extensions/serialization_spec.rb +1 -1
- data/spec/extensions/single_table_inheritance_spec.rb +16 -0
- data/spec/extensions/validation_helpers_spec.rb +1 -2
- data/spec/integration/associations_test.rb +8 -0
- data/spec/integration/plugin_test.rb +8 -3
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +29 -9
- data/spec/model/class_dataset_methods_spec.rb +6 -0
- data/spec/model/eager_loading_spec.rb +8 -8
- data/spec/model/plugins_spec.rb +34 -0
- data/spec/model/record_spec.rb +1 -1
- data/spec/spec_config.rb +2 -0
- metadata +5 -2
@@ -53,7 +53,9 @@ module Sequel
|
|
53
53
|
# Address.load(:street=>'123 Foo St', :city=>'Bar Town', :zip=>'12345'))
|
54
54
|
module PgRow
|
55
55
|
ROW = 'ROW'.freeze
|
56
|
+
Sequel::Deprecation.deprecate_constant(self, :ROW)
|
56
57
|
CAST = '::'.freeze
|
58
|
+
Sequel::Deprecation.deprecate_constant(self, :CAST)
|
57
59
|
|
58
60
|
# When loading the extension, make sure the database has the pg_row extension
|
59
61
|
# loaded, load the custom database extensions, and automatically register the
|
@@ -75,9 +77,9 @@ module Sequel
|
|
75
77
|
module InstanceMethods
|
76
78
|
# Literalize the model instance and append it to the sql.
|
77
79
|
def sql_literal_append(ds, sql)
|
78
|
-
sql << ROW
|
80
|
+
sql << 'ROW'
|
79
81
|
ds.literal_append(sql, values.values_at(*columns))
|
80
|
-
sql <<
|
82
|
+
sql << '::'
|
81
83
|
ds.quote_schema_table_append(sql, model.dataset.first_source_table)
|
82
84
|
end
|
83
85
|
end
|
@@ -149,6 +149,7 @@ module Sequel
|
|
149
149
|
# The columns that will be serialized. This is only for
|
150
150
|
# backwards compatibility, use serialization_map in new code.
|
151
151
|
def serialized_columns
|
152
|
+
Sequel::Deprecation.deprecate("#{self}.serialized_columns in the serialization plugin", "Use #{self}.serialization_map.keys instead")
|
152
153
|
serialization_map.keys
|
153
154
|
end
|
154
155
|
|
@@ -182,7 +182,12 @@ module Sequel
|
|
182
182
|
# Return an instance of the class specified by sti_key,
|
183
183
|
# used by the row_proc.
|
184
184
|
def sti_load(r)
|
185
|
-
|
185
|
+
sti_class_from_sti_key(r[sti_key]).call(r)
|
186
|
+
end
|
187
|
+
|
188
|
+
# Return the sti class based on one of the keys from sti_model_map.
|
189
|
+
def sti_class_from_sti_key(key)
|
190
|
+
sti_class(sti_model_map[key])
|
186
191
|
end
|
187
192
|
|
188
193
|
# Make sure that all subclasses of the parent class correctly include
|
data/lib/sequel/plugins/touch.rb
CHANGED
@@ -31,6 +31,7 @@ module Sequel
|
|
31
31
|
module Touch
|
32
32
|
# The default column to update when touching
|
33
33
|
TOUCH_COLUMN_DEFAULT = :updated_at
|
34
|
+
Sequel::Deprecation.deprecate_constant(self, :TOUCH_COLUMN_DEFAULT)
|
34
35
|
|
35
36
|
def self.apply(model, opts=OPTS)
|
36
37
|
model.instance_variable_set(:@touched_associations, {})
|
@@ -46,7 +47,7 @@ module Sequel
|
|
46
47
|
# If a hash is used, the value is used as the column to update.
|
47
48
|
# :column :: The column to modify when touching a model instance.
|
48
49
|
def self.configure(model, opts=OPTS)
|
49
|
-
model.touch_column = opts[:column] ||
|
50
|
+
model.touch_column = opts[:column] || :updated_at if opts[:column] || !model.touch_column
|
50
51
|
model.touch_associations(opts[:associations]) if opts[:associations]
|
51
52
|
end
|
52
53
|
|
@@ -90,6 +90,8 @@ module Sequel
|
|
90
90
|
:presence=>{:message=>lambda{"is not present"}},
|
91
91
|
:unique=>{:message=>lambda{'is already taken'}}
|
92
92
|
}
|
93
|
+
DEFAULT__OPTIONS = DEFAULT_OPTIONS
|
94
|
+
Sequel::Deprecation.deprecate_constant(self, :DEFAULT_OPTIONS)
|
93
95
|
|
94
96
|
module InstanceMethods
|
95
97
|
# Check that the attribute values are the given exact length.
|
@@ -129,7 +131,13 @@ module Sequel
|
|
129
131
|
# Accepts a :nil_message option that is the error message to use when the
|
130
132
|
# value is nil instead of being too long.
|
131
133
|
def validates_max_length(max, atts, opts=OPTS)
|
132
|
-
validatable_attributes_for_type(:max_length, atts, opts)
|
134
|
+
validatable_attributes_for_type(:max_length, atts, opts) do |a,v,m|
|
135
|
+
if v.nil?
|
136
|
+
validation_error_message(opts[:nil_message] || default_validation_helpers_options(:max_length)[:nil_message])
|
137
|
+
elsif v.length > max
|
138
|
+
validation_error_message(m, max)
|
139
|
+
end
|
140
|
+
end
|
133
141
|
end
|
134
142
|
|
135
143
|
# Check that the attribute values are not shorter than the given min length.
|
@@ -268,7 +276,7 @@ module Sequel
|
|
268
276
|
# The hash return must include a :message option that is either a
|
269
277
|
# proc or string.
|
270
278
|
def default_validation_helpers_options(type)
|
271
|
-
|
279
|
+
DEFAULT__OPTIONS[type]
|
272
280
|
end
|
273
281
|
|
274
282
|
# Skip validating any attribute that matches one of the allow_* options.
|
data/lib/sequel/sql.rb
CHANGED
@@ -1030,10 +1030,13 @@ module Sequel
|
|
1030
1030
|
# The expression to alias
|
1031
1031
|
attr_reader :expression
|
1032
1032
|
|
1033
|
-
# The alias to use for the expression
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1033
|
+
# The alias to use for the expression
|
1034
|
+
attr_reader :alias
|
1035
|
+
|
1036
|
+
def aliaz
|
1037
|
+
Sequel::Deprecation.deprecate("Sequel::SQL::AliasedExpression#aliaz", "Use #alias instead")
|
1038
|
+
self.alias
|
1039
|
+
end
|
1037
1040
|
|
1038
1041
|
# The columns aliases to use, for when the aliased expression is
|
1039
1042
|
# a record or set of records (such as a dataset).
|
@@ -1042,7 +1045,7 @@ module Sequel
|
|
1042
1045
|
# Create an object with the given expression and alias.
|
1043
1046
|
def initialize(expression, aliaz, columns=nil)
|
1044
1047
|
@expression = expression
|
1045
|
-
@
|
1048
|
+
@alias = aliaz
|
1046
1049
|
@columns = columns
|
1047
1050
|
freeze
|
1048
1051
|
end
|
@@ -1359,7 +1362,11 @@ module Sequel
|
|
1359
1362
|
|
1360
1363
|
# The SQL function to call
|
1361
1364
|
attr_reader :name
|
1362
|
-
|
1365
|
+
|
1366
|
+
def f
|
1367
|
+
Sequel::Deprecation.deprecate("Sequel::SQL::Function#f", "Use #name instead")
|
1368
|
+
name
|
1369
|
+
end
|
1363
1370
|
|
1364
1371
|
# The array of arguments to pass to the function (may be blank)
|
1365
1372
|
attr_reader :args
|
@@ -1917,7 +1924,9 @@ module Sequel
|
|
1917
1924
|
# For a more detailed explanation, see the {Virtual Rows guide}[rdoc-ref:doc/virtual_rows.rdoc].
|
1918
1925
|
class VirtualRow < BasicObject
|
1919
1926
|
QUESTION_MARK = LiteralString.new('?').freeze
|
1927
|
+
Sequel::Deprecation.deprecate_constant(self, :QUESTION_MARK)
|
1920
1928
|
DOUBLE_UNDERSCORE = '__'.freeze
|
1929
|
+
Sequel::Deprecation.deprecate_constant(self, :DOUBLE_UNDERSCORE)
|
1921
1930
|
|
1922
1931
|
include OperatorBuilders
|
1923
1932
|
|
@@ -1972,7 +1981,7 @@ module Sequel
|
|
1972
1981
|
end
|
1973
1982
|
elsif args.empty?
|
1974
1983
|
if split = Sequel.split_symbols?
|
1975
|
-
table, column = m.to_s.split(
|
1984
|
+
table, column = m.to_s.split('__', 2)
|
1976
1985
|
if column && split == :deprecated
|
1977
1986
|
Sequel::Deprecation.deprecate("Splitting virtual row method names", "Either set Sequel.split_symbols = true, or change #{m.inspect} to #{table}[:#{column}]")
|
1978
1987
|
end
|
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 = 49
|
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
|
data/spec/adapters/mssql_spec.rb
CHANGED
@@ -17,13 +17,13 @@ describe "A MSSQL database" do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
it "should be able to read fractional part of timestamp" do
|
20
|
-
rs = @db["select getutcdate() as full_date, cast(datepart(millisecond, getutcdate()) as int) as milliseconds"].first
|
21
|
-
rs[:milliseconds].
|
20
|
+
rs = @db["select getutcdate() as full_date, cast(round(datepart(millisecond, getutcdate()), 0) as int) as milliseconds"].first
|
21
|
+
rs[:milliseconds].must_be_close_to(rs[:full_date].usec/1000, 2)
|
22
22
|
end
|
23
23
|
|
24
24
|
it "should be able to write fractional part of timestamp" do
|
25
|
-
t = Time.utc(2001, 12, 31, 23, 59, 59,
|
26
|
-
(t.usec/1000).must_equal @db["select cast(datepart(millisecond, ?) as int) as milliseconds", t].get
|
25
|
+
t = Time.utc(2001, 12, 31, 23, 59, 59, 996000)
|
26
|
+
(t.usec/1000).must_equal @db["select cast(round(datepart(millisecond, ?), 0) as int) as milliseconds", t].get
|
27
27
|
end
|
28
28
|
|
29
29
|
it "should not raise an error when getting the server version" do
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -318,7 +318,7 @@ describe "MySQL join expressions" do
|
|
318
318
|
it "should support cross joins" do
|
319
319
|
@ds.join_table(:cross, :nodes).sql.must_equal 'SELECT * FROM `nodes` CROSS JOIN `nodes`'
|
320
320
|
end
|
321
|
-
|
321
|
+
deprecated "should support cross joins as inner joins if conditions are used" do
|
322
322
|
@ds.join_table(:cross, :nodes, :id=>:id).sql.must_equal 'SELECT * FROM `nodes` INNER JOIN `nodes` ON (`nodes`.`id` = `nodes`.`id`)'
|
323
323
|
end
|
324
324
|
it "should support straight joins (force left table to be read before right)" do
|
@@ -1367,6 +1367,10 @@ if DB.adapter_scheme == :mysql2
|
|
1367
1367
|
it "should correctly handle early returning when streaming results" do
|
1368
1368
|
3.times{@ds.each{|r| break r[:a]}.must_equal 0}
|
1369
1369
|
end
|
1370
|
+
|
1371
|
+
it "#paged_each should bypass streaming when :stream => false passed in" do
|
1372
|
+
DB[:a].order(:a).paged_each(:stream => false){|x| DB[:a].first; break}
|
1373
|
+
end
|
1370
1374
|
end
|
1371
1375
|
end
|
1372
1376
|
|
@@ -2,6 +2,10 @@ SEQUEL_ADAPTER_TEST = :oracle
|
|
2
2
|
|
3
3
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
4
4
|
|
5
|
+
unless DB.opts[:autosequence]
|
6
|
+
warn "Running oracle adapter specs without :autosequence Database option results in many errors, use the :autosequence Database option when testing"
|
7
|
+
end
|
8
|
+
|
5
9
|
describe "An Oracle database" do
|
6
10
|
before(:all) do
|
7
11
|
DB.create_table!(:items) do
|
data/spec/bin_spec.rb
CHANGED
@@ -40,7 +40,13 @@ describe "bin/sequel" do
|
|
40
40
|
DB2.disconnect
|
41
41
|
File.delete(BIN_SPEC_DB) if File.file?(BIN_SPEC_DB)
|
42
42
|
File.delete(BIN_SPEC_DB2) if File.file?(BIN_SPEC_DB2)
|
43
|
-
|
43
|
+
if File.file?(TMP_FILE)
|
44
|
+
begin
|
45
|
+
File.delete(TMP_FILE)
|
46
|
+
rescue Errno::ENOENT
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
end
|
44
50
|
File.delete(OUTPUT) if File.file?(OUTPUT)
|
45
51
|
end
|
46
52
|
|
@@ -18,6 +18,16 @@ describe "An empty ConnectionPool" do
|
|
18
18
|
@cpool = Sequel::ConnectionPool.get_pool(mock_db.call, CONNECTION_POOL_DEFAULTS)
|
19
19
|
end
|
20
20
|
|
21
|
+
deprecated "should support :pool_class option with string" do
|
22
|
+
begin
|
23
|
+
c = Class.new(Sequel::ConnectionPool)
|
24
|
+
Sequel::ConnectionPool::CONNECTION_POOL__MAP[:foo] = c
|
25
|
+
Sequel::ConnectionPool.get_pool(mock_db.call, :pool_class=>:foo).must_be_instance_of c
|
26
|
+
ensure
|
27
|
+
Sequel::ConnectionPool::CONNECTION_POOL__MAP.delete(c)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
21
31
|
it "should have no available connections" do
|
22
32
|
@cpool.available_connections.must_equal []
|
23
33
|
end
|
@@ -26,9 +36,13 @@ describe "An empty ConnectionPool" do
|
|
26
36
|
@cpool.allocated.must_equal({})
|
27
37
|
end
|
28
38
|
|
29
|
-
|
39
|
+
deprecated "should have a created_count of zero" do
|
30
40
|
@cpool.created_count.must_equal 0
|
31
41
|
end
|
42
|
+
|
43
|
+
it "should have a size of zero" do
|
44
|
+
@cpool.size.must_equal 0
|
45
|
+
end
|
32
46
|
end
|
33
47
|
|
34
48
|
describe "ConnectionPool options" do
|
@@ -54,11 +68,11 @@ describe "A connection pool handling connections" do
|
|
54
68
|
@cpool = Sequel::ConnectionPool.get_pool(mock_db.call(proc{|c| msp.call}){:got_connection}, CONNECTION_POOL_DEFAULTS.merge(:max_connections=>@max_size))
|
55
69
|
end
|
56
70
|
|
57
|
-
it "#hold should increment #
|
71
|
+
it "#hold should increment #size" do
|
58
72
|
@cpool.hold do
|
59
|
-
@cpool.
|
60
|
-
@cpool.hold {@cpool.hold {@cpool.
|
61
|
-
Thread.new{@cpool.hold {_(@cpool.
|
73
|
+
@cpool.size.must_equal 1
|
74
|
+
@cpool.hold {@cpool.hold {@cpool.size.must_equal 1}}
|
75
|
+
Thread.new{@cpool.hold {_(@cpool.size).must_equal 2}}.join
|
62
76
|
end
|
63
77
|
end
|
64
78
|
|
@@ -100,7 +114,7 @@ describe "A connection pool handling connections" do
|
|
100
114
|
q = Queue.new
|
101
115
|
50.times{Thread.new{@cpool.hold{q.pop}}}
|
102
116
|
50.times{q.push nil}
|
103
|
-
@cpool.
|
117
|
+
@cpool.size.must_be :<=, @max_size
|
104
118
|
end
|
105
119
|
|
106
120
|
it "database's disconnect connection method should be called when a disconnect is detected" do
|
@@ -110,16 +124,16 @@ describe "A connection pool handling connections" do
|
|
110
124
|
end
|
111
125
|
|
112
126
|
it "#hold should remove the connection if a DatabaseDisconnectError is raised" do
|
113
|
-
@cpool.
|
127
|
+
@cpool.size.must_equal 0
|
114
128
|
q, q1 = Queue.new, Queue.new
|
115
129
|
@cpool.hold{Thread.new{@cpool.hold{q1.pop; q.push nil}; q1.pop; q.push nil}; q1.push nil; q.pop; q1.push nil; q.pop}
|
116
|
-
@cpool.
|
130
|
+
@cpool.size.must_equal 2
|
117
131
|
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
|
118
|
-
@cpool.
|
132
|
+
@cpool.size.must_equal 1
|
119
133
|
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
|
120
|
-
@cpool.
|
134
|
+
@cpool.size.must_equal 0
|
121
135
|
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.must_raise(Sequel::DatabaseDisconnectError)
|
122
|
-
@cpool.
|
136
|
+
@cpool.size.must_equal 0
|
123
137
|
end
|
124
138
|
end
|
125
139
|
|
@@ -127,13 +141,13 @@ describe "A connection pool handling connection errors" do
|
|
127
141
|
it "#hold should raise a Sequel::DatabaseConnectionError if an exception is raised by the connection_proc" do
|
128
142
|
cpool = Sequel::ConnectionPool.get_pool(mock_db.call{raise Interrupt}, CONNECTION_POOL_DEFAULTS)
|
129
143
|
proc{cpool.hold{:block_return}}.must_raise(Sequel::DatabaseConnectionError)
|
130
|
-
cpool.
|
144
|
+
cpool.size.must_equal 0
|
131
145
|
end
|
132
146
|
|
133
147
|
it "#hold should raise a Sequel::DatabaseConnectionError if nil is returned by the connection_proc" do
|
134
148
|
cpool = Sequel::ConnectionPool.get_pool(mock_db.call{nil}, CONNECTION_POOL_DEFAULTS)
|
135
149
|
proc{cpool.hold{:block_return}}.must_raise(Sequel::DatabaseConnectionError)
|
136
|
-
cpool.
|
150
|
+
cpool.size.must_equal 0
|
137
151
|
end
|
138
152
|
end
|
139
153
|
|
@@ -1100,7 +1114,7 @@ AllConnectionPoolClassesSpecs = shared_description do
|
|
1100
1114
|
end
|
1101
1115
|
end
|
1102
1116
|
|
1103
|
-
Sequel::ConnectionPool::
|
1117
|
+
Sequel::ConnectionPool::CONNECTION_POOL__MAP.keys.each do |k, v|
|
1104
1118
|
opts = {:single_threaded=>k, :servers=>(v ? {} : nil)}
|
1105
1119
|
describe "Connection pool with #{opts.inspect}" do
|
1106
1120
|
before(:all) do
|
data/spec/core/database_spec.rb
CHANGED
@@ -517,6 +517,130 @@ describe "Database#extend_datasets" do
|
|
517
517
|
end
|
518
518
|
end
|
519
519
|
|
520
|
+
describe "Database#extend_datasets custom methods" do
|
521
|
+
before do
|
522
|
+
@db = Sequel.mock
|
523
|
+
end
|
524
|
+
|
525
|
+
def ds
|
526
|
+
@db[:items]
|
527
|
+
end
|
528
|
+
|
529
|
+
it "should have dataset_module support a where method" do
|
530
|
+
@db.extend_datasets{where :released, :released}
|
531
|
+
ds.released.sql.must_equal 'SELECT * FROM items WHERE released'
|
532
|
+
ds.where(:foo).released.sql.must_equal 'SELECT * FROM items WHERE (foo AND released)'
|
533
|
+
end
|
534
|
+
|
535
|
+
it "should have dataset_module support a having method" do
|
536
|
+
@db.extend_datasets{having(:released){released}}
|
537
|
+
ds.released.sql.must_equal 'SELECT * FROM items HAVING released'
|
538
|
+
ds.where(:foo).released.sql.must_equal 'SELECT * FROM items WHERE foo HAVING released'
|
539
|
+
end
|
540
|
+
|
541
|
+
it "should have dataset_module support an exclude method" do
|
542
|
+
@db.extend_datasets{exclude :released, :released}
|
543
|
+
ds.released.sql.must_equal 'SELECT * FROM items WHERE NOT released'
|
544
|
+
ds.where(:foo).released.sql.must_equal 'SELECT * FROM items WHERE (foo AND NOT released)'
|
545
|
+
end
|
546
|
+
|
547
|
+
it "should have dataset_module support an exclude_having method" do
|
548
|
+
@db.extend_datasets{exclude_having :released, :released}
|
549
|
+
ds.released.sql.must_equal 'SELECT * FROM items HAVING NOT released'
|
550
|
+
ds.where(:foo).released.sql.must_equal 'SELECT * FROM items WHERE foo HAVING NOT released'
|
551
|
+
end
|
552
|
+
|
553
|
+
it "should have dataset_module support a distinct method" do
|
554
|
+
@db.extend_datasets{def supports_distinct_on?; true end; distinct :foo, :baz}
|
555
|
+
ds.foo.sql.must_equal 'SELECT DISTINCT ON (baz) * FROM items'
|
556
|
+
ds.where(:bar).foo.sql.must_equal 'SELECT DISTINCT ON (baz) * FROM items WHERE bar'
|
557
|
+
end
|
558
|
+
|
559
|
+
it "should have dataset_module support a grep method" do
|
560
|
+
@db.extend_datasets{grep :foo, :baz, 'quux%'}
|
561
|
+
ds.foo.sql.must_equal 'SELECT * FROM items WHERE ((baz LIKE \'quux%\' ESCAPE \'\\\'))'
|
562
|
+
ds.where(:bar).foo.sql.must_equal 'SELECT * FROM items WHERE (bar AND ((baz LIKE \'quux%\' ESCAPE \'\\\')))'
|
563
|
+
end
|
564
|
+
|
565
|
+
it "should have dataset_module support a group method" do
|
566
|
+
@db.extend_datasets{group :foo, :baz}
|
567
|
+
ds.foo.sql.must_equal 'SELECT * FROM items GROUP BY baz'
|
568
|
+
ds.where(:bar).foo.sql.must_equal 'SELECT * FROM items WHERE bar GROUP BY baz'
|
569
|
+
end
|
570
|
+
|
571
|
+
it "should have dataset_module support a group_and_count method" do
|
572
|
+
@db.extend_datasets{group_and_count :foo, :baz}
|
573
|
+
ds.foo.sql.must_equal 'SELECT baz, count(*) AS count FROM items GROUP BY baz'
|
574
|
+
ds.where(:bar).foo.sql.must_equal 'SELECT baz, count(*) AS count FROM items WHERE bar GROUP BY baz'
|
575
|
+
end
|
576
|
+
|
577
|
+
it "should have dataset_module support a group_append method" do
|
578
|
+
@db.extend_datasets{group_append :foo, :baz}
|
579
|
+
ds.foo.sql.must_equal 'SELECT * FROM items GROUP BY baz'
|
580
|
+
ds.group(:bar).foo.sql.must_equal 'SELECT * FROM items GROUP BY bar, baz'
|
581
|
+
end
|
582
|
+
|
583
|
+
it "should have dataset_module support a limit method" do
|
584
|
+
@db.extend_datasets{limit :foo, 1}
|
585
|
+
ds.foo.sql.must_equal 'SELECT * FROM items LIMIT 1'
|
586
|
+
ds.where(:bar).foo.sql.must_equal 'SELECT * FROM items WHERE bar LIMIT 1'
|
587
|
+
end
|
588
|
+
|
589
|
+
it "should have dataset_module support a offset method" do
|
590
|
+
@db.extend_datasets{offset :foo, 1}
|
591
|
+
ds.foo.sql.must_equal 'SELECT * FROM items OFFSET 1'
|
592
|
+
ds.where(:bar).foo.sql.must_equal 'SELECT * FROM items WHERE bar OFFSET 1'
|
593
|
+
end
|
594
|
+
|
595
|
+
it "should have dataset_module support a order method" do
|
596
|
+
@db.extend_datasets{order(:foo){:baz}}
|
597
|
+
ds.foo.sql.must_equal 'SELECT * FROM items ORDER BY baz'
|
598
|
+
ds.where(:bar).foo.sql.must_equal 'SELECT * FROM items WHERE bar ORDER BY baz'
|
599
|
+
end
|
600
|
+
|
601
|
+
it "should have dataset_module support a order_append method" do
|
602
|
+
@db.extend_datasets{order_append :foo, :baz}
|
603
|
+
ds.foo.sql.must_equal 'SELECT * FROM items ORDER BY baz'
|
604
|
+
ds.order(:bar).foo.sql.must_equal 'SELECT * FROM items ORDER BY bar, baz'
|
605
|
+
end
|
606
|
+
|
607
|
+
it "should have dataset_module support a order_prepend method" do
|
608
|
+
@db.extend_datasets{order_prepend :foo, :baz}
|
609
|
+
ds.foo.sql.must_equal 'SELECT * FROM items ORDER BY baz'
|
610
|
+
ds.order(:bar).foo.sql.must_equal 'SELECT * FROM items ORDER BY baz, bar'
|
611
|
+
end
|
612
|
+
|
613
|
+
it "should have dataset_module support a select method" do
|
614
|
+
@db.extend_datasets{select :foo, :baz}
|
615
|
+
ds.foo.sql.must_equal 'SELECT baz FROM items'
|
616
|
+
ds.where(:bar).foo.sql.must_equal 'SELECT baz FROM items WHERE bar'
|
617
|
+
end
|
618
|
+
|
619
|
+
it "should have dataset_module support a select_all method" do
|
620
|
+
@db.extend_datasets{select_all :foo, :baz}
|
621
|
+
ds.foo.sql.must_equal 'SELECT baz.* FROM items'
|
622
|
+
ds.where(:bar).foo.sql.must_equal 'SELECT baz.* FROM items WHERE bar'
|
623
|
+
end
|
624
|
+
|
625
|
+
it "should have dataset_module support a select_append method" do
|
626
|
+
@db.extend_datasets{select_append :foo, :baz}
|
627
|
+
ds.foo.sql.must_equal 'SELECT *, baz FROM items'
|
628
|
+
ds.where(:bar).foo.sql.must_equal 'SELECT *, baz FROM items WHERE bar'
|
629
|
+
end
|
630
|
+
|
631
|
+
it "should have dataset_module support a select_group method" do
|
632
|
+
@db.extend_datasets{select_group :foo, :baz}
|
633
|
+
ds.foo.sql.must_equal 'SELECT baz FROM items GROUP BY baz'
|
634
|
+
ds.where(:bar).foo.sql.must_equal 'SELECT baz FROM items WHERE bar GROUP BY baz'
|
635
|
+
end
|
636
|
+
|
637
|
+
it "should have dataset_module support a server method" do
|
638
|
+
@db.extend_datasets{server :foo, :baz}
|
639
|
+
ds.foo.opts[:server].must_equal :baz
|
640
|
+
ds.where(:bar).foo.opts[:server].must_equal :baz
|
641
|
+
end
|
642
|
+
end
|
643
|
+
|
520
644
|
describe "Database#disconnect_connection" do
|
521
645
|
it "should call close on the connection" do
|
522
646
|
o = Object.new
|
@@ -2257,6 +2381,31 @@ describe "Database#typecast_value" do
|
|
2257
2381
|
end
|
2258
2382
|
end
|
2259
2383
|
|
2384
|
+
it "should have an underlying exception class available at cause" do
|
2385
|
+
begin
|
2386
|
+
@db.typecast_value(:date, 'a')
|
2387
|
+
true.must_equal false
|
2388
|
+
rescue Sequel::InvalidValue => e
|
2389
|
+
e.cause.must_be_kind_of(ArgumentError)
|
2390
|
+
end
|
2391
|
+
end if RUBY_VERSION >= '2.1'
|
2392
|
+
|
2393
|
+
it "should have an underlying exception class available at cause when using nested exceptions" do
|
2394
|
+
begin
|
2395
|
+
begin
|
2396
|
+
raise ArgumentError
|
2397
|
+
rescue => e1
|
2398
|
+
begin
|
2399
|
+
raise RuntimeError
|
2400
|
+
rescue => e2
|
2401
|
+
@db.send(:raise_error, e1)
|
2402
|
+
end
|
2403
|
+
end
|
2404
|
+
rescue Sequel::DatabaseError => e
|
2405
|
+
e.cause.must_be_kind_of(ArgumentError)
|
2406
|
+
end
|
2407
|
+
end if RUBY_VERSION >= '2.1'
|
2408
|
+
|
2260
2409
|
it "should include underlying exception class in #inspect" do
|
2261
2410
|
begin
|
2262
2411
|
@db.typecast_value(:date, 'a')
|