sequel 3.34.1 → 3.35.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.
- data/CHANGELOG +52 -0
- data/README.rdoc +3 -1
- data/Rakefile +2 -10
- data/doc/active_record.rdoc +1 -0
- data/doc/migration.rdoc +18 -7
- data/doc/model_hooks.rdoc +6 -0
- data/doc/opening_databases.rdoc +3 -0
- data/doc/prepared_statements.rdoc +0 -1
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/schema_modification.rdoc +16 -1
- data/doc/thread_safety.rdoc +17 -0
- data/lib/sequel/adapters/do.rb +2 -2
- data/lib/sequel/adapters/do/postgres.rb +1 -52
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/firebird.rb +1 -1
- data/lib/sequel/adapters/ibmdb.rb +2 -2
- data/lib/sequel/adapters/jdbc.rb +23 -19
- data/lib/sequel/adapters/jdbc/db2.rb +0 -5
- data/lib/sequel/adapters/jdbc/derby.rb +29 -2
- data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
- data/lib/sequel/adapters/jdbc/h2.rb +1 -1
- data/lib/sequel/adapters/jdbc/hsqldb.rb +7 -0
- data/lib/sequel/adapters/jdbc/informix.rb +0 -5
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
- data/lib/sequel/adapters/jdbc/mysql.rb +0 -5
- data/lib/sequel/adapters/jdbc/postgresql.rb +4 -35
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
- data/lib/sequel/adapters/jdbc/transactions.rb +4 -4
- data/lib/sequel/adapters/mysql2.rb +1 -1
- data/lib/sequel/adapters/odbc.rb +3 -3
- data/lib/sequel/adapters/odbc/mssql.rb +14 -1
- data/lib/sequel/adapters/oracle.rb +6 -18
- data/lib/sequel/adapters/postgres.rb +36 -53
- data/lib/sequel/adapters/shared/db2.rb +16 -2
- data/lib/sequel/adapters/shared/mssql.rb +40 -9
- data/lib/sequel/adapters/shared/mysql.rb +16 -4
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +2 -2
- data/lib/sequel/adapters/shared/oracle.rb +2 -0
- data/lib/sequel/adapters/shared/postgres.rb +135 -211
- data/lib/sequel/adapters/sqlite.rb +2 -2
- data/lib/sequel/adapters/swift.rb +1 -1
- data/lib/sequel/adapters/swift/postgres.rb +1 -71
- data/lib/sequel/adapters/tinytds.rb +3 -3
- data/lib/sequel/core.rb +27 -4
- data/lib/sequel/database/connecting.rb +7 -8
- data/lib/sequel/database/logging.rb +6 -1
- data/lib/sequel/database/misc.rb +20 -4
- data/lib/sequel/database/query.rb +38 -18
- data/lib/sequel/database/schema_generator.rb +5 -2
- data/lib/sequel/database/schema_methods.rb +34 -8
- data/lib/sequel/dataset/prepared_statements.rb +1 -1
- data/lib/sequel/dataset/sql.rb +18 -24
- data/lib/sequel/extensions/core_extensions.rb +0 -23
- data/lib/sequel/extensions/migration.rb +22 -8
- data/lib/sequel/extensions/pg_auto_parameterize.rb +4 -0
- data/lib/sequel/extensions/schema_dumper.rb +1 -1
- data/lib/sequel/model.rb +2 -2
- data/lib/sequel/model/associations.rb +95 -70
- data/lib/sequel/model/base.rb +16 -18
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/identity_map.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +16 -1
- data/lib/sequel/plugins/many_through_many.rb +22 -32
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +2 -2
- data/lib/sequel/plugins/prepared_statements.rb +22 -8
- data/lib/sequel/plugins/prepared_statements_associations.rb +2 -3
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +1 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/subclasses.rb +10 -2
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/xml_serializer.rb +12 -1
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/postgres_spec.rb +30 -79
- data/spec/core/database_spec.rb +46 -2
- data/spec/core/dataset_spec.rb +28 -22
- data/spec/core/schema_generator_spec.rb +1 -1
- data/spec/core/schema_spec.rb +51 -0
- data/spec/extensions/arbitrary_servers_spec.rb +0 -4
- data/spec/extensions/association_autoreloading_spec.rb +17 -0
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/core_extensions_spec.rb +1 -24
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/json_serializer_spec.rb +13 -0
- data/spec/extensions/migration_spec.rb +28 -15
- data/spec/extensions/named_timezones_spec.rb +6 -8
- data/spec/extensions/pg_auto_parameterize_spec.rb +6 -5
- data/spec/extensions/schema_dumper_spec.rb +3 -1
- data/spec/extensions/xml_serializer_spec.rb +13 -0
- data/spec/files/{transactionless_migrations → transaction_specified_migrations}/001_create_alt_basic.rb +1 -1
- data/spec/files/{transactionless_migrations → transaction_specified_migrations}/002_create_basic.rb +0 -0
- data/spec/files/{transaction_migrations → transaction_unspecified_migrations}/001_create_alt_basic.rb +0 -0
- data/spec/files/{transaction_migrations → transaction_unspecified_migrations}/002_create_basic.rb +0 -0
- data/spec/integration/associations_test.rb +5 -7
- data/spec/integration/dataset_test.rb +25 -7
- data/spec/integration/plugin_test.rb +1 -1
- data/spec/integration/schema_test.rb +16 -1
- data/spec/model/associations_spec.rb +2 -2
- metadata +14 -9
- data/lib/sequel/adapters/odbc/db2.rb +0 -17
|
@@ -53,8 +53,7 @@ module Sequel
|
|
|
53
53
|
when :many_to_many
|
|
54
54
|
association_bound_variable_hash(opts.join_table_alias, opts[:left_keys], opts[:left_primary_keys])
|
|
55
55
|
when :many_through_many
|
|
56
|
-
opts.
|
|
57
|
-
association_bound_variable_hash(opts[:final_reverse_edge][:alias], Array(opts[:left_key]), opts[:left_primary_keys])
|
|
56
|
+
association_bound_variable_hash(opts.final_reverse_edge[:alias], Array(opts[:left_key]), opts[:left_primary_keys])
|
|
58
57
|
end
|
|
59
58
|
end
|
|
60
59
|
|
|
@@ -62,7 +61,7 @@ module Sequel
|
|
|
62
61
|
# that, given appropriate bound variables, the prepared statement will work correctly for any
|
|
63
62
|
# instance.
|
|
64
63
|
def association_prepared_statement(opts)
|
|
65
|
-
opts
|
|
64
|
+
opts.send(:cached_fetch, :prepared_statement) do
|
|
66
65
|
ps = _associated_dataset(opts, {}).unbind.first.prepare(opts.returns_array? ? :select : :first, :"smpsap_#{NEXT.call}")
|
|
67
66
|
ps.log_sql = true
|
|
68
67
|
ps
|
|
@@ -31,7 +31,7 @@ module Sequel
|
|
|
31
31
|
# Return a prepared statement that can be used to lookup a row given a dataset for the row matching
|
|
32
32
|
# the primary key.
|
|
33
33
|
def prepared_lookup_dataset(ds)
|
|
34
|
-
|
|
34
|
+
cached_prepared_statement(:lookup_sql, ds.sql){prepare_statement(ds.filter(prepared_statement_key_array(primary_key).map{|k, v| [SQL::QualifiedIdentifier.new(ds.model.table_name, k), v]}), :first)}
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
@@ -28,7 +28,7 @@ module Sequel
|
|
|
28
28
|
|
|
29
29
|
# All descendent classes of this model.
|
|
30
30
|
def descendents
|
|
31
|
-
|
|
31
|
+
Sequel.synchronize{_descendents}
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
# Add the subclass to this model's current subclasses,
|
|
@@ -36,9 +36,17 @@ module Sequel
|
|
|
36
36
|
# in the subclass.
|
|
37
37
|
def inherited(subclass)
|
|
38
38
|
super
|
|
39
|
-
subclasses << subclass
|
|
39
|
+
Sequel.synchronize{subclasses << subclass}
|
|
40
40
|
subclass.instance_variable_set(:@subclasses, [])
|
|
41
41
|
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
# Recursive, non-thread safe version of descendents, since
|
|
46
|
+
# the mutex Sequel uses isn't reentrant.
|
|
47
|
+
def _descendents
|
|
48
|
+
subclasses.map{|x| [x] + x.send(:_descendents)}.flatten
|
|
49
|
+
end
|
|
42
50
|
end
|
|
43
51
|
end
|
|
44
52
|
end
|
|
@@ -19,7 +19,7 @@ module Sequel
|
|
|
19
19
|
# # timestamp, and setting the update timestamp when creating
|
|
20
20
|
# Album.plugin :timestamps, :force=>true, :update_on_create=>true
|
|
21
21
|
module Timestamps
|
|
22
|
-
# Configure the plugin by setting the
|
|
22
|
+
# Configure the plugin by setting the available options. Note that
|
|
23
23
|
# if this method is run more than once, previous settings are ignored,
|
|
24
24
|
# and it will just use the settings given or the default settings. Options:
|
|
25
25
|
# * :create - The field to hold the create timestamp (default: :created_at)
|
|
@@ -79,6 +79,11 @@ module Sequel
|
|
|
79
79
|
#
|
|
80
80
|
# Album.array_from_xml(Album.to_xml) # same as Album.all
|
|
81
81
|
#
|
|
82
|
+
# If you have an existing array of model instances you want to convert to
|
|
83
|
+
# XML, you can call the class to_xml method with the :array option:
|
|
84
|
+
#
|
|
85
|
+
# Album.to_xml(:array=>[Album[1], Album[2]])
|
|
86
|
+
#
|
|
82
87
|
# Usage:
|
|
83
88
|
#
|
|
84
89
|
# # Add XML output capability to all model subclass instances (called before loading subclasses)
|
|
@@ -316,8 +321,14 @@ module Sequel
|
|
|
316
321
|
raise(Sequel::Error, "Dataset#to_xml") unless row_proc
|
|
317
322
|
x = model.xml_builder(opts)
|
|
318
323
|
name_proc = model.xml_serialize_name_proc(opts)
|
|
324
|
+
array = if opts[:array]
|
|
325
|
+
opts = opts.dup
|
|
326
|
+
opts.delete(:array)
|
|
327
|
+
else
|
|
328
|
+
all
|
|
329
|
+
end
|
|
319
330
|
x.send(name_proc[opts.fetch(:array_root_name, model.send(:pluralize, model.send(:underscore, model.name))).to_s]) do |x1|
|
|
320
|
-
|
|
331
|
+
array.each do |obj|
|
|
321
332
|
obj.to_xml(opts.merge(:builder=>x1))
|
|
322
333
|
end
|
|
323
334
|
end
|
data/lib/sequel/sql.rb
CHANGED
|
@@ -138,7 +138,7 @@ module Sequel
|
|
|
138
138
|
MATHEMATICAL_OPERATORS = [:+, :-, :/, :*]
|
|
139
139
|
|
|
140
140
|
# Bitwise mathematical operators used in +NumericMethods+
|
|
141
|
-
BITWISE_OPERATORS = [:&, :|, :^, :<<,
|
|
141
|
+
BITWISE_OPERATORS = [:&, :|, :^, :<<, :>>, :%]
|
|
142
142
|
|
|
143
143
|
# Inequality operators used in +InequalityMethods+
|
|
144
144
|
INEQUALITY_OPERATORS = [:<, :>, :<=, :>=]
|
data/lib/sequel/version.rb
CHANGED
|
@@ -3,10 +3,10 @@ module Sequel
|
|
|
3
3
|
MAJOR = 3
|
|
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 = 35
|
|
7
7
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
|
8
8
|
# releases that fix regressions from previous versions.
|
|
9
|
-
TINY =
|
|
9
|
+
TINY = 0
|
|
10
10
|
|
|
11
11
|
# The version of Sequel you are using, as a string (e.g. "2.11.0")
|
|
12
12
|
VERSION = [MAJOR, MINOR, TINY].join('.')
|
|
@@ -23,7 +23,7 @@ def logger.method_missing(m, msg)
|
|
|
23
23
|
end
|
|
24
24
|
POSTGRES_DB.loggers << logger
|
|
25
25
|
|
|
26
|
-
#POSTGRES_DB.instance_variable_set(:@server_version,
|
|
26
|
+
#POSTGRES_DB.instance_variable_set(:@server_version, 80200)
|
|
27
27
|
POSTGRES_DB.create_table! :test do
|
|
28
28
|
text :name
|
|
29
29
|
integer :value, :index => true
|
|
@@ -111,9 +111,6 @@ describe "A PostgreSQL dataset" do
|
|
|
111
111
|
|
|
112
112
|
@d.insert_sql(:value => 333).should =~ \
|
|
113
113
|
/\AINSERT INTO "test" \("value"\) VALUES \(333\)( RETURNING NULL)?\z/
|
|
114
|
-
|
|
115
|
-
@d.disable_insert_returning.insert_sql(:value => 333).should =~ \
|
|
116
|
-
/\AINSERT INTO "test" \("value"\) VALUES \(333\)\z/
|
|
117
114
|
end
|
|
118
115
|
end
|
|
119
116
|
|
|
@@ -163,6 +160,25 @@ describe "A PostgreSQL dataset" do
|
|
|
163
160
|
specify "should raise an error if attempting to update a joined dataset with a single FROM table" do
|
|
164
161
|
proc{POSTGRES_DB[:test].join(:test2, [:name]).update(:name=>'a')}.should raise_error(Sequel::Error, 'Need multiple FROM tables if updating/deleting a dataset with JOINs')
|
|
165
162
|
end
|
|
163
|
+
|
|
164
|
+
specify "should truncate with options" do
|
|
165
|
+
@d << { :name => 'abc', :value => 1}
|
|
166
|
+
@d.count.should == 1
|
|
167
|
+
@d.truncate(:cascade => true)
|
|
168
|
+
@d.count.should == 0
|
|
169
|
+
if @d.db.server_version > 80400
|
|
170
|
+
@d << { :name => 'abc', :value => 1}
|
|
171
|
+
@d.truncate(:cascade => true, :only=>true, :restart=>true)
|
|
172
|
+
@d.count.should == 0
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
specify "should truncate multiple tables at once" do
|
|
177
|
+
tables = [:test, :test2, :test3, :test4]
|
|
178
|
+
tables.each{|t| @d.from(t).insert}
|
|
179
|
+
@d.from(:test, :test2, :test3, :test4).truncate
|
|
180
|
+
tables.each{|t| @d.from(t).count.should == 0}
|
|
181
|
+
end
|
|
166
182
|
end
|
|
167
183
|
|
|
168
184
|
describe "Dataset#distinct" do
|
|
@@ -262,7 +278,7 @@ describe "A PostgreSQL dataset with a timestamp field" do
|
|
|
262
278
|
t2 = @d[:value =>1][:time]
|
|
263
279
|
@d.literal(t2).should == @d.literal(t)
|
|
264
280
|
t2.strftime('%Y-%m-%d %H:%M:%S').should == t.strftime('%Y-%m-%d %H:%M:%S')
|
|
265
|
-
t2.is_a?(Time) ? t2.usec : t2.strftime('%N').to_i/1000 == t.usec
|
|
281
|
+
(t2.is_a?(Time) ? t2.usec : t2.strftime('%N').to_i/1000).should == t.usec
|
|
266
282
|
end
|
|
267
283
|
|
|
268
284
|
cspecify "should store milliseconds in time fields for DateTime objects", :do, :swift do
|
|
@@ -271,7 +287,7 @@ describe "A PostgreSQL dataset with a timestamp field" do
|
|
|
271
287
|
t2 = @d[:value =>1][:time]
|
|
272
288
|
@d.literal(t2).should == @d.literal(t)
|
|
273
289
|
t2.strftime('%Y-%m-%d %H:%M:%S').should == t.strftime('%Y-%m-%d %H:%M:%S')
|
|
274
|
-
t2.is_a?(Time) ? t2.usec : t2.strftime('%N').to_i/1000 == t.strftime('%N').to_i/1000
|
|
290
|
+
(t2.is_a?(Time) ? t2.usec : t2.strftime('%N').to_i/1000).should == t.strftime('%N').to_i/1000
|
|
275
291
|
end
|
|
276
292
|
|
|
277
293
|
if POSTGRES_DB.adapter_scheme == :postgres
|
|
@@ -483,46 +499,24 @@ describe "Postgres::Dataset#import" do
|
|
|
483
499
|
@db.drop_table?(:test)
|
|
484
500
|
end
|
|
485
501
|
|
|
486
|
-
specify "#import should return separate insert statements if server_version < 80200" do
|
|
487
|
-
@ds.meta_def(:server_version){80199}
|
|
488
|
-
@ds.import([:x, :y], [[1, 2], [3, 4]])
|
|
489
|
-
@db.sqls.should == ['BEGIN', 'INSERT INTO "test" ("x", "y") VALUES (1, 2)', 'INSERT INTO "test" ("x", "y") VALUES (3, 4)', 'COMMIT'] if check_sqls
|
|
490
|
-
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
491
|
-
end
|
|
492
502
|
|
|
493
|
-
specify "#import should a single insert statement
|
|
494
|
-
@ds.meta_def(:server_version){80200}
|
|
503
|
+
specify "#import should a single insert statement" do
|
|
495
504
|
@ds.import([:x, :y], [[1, 2], [3, 4]])
|
|
496
505
|
@db.sqls.should == ['BEGIN', 'INSERT INTO "test" ("x", "y") VALUES (1, 2), (3, 4)', 'COMMIT']
|
|
497
506
|
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
498
507
|
end
|
|
499
508
|
|
|
500
|
-
specify "#import should work correctly when returning primary keys
|
|
501
|
-
@ds.meta_def(:server_version){80199}
|
|
509
|
+
specify "#import should work correctly when returning primary keys" do
|
|
502
510
|
@ds.import([:x, :y], [[1, 2], [3, 4]], :return=>:primary_key).should == [1, 3]
|
|
503
511
|
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
504
512
|
end
|
|
505
513
|
|
|
506
|
-
specify "#import should work correctly when returning primary keys
|
|
507
|
-
@ds.meta_def(:server_version){80200}
|
|
508
|
-
@ds.import([:x, :y], [[1, 2], [3, 4]], :return=>:primary_key).should == [1, 3]
|
|
509
|
-
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
510
|
-
end
|
|
511
|
-
|
|
512
|
-
specify "#import should work correctly when returning primary keys with :slice option for server_version < 80200" do
|
|
513
|
-
@ds.meta_def(:server_version){80199}
|
|
514
|
-
@ds.import([:x, :y], [[1, 2], [3, 4]], :return=>:primary_key, :slice=>1).should == [1, 3]
|
|
515
|
-
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
516
|
-
end
|
|
517
|
-
|
|
518
|
-
specify "#import should work correctly when returning primary keys with :slice option for server_version >= 80200" do
|
|
519
|
-
@ds.meta_def(:server_version){80200}
|
|
514
|
+
specify "#import should work correctly when returning primary keys with :slice option" do
|
|
520
515
|
@ds.import([:x, :y], [[1, 2], [3, 4]], :return=>:primary_key, :slice=>1).should == [1, 3]
|
|
521
516
|
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
522
517
|
end
|
|
523
518
|
|
|
524
519
|
specify "#import should work correctly with an arbitrary returning value" do
|
|
525
|
-
@ds.meta_def(:server_version){80200}
|
|
526
520
|
@ds.returning(:y, :x).import([:x, :y], [[1, 2], [3, 4]]).should == [{:y=>2, :x=>1}, {:y=>4, :x=>3}]
|
|
527
521
|
@ds.all.should == [{:x=>1, :y=>2}, {:x=>3, :y=>4}]
|
|
528
522
|
end
|
|
@@ -545,56 +539,17 @@ describe "Postgres::Dataset#insert" do
|
|
|
545
539
|
@ds.all.should == [{:xid=>1, :value=>10}, {:xid=>2, :value=>20}]
|
|
546
540
|
end
|
|
547
541
|
|
|
548
|
-
specify "should
|
|
549
|
-
@ds.insert(:value=>10).should == 1
|
|
550
|
-
@ds.disable_insert_returning.insert(:value=>20).should == 2
|
|
551
|
-
@ds.meta_def(:server_version){80100}
|
|
552
|
-
@ds.insert(:value=>13).should == 3
|
|
553
|
-
|
|
554
|
-
@db.sqls.reject{|x| x =~ /pg_class/}.should == [
|
|
555
|
-
'INSERT INTO "test5" ("value") VALUES (10) RETURNING "xid"',
|
|
556
|
-
'INSERT INTO "test5" ("value") VALUES (20)',
|
|
557
|
-
"SELECT currval('\"public\".test5_xid_seq')",
|
|
558
|
-
'INSERT INTO "test5" ("value") VALUES (13)',
|
|
559
|
-
"SELECT currval('\"public\".test5_xid_seq')"
|
|
560
|
-
] if check_sqls
|
|
561
|
-
@ds.all.should == [{:xid=>1, :value=>10}, {:xid=>2, :value=>20}, {:xid=>3, :value=>13}]
|
|
562
|
-
end
|
|
563
|
-
|
|
564
|
-
specify "should insert correctly if server_version < 80200" do
|
|
565
|
-
@ds.meta_def(:server_version){80100}
|
|
566
|
-
@ds.insert(:value=>10).should == 1
|
|
567
|
-
@ds.all.should == [{:xid=>1, :value=>10}]
|
|
568
|
-
end
|
|
569
|
-
|
|
570
|
-
specify "should insert correctly if disabling insert returning" do
|
|
571
|
-
@ds.disable_insert_returning.insert(:value=>10).should == 1
|
|
572
|
-
@ds.all.should == [{:xid=>1, :value=>10}]
|
|
573
|
-
end
|
|
574
|
-
|
|
575
|
-
specify "should insert correctly if using a column array and a value array and server_version < 80200" do
|
|
576
|
-
@ds.meta_def(:server_version){80100}
|
|
542
|
+
specify "should insert correctly if using a column array and a value array" do
|
|
577
543
|
@ds.insert([:value], [10]).should == 1
|
|
578
544
|
@ds.all.should == [{:xid=>1, :value=>10}]
|
|
579
545
|
end
|
|
580
546
|
|
|
581
|
-
specify "should use INSERT RETURNING
|
|
582
|
-
@ds.meta_def(:server_version){80201}
|
|
547
|
+
specify "should use INSERT RETURNING" do
|
|
583
548
|
@ds.insert(:value=>10).should == 1
|
|
584
549
|
@db.sqls.last.should == 'INSERT INTO "test5" ("value") VALUES (10) RETURNING "xid"' if check_sqls
|
|
585
550
|
end
|
|
586
551
|
|
|
587
|
-
specify "should have insert_select
|
|
588
|
-
@ds.meta_def(:server_version){80100}
|
|
589
|
-
@ds.insert_select(:value=>10).should == nil
|
|
590
|
-
end
|
|
591
|
-
|
|
592
|
-
specify "should have insert_select return nil if disable_insert_returning is used" do
|
|
593
|
-
@ds.disable_insert_returning.insert_select(:value=>10).should == nil
|
|
594
|
-
end
|
|
595
|
-
|
|
596
|
-
specify "should have insert_select insert the record and return the inserted record if server_version >= 80200" do
|
|
597
|
-
@ds.meta_def(:server_version){80201}
|
|
552
|
+
specify "should have insert_select insert the record and return the inserted record" do
|
|
598
553
|
h = @ds.insert_select(:value=>10)
|
|
599
554
|
h[:value].should == 10
|
|
600
555
|
@ds.first(:xid=>h[:xid])[:value].should == 10
|
|
@@ -1024,11 +979,7 @@ describe "Postgres::Database functions, languages, schemas, and triggers" do
|
|
|
1024
979
|
@d.send(:drop_schema_sql, :sequel, :if_exists=>true, :cascade=>true).should == 'DROP SCHEMA IF EXISTS "sequel" CASCADE'
|
|
1025
980
|
@d.create_schema(:sequel)
|
|
1026
981
|
@d.create_table(:sequel__test){Integer :a}
|
|
1027
|
-
|
|
1028
|
-
@d.drop_schema(:sequel, :if_exists=>true, :cascade=>true)
|
|
1029
|
-
else
|
|
1030
|
-
@d.drop_schema(:sequel, :cascade=>true)
|
|
1031
|
-
end
|
|
982
|
+
@d.drop_schema(:sequel, :if_exists=>true, :cascade=>true)
|
|
1032
983
|
end
|
|
1033
984
|
|
|
1034
985
|
specify "#create_trigger and #drop_trigger should create and drop triggers" do
|
|
@@ -1237,7 +1188,7 @@ if POSTGRES_DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG && POSTGRE
|
|
|
1237
1188
|
i = 0
|
|
1238
1189
|
@db.listen('foo2', :timeout=>0.001, :loop=>proc{i+=1; throw :stop if i > 3}){|ev, pid, payload| called = true}.should == nil
|
|
1239
1190
|
i.should == 4
|
|
1240
|
-
end unless RUBY_VERSION
|
|
1191
|
+
end unless RUBY_VERSION =~ /1.8.7|1.9.2/ && RUBY_PLATFORM =~ /mingw/ # Ruby freezes on this spec on this platform/version
|
|
1241
1192
|
end
|
|
1242
1193
|
end
|
|
1243
1194
|
|
data/spec/core/database_spec.rb
CHANGED
|
@@ -193,8 +193,7 @@ describe "A new Database" do
|
|
|
193
193
|
end
|
|
194
194
|
|
|
195
195
|
specify "should populate :adapter option when using connection string" do
|
|
196
|
-
Sequel
|
|
197
|
-
Sequel.connect('do:test://host/db_name').opts[:adapter] == :do
|
|
196
|
+
Sequel.connect('mock:/').opts[:adapter].should == "mock"
|
|
198
197
|
end
|
|
199
198
|
end
|
|
200
199
|
|
|
@@ -637,6 +636,45 @@ shared_examples_for "Database#transaction" do
|
|
|
637
636
|
proc {@db.transaction {raise RuntimeError}}.should raise_error(RuntimeError)
|
|
638
637
|
end
|
|
639
638
|
|
|
639
|
+
specify "should handle errors when sending BEGIN" do
|
|
640
|
+
ec = Class.new(StandardError)
|
|
641
|
+
@db.meta_def(:database_error_classes){[ec]}
|
|
642
|
+
@db.meta_def(:log_connection_execute){|c, sql| sql =~ /BEGIN/ ? raise(ec, 'bad') : super(c, sql)}
|
|
643
|
+
begin
|
|
644
|
+
@db.transaction{@db.execute 'DROP TABLE test;'}
|
|
645
|
+
rescue Sequel::DatabaseError => e
|
|
646
|
+
end
|
|
647
|
+
e.should_not be_nil
|
|
648
|
+
e.wrapped_exception.should be_a_kind_of(ec)
|
|
649
|
+
@db.sqls.should == ['ROLLBACK']
|
|
650
|
+
end
|
|
651
|
+
|
|
652
|
+
specify "should handle errors when sending COMMIT" do
|
|
653
|
+
ec = Class.new(StandardError)
|
|
654
|
+
@db.meta_def(:database_error_classes){[ec]}
|
|
655
|
+
@db.meta_def(:log_connection_execute){|c, sql| sql =~ /COMMIT/ ? raise(ec, 'bad') : super(c, sql)}
|
|
656
|
+
begin
|
|
657
|
+
@db.transaction{@db.execute 'DROP TABLE test;'}
|
|
658
|
+
rescue Sequel::DatabaseError => e
|
|
659
|
+
end
|
|
660
|
+
e.should_not be_nil
|
|
661
|
+
e.wrapped_exception.should be_a_kind_of(ec)
|
|
662
|
+
@db.sqls.should == ['BEGIN', 'DROP TABLE test;']
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
specify "should handle errors when sending ROLLBACK" do
|
|
666
|
+
ec = Class.new(StandardError)
|
|
667
|
+
@db.meta_def(:database_error_classes){[ec]}
|
|
668
|
+
@db.meta_def(:log_connection_execute){|c, sql| sql =~ /ROLLBACK/ ? raise(ec, 'bad') : super(c, sql)}
|
|
669
|
+
begin
|
|
670
|
+
@db.transaction{raise ArgumentError, 'asdf'}
|
|
671
|
+
rescue Sequel::DatabaseError => e
|
|
672
|
+
end
|
|
673
|
+
e.should_not be_nil
|
|
674
|
+
e.wrapped_exception.should be_a_kind_of(ec)
|
|
675
|
+
@db.sqls.should == ['BEGIN']
|
|
676
|
+
end
|
|
677
|
+
|
|
640
678
|
specify "should issue ROLLBACK if Sequel::Rollback is called in the transaction" do
|
|
641
679
|
@db.transaction do
|
|
642
680
|
@db.drop_table(:a)
|
|
@@ -1952,6 +1990,12 @@ describe "Database#schema_autoincrementing_primary_key?" do
|
|
|
1952
1990
|
end
|
|
1953
1991
|
end
|
|
1954
1992
|
|
|
1993
|
+
describe "Database#supports_transactional_ddl?" do
|
|
1994
|
+
specify "should be false by default" do
|
|
1995
|
+
Sequel::Database.new.supports_transactional_ddl?.should == false
|
|
1996
|
+
end
|
|
1997
|
+
end
|
|
1998
|
+
|
|
1955
1999
|
describe "Database#supports_savepoints?" do
|
|
1956
2000
|
specify "should be false by default" do
|
|
1957
2001
|
Sequel::Database.new.supports_savepoints?.should == false
|
data/spec/core/dataset_spec.rb
CHANGED
|
@@ -214,6 +214,11 @@ describe "A simple dataset" do
|
|
|
214
214
|
@dataset.truncate_sql.should == 'TRUNCATE TABLE test'
|
|
215
215
|
end
|
|
216
216
|
|
|
217
|
+
specify "should format a truncate statement with multiple tables if supported" do
|
|
218
|
+
@dataset.meta_def(:check_truncation_allowed!){}
|
|
219
|
+
@dataset.from(:test, :test2).truncate_sql.should == 'TRUNCATE TABLE test, test2'
|
|
220
|
+
end
|
|
221
|
+
|
|
217
222
|
specify "should format an insert statement with default values" do
|
|
218
223
|
@dataset.insert_sql.should == 'INSERT INTO test DEFAULT VALUES'
|
|
219
224
|
end
|
|
@@ -709,7 +714,7 @@ describe "Dataset#and" do
|
|
|
709
714
|
specify "should raise if no filter exists" do
|
|
710
715
|
proc {@dataset.and(:a => 1)}.should raise_error(Sequel::Error)
|
|
711
716
|
proc {@dataset.where(:a => 1).group(:t).and(:b => 2)}.should_not raise_error(Sequel::Error)
|
|
712
|
-
@dataset.where(:a => 1).group(:t).and(:b => 2).sql == "SELECT * FROM test WHERE (a = 1) AND (b = 2) GROUP BY t"
|
|
717
|
+
@dataset.where(:a => 1).group(:t).and(:b => 2).sql.should == "SELECT * FROM test WHERE ((a = 1) AND (b = 2)) GROUP BY t"
|
|
713
718
|
end
|
|
714
719
|
|
|
715
720
|
specify "should add an alternative expression to the where clause" do
|
|
@@ -987,9 +992,9 @@ describe "Dataset#literal" do
|
|
|
987
992
|
@dataset.literal('a"x"bc').should == "'a\"x\"bc'"
|
|
988
993
|
@dataset.literal("a'bc").should == "'a''bc'"
|
|
989
994
|
@dataset.literal("a''bc").should == "'a''''bc'"
|
|
990
|
-
@dataset.literal("a\\bc").should == "'a
|
|
991
|
-
@dataset.literal("a\\\\bc").should == "'a
|
|
992
|
-
@dataset.literal("a\\'bc").should == "'a
|
|
995
|
+
@dataset.literal("a\\bc").should == "'a\\bc'"
|
|
996
|
+
@dataset.literal("a\\\\bc").should == "'a\\\\bc'"
|
|
997
|
+
@dataset.literal("a\\'bc").should == "'a\\''bc'"
|
|
993
998
|
end
|
|
994
999
|
|
|
995
1000
|
specify "should escape blobs as strings by default" do
|
|
@@ -3216,6 +3221,7 @@ describe "Dataset default #fetch_rows, #insert, #update, #delete, #with_sql_dele
|
|
|
3216
3221
|
|
|
3217
3222
|
specify "#truncate should raise an InvalidOperation exception if the dataset is filtered" do
|
|
3218
3223
|
proc{@ds.filter(:a=>1).truncate}.should raise_error(Sequel::InvalidOperation)
|
|
3224
|
+
proc{@ds.having(:a=>1).truncate}.should raise_error(Sequel::InvalidOperation)
|
|
3219
3225
|
end
|
|
3220
3226
|
|
|
3221
3227
|
specify "#execute should execute the SQL on the database" do
|
|
@@ -3677,42 +3683,42 @@ describe Sequel::SQL::Constants do
|
|
|
3677
3683
|
end
|
|
3678
3684
|
|
|
3679
3685
|
it "should have CURRENT_DATE" do
|
|
3680
|
-
@db.literal(Sequel::SQL::Constants::CURRENT_DATE) == 'CURRENT_DATE'
|
|
3681
|
-
@db.literal(Sequel::CURRENT_DATE) == 'CURRENT_DATE'
|
|
3686
|
+
@db.literal(Sequel::SQL::Constants::CURRENT_DATE).should == 'CURRENT_DATE'
|
|
3687
|
+
@db.literal(Sequel::CURRENT_DATE).should == 'CURRENT_DATE'
|
|
3682
3688
|
end
|
|
3683
3689
|
|
|
3684
3690
|
it "should have CURRENT_TIME" do
|
|
3685
|
-
@db.literal(Sequel::SQL::Constants::CURRENT_TIME) == 'CURRENT_TIME'
|
|
3686
|
-
@db.literal(Sequel::CURRENT_TIME) == 'CURRENT_TIME'
|
|
3691
|
+
@db.literal(Sequel::SQL::Constants::CURRENT_TIME).should == 'CURRENT_TIME'
|
|
3692
|
+
@db.literal(Sequel::CURRENT_TIME).should == 'CURRENT_TIME'
|
|
3687
3693
|
end
|
|
3688
3694
|
|
|
3689
3695
|
it "should have CURRENT_TIMESTAMP" do
|
|
3690
|
-
@db.literal(Sequel::SQL::Constants::CURRENT_TIMESTAMP) == 'CURRENT_TIMESTAMP'
|
|
3691
|
-
@db.literal(Sequel::CURRENT_TIMESTAMP) == 'CURRENT_TIMESTAMP'
|
|
3696
|
+
@db.literal(Sequel::SQL::Constants::CURRENT_TIMESTAMP).should == 'CURRENT_TIMESTAMP'
|
|
3697
|
+
@db.literal(Sequel::CURRENT_TIMESTAMP).should == 'CURRENT_TIMESTAMP'
|
|
3692
3698
|
end
|
|
3693
3699
|
|
|
3694
3700
|
it "should have NULL" do
|
|
3695
|
-
@db.literal(Sequel::SQL::Constants::NULL) == 'NULL'
|
|
3696
|
-
@db.literal(Sequel::NULL) == 'NULL'
|
|
3701
|
+
@db.literal(Sequel::SQL::Constants::NULL).should == 'NULL'
|
|
3702
|
+
@db.literal(Sequel::NULL).should == 'NULL'
|
|
3697
3703
|
end
|
|
3698
3704
|
|
|
3699
3705
|
it "should have NOTNULL" do
|
|
3700
|
-
@db.literal(Sequel::SQL::Constants::NOTNULL) == 'NOT NULL'
|
|
3701
|
-
@db.literal(Sequel::NOTNULL) == 'NOT NULL'
|
|
3706
|
+
@db.literal(Sequel::SQL::Constants::NOTNULL).should == 'NOT NULL'
|
|
3707
|
+
@db.literal(Sequel::NOTNULL).should == 'NOT NULL'
|
|
3702
3708
|
end
|
|
3703
3709
|
|
|
3704
3710
|
it "should have TRUE and SQLTRUE" do
|
|
3705
|
-
@db.literal(Sequel::SQL::Constants::TRUE) == '
|
|
3706
|
-
@db.literal(Sequel::TRUE) == '
|
|
3707
|
-
@db.literal(Sequel::SQL::Constants::SQLTRUE) == '
|
|
3708
|
-
@db.literal(Sequel::SQLTRUE) == '
|
|
3711
|
+
@db.literal(Sequel::SQL::Constants::TRUE).should == "'t'"
|
|
3712
|
+
@db.literal(Sequel::TRUE).should == "'t'"
|
|
3713
|
+
@db.literal(Sequel::SQL::Constants::SQLTRUE).should == "'t'"
|
|
3714
|
+
@db.literal(Sequel::SQLTRUE).should == "'t'"
|
|
3709
3715
|
end
|
|
3710
3716
|
|
|
3711
3717
|
it "should have FALSE and SQLFALSE" do
|
|
3712
|
-
@db.literal(Sequel::SQL::Constants::FALSE) == '
|
|
3713
|
-
@db.literal(Sequel::FALSE) == '
|
|
3714
|
-
@db.literal(Sequel::SQL::Constants::SQLFALSE) == '
|
|
3715
|
-
@db.literal(Sequel::SQLFALSE) == '
|
|
3718
|
+
@db.literal(Sequel::SQL::Constants::FALSE).should == "'f'"
|
|
3719
|
+
@db.literal(Sequel::FALSE).should == "'f'"
|
|
3720
|
+
@db.literal(Sequel::SQL::Constants::SQLFALSE).should == "'f'"
|
|
3721
|
+
@db.literal(Sequel::SQLFALSE).should == "'f'"
|
|
3716
3722
|
end
|
|
3717
3723
|
end
|
|
3718
3724
|
|