sequel 4.48.0 → 4.49.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 +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')
|