sequel 3.44.0 → 3.45.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 +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
|
|