sequel 4.0.0 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +32 -0
- data/doc/active_record.rdoc +2 -2
- data/doc/cheat_sheet.rdoc +0 -5
- data/doc/opening_databases.rdoc +3 -2
- data/doc/prepared_statements.rdoc +6 -0
- data/doc/release_notes/4.1.0.txt +85 -0
- data/doc/schema_modification.rdoc +9 -2
- data/lib/sequel/adapters/jdbc.rb +5 -0
- data/lib/sequel/adapters/mysql2.rb +24 -3
- data/lib/sequel/adapters/odbc.rb +6 -4
- data/lib/sequel/adapters/postgres.rb +25 -0
- data/lib/sequel/adapters/shared/mysql.rb +4 -29
- data/lib/sequel/adapters/shared/postgres.rb +14 -3
- data/lib/sequel/adapters/shared/sqlite.rb +4 -0
- data/lib/sequel/adapters/utils/replace.rb +36 -0
- data/lib/sequel/database/query.rb +1 -0
- data/lib/sequel/database/schema_generator.rb +12 -5
- data/lib/sequel/database/schema_methods.rb +2 -0
- data/lib/sequel/dataset/features.rb +5 -0
- data/lib/sequel/extensions/pg_json_ops.rb +0 -6
- data/lib/sequel/model/associations.rb +1 -1
- data/lib/sequel/plugins/instance_filters.rb +11 -1
- data/lib/sequel/plugins/pg_typecast_on_load.rb +3 -2
- data/lib/sequel/plugins/prepared_statements.rb +38 -9
- data/lib/sequel/plugins/update_primary_key.rb +10 -0
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +1 -22
- data/spec/adapters/postgres_spec.rb +79 -2
- data/spec/core/database_spec.rb +10 -0
- data/spec/core/dataset_spec.rb +8 -3
- data/spec/core/expression_filters_spec.rb +1 -1
- data/spec/core/schema_spec.rb +17 -2
- data/spec/extensions/caching_spec.rb +2 -2
- data/spec/extensions/hook_class_methods_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +22 -0
- data/spec/extensions/migration_spec.rb +5 -5
- data/spec/extensions/nested_attributes_spec.rb +4 -4
- data/spec/extensions/prepared_statements_spec.rb +37 -26
- data/spec/extensions/update_primary_key_spec.rb +13 -0
- data/spec/integration/dataset_test.rb +36 -0
- data/spec/model/associations_spec.rb +20 -2
- data/spec/model/hooks_spec.rb +1 -7
- metadata +5 -2
@@ -1,3 +1,5 @@
|
|
1
|
+
Sequel.require 'adapters/utils/replace'
|
2
|
+
|
1
3
|
module Sequel
|
2
4
|
module SQLite
|
3
5
|
# No matter how you connect to SQLite, the following Database options
|
@@ -473,6 +475,8 @@ module Sequel
|
|
473
475
|
|
474
476
|
# Instance methods for datasets that connect to an SQLite database
|
475
477
|
module DatasetMethods
|
478
|
+
include Dataset::Replace
|
479
|
+
|
476
480
|
SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'select distinct columns from join where group having compounds order limit')
|
477
481
|
CONSTANT_MAP = {:CURRENT_DATE=>"date(CURRENT_TIMESTAMP, 'localtime')".freeze, :CURRENT_TIMESTAMP=>"datetime(CURRENT_TIMESTAMP, 'localtime')".freeze, :CURRENT_TIME=>"time(CURRENT_TIMESTAMP, 'localtime')".freeze}
|
478
482
|
EMULATED_FUNCTION_MAP = {:char_length=>'length'.freeze}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Sequel
|
2
|
+
class Dataset
|
3
|
+
module Replace
|
4
|
+
INSERT = Dataset::INSERT
|
5
|
+
REPLACE = 'REPLACE'.freeze
|
6
|
+
|
7
|
+
# Execute a REPLACE statement on the database (deletes any duplicate
|
8
|
+
# rows before inserting).
|
9
|
+
def replace(*values)
|
10
|
+
execute_insert(replace_sql(*values))
|
11
|
+
end
|
12
|
+
|
13
|
+
# SQL statement for REPLACE
|
14
|
+
def replace_sql(*values)
|
15
|
+
clone(:replace=>true).insert_sql(*values)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Replace multiple rows in a single query.
|
19
|
+
def multi_replace(*values)
|
20
|
+
clone(:replace=>true).multi_insert(*values)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Databases using this module support REPLACE.
|
24
|
+
def supports_replace?
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# If this is an replace instead of an insert, use replace instead
|
31
|
+
def insert_insert_sql(sql)
|
32
|
+
sql << (@opts[:replace] ? REPLACE : INSERT)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -116,12 +116,16 @@ module Sequel
|
|
116
116
|
end
|
117
117
|
|
118
118
|
# Adds a named constraint (or unnamed if name is nil) to the DDL,
|
119
|
-
# with the given block or args.
|
119
|
+
# with the given block or args. To provide options for the constraint, pass
|
120
|
+
# a hash as the first argument.
|
120
121
|
#
|
121
|
-
# constraint(:blah, :num=>1..5)
|
122
|
-
#
|
122
|
+
# constraint(:blah, :num=>1..5)
|
123
|
+
# # CONSTRAINT blah CHECK num >= 1 AND num <= 5
|
124
|
+
# constraint({:name=>:blah, :deferrable=>true}, :num=>1..5)
|
125
|
+
# # CONSTRAINT blah CHECK num >= 1 AND num <= 5 DEFERRABLE INITIALLY DEFERRED
|
123
126
|
def constraint(name, *args, &block)
|
124
|
-
|
127
|
+
opts = name.is_a?(Hash) ? name : {:name=>name}
|
128
|
+
constraints << opts.merge(:type=>:check, :check=>block || args)
|
125
129
|
end
|
126
130
|
|
127
131
|
# Add a foreign key in the table that references another table to the DDL. See column
|
@@ -319,8 +323,11 @@ module Sequel
|
|
319
323
|
#
|
320
324
|
# add_constraint(:valid_name, Sequel.like(:name, 'A%'))
|
321
325
|
# # ADD CONSTRAINT valid_name CHECK (name LIKE 'A%')
|
326
|
+
# add_constraint({:name=>:valid_name, :deferrable=>true}, :num=>1..5)
|
327
|
+
# # CONSTRAINT valid_name CHECK (name LIKE 'A%') DEFERRABLE INITIALLY DEFERRED
|
322
328
|
def add_constraint(name, *args, &block)
|
323
|
-
|
329
|
+
opts = name.is_a?(Hash) ? name : {:name=>name}
|
330
|
+
@operations << opts.merge(:op=>:add_constraint, :type=>:check, :check=>block || args)
|
324
331
|
end
|
325
332
|
|
326
333
|
# Add a unique constraint to the given column(s)
|
@@ -156,6 +156,8 @@ module Sequel
|
|
156
156
|
#
|
157
157
|
# PostgreSQL specific options:
|
158
158
|
# :unlogged :: Create the table as an unlogged table.
|
159
|
+
# :inherits :: Inherit from a different tables. An array can be
|
160
|
+
# specified to inherit from multiple tables.
|
159
161
|
#
|
160
162
|
# See <tt>Schema::Generator</tt> and the {"Schema Modification" guide}[link:files/doc/schema_modification_rdoc.html].
|
161
163
|
def create_table(name, options=OPTS, &block)
|
@@ -117,6 +117,11 @@ module Sequel
|
|
117
117
|
false
|
118
118
|
end
|
119
119
|
|
120
|
+
# Whether the dataset supports REPLACE syntax, false by default.
|
121
|
+
def supports_replace?
|
122
|
+
false
|
123
|
+
end
|
124
|
+
|
120
125
|
# Whether the RETURNING clause is supported for the given type of query.
|
121
126
|
# +type+ can be :insert, :update, or :delete.
|
122
127
|
def supports_returning?(type)
|
@@ -184,12 +184,6 @@ module Sequel
|
|
184
184
|
a.is_a?(Array) || (defined?(PGArray) && a.is_a?(PGArray)) || (defined?(ArrayOp) && a.is_a?(ArrayOp))
|
185
185
|
end
|
186
186
|
|
187
|
-
# Return a placeholder literal with the given str and args, wrapped
|
188
|
-
# in an SQL::StringExpression, used by operators that return text.
|
189
|
-
def text_op(str, args)
|
190
|
-
Sequel::SQL::StringExpression.new(:NOOP, Sequel::SQL::PlaceholderLiteralString.new(str, [self, args]))
|
191
|
-
end
|
192
|
-
|
193
187
|
# Automatically wrap argument in a PGArray if it is a plain Array.
|
194
188
|
# Requires that the pg_array extension has been loaded to work.
|
195
189
|
def wrap_array(arg)
|
@@ -1512,7 +1512,7 @@ module Sequel
|
|
1512
1512
|
if o.is_a?(Hash)
|
1513
1513
|
o = klass.new(o)
|
1514
1514
|
elsif o.is_a?(Integer) || o.is_a?(String) || o.is_a?(Array)
|
1515
|
-
o = klass
|
1515
|
+
o = klass.with_pk!(o)
|
1516
1516
|
elsif !o.is_a?(klass)
|
1517
1517
|
raise(Sequel::Error, "associated object #{o.inspect} not of correct type #{klass}")
|
1518
1518
|
end
|
@@ -22,7 +22,7 @@ module Sequel
|
|
22
22
|
#
|
23
23
|
# # Attempting to delete the object where the filter doesn't
|
24
24
|
# # match any rows raises an error.
|
25
|
-
# i1.delete # raises Sequel::
|
25
|
+
# i1.delete # raises Sequel::NoExistingObject
|
26
26
|
#
|
27
27
|
# # The other object that represents the same row has no
|
28
28
|
# # instance filters, and can be updated normally.
|
@@ -108,6 +108,16 @@ module Sequel
|
|
108
108
|
def _update_dataset
|
109
109
|
apply_instance_filters(super)
|
110
110
|
end
|
111
|
+
|
112
|
+
# Only use prepared statements for update and delete queries
|
113
|
+
# if there are no instance filters.
|
114
|
+
def use_prepared_statements_for?(type)
|
115
|
+
if (type == :update || type == :delete) && !instance_filters.empty?
|
116
|
+
false
|
117
|
+
else
|
118
|
+
super
|
119
|
+
end
|
120
|
+
end
|
111
121
|
end
|
112
122
|
end
|
113
123
|
end
|
@@ -21,8 +21,9 @@ module Sequel
|
|
21
21
|
# Album.add_pg_typecast_on_load_columns :aliases, :config
|
22
22
|
#
|
23
23
|
# This plugin only handles values that the adapter returns as strings. If
|
24
|
-
# the adapter returns a value other than a string
|
25
|
-
#
|
24
|
+
# the adapter returns a value other than a string, this plugin will have no
|
25
|
+
# effect. You may be able to use the regular typecast_on_load plugin to
|
26
|
+
# handle those cases.
|
26
27
|
module PgTypecastOnLoad
|
27
28
|
# Call add_pg_typecast_on_load_columns on the passed column arguments.
|
28
29
|
def self.configure(model, *columns)
|
@@ -1,4 +1,16 @@
|
|
1
1
|
module Sequel
|
2
|
+
class Model
|
3
|
+
module InstanceMethods
|
4
|
+
# Whether prepared statements should be used for the given type of query
|
5
|
+
# (:insert, :insert_select, :refresh, :update, or :delete). True by default,
|
6
|
+
# can be overridden in other plugins to disallow prepared statements for
|
7
|
+
# specific types of queries.
|
8
|
+
def use_prepared_statements_for?(type)
|
9
|
+
true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
2
14
|
module Plugins
|
3
15
|
# The prepared_statements plugin modifies the model to use prepared statements for
|
4
16
|
# instance level deletes and saves, as well as class level lookups by
|
@@ -11,9 +23,6 @@ module Sequel
|
|
11
23
|
# of prepared statements that can be created, unless you tightly control how your
|
12
24
|
# model instances are saved.
|
13
25
|
#
|
14
|
-
# This plugin does not work correctly with the instance filters plugin
|
15
|
-
# or the update_primary_key plugin.
|
16
|
-
#
|
17
26
|
# Usage:
|
18
27
|
#
|
19
28
|
# # Make all model subclasses use prepared statements (called before loading subclasses)
|
@@ -133,30 +142,50 @@ module Sequel
|
|
133
142
|
|
134
143
|
# Use a prepared statement to delete the row.
|
135
144
|
def _delete_without_checking
|
136
|
-
|
145
|
+
if use_prepared_statements_for?(:delete)
|
146
|
+
model.send(:prepared_delete).call(pk_hash)
|
147
|
+
else
|
148
|
+
super
|
149
|
+
end
|
137
150
|
end
|
138
151
|
|
139
152
|
# Use a prepared statement to insert the values into the model's dataset.
|
140
153
|
def _insert_raw(ds)
|
141
|
-
|
154
|
+
if use_prepared_statements_for?(:insert)
|
155
|
+
model.send(:prepared_insert, @values.keys).call(@values)
|
156
|
+
else
|
157
|
+
super
|
158
|
+
end
|
142
159
|
end
|
143
160
|
|
144
161
|
# Use a prepared statement to insert the values into the model's dataset
|
145
162
|
# and return the new column values.
|
146
163
|
def _insert_select_raw(ds)
|
147
|
-
if
|
148
|
-
ps.
|
164
|
+
if use_prepared_statements_for?(:insert_select)
|
165
|
+
if ps = model.send(:prepared_insert_select, @values.keys)
|
166
|
+
ps.call(@values)
|
167
|
+
end
|
168
|
+
else
|
169
|
+
super
|
149
170
|
end
|
150
171
|
end
|
151
172
|
|
152
173
|
# Use a prepared statement to refresh this model's column values.
|
153
174
|
def _refresh_get(ds)
|
154
|
-
|
175
|
+
if use_prepared_statements_for?(:refresh)
|
176
|
+
model.send(:prepared_refresh).call(pk_hash)
|
177
|
+
else
|
178
|
+
super
|
179
|
+
end
|
155
180
|
end
|
156
181
|
|
157
182
|
# Use a prepared statement to update this model's columns in the database.
|
158
183
|
def _update_without_checking(columns)
|
159
|
-
|
184
|
+
if use_prepared_statements_for?(:update)
|
185
|
+
model.send(:prepared_update, columns.keys).call(columns.merge(pk_hash))
|
186
|
+
else
|
187
|
+
super
|
188
|
+
end
|
160
189
|
end
|
161
190
|
end
|
162
191
|
end
|
@@ -54,6 +54,16 @@ module Sequel
|
|
54
54
|
associations.delete(k) if model.association_reflection(k)[:type] != :many_to_one
|
55
55
|
end
|
56
56
|
end
|
57
|
+
|
58
|
+
# Do not use prepared statements for update queries, since they don't work
|
59
|
+
# in the case where the primary key has changed.
|
60
|
+
def use_prepared_statements_for?(type)
|
61
|
+
if type == :update
|
62
|
+
false
|
63
|
+
else
|
64
|
+
super
|
65
|
+
end
|
66
|
+
end
|
57
67
|
end
|
58
68
|
end
|
59
69
|
end
|
data/lib/sequel/sql.rb
CHANGED
@@ -1624,7 +1624,7 @@ module Sequel
|
|
1624
1624
|
fun_args = ::Kernel.Array(opts[:*] ? WILDCARD : opts[:args])
|
1625
1625
|
WindowFunction.new(Function.new(m, *fun_args), Window.new(opts))
|
1626
1626
|
else
|
1627
|
-
raise
|
1627
|
+
Kernel.raise(Error, 'unsupported VirtualRow method argument used with block')
|
1628
1628
|
end
|
1629
1629
|
end
|
1630
1630
|
elsif args.empty?
|
data/lib/sequel/version.rb
CHANGED
@@ -3,7 +3,7 @@ module Sequel
|
|
3
3
|
MAJOR = 4
|
4
4
|
# The minor version of Sequel. Bumped for every non-patch level
|
5
5
|
# release, generally around once a month.
|
6
|
-
MINOR =
|
6
|
+
MINOR = 1
|
7
7
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
8
8
|
# releases that fix regressions from previous versions.
|
9
9
|
TINY = 0
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -1070,27 +1070,6 @@ describe "MySQL::Dataset#replace" do
|
|
1070
1070
|
@d.replace({})
|
1071
1071
|
@d.all.should == [{:id=>1, :value=>2}]
|
1072
1072
|
end
|
1073
|
-
|
1074
|
-
specify "should use support arrays, datasets, and multiple values" do
|
1075
|
-
@d.replace([1, 2])
|
1076
|
-
@d.all.should == [{:id=>1, :value=>2}]
|
1077
|
-
@d.replace(1, 2)
|
1078
|
-
@d.all.should == [{:id=>1, :value=>2}]
|
1079
|
-
@d.replace(@d)
|
1080
|
-
@d.all.should == [{:id=>1, :value=>2}]
|
1081
|
-
end
|
1082
|
-
|
1083
|
-
specify "should create a record if the condition is not met" do
|
1084
|
-
@d.replace(:id => 111, :value => 333)
|
1085
|
-
@d.all.should == [{:id => 111, :value => 333}]
|
1086
|
-
end
|
1087
|
-
|
1088
|
-
specify "should update a record if the condition is met" do
|
1089
|
-
@d << {:id => 111}
|
1090
|
-
@d.all.should == [{:id => 111, :value => nil}]
|
1091
|
-
@d.replace(:id => 111, :value => 333)
|
1092
|
-
@d.all.should == [{:id => 111, :value => 333}]
|
1093
|
-
end
|
1094
1073
|
end
|
1095
1074
|
|
1096
1075
|
describe "MySQL::Dataset#complex_expression_sql" do
|
@@ -1303,5 +1282,5 @@ if DB.adapter_scheme == :mysql2
|
|
1303
1282
|
specify "should correctly handle early returning when streaming results" do
|
1304
1283
|
3.times{@ds.each{|r| break r[:a]}.should == 0}
|
1305
1284
|
end
|
1306
|
-
end
|
1285
|
+
end
|
1307
1286
|
end
|
@@ -17,8 +17,7 @@ describe "PostgreSQL", '#create_table' do
|
|
17
17
|
DB.sqls.clear
|
18
18
|
end
|
19
19
|
after do
|
20
|
-
@db.drop_table?(:tmp_dolls)
|
21
|
-
@db.drop_table?(:unlogged_dolls)
|
20
|
+
@db.drop_table?(:tmp_dolls, :unlogged_dolls)
|
22
21
|
end
|
23
22
|
|
24
23
|
specify "should create a temporary table" do
|
@@ -35,6 +34,27 @@ describe "PostgreSQL", '#create_table' do
|
|
35
34
|
end
|
36
35
|
end
|
37
36
|
|
37
|
+
specify "should create a table inheriting from another table" do
|
38
|
+
@db.create_table(:unlogged_dolls){text :name}
|
39
|
+
@db.create_table(:tmp_dolls, :inherits=>:unlogged_dolls){}
|
40
|
+
@db[:tmp_dolls].insert('a')
|
41
|
+
@db[:unlogged_dolls].all.should == [{:name=>'a'}]
|
42
|
+
end
|
43
|
+
|
44
|
+
specify "should create a table inheriting from multiple tables" do
|
45
|
+
begin
|
46
|
+
@db.create_table(:unlogged_dolls){text :name}
|
47
|
+
@db.create_table(:tmp_dolls){text :bar}
|
48
|
+
@db.create_table!(:items, :inherits=>[:unlogged_dolls, :tmp_dolls]){text :foo}
|
49
|
+
@db[:items].insert(:name=>'a', :bar=>'b', :foo=>'c')
|
50
|
+
@db[:unlogged_dolls].all.should == [{:name=>'a'}]
|
51
|
+
@db[:tmp_dolls].all.should == [{:bar=>'b'}]
|
52
|
+
@db[:items].all.should == [{:name=>'a', :bar=>'b', :foo=>'c'}]
|
53
|
+
ensure
|
54
|
+
@db.drop_table?(:items)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
38
58
|
specify "should not allow to pass both :temp and :unlogged" do
|
39
59
|
proc do
|
40
60
|
@db.create_table(:temp_unlogged_dolls, :temp => true, :unlogged => true){text :name}
|
@@ -232,6 +252,43 @@ describe "A PostgreSQL dataset" do
|
|
232
252
|
proc{@db[:atest].insert(2)}.should raise_error(Sequel::Postgres::ExclusionConstraintViolation)
|
233
253
|
@db.alter_table(:atest){drop_constraint 'atest_ex'}
|
234
254
|
end if DB.server_version >= 90000
|
255
|
+
|
256
|
+
specify "should support deferrable exclusion constraints" do
|
257
|
+
@db.create_table!(:atest){Integer :t; exclude [[Sequel.desc(:t, :nulls=>:last), '=']], :using=>:btree, :where=>proc{t > 0}, :deferrable => true}
|
258
|
+
proc do
|
259
|
+
@db.transaction do
|
260
|
+
@db[:atest].insert(2)
|
261
|
+
proc{@db[:atest].insert(2)}.should_not raise_error
|
262
|
+
end
|
263
|
+
end.should raise_error(Sequel::Postgres::ExclusionConstraintViolation)
|
264
|
+
end if DB.server_version >= 90000
|
265
|
+
|
266
|
+
specify "should support Database#error_info for getting info hash on the given error" do
|
267
|
+
@db.create_table!(:atest){Integer :t; Integer :t2, :null=>false, :default=>1; constraint :f, :t=>0}
|
268
|
+
begin
|
269
|
+
@db[:atest].insert(1)
|
270
|
+
rescue => e
|
271
|
+
end
|
272
|
+
e.should_not be_nil
|
273
|
+
info = @db.error_info(e)
|
274
|
+
info[:schema].should == 'public'
|
275
|
+
info[:table].should == 'atest'
|
276
|
+
info[:constraint].should == 'f'
|
277
|
+
info[:column].should be_nil
|
278
|
+
info[:type].should be_nil
|
279
|
+
|
280
|
+
begin
|
281
|
+
@db[:atest].insert(0, nil)
|
282
|
+
rescue => e
|
283
|
+
end
|
284
|
+
e.should_not be_nil
|
285
|
+
info = @db.error_info(e.wrapped_exception)
|
286
|
+
info[:schema].should == 'public'
|
287
|
+
info[:table].should == 'atest'
|
288
|
+
info[:constraint].should be_nil
|
289
|
+
info[:column].should == 't2'
|
290
|
+
info[:type].should be_nil
|
291
|
+
end if DB.server_version >= 90300 && DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG && Object.const_defined?(:PG) && ::PG.const_defined?(:Constants) && ::PG::Constants.const_defined?(:PG_DIAG_SCHEMA_NAME)
|
235
292
|
|
236
293
|
specify "should support Database#do for executing anonymous code blocks" do
|
237
294
|
@db.drop_table?(:btest)
|
@@ -255,6 +312,19 @@ describe "A PostgreSQL dataset" do
|
|
255
312
|
proc{@db.alter_table(:atest){validate_constraint :atest_fk}}.should_not raise_error
|
256
313
|
end if DB.server_version >= 90200
|
257
314
|
|
315
|
+
specify "should support adding check constarints that are not yet valid, and validating them later" do
|
316
|
+
@db.create_table!(:atest){Integer :a}
|
317
|
+
@db[:atest].insert(5)
|
318
|
+
@db.alter_table(:atest){add_constraint({:name=>:atest_check, :not_valid=>true}){a >= 10}}
|
319
|
+
@db[:atest].insert(10)
|
320
|
+
proc{@db[:atest].insert(6)}.should raise_error(Sequel::DatabaseError)
|
321
|
+
|
322
|
+
proc{@db.alter_table(:atest){validate_constraint :atest_check}}.should raise_error(Sequel::DatabaseError)
|
323
|
+
@db[:atest].where{a < 10}.update(:a=>Sequel.+(:a, 10))
|
324
|
+
@db.alter_table(:atest){validate_constraint :atest_check}
|
325
|
+
proc{@db.alter_table(:atest){validate_constraint :atest_check}}.should_not raise_error
|
326
|
+
end if DB.server_version >= 90200
|
327
|
+
|
258
328
|
specify "should support :using when altering a column's type" do
|
259
329
|
@db.create_table!(:atest){Integer :t}
|
260
330
|
@db[:atest].insert(1262304000)
|
@@ -927,6 +997,13 @@ describe "Postgres::Database schema qualified tables" do
|
|
927
997
|
@db.table_exists?(:schema_test__schema_test).should == true
|
928
998
|
end
|
929
999
|
|
1000
|
+
specify "should be able to add and drop indexes in a schema" do
|
1001
|
+
@db.create_table(:schema_test__schema_test){Integer :i, :index=>true}
|
1002
|
+
@db.indexes(:schema_test__schema_test).keys.should == [:schema_test_schema_test_i_index]
|
1003
|
+
@db.drop_index :schema_test__schema_test, :i
|
1004
|
+
@db.indexes(:schema_test__schema_test).keys.should == []
|
1005
|
+
end
|
1006
|
+
|
930
1007
|
specify "should be able to get primary keys for tables in a given schema" do
|
931
1008
|
@db.create_table(:schema_test__schema_test){primary_key :i}
|
932
1009
|
@db.primary_key(:schema_test__schema_test).should == 'i'
|