sequel 3.42.0 → 3.43.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +40 -0
- data/MIT-LICENSE +1 -1
- data/Rakefile +1 -1
- data/doc/opening_databases.rdoc +2 -2
- data/doc/prepared_statements.rdoc +7 -0
- data/doc/release_notes/3.43.0.txt +105 -0
- data/doc/schema_modification.rdoc +19 -0
- data/lib/sequel/adapters/do/mysql.rb +1 -1
- data/lib/sequel/adapters/jdbc.rb +13 -8
- data/lib/sequel/adapters/jdbc/hsqldb.rb +5 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +1 -1
- data/lib/sequel/adapters/jdbc/oracle.rb +6 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +9 -3
- data/lib/sequel/adapters/mysql.rb +1 -1
- data/lib/sequel/adapters/mysql2.rb +1 -1
- data/lib/sequel/adapters/oracle.rb +1 -1
- data/lib/sequel/adapters/postgres.rb +4 -2
- data/lib/sequel/adapters/shared/db2.rb +12 -0
- data/lib/sequel/adapters/shared/mssql.rb +9 -5
- data/lib/sequel/adapters/shared/postgres.rb +2 -0
- data/lib/sequel/adapters/swift/mysql.rb +1 -1
- data/lib/sequel/core.rb +2 -2
- data/lib/sequel/database.rb +0 -2
- data/lib/sequel/database/query.rb +20 -5
- data/lib/sequel/database/schema_generator.rb +5 -0
- data/lib/sequel/database/schema_methods.rb +5 -0
- data/lib/sequel/dataset.rb +0 -2
- data/lib/sequel/dataset/actions.rb +25 -2
- data/lib/sequel/dataset/misc.rb +1 -1
- data/lib/sequel/dataset/sql.rb +28 -6
- data/lib/sequel/extensions/core_refinements.rb +221 -0
- data/lib/sequel/extensions/date_arithmetic.rb +194 -0
- data/lib/sequel/extensions/meta_def.rb +30 -0
- data/lib/sequel/extensions/migration.rb +5 -0
- data/lib/sequel/extensions/null_dataset.rb +2 -0
- data/lib/sequel/extensions/pagination.rb +2 -0
- data/lib/sequel/extensions/pg_array.rb +12 -1
- data/lib/sequel/extensions/pg_array_ops.rb +10 -1
- data/lib/sequel/extensions/pg_hstore.rb +12 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +10 -1
- data/lib/sequel/extensions/pg_json.rb +18 -1
- data/lib/sequel/extensions/pg_range.rb +12 -1
- data/lib/sequel/extensions/pg_range_ops.rb +10 -1
- data/lib/sequel/extensions/pg_row.rb +18 -2
- data/lib/sequel/extensions/pg_row_ops.rb +10 -1
- data/lib/sequel/extensions/query.rb +2 -0
- data/lib/sequel/model/associations.rb +5 -13
- data/lib/sequel/model/base.rb +4 -6
- data/lib/sequel/plugins/boolean_readers.rb +4 -2
- data/lib/sequel/plugins/many_through_many.rb +23 -0
- data/lib/sequel/plugins/string_stripper.rb +53 -3
- data/lib/sequel/plugins/validation_class_methods.rb +5 -0
- data/lib/sequel/sql.rb +3 -3
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +19 -8
- data/spec/adapters/mssql_spec.rb +1 -2
- data/spec/adapters/mysql_spec.rb +2 -2
- data/spec/adapters/postgres_spec.rb +29 -3
- data/spec/core/dataset_spec.rb +107 -0
- data/spec/core/expression_filters_spec.rb +5 -0
- data/spec/core/schema_spec.rb +14 -3
- data/spec/core/spec_helper.rb +2 -0
- data/spec/extensions/core_refinements_spec.rb +551 -0
- data/spec/extensions/date_arithmetic_spec.rb +150 -0
- data/spec/extensions/force_encoding_spec.rb +1 -1
- data/spec/extensions/meta_def_spec.rb +21 -0
- data/spec/extensions/spec_helper.rb +5 -0
- data/spec/extensions/string_stripper_spec.rb +44 -2
- data/spec/integration/associations_test.rb +2 -2
- data/spec/integration/plugin_test.rb +90 -0
- data/spec/integration/schema_test.rb +1 -1
- data/spec/model/association_reflection_spec.rb +4 -4
- data/spec/model/associations_spec.rb +2 -2
- data/spec/model/base_spec.rb +2 -2
- data/spec/model/eager_loading_spec.rb +5 -5
- data/spec/model/hooks_spec.rb +4 -4
- data/spec/model/model_spec.rb +9 -9
- data/spec/model/record_spec.rb +15 -18
- metadata +12 -5
- data/lib/sequel/metaprogramming.rb +0 -13
@@ -20,7 +20,8 @@
|
|
20
20
|
# r = Sequel.expr(:row_column).pg_row
|
21
21
|
#
|
22
22
|
# If you have loaded the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html]),
|
23
|
-
# you
|
23
|
+
# or you have loaded the {core_refinements extension}[link:files/doc/core_refinements_rdoc.html])
|
24
|
+
# and have activated refinements for the file, you can also use Symbol#pg_row:
|
24
25
|
#
|
25
26
|
# r = :row_column.pg_row
|
26
27
|
#
|
@@ -180,3 +181,11 @@ if Sequel.core_extensions?
|
|
180
181
|
include Sequel::Postgres::PGRowOp::ExpressionMethods
|
181
182
|
end
|
182
183
|
end
|
184
|
+
|
185
|
+
if defined?(Sequel::CoreRefinements)
|
186
|
+
module Sequel::CoreRefinements
|
187
|
+
refine Symbol do
|
188
|
+
include Sequel::Postgres::PGRowOp::ExpressionMethods
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -69,11 +69,6 @@ module Sequel
|
|
69
69
|
:"#{self[:name]}_dataset"
|
70
70
|
end
|
71
71
|
|
72
|
-
# Name symbol for the _helper internal association method
|
73
|
-
def dataset_helper_method
|
74
|
-
:"_#{self[:name]}_dataset_helper"
|
75
|
-
end
|
76
|
-
|
77
72
|
# Whether the dataset needs a primary key to function, true by default.
|
78
73
|
def dataset_need_primary_key?
|
79
74
|
true
|
@@ -1096,9 +1091,6 @@ module Sequel
|
|
1096
1091
|
|
1097
1092
|
# Adds the association dataset methods to the association methods module.
|
1098
1093
|
def def_association_dataset_methods(opts)
|
1099
|
-
# If a block is given, define a helper method for it, because it takes
|
1100
|
-
# an argument. This is unnecessary in Ruby 1.9, as that has instance_exec.
|
1101
|
-
association_module_private_def(opts.dataset_helper_method, opts, &opts[:block]) if opts[:block]
|
1102
1094
|
association_module_private_def(opts._dataset_method, opts, &opts[:dataset])
|
1103
1095
|
association_module_def(opts.dataset_method, opts){_dataset(opts)}
|
1104
1096
|
def_association_method(opts)
|
@@ -1122,10 +1114,10 @@ module Sequel
|
|
1122
1114
|
lcpks = opts[:left_primary_keys] = Array(left_pk)
|
1123
1115
|
lpkc = opts[:left_primary_key_column] ||= left_pk
|
1124
1116
|
lpkcs = opts[:left_primary_key_columns] ||= Array(lpkc)
|
1125
|
-
raise(Error, "mismatched number of left
|
1117
|
+
raise(Error, "mismatched number of left keys: #{lcks.inspect} vs #{lcpks.inspect}") unless lcks.length == lcpks.length
|
1126
1118
|
if opts[:right_primary_key]
|
1127
1119
|
rcpks = Array(opts[:right_primary_key])
|
1128
|
-
raise(Error, "mismatched number of right
|
1120
|
+
raise(Error, "mismatched number of right keys: #{rcks.inspect} vs #{rcpks.inspect}") unless rcks.length == rcpks.length
|
1129
1121
|
end
|
1130
1122
|
uses_lcks = opts[:uses_left_composite_keys] = lcks.length > 1
|
1131
1123
|
uses_rcks = opts[:uses_right_composite_keys] = rcks.length > 1
|
@@ -1221,7 +1213,7 @@ module Sequel
|
|
1221
1213
|
opts[:qualified_key] = opts.qualify_cur(key)
|
1222
1214
|
if opts[:primary_key]
|
1223
1215
|
cpks = Array(opts[:primary_key])
|
1224
|
-
raise(Error, "mismatched number of
|
1216
|
+
raise(Error, "mismatched number of keys: #{cks.inspect} vs #{cpks.inspect}") unless cks.length == cpks.length
|
1225
1217
|
end
|
1226
1218
|
uses_cks = opts[:uses_composite_keys] = cks.length > 1
|
1227
1219
|
qualify = opts[:qualify] != false
|
@@ -1281,7 +1273,7 @@ module Sequel
|
|
1281
1273
|
cpks = opts[:primary_keys] = Array(primary_key)
|
1282
1274
|
pkc = opts[:primary_key_column] ||= primary_key
|
1283
1275
|
pkcs = opts[:primary_key_columns] ||= Array(pkc)
|
1284
|
-
raise(Error, "mismatched number of
|
1276
|
+
raise(Error, "mismatched number of keys: #{cks.inspect} vs #{cpks.inspect}") unless cks.length == cpks.length
|
1285
1277
|
uses_cks = opts[:uses_composite_keys] = cks.length > 1
|
1286
1278
|
opts[:dataset] ||= proc do
|
1287
1279
|
opts.associated_class.filter(opts.predicate_keys.zip(cpks.map{|k| send(k)}))
|
@@ -1452,7 +1444,7 @@ module Sequel
|
|
1452
1444
|
ds = ds.eager(*opts[:eager]) if opts[:eager]
|
1453
1445
|
ds = ds.distinct if opts[:distinct]
|
1454
1446
|
ds = ds.eager_graph(opts[:eager_graph]) if opts[:eager_graph] && opts.eager_graph_lazy_dataset?
|
1455
|
-
ds =
|
1447
|
+
ds = instance_exec(ds, &opts[:block]) if opts[:block]
|
1456
1448
|
ds
|
1457
1449
|
end
|
1458
1450
|
|
data/lib/sequel/model/base.rb
CHANGED
@@ -2,8 +2,6 @@ module Sequel
|
|
2
2
|
class Model
|
3
3
|
extend Enumerable
|
4
4
|
extend Inflections
|
5
|
-
extend Metaprogramming
|
6
|
-
include Metaprogramming
|
7
5
|
|
8
6
|
# Class methods for Sequel::Model that implement basic model functionality.
|
9
7
|
#
|
@@ -686,7 +684,7 @@ module Sequel
|
|
686
684
|
if meth.to_s =~ NORMAL_METHOD_NAME_REGEXP
|
687
685
|
instance_eval("def #{meth}(*args, &block); dataset.#{meth}(*args, &block) end", __FILE__, __LINE__)
|
688
686
|
else
|
689
|
-
|
687
|
+
(class << self; self; end).send(:define_method, meth){|*args, &block| dataset.send(meth, *args, &block)}
|
690
688
|
end
|
691
689
|
end
|
692
690
|
|
@@ -1085,11 +1083,11 @@ module Sequel
|
|
1085
1083
|
def hash
|
1086
1084
|
case primary_key
|
1087
1085
|
when Array
|
1088
|
-
[model, !pk.all? ? @values
|
1086
|
+
[model, !pk.all? ? @values : pk].hash
|
1089
1087
|
when Symbol
|
1090
|
-
[model, pk.nil? ? @values
|
1088
|
+
[model, pk.nil? ? @values : pk].hash
|
1091
1089
|
else
|
1092
|
-
[model, @values
|
1090
|
+
[model, @values].hash
|
1093
1091
|
end
|
1094
1092
|
end
|
1095
1093
|
|
@@ -26,8 +26,10 @@ module Sequel
|
|
26
26
|
# Add the boolean_attribute? class method to the model, and create
|
27
27
|
# attribute? boolean reader methods for the class's columns if the class has a dataset.
|
28
28
|
def self.configure(model, &block)
|
29
|
-
model.
|
30
|
-
|
29
|
+
model.instance_eval do
|
30
|
+
(class << self; self; end).send(:define_method, :boolean_attribute?, &(block || DEFAULT_BOOLEAN_ATTRIBUTE_PROC))
|
31
|
+
send(:create_boolean_readers) if @dataset
|
32
|
+
end
|
31
33
|
end
|
32
34
|
|
33
35
|
module ClassMethods
|
@@ -13,6 +13,29 @@ module Sequel
|
|
13
13
|
#
|
14
14
|
# Which will give you the tags for all of the artist's albums.
|
15
15
|
#
|
16
|
+
# Let's break down the 2nd argument of the many_through_many call:
|
17
|
+
#
|
18
|
+
# [[:albums_artists, :artist_id, :album_id],
|
19
|
+
# [:albums, :id, :id],
|
20
|
+
# [:albums_tags, :album_id, :tag_id]]
|
21
|
+
#
|
22
|
+
# This argument is an array of arrays with three elements. Each entry in the main array represents a JOIN in SQL:
|
23
|
+
#
|
24
|
+
# * The first element in each array represents the name of the table to join.
|
25
|
+
# * The second element in each array represents the column used to join to the previous table.
|
26
|
+
# * The third element in each array represents the column used to join to the next table.
|
27
|
+
#
|
28
|
+
# So the "Artist.many_through_many :tags" is translated into something similar to:
|
29
|
+
#
|
30
|
+
# FROM artists
|
31
|
+
# JOIN albums_artists ON (artists.id = albums_artists.artist_id)
|
32
|
+
# JOIN albums ON (albums_artists.album_id = albums.id)
|
33
|
+
# JOIN albums_tags ON (albums.id = albums_tag.album_id)
|
34
|
+
# JOIN tags ON (albums_tags.tag_id = tags.id)
|
35
|
+
#
|
36
|
+
# The "artists.id" and "tags.id" criteria come from other association options (defaulting to the primary keys of the current and
|
37
|
+
# associated tables), but hopefully you can see how each argument in the array is used in the JOIN clauses.
|
38
|
+
#
|
16
39
|
# Here are some more examples:
|
17
40
|
#
|
18
41
|
# # Same as Artist.many_to_many :albums
|
@@ -1,10 +1,18 @@
|
|
1
1
|
module Sequel
|
2
2
|
module Plugins
|
3
|
-
# StringStripper is a
|
3
|
+
# StringStripper is a plugin that strips all input strings
|
4
4
|
# when assigning to the model's values. Example:
|
5
5
|
#
|
6
6
|
# album = Album.new(:name=>' A ')
|
7
7
|
# album.name # => 'A'
|
8
|
+
#
|
9
|
+
# SQL::Blob instances and all non-strings are not modified by
|
10
|
+
# this plugin. Additionally, strings passed to a blob column
|
11
|
+
# setter are also not modified. You can explicitly set
|
12
|
+
# other columns to skip the stripping:
|
13
|
+
#
|
14
|
+
# Album.skip_string_stripping :foo
|
15
|
+
# Album.new(:foo=>' A ').foo # => ' A '
|
8
16
|
#
|
9
17
|
# Usage:
|
10
18
|
#
|
@@ -14,11 +22,53 @@ module Sequel
|
|
14
22
|
# # Make the Album class strip strings
|
15
23
|
# Album.plugin :string_stripper
|
16
24
|
module StringStripper
|
25
|
+
# Set blob columns as skipping stripping when plugin is loaded.
|
26
|
+
def self.configure(model)
|
27
|
+
model.instance_variable_set(:@skipped_string_stripping_columns, [])
|
28
|
+
model.send(:set_skipped_string_stripping_columns)
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
# Copy skipped stripping columns from superclass into subclass.
|
33
|
+
def inherited(subclass)
|
34
|
+
subclass.instance_variable_set(:@skipped_string_stripping_columns, @skipped_string_stripping_columns.dup)
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
# Set blob columns as skipping stripping when plugin is loaded.
|
39
|
+
def set_dataset(*)
|
40
|
+
super
|
41
|
+
set_skipped_string_stripping_columns
|
42
|
+
end
|
43
|
+
|
44
|
+
# Skip stripping for the given columns.
|
45
|
+
def skip_string_stripping(*columns)
|
46
|
+
@skipped_string_stripping_columns.concat(columns).uniq!
|
47
|
+
end
|
48
|
+
|
49
|
+
# Return true if the column should not have values stripped.
|
50
|
+
def skip_string_stripping?(column)
|
51
|
+
@skipped_string_stripping_columns.include?(column)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
# Automatically skip stripping of blob columns
|
57
|
+
def set_skipped_string_stripping_columns
|
58
|
+
if @db_schema
|
59
|
+
blob_columns = @db_schema.map{|k,v| k if v[:type] == :blob}.compact
|
60
|
+
skip_string_stripping(*blob_columns)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
17
65
|
module InstanceMethods
|
18
|
-
# Strip value if it is a string
|
66
|
+
# Strip value if it is a non-blob string and the model hasn't been set
|
67
|
+
# to skip stripping for the column, before attempting to assign
|
19
68
|
# it to the model's values.
|
20
69
|
def []=(k, v)
|
21
|
-
v.is_a?(String)
|
70
|
+
v = v.strip if v.is_a?(String) && !v.is_a?(SQL::Blob) && !model.skip_string_stripping?(k)
|
71
|
+
super(k, v)
|
22
72
|
end
|
23
73
|
end
|
24
74
|
end
|
@@ -51,6 +51,11 @@ module Sequel
|
|
51
51
|
def method_missing(m, *args, &block)
|
52
52
|
@receiver.send(:"validates_#{m}", *args, &block)
|
53
53
|
end
|
54
|
+
|
55
|
+
# This object responds to all validates_* methods the model responds to.
|
56
|
+
def respond_to_missing?(meth, include_private)
|
57
|
+
@receiver.respond_to?(:"validates_#{meth}", include_private)
|
58
|
+
end
|
54
59
|
end
|
55
60
|
|
56
61
|
# Returns true if validations are defined.
|
data/lib/sequel/sql.rb
CHANGED
@@ -6,7 +6,7 @@ module Sequel
|
|
6
6
|
class BasicObject
|
7
7
|
# The instance methods to not remove from the class when removing
|
8
8
|
# other methods.
|
9
|
-
KEEP_METHODS = %w"__id__ __send__ __metaclass__ instance_eval == equal? initialize method_missing"
|
9
|
+
KEEP_METHODS = %w"__id__ __send__ __metaclass__ instance_eval instance_exec == equal? initialize method_missing"
|
10
10
|
|
11
11
|
# Remove all but the most basic instance methods from the class. A separate
|
12
12
|
# method so that it can be called again if necessary if you load libraries
|
@@ -655,7 +655,7 @@ module Sequel
|
|
655
655
|
# Sequel.function(:func).cast_numeric # CAST(func() AS integer)
|
656
656
|
# Sequel.function(:func).cast_numeric(Float) # CAST(func() AS double precision)
|
657
657
|
def cast_numeric(sql_type = nil)
|
658
|
-
|
658
|
+
Cast.new(self, sql_type || Integer).sql_number
|
659
659
|
end
|
660
660
|
|
661
661
|
# Cast the reciever to the given SQL type (or the database's default String type if none given),
|
@@ -665,7 +665,7 @@ module Sequel
|
|
665
665
|
# Sequel.function(:func).cast_string # CAST(func() AS varchar(255))
|
666
666
|
# Sequel.function(:func).cast_string(:text) # CAST(func() AS text)
|
667
667
|
def cast_string(sql_type = nil)
|
668
|
-
|
668
|
+
Cast.new(self, sql_type || String).sql_string
|
669
669
|
end
|
670
670
|
end
|
671
671
|
|
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 = 43
|
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/db2_spec.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# coding: utf-8
|
3
2
|
#Author: Roy L Zuo (roylzuo at gmail dot com)
|
4
3
|
#Description:
|
5
4
|
|
@@ -39,21 +38,33 @@ describe Sequel::Database do
|
|
39
38
|
end
|
40
39
|
|
41
40
|
describe "Simple Dataset operations" do
|
42
|
-
before do
|
41
|
+
before(:all) do
|
42
|
+
Sequel::DB2.use_clob_as_blob = false
|
43
43
|
DB2_DB.create_table!(:items) do
|
44
44
|
Integer :id, :primary_key => true
|
45
45
|
Integer :number
|
46
|
+
column :bin_string, 'varchar(20) for bit data'
|
47
|
+
column :bin_blob, 'blob'
|
46
48
|
end
|
47
49
|
@ds = DB2_DB[:items]
|
48
|
-
@ds.insert(:number=>10, :id => 1 )
|
49
50
|
end
|
50
|
-
after do
|
51
|
+
after(:each) do
|
52
|
+
@ds.delete
|
53
|
+
end
|
54
|
+
after(:all) do
|
55
|
+
Sequel::DB2.use_clob_as_blob = true
|
51
56
|
DB2_DB.drop_table(:items)
|
52
57
|
end
|
53
|
-
|
54
|
-
|
55
|
-
@ds.
|
56
|
-
@ds.
|
58
|
+
|
59
|
+
specify "should insert with a primary key specified" do
|
60
|
+
@ds.insert(:id => 1, :number => 10)
|
61
|
+
@ds.insert(:id => 100, :number => 20)
|
62
|
+
@ds.select_hash(:id, :number).should == {1 => 10, 100 => 20}
|
63
|
+
end
|
64
|
+
|
65
|
+
specify "should insert into binary columns" do
|
66
|
+
@ds.insert(:id => 1, :bin_string => Sequel.blob("\1"), :bin_blob => Sequel.blob("\2"))
|
67
|
+
@ds.select(:bin_string, :bin_blob).first.should == {:bin_string => "\1", :bin_blob => "\2"}
|
57
68
|
end
|
58
69
|
end
|
59
70
|
|
data/spec/adapters/mssql_spec.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
1
|
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
3
2
|
|
4
3
|
require ENV['SEQUEL_MSSQL_SPEC_REQUIRE'] if ENV['SEQUEL_MSSQL_SPEC_REQUIRE']
|
@@ -391,7 +390,7 @@ describe "MSSSQL::Dataset#insert" do
|
|
391
390
|
end
|
392
391
|
|
393
392
|
specify "should have insert_select return nil if the server version is not 2005+" do
|
394
|
-
@ds.
|
393
|
+
def @ds.server_version() 8000760 end
|
395
394
|
@ds.insert_select(:value=>10).should == nil
|
396
395
|
end
|
397
396
|
|
data/spec/adapters/mysql_spec.rb
CHANGED
@@ -150,8 +150,8 @@ if [:mysql, :mysql2].include?(MYSQL_DB.adapter_scheme)
|
|
150
150
|
specify "should allow disabling the conversion on a per-dataset basis" do
|
151
151
|
@db.convert_tinyint_to_bool = true
|
152
152
|
ds = @ds.clone
|
153
|
-
ds.
|
154
|
-
ds.
|
153
|
+
def ds.cast_tinyint_integer?(f) true end #mysql
|
154
|
+
def ds.convert_tinyint_to_bool?() false end #mysql2
|
155
155
|
ds.delete
|
156
156
|
ds << {:b=>true, :i=>10}
|
157
157
|
ds.all.should == [{:b=>1, :i=>10}]
|
@@ -539,6 +539,25 @@ describe "A PostgreSQL database" do
|
|
539
539
|
@db[:posts].insert.should == 21
|
540
540
|
@db[:posts].order(:a).map(:a).should == [1, 2, 10, 20, 21]
|
541
541
|
end
|
542
|
+
|
543
|
+
specify "should support resetting the primary key sequence with default_schema" do
|
544
|
+
begin
|
545
|
+
@db.run("DROP SCHEMA p") rescue nil
|
546
|
+
@db.run("CREATE SCHEMA p")
|
547
|
+
@db.default_schema = :p
|
548
|
+
@db.create_table(:posts){primary_key :a}
|
549
|
+
@db[:p__posts].insert(:a=>20).should == 20
|
550
|
+
@db[:p__posts].insert.should == 1
|
551
|
+
@db[:p__posts].insert.should == 2
|
552
|
+
@db[:p__posts].insert(:a=>10).should == 10
|
553
|
+
@db.reset_primary_key_sequence(:posts).should == 21
|
554
|
+
@db[:p__posts].insert.should == 21
|
555
|
+
@db[:p__posts].order(:a).map(:a).should == [1, 2, 10, 20, 21]
|
556
|
+
ensure
|
557
|
+
@db.default_schema = nil
|
558
|
+
@db.run("DROP SCHEMA p CASCADE")
|
559
|
+
end
|
560
|
+
end
|
542
561
|
|
543
562
|
specify "should support specifying Integer/Bignum/Fixnum types in primary keys and have them be auto incrementing" do
|
544
563
|
@db.create_table(:posts){primary_key :a, :type=>Integer}
|
@@ -1295,6 +1314,13 @@ if ((POSTGRES_DB.adapter_scheme == :postgres && SEQUEL_POSTGRES_USES_PG) || POST
|
|
1295
1314
|
end
|
1296
1315
|
end
|
1297
1316
|
|
1317
|
+
specify "should handle database errors with a rollback of copied data and still have a usable connection" do
|
1318
|
+
2.times do
|
1319
|
+
proc{@db.copy_into(:test_copy, :data=>["1\t2\n", "3\ta\n"])}.should raise_error(Sequel::DatabaseError)
|
1320
|
+
@ds.select_map([:x, :y]).should == []
|
1321
|
+
end
|
1322
|
+
end
|
1323
|
+
|
1298
1324
|
specify "should raise an Error if both :data and a block are provided" do
|
1299
1325
|
proc{@db.copy_into(:test_copy, :data=>["1\t2\n", "3\t4\n"]){}}.should raise_error(Sequel::Error)
|
1300
1326
|
end
|
@@ -2524,7 +2550,7 @@ describe 'PostgreSQL interval types' do
|
|
2524
2550
|
v.should == ActiveSupport::Duration.new(31557600 + 2*86400*30 + 3*86400*7 + 4*86400 + 5*3600 + 6*60 + 7, [[:years, 1], [:months, 2], [:days, 25], [:seconds, 18367]])
|
2525
2551
|
v.parts.sort_by{|k,v| k.to_s}.should == [[:years, 1], [:months, 2], [:days, 25], [:seconds, 18367]].sort_by{|k,v| k.to_s}
|
2526
2552
|
end
|
2527
|
-
end if (
|
2553
|
+
end if (begin require 'active_support/duration'; require 'active_support/inflector'; require 'active_support/core_ext/string/inflections'; true; rescue LoadError; false end)
|
2528
2554
|
|
2529
2555
|
describe 'PostgreSQL row-valued/composite types' do
|
2530
2556
|
before(:all) do
|
@@ -2547,8 +2573,8 @@ describe 'PostgreSQL row-valued/composite types' do
|
|
2547
2573
|
column :employees, 'person[]'
|
2548
2574
|
end
|
2549
2575
|
@db.register_row_type(:address)
|
2550
|
-
@db.register_row_type(:person)
|
2551
|
-
@db.register_row_type(:
|
2576
|
+
@db.register_row_type(Sequel.qualify(:public, :person))
|
2577
|
+
@db.register_row_type(:public__company)
|
2552
2578
|
|
2553
2579
|
@native = POSTGRES_DB.adapter_scheme == :postgres
|
2554
2580
|
end
|
data/spec/core/dataset_spec.rb
CHANGED
@@ -2686,6 +2686,40 @@ describe "Dataset#get" do
|
|
2686
2686
|
@d.get(false).should == "SELECT 'f' FROM test LIMIT 1"
|
2687
2687
|
@d.get(nil).should == "SELECT NULL FROM test LIMIT 1"
|
2688
2688
|
end
|
2689
|
+
|
2690
|
+
specify "should support an array of expressions to get an array of results" do
|
2691
|
+
@d._fetch = {:name=>1, :abc=>2}
|
2692
|
+
@d.get([:name, :abc]).should == [1, 2]
|
2693
|
+
@d.db.sqls.should == ['SELECT name, abc FROM test LIMIT 1']
|
2694
|
+
end
|
2695
|
+
|
2696
|
+
specify "should support an array with a single expression" do
|
2697
|
+
@d.get([:name]).should == ['SELECT name FROM test LIMIT 1']
|
2698
|
+
end
|
2699
|
+
|
2700
|
+
specify "should handle an array with aliases" do
|
2701
|
+
@d._fetch = {:name=>1, :abc=>2}
|
2702
|
+
@d.get([:n___name, Sequel.as(:a, :abc)]).should == [1, 2]
|
2703
|
+
@d.db.sqls.should == ['SELECT n AS name, a AS abc FROM test LIMIT 1']
|
2704
|
+
end
|
2705
|
+
|
2706
|
+
specify "should raise an Error if an alias cannot be determined" do
|
2707
|
+
@d._fetch = {:name=>1, :abc=>2}
|
2708
|
+
proc{@d.get([Sequel.+(:a, 1), :a])}.should raise_error(Sequel::Error)
|
2709
|
+
end
|
2710
|
+
|
2711
|
+
specify "should support an array of expressions in a virtual row" do
|
2712
|
+
@d._fetch = {:name=>1, :abc=>2}
|
2713
|
+
@d.get{[name, n__abc]}.should == [1, 2]
|
2714
|
+
@d.db.sqls.should == ['SELECT name, n.abc FROM test LIMIT 1']
|
2715
|
+
end
|
2716
|
+
|
2717
|
+
specify "should work with static SQL" do
|
2718
|
+
@d.with_sql('SELECT foo').get(:name).should == "SELECT foo"
|
2719
|
+
@d._fetch = {:name=>1, :abc=>2}
|
2720
|
+
@d.with_sql('SELECT foo').get{[name, n__abc]}.should == [1, 2]
|
2721
|
+
@d.db.sqls.should == ['SELECT foo'] * 2
|
2722
|
+
end
|
2689
2723
|
end
|
2690
2724
|
|
2691
2725
|
describe "Dataset#set_row_proc" do
|
@@ -4414,3 +4448,76 @@ describe "Dataset extensions" do
|
|
4414
4448
|
proc{@ds.extension(:foo2)}.should raise_error(Sequel::Error)
|
4415
4449
|
end
|
4416
4450
|
end
|
4451
|
+
|
4452
|
+
describe "Dataset#schema_and_table" do
|
4453
|
+
before do
|
4454
|
+
@ds = Sequel.mock[:test]
|
4455
|
+
end
|
4456
|
+
|
4457
|
+
it "should correctly handle symbols" do
|
4458
|
+
@ds.schema_and_table(:s).should == [nil, 's']
|
4459
|
+
@ds.schema_and_table(:s___a).should == [nil, 's']
|
4460
|
+
@ds.schema_and_table(:t__s).should == ['t', 's']
|
4461
|
+
@ds.schema_and_table(:t__s___a).should == ['t', 's']
|
4462
|
+
end
|
4463
|
+
|
4464
|
+
it "should correctly handle strings" do
|
4465
|
+
@ds.schema_and_table('s').should == [nil, 's']
|
4466
|
+
end
|
4467
|
+
|
4468
|
+
it "should correctly handle identifiers" do
|
4469
|
+
@ds.schema_and_table(Sequel.identifier(:s)).should == [nil, 's']
|
4470
|
+
end
|
4471
|
+
|
4472
|
+
it "should correctly handle qualified identifiers" do
|
4473
|
+
@ds.schema_and_table(Sequel.qualify(:t, :s)).should == ['t', 's']
|
4474
|
+
end
|
4475
|
+
|
4476
|
+
it "should respect default_schema" do
|
4477
|
+
@ds.db.default_schema = :foo
|
4478
|
+
@ds.schema_and_table(:s).should == ['foo', 's']
|
4479
|
+
@ds.schema_and_table(:s, nil).should == [nil, 's']
|
4480
|
+
end
|
4481
|
+
end
|
4482
|
+
|
4483
|
+
describe "Dataset#split_qualifiers" do
|
4484
|
+
before do
|
4485
|
+
@ds = Sequel.mock[:test]
|
4486
|
+
end
|
4487
|
+
|
4488
|
+
it "should correctly handle symbols" do
|
4489
|
+
@ds.split_qualifiers(:s).should == ['s']
|
4490
|
+
@ds.split_qualifiers(:s___a).should == ['s']
|
4491
|
+
@ds.split_qualifiers(:t__s).should == ['t', 's']
|
4492
|
+
@ds.split_qualifiers(:t__s___a).should == ['t', 's']
|
4493
|
+
end
|
4494
|
+
|
4495
|
+
it "should correctly handle strings" do
|
4496
|
+
@ds.split_qualifiers('s').should == ['s']
|
4497
|
+
end
|
4498
|
+
|
4499
|
+
it "should correctly handle identifiers" do
|
4500
|
+
@ds.split_qualifiers(Sequel.identifier(:s)).should == ['s']
|
4501
|
+
end
|
4502
|
+
|
4503
|
+
it "should correctly handle simple qualified identifiers" do
|
4504
|
+
@ds.split_qualifiers(Sequel.qualify(:t, :s)).should == ['t', 's']
|
4505
|
+
end
|
4506
|
+
|
4507
|
+
it "should correctly handle complex qualified identifiers" do
|
4508
|
+
@ds.split_qualifiers(Sequel.qualify(:d__t, :s)).should == ['d', 't', 's']
|
4509
|
+
@ds.split_qualifiers(Sequel.qualify(Sequel.qualify(:d, :t), :s)).should == ['d', 't', 's']
|
4510
|
+
@ds.split_qualifiers(Sequel.qualify(:d, :t__s)).should == ['d', 't', 's']
|
4511
|
+
@ds.split_qualifiers(Sequel.qualify(:d, Sequel.qualify(:t, :s))).should == ['d', 't', 's']
|
4512
|
+
@ds.split_qualifiers(Sequel.qualify(:d__t, :s__s2)).should == ['d', 't', 's', 's2']
|
4513
|
+
@ds.split_qualifiers(Sequel.qualify(Sequel.qualify(:d, :t), Sequel.qualify(:s, :s2))).should == ['d', 't', 's', 's2']
|
4514
|
+
end
|
4515
|
+
|
4516
|
+
it "should respect default_schema" do
|
4517
|
+
@ds.db.default_schema = :foo
|
4518
|
+
@ds.split_qualifiers(:s).should == ['foo', 's']
|
4519
|
+
@ds.split_qualifiers(:s, nil).should == ['s']
|
4520
|
+
@ds.split_qualifiers(Sequel.qualify(:d__t, :s)).should == ['d', 't', 's']
|
4521
|
+
end
|
4522
|
+
end
|
4523
|
+
|