sequel 3.42.0 → 3.43.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 +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
|
+
|