sequel 3.44.0 → 3.45.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +44 -0
- data/Rakefile +12 -4
- data/doc/reflection.rdoc +3 -3
- data/doc/release_notes/3.45.0.txt +179 -0
- data/doc/schema_modification.rdoc +1 -1
- data/doc/transactions.rdoc +23 -0
- data/lib/sequel/adapters/db2.rb +1 -0
- data/lib/sequel/adapters/ibmdb.rb +19 -3
- data/lib/sequel/adapters/jdbc.rb +15 -0
- data/lib/sequel/adapters/jdbc/derby.rb +1 -5
- data/lib/sequel/adapters/jdbc/h2.rb +1 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +2 -1
- data/lib/sequel/adapters/jdbc/jtds.rb +5 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +5 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +7 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +1 -1
- data/lib/sequel/adapters/jdbc/transactions.rb +28 -1
- data/lib/sequel/adapters/mysql.rb +4 -0
- data/lib/sequel/adapters/mysql2.rb +5 -1
- data/lib/sequel/adapters/oracle.rb +18 -0
- data/lib/sequel/adapters/postgres.rb +11 -1
- data/lib/sequel/adapters/shared/access.rb +14 -2
- data/lib/sequel/adapters/shared/cubrid.rb +1 -11
- data/lib/sequel/adapters/shared/db2.rb +11 -6
- data/lib/sequel/adapters/shared/mssql.rb +10 -10
- data/lib/sequel/adapters/shared/mysql.rb +11 -1
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +17 -1
- data/lib/sequel/adapters/shared/oracle.rb +16 -15
- data/lib/sequel/adapters/shared/postgres.rb +91 -59
- data/lib/sequel/adapters/shared/sqlite.rb +1 -4
- data/lib/sequel/adapters/tinytds.rb +15 -0
- data/lib/sequel/connection_pool/threaded.rb +1 -1
- data/lib/sequel/core.rb +10 -0
- data/lib/sequel/database/connecting.rb +2 -0
- data/lib/sequel/database/misc.rb +46 -4
- data/lib/sequel/database/query.rb +33 -14
- data/lib/sequel/database/schema_methods.rb +0 -5
- data/lib/sequel/dataset/misc.rb +9 -0
- data/lib/sequel/dataset/mutation.rb +9 -7
- data/lib/sequel/dataset/sql.rb +13 -0
- data/lib/sequel/exceptions.rb +3 -0
- data/lib/sequel/extensions/connection_validator.rb +1 -1
- data/lib/sequel/extensions/date_arithmetic.rb +0 -8
- data/lib/sequel/extensions/eval_inspect.rb +2 -0
- data/lib/sequel/extensions/named_timezones.rb +18 -2
- data/lib/sequel/extensions/pg_array.rb +5 -1
- data/lib/sequel/extensions/pg_array_ops.rb +2 -0
- data/lib/sequel/extensions/pg_hstore.rb +2 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +2 -0
- data/lib/sequel/extensions/pg_json.rb +3 -1
- data/lib/sequel/extensions/pg_range.rb +2 -0
- data/lib/sequel/extensions/pg_range_ops.rb +2 -0
- data/lib/sequel/extensions/pg_row.rb +2 -0
- data/lib/sequel/extensions/pg_row_ops.rb +2 -0
- data/lib/sequel/extensions/query.rb +18 -22
- data/lib/sequel/model/associations.rb +3 -4
- data/lib/sequel/model/base.rb +2 -0
- data/lib/sequel/plugins/force_encoding.rb +2 -0
- data/lib/sequel/plugins/json_serializer.rb +155 -39
- data/lib/sequel/plugins/serialization.rb +14 -2
- data/lib/sequel/plugins/unlimited_update.rb +31 -0
- data/lib/sequel/plugins/validation_class_methods.rb +6 -4
- data/lib/sequel/plugins/xml_serializer.rb +133 -30
- data/lib/sequel/sql.rb +2 -0
- data/lib/sequel/timezones.rb +4 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +0 -11
- data/spec/adapters/postgres_spec.rb +86 -54
- data/spec/adapters/spec_helper.rb +6 -0
- data/spec/core/connection_pool_spec.rb +16 -0
- data/spec/core/database_spec.rb +77 -1
- data/spec/core/dataset_spec.rb +30 -15
- data/spec/core/expression_filters_spec.rb +55 -13
- data/spec/core/mock_adapter_spec.rb +4 -0
- data/spec/core/schema_spec.rb +0 -2
- data/spec/core/spec_helper.rb +5 -0
- data/spec/core_extensions_spec.rb +33 -28
- data/spec/extensions/constraint_validations_spec.rb +2 -2
- data/spec/extensions/core_refinements_spec.rb +12 -12
- data/spec/extensions/json_serializer_spec.rb +137 -31
- data/spec/extensions/named_timezones_spec.rb +10 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +5 -0
- data/spec/extensions/pg_json_spec.rb +14 -0
- data/spec/extensions/pg_row_spec.rb +11 -0
- data/spec/extensions/pretty_table_spec.rb +2 -2
- data/spec/extensions/query_spec.rb +11 -8
- data/spec/extensions/serialization_spec.rb +20 -0
- data/spec/extensions/spec_helper.rb +8 -2
- data/spec/extensions/sql_expr_spec.rb +1 -1
- data/spec/extensions/unlimited_update_spec.rb +20 -0
- data/spec/extensions/xml_serializer_spec.rb +68 -16
- data/spec/integration/dataset_test.rb +28 -0
- data/spec/integration/spec_helper.rb +6 -0
- data/spec/integration/transaction_test.rb +39 -0
- data/spec/model/model_spec.rb +1 -1
- data/spec/sequel_coverage.rb +15 -0
- metadata +8 -3
@@ -0,0 +1,31 @@
|
|
1
|
+
module Sequel
|
2
|
+
module Plugins
|
3
|
+
# The unlimited_update plugin is designed to work around a
|
4
|
+
# MySQL warning in replicated environments, which occurs if
|
5
|
+
# you issue an UPDATE with a LIMIT clause. No other
|
6
|
+
# database Sequel supports will create an UPDATE clause with
|
7
|
+
# a LIMIT, and in non-replicated MySQL environments, MySQL
|
8
|
+
# doesn't issue a warning. Note that even in replicated
|
9
|
+
# environments the MySQL warning is harmless, as Sequel
|
10
|
+
# restricts an update to rows with a matching primary key,
|
11
|
+
# which should be unique.
|
12
|
+
#
|
13
|
+
# Usage:
|
14
|
+
#
|
15
|
+
# # Make all model subclass not use a limit for update
|
16
|
+
# Sequel::Model.plugin :unlimited_update
|
17
|
+
#
|
18
|
+
# # Make the Album class not use a limit for update
|
19
|
+
# Album.plugin :unlimited_update
|
20
|
+
module UnlimitedUpdate
|
21
|
+
module InstanceMethods
|
22
|
+
private
|
23
|
+
|
24
|
+
# Use an unlimited dataset for updates.
|
25
|
+
def _update_dataset
|
26
|
+
super.unlimited
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -432,10 +432,12 @@ module Sequel
|
|
432
432
|
# Handle the :if option for validations
|
433
433
|
def validation_if_proc(o, i)
|
434
434
|
case i
|
435
|
-
when Symbol
|
436
|
-
|
437
|
-
when
|
438
|
-
|
435
|
+
when Symbol
|
436
|
+
o.send(i)
|
437
|
+
when Proc
|
438
|
+
o.instance_eval(&i)
|
439
|
+
else
|
440
|
+
raise(::Sequel::Error, "invalid value for :if validation option")
|
439
441
|
end
|
440
442
|
end
|
441
443
|
end
|
@@ -57,32 +57,54 @@ module Sequel
|
|
57
57
|
# </artist>
|
58
58
|
# </album>
|
59
59
|
#
|
60
|
+
# +to_xml+ also exists as a class and dataset method, both
|
61
|
+
# of which return all objects in the dataset:
|
62
|
+
#
|
63
|
+
# Album.to_xml
|
64
|
+
# Album.filter(:artist_id=>1).to_xml(:include=>:tags)
|
65
|
+
#
|
66
|
+
# If you have an existing array of model instances you want to convert to
|
67
|
+
# XML, you can call the class to_xml method with the :array option:
|
68
|
+
#
|
69
|
+
# Album.to_xml(:array=>[Album[1], Album[2]])
|
70
|
+
#
|
60
71
|
# In addition to creating XML, this plugin also enables Sequel::Model
|
61
|
-
#
|
72
|
+
# classes to create instances directly from XML using the from_xml class
|
73
|
+
# method:
|
62
74
|
#
|
63
75
|
# xml = album.to_xml
|
64
76
|
# album = Album.from_xml(xml)
|
65
77
|
#
|
66
|
-
#
|
67
|
-
#
|
78
|
+
# The array_from_xml class method exists to parse arrays of model instances
|
79
|
+
# from xml:
|
68
80
|
#
|
69
|
-
#
|
81
|
+
# xml = Album.filter(:artist_id=>1).to_xml
|
82
|
+
# albums = Album.array_from_xml(xml)
|
70
83
|
#
|
71
|
-
#
|
72
|
-
#
|
84
|
+
# These does not necessarily round trip, since doing so would let users
|
85
|
+
# create model objects with arbitrary values. By default, from_xml will
|
86
|
+
# call set using values from the tags in the xml. If you want to specify the allowed
|
87
|
+
# fields, you can use the :fields option, which will call set_fields with
|
88
|
+
# the given fields:
|
73
89
|
#
|
74
|
-
# Album.to_xml
|
75
|
-
# Album.filter(:artist_id=>1).to_xml(:include=>:tags)
|
90
|
+
# Album.from_xml(album.to_xml, :fields=>%w'id name')
|
76
91
|
#
|
77
|
-
#
|
78
|
-
#
|
92
|
+
# If you want to update an existing instance, you can use the from_xml
|
93
|
+
# instance method:
|
79
94
|
#
|
80
|
-
#
|
95
|
+
# album.from_xml(xml)
|
81
96
|
#
|
82
|
-
#
|
83
|
-
#
|
97
|
+
# Both of these allow creation of cached associated objects, if you provide
|
98
|
+
# the :associations option:
|
84
99
|
#
|
85
|
-
#
|
100
|
+
# album.from_xml(xml, :associations=>:artist)
|
101
|
+
#
|
102
|
+
# You can even provide options when setting up the associated objects:
|
103
|
+
#
|
104
|
+
# album.from_xml(xml, :associations=>{:artist=>{:fields=>%w'id name', :associations=>:tags}})
|
105
|
+
#
|
106
|
+
# If the xml is trusted and should be allowed to set all column and association
|
107
|
+
# values, you can use the :all_columns and :all_associations options.
|
86
108
|
#
|
87
109
|
# Usage:
|
88
110
|
#
|
@@ -109,7 +131,11 @@ module Sequel
|
|
109
131
|
# Return an array of instances of this class based on
|
110
132
|
# the provided XML.
|
111
133
|
def array_from_xml(xml, opts={})
|
112
|
-
Nokogiri::XML(xml).children.first
|
134
|
+
node = Nokogiri::XML(xml).children.first
|
135
|
+
unless node
|
136
|
+
raise Error, "Malformed XML used"
|
137
|
+
end
|
138
|
+
node.children.reject{|c| c.is_a?(Nokogiri::XML::Text)}.map{|c| from_xml_node(c, opts)}
|
113
139
|
end
|
114
140
|
|
115
141
|
# Return an instance of this class based on the provided
|
@@ -193,30 +219,107 @@ module Sequel
|
|
193
219
|
|
194
220
|
# Update the contents of this instance based on the given
|
195
221
|
# XML node, which should be a Nokogiri::XML::Node instance.
|
222
|
+
# By default, just calls set with a hash created from the content of the node.
|
223
|
+
#
|
224
|
+
# Options:
|
225
|
+
# :all_associations :: Indicates that all associations supported by the model should be tried.
|
226
|
+
# This option also cascades to associations if used. It is better to use the
|
227
|
+
# :associations option instead of this option. This option only exists for
|
228
|
+
# backwards compatibility.
|
229
|
+
# :all_columns :: Overrides the setting logic allowing all setter methods be used,
|
230
|
+
# even if access to the setter method is restricted.
|
231
|
+
# This option cascades to associations if used, and can be reset in those associations
|
232
|
+
# using the :all_columns=>false or :fields options. This option is considered a
|
233
|
+
# security risk, and only exists for backwards compatibility. It is better to use
|
234
|
+
# the :fields option appropriately instead of this option, or no option at all.
|
235
|
+
# :associations :: Indicates that the associations cache should be updated by creating
|
236
|
+
# a new associated object using data from the hash. Should be a Symbol
|
237
|
+
# for a single association, an array of symbols for multiple associations,
|
238
|
+
# or a hash with symbol keys and dependent association option hash values.
|
239
|
+
# :fields :: Changes the behavior to call set_fields using the provided fields, instead of calling set.
|
196
240
|
def from_xml_node(parent, opts={})
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
241
|
+
unless parent
|
242
|
+
raise Error, "Malformed XML used"
|
243
|
+
end
|
244
|
+
if !parent.children.empty? && parent.children.all?{|node| node.is_a?(Nokogiri::XML::Text)}
|
245
|
+
raise Error, "XML consisting of just text nodes used"
|
246
|
+
end
|
247
|
+
|
248
|
+
unless assocs = opts[:associations]
|
249
|
+
if opts[:all_associations]
|
250
|
+
assocs = {}
|
251
|
+
model.associations.each{|v| assocs[v] = {:all_associations=>true}}
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
if assocs
|
256
|
+
assocs = case assocs
|
257
|
+
when Symbol
|
258
|
+
{assocs=>{}}
|
259
|
+
when Array
|
260
|
+
assocs_tmp = {}
|
261
|
+
assocs.each{|v| assocs_tmp[v] = {}}
|
262
|
+
assocs_tmp
|
263
|
+
when Hash
|
264
|
+
assocs
|
265
|
+
else
|
266
|
+
raise Error, ":associations should be Symbol, Array, or Hash if present"
|
267
|
+
end
|
268
|
+
|
269
|
+
if opts[:all_columns]
|
270
|
+
assocs.each_value do |assoc_opts|
|
271
|
+
assoc_opts[:all_columns] = true unless assoc_opts.has_key?(:fields) || assoc_opts.has_key?(:all_columns)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
assocs_hash = {}
|
276
|
+
assocs.each{|k,v| assocs_hash[k.to_s] = v}
|
277
|
+
assocs_present = []
|
278
|
+
end
|
279
|
+
|
280
|
+
hash = {}
|
201
281
|
name_proc = model.xml_deserialize_name_proc(opts)
|
202
282
|
parent.children.each do |node|
|
203
283
|
next if node.is_a?(Nokogiri::XML::Text)
|
204
284
|
k = name_proc[node.name]
|
205
|
-
if
|
206
|
-
|
207
|
-
|
208
|
-
|
285
|
+
if assocs_hash && (assoc = assocs_hash[k])
|
286
|
+
assocs_present << [k.to_sym, node]
|
287
|
+
else
|
288
|
+
hash[k] = node.key?('nil') ? nil : node.children.first.to_s
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
if assocs_present
|
293
|
+
assocs_present.each do |assoc, node|
|
294
|
+
assoc_opts = assocs[assoc]
|
295
|
+
|
296
|
+
unless r = model.association_reflection(assoc)
|
297
|
+
raise Error, "Association #{assoc} is not defined for #{model}"
|
298
|
+
end
|
299
|
+
|
300
|
+
associations[assoc] = if r.returns_array?
|
301
|
+
node.children.reject{|c| c.is_a?(Nokogiri::XML::Text)}.map{|c| r.associated_class.from_xml_node(c, assoc_opts)}
|
209
302
|
else
|
210
|
-
|
303
|
+
r.associated_class.from_xml_node(node, assoc_opts)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
if fields = opts[:fields]
|
309
|
+
set_fields(hash, fields, opts)
|
310
|
+
elsif opts[:all_columns]
|
311
|
+
meths = methods.collect{|x| x.to_s}.grep(Model::SETTER_METHOD_REGEXP) - Model::RESTRICTED_SETTER_METHODS
|
312
|
+
hash.each do |k, v|
|
313
|
+
if meths.include?(setter_meth = "#{k}=")
|
314
|
+
send(setter_meth, v)
|
315
|
+
else
|
316
|
+
raise Error, "Entry in XML does not have a matching setter method: #{k}"
|
211
317
|
end
|
212
|
-
elsif cols.include?(k)
|
213
|
-
self[k.to_sym] = node.key?('nil') ? nil : node.children.first.to_s
|
214
|
-
elsif meths.include?("#{k}=")
|
215
|
-
send("#{k}=", node.key?('nil') ? nil : node.children.first.to_s)
|
216
|
-
else
|
217
|
-
raise Error, "Entry in XML not an association or column and no setter method exists: #{k}"
|
218
318
|
end
|
319
|
+
else
|
320
|
+
set(hash)
|
219
321
|
end
|
322
|
+
|
220
323
|
self
|
221
324
|
end
|
222
325
|
|
data/lib/sequel/sql.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Sequel
|
2
2
|
if RUBY_VERSION < '1.9.0'
|
3
|
+
# :nocov:
|
3
4
|
# If on Ruby 1.8, create a <tt>Sequel::BasicObject</tt> class that is similar to the
|
4
5
|
# the Ruby 1.9 +BasicObject+ class. This is used in a few places where proxy
|
5
6
|
# objects are needed that respond to any method call.
|
@@ -16,6 +17,7 @@ module Sequel
|
|
16
17
|
end
|
17
18
|
remove_methods!
|
18
19
|
end
|
20
|
+
# :nocov:
|
19
21
|
else
|
20
22
|
# If on 1.9, create a <tt>Sequel::BasicObject</tt> class that is just like the
|
21
23
|
# default +BasicObject+ class, except that missing constants are resolved in
|
data/lib/sequel/timezones.rb
CHANGED
@@ -168,9 +168,11 @@ module Sequel
|
|
168
168
|
if v.respond_to?(:to_datetime)
|
169
169
|
v.to_datetime
|
170
170
|
else
|
171
|
+
# :nocov:
|
171
172
|
# Ruby 1.8 code, %N not available and %z broken on Windows
|
172
173
|
offset_hours, offset_minutes = (v.utc_offset/60).divmod(60)
|
173
174
|
string_to_datetime(v.strftime("%Y-%m-%dT%H:%M:%S") << sprintf(".%06i%+03i%02i", v.usec, offset_hours, offset_minutes))
|
175
|
+
# :nocov:
|
174
176
|
end
|
175
177
|
else
|
176
178
|
v
|
@@ -181,7 +183,9 @@ module Sequel
|
|
181
183
|
elsif v.respond_to?(:to_time)
|
182
184
|
v.to_time
|
183
185
|
else
|
186
|
+
# :nocov:
|
184
187
|
string_to_datetime(v.strftime("%FT%T.%N%z"))
|
188
|
+
# :nocov:
|
185
189
|
end
|
186
190
|
else
|
187
191
|
raise InvalidValue, "Invalid convert_input_timestamp type: #{v.inspect}"
|
data/lib/sequel/version.rb
CHANGED
@@ -3,7 +3,7 @@ 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 = 45
|
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
@@ -1105,17 +1105,6 @@ describe "MySQL::Dataset#complex_expression_sql" do
|
|
1105
1105
|
@d = MYSQL_DB.dataset
|
1106
1106
|
end
|
1107
1107
|
|
1108
|
-
specify "should handle pattern matches correctly" do
|
1109
|
-
@d.literal(Sequel.expr(:x).like('a')).should == "(`x` LIKE BINARY 'a')"
|
1110
|
-
@d.literal(~Sequel.expr(:x).like('a')).should == "(`x` NOT LIKE BINARY 'a')"
|
1111
|
-
@d.literal(Sequel.expr(:x).ilike('a')).should == "(`x` LIKE 'a')"
|
1112
|
-
@d.literal(~Sequel.expr(:x).ilike('a')).should == "(`x` NOT LIKE 'a')"
|
1113
|
-
@d.literal(Sequel.expr(:x).like(/a/)).should == "(`x` REGEXP BINARY 'a')"
|
1114
|
-
@d.literal(~Sequel.expr(:x).like(/a/)).should == "(`x` NOT REGEXP BINARY 'a')"
|
1115
|
-
@d.literal(Sequel.expr(:x).like(/a/i)).should == "(`x` REGEXP 'a')"
|
1116
|
-
@d.literal(~Sequel.expr(:x).like(/a/i)).should == "(`x` NOT REGEXP 'a')"
|
1117
|
-
end
|
1118
|
-
|
1119
1108
|
specify "should handle string concatenation with CONCAT if more than one record" do
|
1120
1109
|
@d.literal(Sequel.join([:x, :y])).should == "CONCAT(`x`, `y`)"
|
1121
1110
|
@d.literal(Sequel.join([:x, :y], ' ')).should == "CONCAT(`x`, ' ', `y`)"
|
@@ -83,6 +83,16 @@ describe "A PostgreSQL database" do
|
|
83
83
|
@db.server_version.should > 70000
|
84
84
|
end
|
85
85
|
|
86
|
+
specify "should support a :qualify option to tables and views" do
|
87
|
+
@db.tables(:qualify=>true).should include(Sequel.qualify(:public, :testfk))
|
88
|
+
begin
|
89
|
+
@db.create_view(:testfkv, @db[:testfk])
|
90
|
+
@db.views(:qualify=>true).should include(Sequel.qualify(:public, :testfkv))
|
91
|
+
ensure
|
92
|
+
@db.drop_view(:testfkv)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
86
96
|
specify "should not typecast the int2vector type incorrectly" do
|
87
97
|
@db.get(Sequel.cast('10 20', :int2vector)).should_not == 10
|
88
98
|
end
|
@@ -790,109 +800,131 @@ end
|
|
790
800
|
|
791
801
|
describe "Postgres::Database schema qualified tables" do
|
792
802
|
before do
|
793
|
-
|
794
|
-
|
795
|
-
|
803
|
+
@db = POSTGRES_DB
|
804
|
+
@db << "CREATE SCHEMA schema_test"
|
805
|
+
@db.instance_variable_set(:@primary_keys, {})
|
806
|
+
@db.instance_variable_set(:@primary_key_sequences, {})
|
796
807
|
end
|
797
808
|
after do
|
798
|
-
|
799
|
-
|
809
|
+
@db << "DROP SCHEMA schema_test CASCADE"
|
810
|
+
@db.default_schema = nil
|
800
811
|
end
|
801
812
|
|
802
813
|
specify "should be able to create, drop, select and insert into tables in a given schema" do
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
814
|
+
@db.create_table(:schema_test__schema_test){primary_key :i}
|
815
|
+
@db[:schema_test__schema_test].first.should == nil
|
816
|
+
@db[:schema_test__schema_test].insert(:i=>1).should == 1
|
817
|
+
@db[:schema_test__schema_test].first.should == {:i=>1}
|
818
|
+
@db.from(Sequel.lit('schema_test.schema_test')).first.should == {:i=>1}
|
819
|
+
@db.drop_table(:schema_test__schema_test)
|
820
|
+
@db.create_table(Sequel.qualify(:schema_test, :schema_test)){integer :i}
|
821
|
+
@db[:schema_test__schema_test].first.should == nil
|
822
|
+
@db.from(Sequel.lit('schema_test.schema_test')).first.should == nil
|
823
|
+
@db.drop_table(Sequel.qualify(:schema_test, :schema_test))
|
813
824
|
end
|
814
825
|
|
815
826
|
specify "#tables should not include tables in a default non-public schema" do
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
827
|
+
@db.create_table(:schema_test__schema_test){integer :i}
|
828
|
+
@db.tables.should include(:schema_test)
|
829
|
+
@db.tables.should_not include(:pg_am)
|
830
|
+
@db.tables.should_not include(:domain_udt_usage)
|
820
831
|
end
|
821
832
|
|
822
833
|
specify "#tables should return tables in the schema provided by the :schema argument" do
|
823
|
-
|
824
|
-
|
834
|
+
@db.create_table(:schema_test__schema_test){integer :i}
|
835
|
+
@db.tables(:schema=>:schema_test).should == [:schema_test]
|
825
836
|
end
|
826
837
|
|
827
838
|
specify "#schema should not include columns from tables in a default non-public schema" do
|
828
|
-
|
829
|
-
sch =
|
839
|
+
@db.create_table(:schema_test__domains){integer :i}
|
840
|
+
sch = @db.schema(:schema_test__domains)
|
830
841
|
cs = sch.map{|x| x.first}
|
831
842
|
cs.should include(:i)
|
832
843
|
cs.should_not include(:data_type)
|
833
844
|
end
|
834
845
|
|
835
846
|
specify "#schema should only include columns from the table in the given :schema argument" do
|
836
|
-
|
837
|
-
|
838
|
-
sch =
|
847
|
+
@db.create_table!(:domains){integer :d}
|
848
|
+
@db.create_table(:schema_test__domains){integer :i}
|
849
|
+
sch = @db.schema(:domains, :schema=>:schema_test)
|
839
850
|
cs = sch.map{|x| x.first}
|
840
851
|
cs.should include(:i)
|
841
852
|
cs.should_not include(:d)
|
842
|
-
|
853
|
+
@db.drop_table(:domains)
|
843
854
|
end
|
844
855
|
|
845
|
-
specify "#schema should
|
846
|
-
|
847
|
-
|
856
|
+
specify "#schema should not include columns in tables from other domains by default" do
|
857
|
+
@db.create_table!(:public__domains){integer :d}
|
858
|
+
@db.create_table(:schema_test__domains){integer :i}
|
848
859
|
begin
|
849
|
-
|
850
|
-
|
851
|
-
POSTGRES_DB.schema(:schema_test__domains).map{|x| x.first}.should == [:i]
|
860
|
+
@db.schema(:domains).map{|x| x.first}.should == [:d]
|
861
|
+
@db.schema(:schema_test__domains).map{|x| x.first}.should == [:i]
|
852
862
|
ensure
|
853
|
-
|
863
|
+
@db.drop_table?(:public__domains)
|
854
864
|
end
|
855
865
|
end
|
856
866
|
|
857
867
|
specify "#table_exists? should see if the table is in a given schema" do
|
858
|
-
|
859
|
-
|
868
|
+
@db.create_table(:schema_test__schema_test){integer :i}
|
869
|
+
@db.table_exists?(:schema_test__schema_test).should == true
|
860
870
|
end
|
861
871
|
|
862
872
|
specify "should be able to get primary keys for tables in a given schema" do
|
863
|
-
|
864
|
-
|
873
|
+
@db.create_table(:schema_test__schema_test){primary_key :i}
|
874
|
+
@db.primary_key(:schema_test__schema_test).should == 'i'
|
865
875
|
end
|
866
876
|
|
867
877
|
specify "should be able to get serial sequences for tables in a given schema" do
|
868
|
-
|
869
|
-
|
878
|
+
@db.create_table(:schema_test__schema_test){primary_key :i}
|
879
|
+
@db.primary_key_sequence(:schema_test__schema_test).should == '"schema_test"."schema_test_i_seq"'
|
870
880
|
end
|
871
881
|
|
872
882
|
specify "should be able to get serial sequences for tables that have spaces in the name in a given schema" do
|
873
|
-
|
874
|
-
|
883
|
+
@db.create_table(:"schema_test__schema test"){primary_key :i}
|
884
|
+
@db.primary_key_sequence(:"schema_test__schema test").should == '"schema_test"."schema test_i_seq"'
|
875
885
|
end
|
876
886
|
|
877
887
|
specify "should be able to get custom sequences for tables in a given schema" do
|
878
|
-
|
879
|
-
|
880
|
-
|
888
|
+
@db << "CREATE SEQUENCE schema_test.kseq"
|
889
|
+
@db.create_table(:schema_test__schema_test){integer :j; primary_key :k, :type=>:integer, :default=>Sequel.lit("nextval('schema_test.kseq'::regclass)")}
|
890
|
+
@db.primary_key_sequence(:schema_test__schema_test).should == '"schema_test".kseq'
|
881
891
|
end
|
882
892
|
|
883
893
|
specify "should be able to get custom sequences for tables that have spaces in the name in a given schema" do
|
884
|
-
|
885
|
-
|
886
|
-
|
894
|
+
@db << "CREATE SEQUENCE schema_test.\"ks eq\""
|
895
|
+
@db.create_table(:"schema_test__schema test"){integer :j; primary_key :k, :type=>:integer, :default=>Sequel.lit("nextval('schema_test.\"ks eq\"'::regclass)")}
|
896
|
+
@db.primary_key_sequence(:"schema_test__schema test").should == '"schema_test"."ks eq"'
|
887
897
|
end
|
888
898
|
|
889
899
|
specify "#default_schema= should change the default schema used from public" do
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
900
|
+
@db.create_table(:schema_test__schema_test){primary_key :i}
|
901
|
+
@db.default_schema = :schema_test
|
902
|
+
@db.table_exists?(:schema_test).should == true
|
903
|
+
@db.tables.should == [:schema_test]
|
904
|
+
@db.primary_key(:schema_test__schema_test).should == 'i'
|
905
|
+
@db.primary_key_sequence(:schema_test__schema_test).should == '"schema_test"."schema_test_i_seq"'
|
906
|
+
end
|
907
|
+
|
908
|
+
specify "should handle schema introspection cases with tables with same name in multiple schemas" do
|
909
|
+
begin
|
910
|
+
@db.create_table(:schema_test__schema_test) do
|
911
|
+
primary_key :id
|
912
|
+
foreign_key :i, :schema_test__schema_test, :index=>{:name=>:schema_test_sti}
|
913
|
+
end
|
914
|
+
@db.create_table!(:public__schema_test) do
|
915
|
+
primary_key :id
|
916
|
+
foreign_key :j, :public__schema_test, :index=>{:name=>:public_test_sti}
|
917
|
+
end
|
918
|
+
|
919
|
+
h = @db.schema(:schema_test)
|
920
|
+
h.length.should == 2
|
921
|
+
h.last.first.should == :j
|
922
|
+
|
923
|
+
@db.indexes(:schema_test).should == {:public_test_sti=>{:unique=>false, :columns=>[:j], :deferrable=>nil}}
|
924
|
+
@db.foreign_key_list(:schema_test).should == [{:on_update=>:no_action, :columns=>[:j], :deferrable=>false, :key=>[:id], :table=>:schema_test, :on_delete=>:no_action, :name=>:schema_test_j_fkey}]
|
925
|
+
ensure
|
926
|
+
@db.drop_table?(:public__schema_test)
|
927
|
+
end
|
896
928
|
end
|
897
929
|
end
|
898
930
|
|