sequel 3.12.1 → 3.13.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 +42 -0
- data/README.rdoc +137 -118
- data/Rakefile +21 -66
- data/doc/active_record.rdoc +9 -9
- data/doc/advanced_associations.rdoc +59 -188
- data/doc/association_basics.rdoc +15 -2
- data/doc/cheat_sheet.rdoc +38 -33
- data/doc/dataset_filtering.rdoc +16 -7
- data/doc/prepared_statements.rdoc +7 -7
- data/doc/querying.rdoc +5 -4
- data/doc/release_notes/3.13.0.txt +210 -0
- data/doc/sharding.rdoc +1 -1
- data/doc/sql.rdoc +5 -5
- data/doc/validations.rdoc +11 -11
- data/lib/sequel/adapters/ado.rb +1 -1
- data/lib/sequel/adapters/do.rb +3 -3
- data/lib/sequel/adapters/firebird.rb +3 -3
- data/lib/sequel/adapters/jdbc/h2.rb +39 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +5 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +3 -3
- data/lib/sequel/adapters/mysql.rb +7 -4
- data/lib/sequel/adapters/oracle.rb +3 -3
- data/lib/sequel/adapters/shared/mssql.rb +10 -1
- data/lib/sequel/adapters/shared/mysql.rb +63 -0
- data/lib/sequel/adapters/shared/postgres.rb +61 -3
- data/lib/sequel/adapters/sqlite.rb +105 -18
- data/lib/sequel/connection_pool.rb +31 -30
- data/lib/sequel/core.rb +58 -58
- data/lib/sequel/core_sql.rb +52 -43
- data/lib/sequel/database/misc.rb +11 -0
- data/lib/sequel/database/query.rb +55 -17
- data/lib/sequel/dataset/actions.rb +2 -1
- data/lib/sequel/dataset/query.rb +2 -3
- data/lib/sequel/dataset/sql.rb +24 -11
- data/lib/sequel/extensions/schema_dumper.rb +1 -1
- data/lib/sequel/metaprogramming.rb +4 -0
- data/lib/sequel/model.rb +37 -19
- data/lib/sequel/model/associations.rb +33 -25
- data/lib/sequel/model/base.rb +2 -2
- data/lib/sequel/model/plugins.rb +7 -2
- data/lib/sequel/plugins/active_model.rb +1 -1
- data/lib/sequel/plugins/association_pks.rb +2 -2
- data/lib/sequel/plugins/association_proxies.rb +1 -1
- data/lib/sequel/plugins/boolean_readers.rb +2 -2
- data/lib/sequel/plugins/class_table_inheritance.rb +10 -2
- data/lib/sequel/plugins/identity_map.rb +3 -3
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +212 -0
- data/lib/sequel/plugins/lazy_attributes.rb +1 -1
- data/lib/sequel/plugins/list.rb +174 -0
- data/lib/sequel/plugins/many_through_many.rb +2 -2
- data/lib/sequel/plugins/rcte_tree.rb +6 -7
- data/lib/sequel/plugins/tree.rb +118 -0
- data/lib/sequel/plugins/xml_serializer.rb +321 -0
- data/lib/sequel/sql.rb +315 -206
- data/lib/sequel/timezones.rb +40 -17
- data/lib/sequel/version.rb +8 -2
- data/spec/adapters/firebird_spec.rb +2 -2
- data/spec/adapters/informix_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +2 -2
- data/spec/adapters/mysql_spec.rb +2 -2
- data/spec/adapters/oracle_spec.rb +1 -1
- data/spec/adapters/postgres_spec.rb +36 -6
- data/spec/adapters/spec_helper.rb +2 -2
- data/spec/adapters/sqlite_spec.rb +1 -1
- data/spec/core/connection_pool_spec.rb +3 -3
- data/spec/core/core_sql_spec.rb +31 -13
- data/spec/core/database_spec.rb +39 -2
- data/spec/core/dataset_spec.rb +24 -12
- data/spec/core/expression_filters_spec.rb +5 -1
- data/spec/core/object_graph_spec.rb +1 -1
- data/spec/core/schema_generator_spec.rb +1 -1
- data/spec/core/schema_spec.rb +1 -1
- data/spec/core/spec_helper.rb +1 -1
- data/spec/core/version_spec.rb +1 -1
- data/spec/extensions/active_model_spec.rb +82 -67
- data/spec/extensions/association_dependencies_spec.rb +1 -1
- data/spec/extensions/association_pks_spec.rb +1 -1
- data/spec/extensions/association_proxies_spec.rb +1 -1
- data/spec/extensions/blank_spec.rb +1 -1
- data/spec/extensions/boolean_readers_spec.rb +1 -1
- data/spec/extensions/caching_spec.rb +1 -1
- data/spec/extensions/class_table_inheritance_spec.rb +3 -2
- data/spec/extensions/composition_spec.rb +2 -5
- data/spec/extensions/force_encoding_spec.rb +3 -1
- data/spec/extensions/hook_class_methods_spec.rb +1 -1
- data/spec/extensions/identity_map_spec.rb +1 -1
- data/spec/extensions/inflector_spec.rb +1 -1
- data/spec/extensions/instance_filters_spec.rb +1 -1
- data/spec/extensions/instance_hooks_spec.rb +1 -1
- data/spec/extensions/json_serializer_spec.rb +154 -0
- data/spec/extensions/lazy_attributes_spec.rb +1 -2
- data/spec/extensions/list_spec.rb +251 -0
- data/spec/extensions/looser_typecasting_spec.rb +1 -1
- data/spec/extensions/many_through_many_spec.rb +3 -3
- data/spec/extensions/migration_spec.rb +1 -1
- data/spec/extensions/named_timezones_spec.rb +5 -6
- data/spec/extensions/nested_attributes_spec.rb +1 -1
- data/spec/extensions/optimistic_locking_spec.rb +1 -1
- data/spec/extensions/pagination_spec.rb +1 -1
- data/spec/extensions/pretty_table_spec.rb +1 -1
- data/spec/extensions/query_spec.rb +1 -1
- data/spec/extensions/rcte_tree_spec.rb +1 -1
- data/spec/extensions/schema_dumper_spec.rb +3 -2
- data/spec/extensions/schema_spec.rb +1 -1
- data/spec/extensions/serialization_spec.rb +6 -2
- data/spec/extensions/sharding_spec.rb +1 -1
- data/spec/extensions/single_table_inheritance_spec.rb +1 -1
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +7 -3
- data/spec/extensions/sql_expr_spec.rb +1 -1
- data/spec/extensions/string_date_time_spec.rb +1 -1
- data/spec/extensions/string_stripper_spec.rb +1 -1
- data/spec/extensions/subclasses_spec.rb +1 -1
- data/spec/extensions/tactical_eager_loading_spec.rb +1 -1
- data/spec/extensions/thread_local_timezones_spec.rb +1 -1
- data/spec/extensions/timestamps_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +1 -1
- data/spec/extensions/tree_spec.rb +119 -0
- data/spec/extensions/typecast_on_load_spec.rb +1 -1
- data/spec/extensions/update_primary_key_spec.rb +1 -1
- data/spec/extensions/validation_class_methods_spec.rb +1 -1
- data/spec/extensions/validation_helpers_spec.rb +1 -1
- data/spec/extensions/xml_serializer_spec.rb +142 -0
- data/spec/integration/associations_test.rb +1 -1
- data/spec/integration/database_test.rb +1 -1
- data/spec/integration/dataset_test.rb +29 -14
- data/spec/integration/eager_loader_test.rb +1 -1
- data/spec/integration/migrator_test.rb +1 -1
- data/spec/integration/model_test.rb +1 -1
- data/spec/integration/plugin_test.rb +316 -1
- data/spec/integration/prepared_statement_test.rb +1 -1
- data/spec/integration/schema_test.rb +8 -8
- data/spec/integration/spec_helper.rb +1 -1
- data/spec/integration/timezone_test.rb +1 -1
- data/spec/integration/transaction_test.rb +35 -20
- data/spec/integration/type_test.rb +1 -1
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +49 -34
- data/spec/model/base_spec.rb +1 -1
- data/spec/model/dataset_methods_spec.rb +4 -4
- data/spec/model/eager_loading_spec.rb +1 -1
- data/spec/model/hooks_spec.rb +1 -1
- data/spec/model/inflector_spec.rb +1 -1
- data/spec/model/model_spec.rb +7 -1
- data/spec/model/plugins_spec.rb +1 -1
- data/spec/model/record_spec.rb +1 -3
- data/spec/model/spec_helper.rb +2 -2
- data/spec/model/validations_spec.rb +1 -1
- metadata +29 -5
data/lib/sequel/timezones.rb
CHANGED
|
@@ -9,21 +9,44 @@ module Sequel
|
|
|
9
9
|
@database_timezone = nil
|
|
10
10
|
@typecast_timezone = nil
|
|
11
11
|
|
|
12
|
+
# Sequel doesn't pay much attention to timezones by default, but you can set it
|
|
13
|
+
# handle timezones if you want. There are three separate timezone settings, application_timezone,
|
|
14
|
+
# database_timezone, and typecast_timezone. All three timezones have getter and setter methods.
|
|
15
|
+
# You can set all three timezones to the same value at once via <tt>Sequel.default_timezone=</tt>.
|
|
16
|
+
#
|
|
17
|
+
# The only timezone values that are supported by default are <tt>:utc</tt> (convert to UTC),
|
|
18
|
+
# <tt>:local</tt> (convert to local time), and +nil+ (don't convert). If you need to
|
|
19
|
+
# convert to a specific timezone, or need the timezones being used to change based
|
|
20
|
+
# on the environment (e.g. current user), you need to use the +named_timezones+ extension (and use
|
|
21
|
+
# +DateTime+ as the +datetime_class+). Sequel also ships with a +thread_local_timezones+ extensions
|
|
22
|
+
# which allows each thread to have its own timezone values for each of the timezones.
|
|
12
23
|
module Timezones
|
|
13
|
-
|
|
24
|
+
# The timezone you want the application to use. This is the timezone
|
|
25
|
+
# that incoming times from the database and typecasting are converted to.
|
|
26
|
+
attr_reader :application_timezone
|
|
27
|
+
|
|
28
|
+
# The timezone for storage in the database. This is the
|
|
29
|
+
# timezone to which Sequel will convert timestamps before literalizing them
|
|
30
|
+
# for storage in the database. It is also the timezone that Sequel will assume
|
|
31
|
+
# database timestamp values are already in (if they don't include an offset).
|
|
32
|
+
attr_reader :database_timezone
|
|
33
|
+
|
|
34
|
+
# The timezone that incoming data that Sequel needs to typecast
|
|
35
|
+
# is assumed to be already in (if they don't include an offset).
|
|
36
|
+
attr_reader :typecast_timezone
|
|
14
37
|
|
|
15
38
|
%w'application database typecast'.each do |t|
|
|
16
39
|
class_eval("def #{t}_timezone=(tz); @#{t}_timezone = convert_timezone_setter_arg(tz) end", __FILE__, __LINE__)
|
|
17
40
|
end
|
|
18
41
|
|
|
19
|
-
# Convert the given Time
|
|
42
|
+
# Convert the given +Time+/+DateTime+ object into the database timezone, used when
|
|
20
43
|
# literalizing objects in an SQL string.
|
|
21
44
|
def application_to_database_timestamp(v)
|
|
22
45
|
convert_output_timestamp(v, Sequel.database_timezone)
|
|
23
46
|
end
|
|
24
47
|
|
|
25
|
-
# Convert the given object into an object of Sequel.datetime_class in the
|
|
26
|
-
# application_timezone
|
|
48
|
+
# Convert the given object into an object of <tt>Sequel.datetime_class</tt> in the
|
|
49
|
+
# +application_timezone+. Used when coverting datetime/timestamp columns
|
|
27
50
|
# returned by the database.
|
|
28
51
|
def database_to_application_timestamp(v)
|
|
29
52
|
convert_timestamp(v, Sequel.database_timezone)
|
|
@@ -36,8 +59,8 @@ module Sequel
|
|
|
36
59
|
self.typecast_timezone = tz
|
|
37
60
|
end
|
|
38
61
|
|
|
39
|
-
# Convert the given object into an object of Sequel.datetime_class in the
|
|
40
|
-
# application_timezone
|
|
62
|
+
# Convert the given object into an object of <tt>Sequel.datetime_class</tt> in the
|
|
63
|
+
# +application_timezone+. Used when typecasting values when assigning them
|
|
41
64
|
# to model datetime attributes.
|
|
42
65
|
def typecast_to_application_timestamp(v)
|
|
43
66
|
convert_timestamp(v, Sequel.typecast_timezone)
|
|
@@ -45,7 +68,7 @@ module Sequel
|
|
|
45
68
|
|
|
46
69
|
private
|
|
47
70
|
|
|
48
|
-
# Convert the given DateTime to the given input_timezone, keeping the
|
|
71
|
+
# Convert the given +DateTime+ to the given input_timezone, keeping the
|
|
49
72
|
# same time and just modifying the timezone.
|
|
50
73
|
def convert_input_datetime_no_offset(v, input_timezone)
|
|
51
74
|
case input_timezone
|
|
@@ -58,16 +81,16 @@ module Sequel
|
|
|
58
81
|
end
|
|
59
82
|
end
|
|
60
83
|
|
|
61
|
-
# Convert the given DateTime to the given input_timezone that is not supported
|
|
62
|
-
# by default (
|
|
84
|
+
# Convert the given +DateTime+ to the given input_timezone that is not supported
|
|
85
|
+
# by default (i.e. one other than +nil+, <tt>:local</tt>, or <tt>:utc</tt>). Raises an +InvalidValue+ by default.
|
|
63
86
|
# Can be overridden in extensions.
|
|
64
87
|
def convert_input_datetime_other(v, input_timezone)
|
|
65
88
|
raise InvalidValue, "Invalid input_timezone: #{input_timezone.inspect}"
|
|
66
89
|
end
|
|
67
90
|
|
|
68
|
-
# Converts the object from a String
|
|
69
|
-
# instance of Sequel.datetime_class
|
|
70
|
-
# contain an offset, assume that the array/string is already in the given input_timezone
|
|
91
|
+
# Converts the object from a +String+, +Array+, +Date+, +DateTime+, or +Time+ into an
|
|
92
|
+
# instance of <tt>Sequel.datetime_class</tt>. If given an array or a string that doesn't
|
|
93
|
+
# contain an offset, assume that the array/string is already in the given +input_timezone+.
|
|
71
94
|
def convert_input_timestamp(v, input_timezone)
|
|
72
95
|
case v
|
|
73
96
|
when String
|
|
@@ -110,14 +133,14 @@ module Sequel
|
|
|
110
133
|
end
|
|
111
134
|
end
|
|
112
135
|
|
|
113
|
-
# Convert the given DateTime to the given output_timezone that is not supported
|
|
114
|
-
# by default (
|
|
136
|
+
# Convert the given +DateTime+ to the given output_timezone that is not supported
|
|
137
|
+
# by default (i.e. one other than +nil+, <tt>:local</tt>, or <tt>:utc</tt>). Raises an +InvalidValue+ by default.
|
|
115
138
|
# Can be overridden in extensions.
|
|
116
139
|
def convert_output_datetime_other(v, output_timezone)
|
|
117
140
|
raise InvalidValue, "Invalid output_timezone: #{output_timezone.inspect}"
|
|
118
141
|
end
|
|
119
142
|
|
|
120
|
-
# Converts the object to the given output_timezone
|
|
143
|
+
# Converts the object to the given +output_timezone+.
|
|
121
144
|
def convert_output_timestamp(v, output_timezone)
|
|
122
145
|
if output_timezone
|
|
123
146
|
if v.is_a?(DateTime)
|
|
@@ -138,8 +161,8 @@ module Sequel
|
|
|
138
161
|
end
|
|
139
162
|
|
|
140
163
|
# Converts the given object from the given input timezone to the
|
|
141
|
-
#
|
|
142
|
-
# convert_output_timestamp
|
|
164
|
+
# +application_timezone+ using +convert_input_timestamp+ and
|
|
165
|
+
# +convert_output_timestamp+.
|
|
143
166
|
def convert_timestamp(v, input_timezone)
|
|
144
167
|
begin
|
|
145
168
|
convert_output_timestamp(convert_input_timestamp(v, input_timezone), Sequel.application_timezone)
|
data/lib/sequel/version.rb
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
module Sequel
|
|
2
|
+
# The major version of Sequel. Only bumped for major changes.
|
|
2
3
|
MAJOR = 3
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
# The minor version of Sequel. Bumped for every non-patch level
|
|
5
|
+
# release, generally around once a month.
|
|
6
|
+
MINOR = 13
|
|
7
|
+
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
|
8
|
+
# releases that fix regressions from previous versions.
|
|
9
|
+
TINY = 0
|
|
5
10
|
|
|
11
|
+
# The version of Sequel you are using, as a string (e.g. "2.11.0")
|
|
6
12
|
VERSION = [MAJOR, MINOR, TINY].join('.')
|
|
7
13
|
|
|
8
14
|
# The version of Sequel you are using, as a string (e.g. "2.11.0")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'spec_helper.rb')
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
2
2
|
|
|
3
3
|
unless defined?(FIREBIRD_DB)
|
|
4
4
|
FIREBIRD_URL = 'firebird://sysdba:masterkey@localhost/reality_spec' unless defined? FIREBIRD_URL
|
|
@@ -13,7 +13,7 @@ logger = Object.new
|
|
|
13
13
|
def logger.method_missing(m, msg)
|
|
14
14
|
FIREBIRD_DB.sqls.push(msg)
|
|
15
15
|
end
|
|
16
|
-
FIREBIRD_DB.
|
|
16
|
+
FIREBIRD_DB.loggers = [logger]
|
|
17
17
|
|
|
18
18
|
FIREBIRD_DB.create_table! :test do
|
|
19
19
|
varchar :name, :size => 50
|
data/spec/adapters/mssql_spec.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'spec_helper.rb')
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
2
2
|
|
|
3
3
|
require ENV['SEQUEL_MSSQL_SPEC_REQUIRE'] if ENV['SEQUEL_MSSQL_SPEC_REQUIRE']
|
|
4
4
|
|
|
@@ -15,7 +15,7 @@ logger = Object.new
|
|
|
15
15
|
def logger.method_missing(m, msg)
|
|
16
16
|
MSSQL_DB.sqls << msg
|
|
17
17
|
end
|
|
18
|
-
MSSQL_DB.
|
|
18
|
+
MSSQL_DB.loggers = [logger]
|
|
19
19
|
|
|
20
20
|
MSSQL_DB.create_table! :test do
|
|
21
21
|
text :name
|
data/spec/adapters/mysql_spec.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'spec_helper.rb')
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
2
2
|
|
|
3
3
|
unless defined?(MYSQL_USER)
|
|
4
4
|
MYSQL_USER = 'root'
|
|
@@ -25,7 +25,7 @@ logger = Object.new
|
|
|
25
25
|
def logger.method_missing(m, msg)
|
|
26
26
|
MYSQL_DB.sqls << msg
|
|
27
27
|
end
|
|
28
|
-
MYSQL_DB.
|
|
28
|
+
MYSQL_DB.loggers = [logger]
|
|
29
29
|
MYSQL_DB.drop_table(:items) rescue nil
|
|
30
30
|
MYSQL_DB.drop_table(:dolls) rescue nil
|
|
31
31
|
MYSQL_DB.drop_table(:booltest) rescue nil
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'spec_helper.rb')
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
2
2
|
|
|
3
3
|
unless defined?(POSTGRES_DB)
|
|
4
4
|
POSTGRES_URL = 'postgres://postgres:postgres@localhost:5432/reality_spec' unless defined? POSTGRES_URL
|
|
@@ -13,7 +13,7 @@ logger = Object.new
|
|
|
13
13
|
def logger.method_missing(m, msg)
|
|
14
14
|
POSTGRES_DB.sqls << msg
|
|
15
15
|
end
|
|
16
|
-
POSTGRES_DB.
|
|
16
|
+
POSTGRES_DB.loggers = [logger]
|
|
17
17
|
|
|
18
18
|
#POSTGRES_DB.instance_variable_set(:@server_version, 80100)
|
|
19
19
|
POSTGRES_DB.create_table! :test do
|
|
@@ -130,6 +130,15 @@ context "A PostgreSQL dataset" do
|
|
|
130
130
|
@d.filter(:name => /^bc/).count.should == 1
|
|
131
131
|
end
|
|
132
132
|
|
|
133
|
+
specify "should support NULLS FIRST and NULLS LAST" do
|
|
134
|
+
@d << {:name => 'abc'}
|
|
135
|
+
@d << {:name => 'bcd'}
|
|
136
|
+
@d << {:name => 'bcd', :value => 2}
|
|
137
|
+
@d.order(:value.asc(:nulls=>:first), :name).select_map(:name).should == %w[abc bcd bcd]
|
|
138
|
+
@d.order(:value.asc(:nulls=>:last), :name).select_map(:name).should == %w[bcd abc bcd]
|
|
139
|
+
@d.order(:value.asc(:nulls=>:first), :name).reverse.select_map(:name).should == %w[bcd bcd abc]
|
|
140
|
+
end
|
|
141
|
+
|
|
133
142
|
specify "#lock should lock tables and yield if a block is given" do
|
|
134
143
|
@d.lock('EXCLUSIVE'){@d.insert(:name=>'a')}
|
|
135
144
|
end
|
|
@@ -557,9 +566,11 @@ context "Postgres::Database schema qualified tables" do
|
|
|
557
566
|
POSTGRES_DB.drop_table(:schema_test.qualify(:schema_test))
|
|
558
567
|
end
|
|
559
568
|
|
|
560
|
-
specify "#tables should include
|
|
569
|
+
specify "#tables should not include tables in a default non-public schema" do
|
|
561
570
|
POSTGRES_DB.create_table(:schema_test__schema_test){integer :i}
|
|
562
|
-
POSTGRES_DB.tables.
|
|
571
|
+
POSTGRES_DB.tables.should include(:schema_test)
|
|
572
|
+
POSTGRES_DB.tables.should_not include(:pg_am)
|
|
573
|
+
POSTGRES_DB.tables.should_not include(:domain_udt_usage)
|
|
563
574
|
end
|
|
564
575
|
|
|
565
576
|
specify "#tables should return tables in the schema provided by the :schema argument" do
|
|
@@ -567,9 +578,28 @@ context "Postgres::Database schema qualified tables" do
|
|
|
567
578
|
POSTGRES_DB.tables(:schema=>:schema_test).should == [:schema_test]
|
|
568
579
|
end
|
|
569
580
|
|
|
570
|
-
specify "#
|
|
581
|
+
specify "#schema should not include columns from tables in a default non-public schema" do
|
|
582
|
+
POSTGRES_DB.create_table(:schema_test__domains){integer :i}
|
|
583
|
+
sch = POSTGRES_DB.schema(:domains)
|
|
584
|
+
cs = sch.map{|x| x.first}
|
|
585
|
+
cs.should include(:i)
|
|
586
|
+
cs.should_not include(:data_type)
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
specify "#schema should only include columns from the table in the given :schema argument" do
|
|
590
|
+
POSTGRES_DB.create_table!(:domains){integer :d}
|
|
591
|
+
POSTGRES_DB.create_table(:schema_test__domains){integer :i}
|
|
592
|
+
sch = POSTGRES_DB.schema(:domains, :schema=>:schema_test)
|
|
593
|
+
cs = sch.map{|x| x.first}
|
|
594
|
+
cs.should include(:i)
|
|
595
|
+
cs.should_not include(:d)
|
|
596
|
+
POSTGRES_DB.drop_table(:domains)
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
specify "#table_exists? should not include tables from the default non-public schemas" do
|
|
571
600
|
POSTGRES_DB.create_table(:schema_test__schema_test){integer :i}
|
|
572
|
-
POSTGRES_DB.table_exists?(:schema_test).should ==
|
|
601
|
+
POSTGRES_DB.table_exists?(:schema_test).should == true
|
|
602
|
+
POSTGRES_DB.table_exists?(:domain_udt_usage).should == false
|
|
573
603
|
end
|
|
574
604
|
|
|
575
605
|
specify "#table_exists? should see if the table is in a given schema" do
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
require 'rubygems'
|
|
2
2
|
require 'logger'
|
|
3
3
|
unless Object.const_defined?('Sequel')
|
|
4
|
-
$:.unshift(File.join(File.dirname(__FILE__), "../../lib/"))
|
|
4
|
+
$:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), "../../lib/"))
|
|
5
5
|
require 'sequel'
|
|
6
6
|
Sequel.quote_identifiers = false
|
|
7
7
|
end
|
|
8
8
|
begin
|
|
9
|
-
require File.join(File.dirname(File.dirname(__FILE__)), 'spec_config.rb')
|
|
9
|
+
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), 'spec_config.rb')
|
|
10
10
|
rescue LoadError
|
|
11
11
|
end
|
|
12
12
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
|
|
2
2
|
CONNECTION_POOL_DEFAULTS = {:pool_timeout=>5, :pool_sleep_time=>0.001, :max_connections=>4}
|
|
3
3
|
|
|
4
4
|
context "An empty ConnectionPool" do
|
|
@@ -70,7 +70,7 @@ context "A connection pool handling connections" do
|
|
|
70
70
|
@cpool.hold {:block_return}.should == :block_return
|
|
71
71
|
end
|
|
72
72
|
|
|
73
|
-
if RUBY_VERSION < '1.9.0' and
|
|
73
|
+
if RUBY_VERSION < '1.9.0' and !defined?(RUBY_ENGINE)
|
|
74
74
|
specify "#hold should remove dead threads from the pool if it reaches its max_size" do
|
|
75
75
|
Thread.new{@cpool.hold{Thread.current.exit!}}.join
|
|
76
76
|
@cpool.allocated.keys.map{|t| t.alive?}.should == [false]
|
|
@@ -96,7 +96,7 @@ context "A connection pool handling connections" do
|
|
|
96
96
|
|
|
97
97
|
specify "#hold should remove the connection if a DatabaseDisconnectError is raised" do
|
|
98
98
|
@cpool.created_count.should == 0
|
|
99
|
-
@cpool.hold{Thread.new{@cpool.hold{}}; sleep 0.
|
|
99
|
+
@cpool.hold{Thread.new{@cpool.hold{}}; sleep 0.03}
|
|
100
100
|
@cpool.created_count.should == 2
|
|
101
101
|
proc{@cpool.hold{raise Sequel::DatabaseDisconnectError}}.should raise_error(Sequel::DatabaseDisconnectError)
|
|
102
102
|
@cpool.created_count.should == 1
|
data/spec/core/core_sql_spec.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
|
|
2
2
|
|
|
3
3
|
context "Array#all_two_pairs?" do
|
|
4
4
|
specify "should return false if empty" do
|
|
@@ -39,6 +39,10 @@ context "Array#case and Hash#case" do
|
|
|
39
39
|
@d.literal([[:x, :y], [:a, :b]].case(:z, :exp__w)).should == '(CASE exp.w WHEN x THEN y WHEN a THEN b ELSE z END)'
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
+
specify "should return SQL CASE expression with expression even if nil" do
|
|
43
|
+
@d.literal({:x=>:y}.case(:z, nil)).should == '(CASE NULL WHEN x THEN y ELSE z END)'
|
|
44
|
+
end
|
|
45
|
+
|
|
42
46
|
specify "should raise an error if an array that isn't all two pairs is used" do
|
|
43
47
|
proc{[:b].case(:a)}.should raise_error(Sequel::Error)
|
|
44
48
|
proc{[:b, :c].case(:a)}.should raise_error(Sequel::Error)
|
|
@@ -51,19 +55,28 @@ context "Array#case and Hash#case" do
|
|
|
51
55
|
end
|
|
52
56
|
end
|
|
53
57
|
|
|
54
|
-
context "Array#sql_array" do
|
|
58
|
+
context "Array#sql_value_list and #sql_array" do
|
|
55
59
|
before do
|
|
56
60
|
@d = Sequel::Dataset.new(nil)
|
|
57
61
|
end
|
|
58
62
|
|
|
59
|
-
specify "should treat the array as an SQL
|
|
60
|
-
@d.
|
|
61
|
-
@d.
|
|
63
|
+
specify "should treat the array as an SQL value list instead of conditions when used as a placeholder value" do
|
|
64
|
+
@d.filter("(a, b) IN ?", [[:x, 1], [:y, 2]]).sql.should == 'SELECT * WHERE ((a, b) IN ((x = 1) AND (y = 2)))'
|
|
65
|
+
@d.filter("(a, b) IN ?", [[:x, 1], [:y, 2]].sql_value_list).sql.should == 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
|
|
66
|
+
@d.filter("(a, b) IN ?", [[:x, 1], [:y, 2]].sql_array).sql.should == 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
specify "should be no difference when used as a hash value" do
|
|
70
|
+
@d.filter([:a, :b]=>[[:x, 1], [:y, 2]]).sql.should == 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
|
|
71
|
+
@d.filter([:a, :b]=>[[:x, 1], [:y, 2]].sql_value_list).sql.should == 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
|
|
62
72
|
@d.filter([:a, :b]=>[[:x, 1], [:y, 2]].sql_array).sql.should == 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
|
|
63
73
|
end
|
|
64
74
|
end
|
|
65
75
|
|
|
66
76
|
context "String#lit" do
|
|
77
|
+
before do
|
|
78
|
+
@ds = ds = MockDatabase.new.dataset
|
|
79
|
+
end
|
|
67
80
|
specify "should return an LiteralString object" do
|
|
68
81
|
'xyz'.lit.should be_a_kind_of(Sequel::LiteralString)
|
|
69
82
|
'xyz'.lit.to_s.should == 'xyz'
|
|
@@ -77,19 +90,24 @@ context "String#lit" do
|
|
|
77
90
|
specify "should return a PlaceholderLiteralString object if args are given" do
|
|
78
91
|
a = 'DISTINCT ?'.lit(:a)
|
|
79
92
|
a.should be_a_kind_of(Sequel::SQL::PlaceholderLiteralString)
|
|
80
|
-
ds
|
|
81
|
-
ds.
|
|
82
|
-
ds.
|
|
83
|
-
ds.literal(a).should == 'DISTINCT "a"'
|
|
93
|
+
@ds.literal(a).should == 'DISTINCT a'
|
|
94
|
+
@ds.quote_identifiers = true
|
|
95
|
+
@ds.literal(a).should == 'DISTINCT "a"'
|
|
84
96
|
end
|
|
85
97
|
|
|
86
98
|
specify "should handle named placeholders if given a single argument hash" do
|
|
87
99
|
a = 'DISTINCT :b'.lit(:b=>:a)
|
|
88
100
|
a.should be_a_kind_of(Sequel::SQL::PlaceholderLiteralString)
|
|
89
|
-
ds
|
|
90
|
-
ds.
|
|
91
|
-
ds.
|
|
92
|
-
|
|
101
|
+
@ds.literal(a).should == 'DISTINCT a'
|
|
102
|
+
@ds.quote_identifiers = true
|
|
103
|
+
@ds.literal(a).should == 'DISTINCT "a"'
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
specify "should treat placeholder literal strings as generic expressions" do
|
|
107
|
+
a = ':b'.lit(:b=>:a)
|
|
108
|
+
@ds.literal(a + 1).should == "(a + 1)"
|
|
109
|
+
@ds.literal(a & :b).should == "(a AND b)"
|
|
110
|
+
@ds.literal(a.sql_string + :b).should == "(a || b)"
|
|
93
111
|
end
|
|
94
112
|
end
|
|
95
113
|
|
data/spec/core/database_spec.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
|
|
2
2
|
|
|
3
3
|
context "A new Database" do
|
|
4
4
|
before do
|
|
@@ -213,6 +213,7 @@ context "Database#log_info" do
|
|
|
213
213
|
before do
|
|
214
214
|
@o = Object.new
|
|
215
215
|
def @o.logs; @logs || []; end
|
|
216
|
+
def @o.to_ary; [self]; end
|
|
216
217
|
def @o.method_missing(*args); (@logs ||= []) << args; end
|
|
217
218
|
@db = Sequel::Database.new(:logger=>@o)
|
|
218
219
|
end
|
|
@@ -234,6 +235,7 @@ context "Database#log_yield" do
|
|
|
234
235
|
def @o.logs; @logs || []; end
|
|
235
236
|
def @o.warn(*args); (@logs ||= []) << [:warn] + args; end
|
|
236
237
|
def @o.method_missing(*args); (@logs ||= []) << args; end
|
|
238
|
+
def @o.to_ary; [self]; end
|
|
237
239
|
@db = Sequel::Database.new(:logger=>@o)
|
|
238
240
|
end
|
|
239
241
|
|
|
@@ -693,10 +695,33 @@ context "Database#transaction" do
|
|
|
693
695
|
end
|
|
694
696
|
|
|
695
697
|
specify "should wrap the supplied block with BEGIN + COMMIT statements" do
|
|
696
|
-
@db.transaction
|
|
698
|
+
@db.transaction{@db.execute 'DROP TABLE test;'}
|
|
697
699
|
@db.sql.should == ['BEGIN', 'DROP TABLE test;', 'COMMIT']
|
|
698
700
|
end
|
|
699
701
|
|
|
702
|
+
specify "should support transaction isolation levels" do
|
|
703
|
+
@db.meta_def(:supports_transaction_isolation_levels?){true}
|
|
704
|
+
[:uncommitted, :committed, :repeatable, :serializable].each do |l|
|
|
705
|
+
@db.transaction(:isolation=>l){@db.run "DROP TABLE #{l}"}
|
|
706
|
+
end
|
|
707
|
+
@db.sql.should == ['BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED', 'DROP TABLE uncommitted', 'COMMIT',
|
|
708
|
+
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED', 'DROP TABLE committed', 'COMMIT',
|
|
709
|
+
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ', 'DROP TABLE repeatable', 'COMMIT',
|
|
710
|
+
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE', 'DROP TABLE serializable', 'COMMIT']
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
specify "should allow specifying a default transaction isolation level" do
|
|
714
|
+
@db.meta_def(:supports_transaction_isolation_levels?){true}
|
|
715
|
+
[:uncommitted, :committed, :repeatable, :serializable].each do |l|
|
|
716
|
+
@db.transaction_isolation_level = l
|
|
717
|
+
@db.transaction{@db.run "DROP TABLE #{l}"}
|
|
718
|
+
end
|
|
719
|
+
@db.sql.should == ['BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED', 'DROP TABLE uncommitted', 'COMMIT',
|
|
720
|
+
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL READ COMMITTED', 'DROP TABLE committed', 'COMMIT',
|
|
721
|
+
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL REPEATABLE READ', 'DROP TABLE repeatable', 'COMMIT',
|
|
722
|
+
'BEGIN', 'SET TRANSACTION ISOLATION LEVEL SERIALIZABLE', 'DROP TABLE serializable', 'COMMIT']
|
|
723
|
+
end
|
|
724
|
+
|
|
700
725
|
specify "should handle returning inside of the block by committing" do
|
|
701
726
|
def @db.ret_commit
|
|
702
727
|
transaction do
|
|
@@ -1581,6 +1606,18 @@ context "Database#supports_savepoints?" do
|
|
|
1581
1606
|
end
|
|
1582
1607
|
end
|
|
1583
1608
|
|
|
1609
|
+
context "Database#supports_prepared_transactions?" do
|
|
1610
|
+
specify "should be false by default" do
|
|
1611
|
+
Sequel::Database.new.supports_prepared_transactions?.should == false
|
|
1612
|
+
end
|
|
1613
|
+
end
|
|
1614
|
+
|
|
1615
|
+
context "Database#supports_transaction_isolation_levels?" do
|
|
1616
|
+
specify "should be false by default" do
|
|
1617
|
+
Sequel::Database.new.supports_transaction_isolation_levels?.should == false
|
|
1618
|
+
end
|
|
1619
|
+
end
|
|
1620
|
+
|
|
1584
1621
|
context "Database#input_identifier_meth" do
|
|
1585
1622
|
specify "should be the input_identifer method of a default dataset for this database" do
|
|
1586
1623
|
db = Sequel::Database.new
|