sequel 4.42.1 → 4.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.
- checksums.yaml +4 -4
- data/CHANGELOG +35 -1
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/doc/release_notes/4.43.0.txt +87 -0
- data/doc/sql.rdoc +26 -27
- data/doc/testing.rdoc +2 -0
- data/doc/validations.rdoc +1 -1
- data/lib/sequel/adapters/ado.rb +5 -0
- data/lib/sequel/adapters/cubrid.rb +5 -0
- data/lib/sequel/adapters/ibmdb.rb +5 -0
- data/lib/sequel/adapters/jdbc.rb +6 -0
- data/lib/sequel/adapters/jdbc/derby.rb +5 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +9 -5
- data/lib/sequel/adapters/jdbc/postgresql.rb +1 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +5 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +5 -0
- data/lib/sequel/adapters/mock.rb +12 -9
- data/lib/sequel/adapters/mysql.rb +6 -0
- data/lib/sequel/adapters/mysql2.rb +7 -2
- data/lib/sequel/adapters/oracle.rb +5 -0
- data/lib/sequel/adapters/shared/db2.rb +7 -1
- data/lib/sequel/adapters/shared/mssql.rb +5 -0
- data/lib/sequel/adapters/shared/mysql.rb +8 -1
- data/lib/sequel/adapters/shared/oracle.rb +20 -12
- data/lib/sequel/adapters/shared/postgres.rb +11 -2
- data/lib/sequel/adapters/shared/sqlanywhere.rb +6 -0
- data/lib/sequel/adapters/shared/sqlite.rb +29 -0
- data/lib/sequel/adapters/sqlanywhere.rb +5 -0
- data/lib/sequel/adapters/sqlite.rb +13 -0
- data/lib/sequel/connection_pool/sharded_single.rb +5 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -0
- data/lib/sequel/connection_pool/single.rb +15 -6
- data/lib/sequel/database/dataset.rb +3 -0
- data/lib/sequel/database/misc.rb +22 -1
- data/lib/sequel/database/query.rb +2 -4
- data/lib/sequel/dataset/actions.rb +0 -1
- data/lib/sequel/dataset/misc.rb +2 -4
- data/lib/sequel/dataset/query.rb +23 -6
- data/lib/sequel/extensions/_model_constraint_validations.rb +16 -0
- data/lib/sequel/extensions/_model_pg_row.rb +47 -0
- data/lib/sequel/extensions/looser_typecasting.rb +2 -0
- data/lib/sequel/extensions/migration.rb +12 -1
- data/lib/sequel/extensions/pg_array.rb +6 -0
- data/lib/sequel/extensions/pg_enum.rb +2 -1
- data/lib/sequel/extensions/pg_range.rb +6 -0
- data/lib/sequel/extensions/pg_row.rb +8 -0
- data/lib/sequel/model/associations.rb +3 -1
- data/lib/sequel/model/base.rb +14 -3
- data/lib/sequel/plugins/constraint_validations.rb +1 -8
- data/lib/sequel/plugins/instance_filters.rb +1 -1
- data/lib/sequel/plugins/pg_row.rb +1 -40
- data/lib/sequel/plugins/prepared_statements.rb +51 -20
- data/lib/sequel/plugins/prepared_statements_associations.rb +22 -4
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +9 -1
- data/lib/sequel/plugins/sharding.rb +5 -0
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/spec_helper.rb +4 -0
- data/spec/core/connection_pool_spec.rb +10 -0
- data/spec/core/database_spec.rb +29 -0
- data/spec/extensions/blacklist_security_spec.rb +4 -4
- data/spec/extensions/defaults_setter_spec.rb +1 -1
- data/spec/extensions/force_encoding_spec.rb +3 -2
- data/spec/extensions/identifier_mangling_spec.rb +7 -0
- data/spec/extensions/instance_filters_spec.rb +1 -0
- data/spec/extensions/migration_spec.rb +19 -0
- data/spec/extensions/pg_array_spec.rb +5 -0
- data/spec/extensions/pg_range_spec.rb +5 -0
- data/spec/extensions/pg_row_spec.rb +9 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +45 -1
- data/spec/extensions/prepared_statements_spec.rb +138 -41
- data/spec/extensions/prepared_statements_with_pk_spec.rb +7 -0
- data/spec/extensions/serialization_spec.rb +6 -6
- data/spec/extensions/single_table_inheritance_spec.rb +3 -3
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/integration/associations_test.rb +2 -2
- data/spec/integration/dataset_test.rb +0 -4
- data/spec/integration/eager_loader_test.rb +5 -5
- data/spec/integration/plugin_test.rb +8 -6
- data/spec/integration/schema_test.rb +2 -2
- data/spec/integration/spec_helper.rb +10 -0
- data/spec/integration/timezone_test.rb +1 -1
- data/spec/integration/transaction_test.rb +5 -5
- data/spec/model/associations_spec.rb +13 -6
- data/spec/model/base_spec.rb +1 -1
- data/spec/model/hooks_spec.rb +4 -4
- data/spec/model/model_spec.rb +2 -2
- data/spec/model/record_spec.rb +17 -18
- metadata +6 -2
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -283,6 +283,12 @@ module Sequel
|
|
283
283
|
execute(sql, opts)
|
284
284
|
end
|
285
285
|
|
286
|
+
def freeze
|
287
|
+
@type_convertor_map.freeze
|
288
|
+
@basic_type_convertor_map.freeze
|
289
|
+
super
|
290
|
+
end
|
291
|
+
|
286
292
|
# Use the JDBC metadata to get a list of foreign keys for the table.
|
287
293
|
def foreign_key_list(table, opts=OPTS)
|
288
294
|
m = output_identifier_meth
|
@@ -34,6 +34,11 @@ module Sequel
|
|
34
34
|
:derby
|
35
35
|
end
|
36
36
|
|
37
|
+
def freeze
|
38
|
+
svn_version
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
37
42
|
# Derby uses an IDENTITY sequence for autoincrementing columns.
|
38
43
|
def serial_primary_key_options
|
39
44
|
{:primary_key => true, :type => :integer, :identity=>true, :start_with=>1}
|
@@ -26,6 +26,11 @@ module Sequel
|
|
26
26
|
:hsqldb
|
27
27
|
end
|
28
28
|
|
29
|
+
def freeze
|
30
|
+
db_version
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
29
34
|
# HSQLDB uses an IDENTITY sequence as the default value for primary
|
30
35
|
# key columns.
|
31
36
|
def serial_primary_key_options
|
@@ -34,11 +39,10 @@ module Sequel
|
|
34
39
|
|
35
40
|
# The version of the database, as an integer (e.g 2.2.5 -> 20205)
|
36
41
|
def db_version
|
37
|
-
@db_version
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
42
|
+
return @db_version if defined?(@db_version)
|
43
|
+
v = get{DATABASE_VERSION(){}}
|
44
|
+
@db_version = if v =~ /(\d+)\.(\d+)\.(\d+)/
|
45
|
+
$1.to_i * 10000 + $2.to_i * 100 + $3.to_i
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
@@ -9,8 +9,8 @@ module Sequel
|
|
9
9
|
module JDBC
|
10
10
|
Sequel.synchronize do
|
11
11
|
DATABASE_SETUP[:postgresql] = proc do |db|
|
12
|
-
db.extend(Sequel::JDBC::Postgres::DatabaseMethods)
|
13
12
|
db.dataset_class = Sequel::JDBC::Postgres::Dataset
|
13
|
+
db.extend(Sequel::JDBC::Postgres::DatabaseMethods)
|
14
14
|
org.postgresql.Driver
|
15
15
|
end
|
16
16
|
end
|
@@ -90,6 +90,11 @@ module Sequel
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
end
|
93
|
+
|
94
|
+
# The result code for the exception, if the jdbc driver supports result codes for exceptions.
|
95
|
+
def sqlite_error_code(exception)
|
96
|
+
exception.resultCode.code if exception.respond_to?(:resultCode)
|
97
|
+
end
|
93
98
|
end
|
94
99
|
end
|
95
100
|
end
|
@@ -10,6 +10,11 @@ module Sequel
|
|
10
10
|
TRANSACTION_ROLLBACK_SP = 'Transaction.rollback_savepoint'.freeze
|
11
11
|
TRANSACTION_SAVEPOINT= 'Transaction.savepoint'.freeze
|
12
12
|
|
13
|
+
def freeze
|
14
|
+
supports_savepoints?
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
13
18
|
# Check the JDBC DatabaseMetaData for savepoint support
|
14
19
|
def supports_savepoints?
|
15
20
|
return @supports_savepoints if defined?(@supports_savepoints)
|
data/lib/sequel/adapters/mock.rb
CHANGED
@@ -48,7 +48,15 @@ module Sequel
|
|
48
48
|
# the value returned
|
49
49
|
# Class :: Should be an Exception subclass, will create a new
|
50
50
|
# instance an raise it wrapped in a DatabaseError.
|
51
|
-
|
51
|
+
def autoid=(v)
|
52
|
+
@autoid = case v
|
53
|
+
when Integer
|
54
|
+
i = v - 1
|
55
|
+
proc{Sequel.synchronize{i+=1}}
|
56
|
+
else
|
57
|
+
v
|
58
|
+
end
|
59
|
+
end
|
52
60
|
|
53
61
|
# Set the columns to set in the dataset when the dataset fetches
|
54
62
|
# rows. Argument types supported:
|
@@ -133,13 +141,8 @@ module Sequel
|
|
133
141
|
private
|
134
142
|
|
135
143
|
def _autoid(sql, v, ds=nil)
|
136
|
-
|
137
|
-
|
138
|
-
if ds
|
139
|
-
ds.send(:cache_set, :_autoid, ds.autoid + 1) if ds.autoid.is_a?(Integer)
|
140
|
-
else
|
141
|
-
@autoid += 1
|
142
|
-
end
|
144
|
+
if ds
|
145
|
+
ds.send(:cache_set, :_autoid, ds.autoid + 1) if ds.autoid.is_a?(Integer)
|
143
146
|
v
|
144
147
|
else
|
145
148
|
_nextres(v, sql, nil)
|
@@ -192,7 +195,7 @@ module Sequel
|
|
192
195
|
if f < Exception
|
193
196
|
raise f
|
194
197
|
else
|
195
|
-
raise Error, "Invalid @
|
198
|
+
raise Error, "Invalid @fetch attribute: #{v.inspect}"
|
196
199
|
end
|
197
200
|
when nil
|
198
201
|
# nothing
|
@@ -163,6 +163,12 @@ module Sequel
|
|
163
163
|
execute(sql, opts){|c| return c.insert_id}
|
164
164
|
end
|
165
165
|
|
166
|
+
def freeze
|
167
|
+
server_version
|
168
|
+
@conversion_procs.freeze
|
169
|
+
super
|
170
|
+
end
|
171
|
+
|
166
172
|
# Return the version of the MySQL server two which we are connecting.
|
167
173
|
def server_version(server=nil)
|
168
174
|
@server_version ||= (synchronize(server){|conn| conn.server_version if conn.respond_to?(:server_version)} || super)
|
@@ -47,7 +47,7 @@ module Sequel
|
|
47
47
|
conn.query_options.merge!(:symbolize_keys=>true, :cache_rows=>false)
|
48
48
|
|
49
49
|
if NativePreparedStatements
|
50
|
-
|
50
|
+
conn.instance_variable_set(:@sequel_default_query_options, conn.query_options.dup)
|
51
51
|
end
|
52
52
|
|
53
53
|
sqls = mysql_connection_setting_sqls
|
@@ -76,6 +76,11 @@ module Sequel
|
|
76
76
|
execute(sql, opts){|c| return c.last_id}
|
77
77
|
end
|
78
78
|
|
79
|
+
def freeze
|
80
|
+
server_version
|
81
|
+
super
|
82
|
+
end
|
83
|
+
|
79
84
|
# Return the version of the MySQL server to which we are connecting.
|
80
85
|
def server_version(server=nil)
|
81
86
|
@server_version ||= (synchronize(server){|conn| conn.server_info[:id]} || super)
|
@@ -158,7 +163,7 @@ module Sequel
|
|
158
163
|
raise_error(e)
|
159
164
|
ensure
|
160
165
|
if stmt
|
161
|
-
conn.query_options.replace(
|
166
|
+
conn.query_options.replace(conn.instance_variable_get(:@sequel_default_query_options))
|
162
167
|
stmt.close if close_stmt
|
163
168
|
end
|
164
169
|
end
|
@@ -26,11 +26,17 @@ module Sequel
|
|
26
26
|
# Return the database version as a string. Don't rely on this,
|
27
27
|
# it may return an integer in the future.
|
28
28
|
def db2_version
|
29
|
-
return @db2_version if @db2_version
|
29
|
+
return @db2_version if defined?(@db2_version)
|
30
30
|
@db2_version = metadata_dataset.with_sql("select service_level from sysibmadm.env_inst_info").first[:service_level]
|
31
31
|
end
|
32
32
|
alias_method :server_version, :db2_version
|
33
33
|
|
34
|
+
def freeze
|
35
|
+
db2_version
|
36
|
+
offset_strategy
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
34
40
|
# Use SYSIBM.SYSCOLUMNS to get the information on the tables.
|
35
41
|
def schema_parse_table(table, opts = OPTS)
|
36
42
|
m = output_identifier_meth(opts[:dataset])
|
@@ -89,6 +89,12 @@ module Sequel
|
|
89
89
|
h.values
|
90
90
|
end
|
91
91
|
|
92
|
+
def freeze
|
93
|
+
server_version
|
94
|
+
supports_timestamp_usecs?
|
95
|
+
super
|
96
|
+
end
|
97
|
+
|
92
98
|
# MySQL namespaces indexes per table.
|
93
99
|
def global_index_namespace?
|
94
100
|
false
|
@@ -155,7 +161,8 @@ module Sequel
|
|
155
161
|
# automatic initialization of datetime values wasn't supported to 5.6.5+,
|
156
162
|
# and this is related to that.
|
157
163
|
def supports_timestamp_usecs?
|
158
|
-
@supports_timestamp_usecs
|
164
|
+
return @supports_timestamp_usecs if defined?(@supports_timestamp_usecs)
|
165
|
+
@supports_timestamp_usecs = server_version >= 50605 && typecast_value_boolean(opts[:fractional_seconds])
|
159
166
|
end
|
160
167
|
|
161
168
|
# MySQL supports transaction isolation levels
|
@@ -74,6 +74,13 @@ module Sequel
|
|
74
74
|
fks.values
|
75
75
|
end
|
76
76
|
|
77
|
+
def freeze
|
78
|
+
current_user
|
79
|
+
server_version
|
80
|
+
@conversion_procs.freeze
|
81
|
+
super
|
82
|
+
end
|
83
|
+
|
77
84
|
# Oracle namespaces indexes per table.
|
78
85
|
def global_index_namespace?
|
79
86
|
false
|
@@ -237,7 +244,7 @@ module Sequel
|
|
237
244
|
end
|
238
245
|
|
239
246
|
def remove_cached_schema(table)
|
240
|
-
@primary_key_sequences.delete(table)
|
247
|
+
Sequel.synchronize{@primary_key_sequences.delete(table)}
|
241
248
|
super
|
242
249
|
end
|
243
250
|
|
@@ -253,19 +260,20 @@ module Sequel
|
|
253
260
|
|
254
261
|
def sequence_for_table(table)
|
255
262
|
return nil unless autosequence
|
256
|
-
@primary_key_sequences.
|
257
|
-
begin
|
258
|
-
sch = schema(table)
|
259
|
-
rescue Sequel::Error
|
260
|
-
return nil
|
261
|
-
end
|
263
|
+
Sequel.synchronize{return @primary_key_sequences[table] if @primary_key_sequences.has_key?(table)}
|
262
264
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
265
|
+
begin
|
266
|
+
sch = schema(table)
|
267
|
+
rescue Sequel::Error
|
268
|
+
return nil
|
269
|
+
end
|
270
|
+
|
271
|
+
pk = sch.select{|k, v| v[:primary_key]}
|
272
|
+
pks = if pk.length == 1
|
273
|
+
seq = "seq_#{table}_#{pk.first.first}"
|
274
|
+
seq.to_sym unless from(:user_sequences).where(:sequence_name=>input_identifier_meth.call(seq)).empty?
|
268
275
|
end
|
276
|
+
Sequel.synchronize{@primary_key_sequences[table] = pks}
|
269
277
|
end
|
270
278
|
|
271
279
|
# Oracle supports CREATE OR REPLACE VIEW.
|
@@ -373,6 +373,13 @@ module Sequel
|
|
373
373
|
h.values
|
374
374
|
end
|
375
375
|
|
376
|
+
def freeze
|
377
|
+
server_version
|
378
|
+
supports_prepared_transactions?
|
379
|
+
@conversion_procs.freeze
|
380
|
+
super
|
381
|
+
end
|
382
|
+
|
376
383
|
# Use the pg_* system tables to determine indexes on a table
|
377
384
|
def indexes(table, opts=OPTS)
|
378
385
|
m = output_identifier_meth
|
@@ -580,8 +587,9 @@ module Sequel
|
|
580
587
|
# Check whether the given type name string/symbol (e.g. :hstore) is supported by
|
581
588
|
# the database.
|
582
589
|
def type_supported?(type)
|
583
|
-
@supported_types
|
584
|
-
|
590
|
+
Sequel.synchronize{return @supported_types[type] if @supported_types.has_key?(type)}
|
591
|
+
supported = from(:pg_type).where(:typtype=>'b', :typname=>type.to_s).count > 0
|
592
|
+
Sequel.synchronize{return @supported_types[type] = supported}
|
585
593
|
end
|
586
594
|
|
587
595
|
# Creates a dataset that uses the VALUES clause:
|
@@ -1032,6 +1040,7 @@ module Sequel
|
|
1032
1040
|
def initialize_postgres_adapter
|
1033
1041
|
@primary_keys = {}
|
1034
1042
|
@primary_key_sequences = {}
|
1043
|
+
@supported_types = {}
|
1035
1044
|
@conversion_procs = PG_TYPES.dup
|
1036
1045
|
reset_conversion_procs
|
1037
1046
|
end
|
@@ -101,6 +101,12 @@ module Sequel
|
|
101
101
|
h.values
|
102
102
|
end
|
103
103
|
|
104
|
+
def freeze
|
105
|
+
sqlite_version
|
106
|
+
use_timestamp_timezones?
|
107
|
+
super
|
108
|
+
end
|
109
|
+
|
104
110
|
# Use the index_list and index_info PRAGMAs to determine the indexes on the table.
|
105
111
|
def indexes(table, opts=OPTS)
|
106
112
|
m = output_identifier_meth
|
@@ -359,6 +365,24 @@ module Sequel
|
|
359
365
|
DATABASE_ERROR_REGEXPS
|
360
366
|
end
|
361
367
|
|
368
|
+
# Recognize SQLite error codes if the exception provides access to them.
|
369
|
+
def database_specific_error_class(exception, opts)
|
370
|
+
case sqlite_error_code(exception)
|
371
|
+
when 1299
|
372
|
+
NotNullConstraintViolation
|
373
|
+
when 2067
|
374
|
+
UniqueConstraintViolation
|
375
|
+
when 787
|
376
|
+
ForeignKeyConstraintViolation
|
377
|
+
when 275
|
378
|
+
CheckConstraintViolation
|
379
|
+
when 19
|
380
|
+
ConstraintViolation
|
381
|
+
else
|
382
|
+
super
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
362
386
|
# The array of column schema hashes for the current columns in the table
|
363
387
|
def defined_columns_for(table)
|
364
388
|
cols = parse_pragma(table, {})
|
@@ -497,6 +521,11 @@ module Sequel
|
|
497
521
|
end
|
498
522
|
end
|
499
523
|
|
524
|
+
# Don't support SQLite error codes for exceptions by default.
|
525
|
+
def sqlite_error_code(exception)
|
526
|
+
nil
|
527
|
+
end
|
528
|
+
|
500
529
|
# Backbone of the tables and views support.
|
501
530
|
def tables_and_views(filter, opts)
|
502
531
|
m = output_identifier_meth
|
@@ -151,6 +151,11 @@ module Sequel
|
|
151
151
|
_execute(:insert, sql, opts)
|
152
152
|
end
|
153
153
|
|
154
|
+
def freeze
|
155
|
+
@conversion_procs.freeze
|
156
|
+
super
|
157
|
+
end
|
158
|
+
|
154
159
|
# Handle Integer and Float arguments, since SQLite can store timestamps as integers and floats.
|
155
160
|
def to_application_timestamp(s)
|
156
161
|
case s
|
@@ -269,6 +274,14 @@ module Sequel
|
|
269
274
|
def database_error_classes
|
270
275
|
[SQLite3::Exception, ArgumentError]
|
271
276
|
end
|
277
|
+
|
278
|
+
# Support SQLite exception codes if ruby-sqlite3 supports them.
|
279
|
+
# This is disabled by default because ruby-sqlite3 doesn't currently
|
280
|
+
# support them (returning nil), and even if it did, it doesn't support
|
281
|
+
# extended error codes, which would lead to worse behavior.
|
282
|
+
#def sqlite_error_code(exception)
|
283
|
+
# exception.code if exception.respond_to?(:code)
|
284
|
+
#end
|
272
285
|
end
|
273
286
|
|
274
287
|
# Dataset class for SQLite datasets that use the ruby-sqlite3 driver.
|
@@ -43,6 +43,11 @@ class Sequel::ShardedSingleConnectionPool < Sequel::ConnectionPool
|
|
43
43
|
def disconnect(opts=OPTS)
|
44
44
|
(opts[:server] ? Array(opts[:server]) : servers).each{|s| disconnect_server(s)}
|
45
45
|
end
|
46
|
+
|
47
|
+
def freeze
|
48
|
+
@servers.freeze
|
49
|
+
super
|
50
|
+
end
|
46
51
|
|
47
52
|
# Yields the connection to the supplied block for the given server.
|
48
53
|
# This method simulates the ConnectionPool#hold API.
|