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