sequel 3.33.0 → 3.34.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 +140 -0
- data/Rakefile +7 -0
- data/bin/sequel +22 -2
- data/doc/dataset_basics.rdoc +1 -1
- data/doc/mass_assignment.rdoc +3 -1
- data/doc/querying.rdoc +28 -4
- data/doc/reflection.rdoc +23 -3
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/schema_modification.rdoc +18 -2
- data/doc/virtual_rows.rdoc +49 -0
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/ibmdb.rb +9 -4
- data/lib/sequel/adapters/jdbc.rb +9 -4
- data/lib/sequel/adapters/jdbc/h2.rb +8 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +0 -5
- data/lib/sequel/adapters/jdbc/postgresql.rb +43 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +19 -0
- data/lib/sequel/adapters/mock.rb +24 -3
- data/lib/sequel/adapters/mysql.rb +29 -50
- data/lib/sequel/adapters/mysql2.rb +13 -28
- data/lib/sequel/adapters/oracle.rb +8 -2
- data/lib/sequel/adapters/postgres.rb +115 -20
- data/lib/sequel/adapters/shared/db2.rb +1 -1
- data/lib/sequel/adapters/shared/mssql.rb +14 -3
- data/lib/sequel/adapters/shared/mysql.rb +59 -11
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
- data/lib/sequel/adapters/shared/oracle.rb +1 -1
- data/lib/sequel/adapters/shared/postgres.rb +127 -30
- data/lib/sequel/adapters/shared/sqlite.rb +55 -38
- data/lib/sequel/adapters/sqlite.rb +9 -3
- data/lib/sequel/adapters/swift.rb +2 -2
- data/lib/sequel/adapters/swift/mysql.rb +0 -5
- data/lib/sequel/adapters/swift/postgres.rb +10 -0
- data/lib/sequel/ast_transformer.rb +4 -0
- data/lib/sequel/connection_pool.rb +8 -0
- data/lib/sequel/connection_pool/sharded_single.rb +5 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +17 -0
- data/lib/sequel/connection_pool/single.rb +5 -0
- data/lib/sequel/connection_pool/threaded.rb +14 -0
- data/lib/sequel/core.rb +24 -3
- data/lib/sequel/database/connecting.rb +24 -14
- data/lib/sequel/database/dataset_defaults.rb +1 -0
- data/lib/sequel/database/misc.rb +16 -25
- data/lib/sequel/database/query.rb +20 -2
- data/lib/sequel/database/schema_generator.rb +2 -2
- data/lib/sequel/database/schema_methods.rb +120 -23
- data/lib/sequel/dataset/actions.rb +91 -18
- data/lib/sequel/dataset/features.rb +5 -0
- data/lib/sequel/dataset/prepared_statements.rb +6 -2
- data/lib/sequel/dataset/sql.rb +68 -51
- data/lib/sequel/extensions/_pretty_table.rb +79 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +18 -13
- data/lib/sequel/extensions/migration.rb +4 -0
- data/lib/sequel/extensions/null_dataset.rb +90 -0
- data/lib/sequel/extensions/pg_array.rb +460 -0
- data/lib/sequel/extensions/pg_array_ops.rb +220 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +174 -0
- data/lib/sequel/extensions/pg_hstore.rb +296 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
- data/lib/sequel/extensions/pretty_table.rb +5 -71
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +227 -31
- data/lib/sequel/extensions/select_remove.rb +35 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -110
- data/lib/sequel/extensions/to_dot.rb +1 -1
- data/lib/sequel/model.rb +11 -2
- data/lib/sequel/model/associations.rb +35 -7
- data/lib/sequel/model/base.rb +159 -36
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/composition.rb +1 -1
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +11 -3
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +4 -3
- data/lib/sequel/plugins/prepared_statements.rb +3 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +5 -1
- data/lib/sequel/plugins/schema.rb +7 -2
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/sql.rb +417 -7
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/firebird_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +12 -15
- data/spec/adapters/mysql_spec.rb +81 -23
- data/spec/adapters/postgres_spec.rb +444 -77
- data/spec/adapters/spec_helper.rb +2 -0
- data/spec/adapters/sqlite_spec.rb +8 -8
- data/spec/core/connection_pool_spec.rb +85 -0
- data/spec/core/database_spec.rb +29 -5
- data/spec/core/dataset_spec.rb +171 -3
- data/spec/core/expression_filters_spec.rb +364 -0
- data/spec/core/mock_adapter_spec.rb +17 -3
- data/spec/core/schema_spec.rb +133 -0
- data/spec/extensions/association_dependencies_spec.rb +13 -13
- data/spec/extensions/caching_spec.rb +26 -3
- data/spec/extensions/class_table_inheritance_spec.rb +2 -2
- data/spec/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +23 -94
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +5 -2
- data/spec/extensions/identity_map_spec.rb +17 -0
- data/spec/extensions/instance_filters_spec.rb +1 -1
- data/spec/extensions/lazy_attributes_spec.rb +2 -2
- data/spec/extensions/list_spec.rb +4 -4
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +6 -2
- data/spec/extensions/nested_attributes_spec.rb +20 -0
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +2 -2
- data/spec/extensions/pg_array_ops_spec.rb +105 -0
- data/spec/extensions/pg_array_spec.rb +196 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +64 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
- data/spec/extensions/pg_hstore_spec.rb +195 -0
- data/spec/extensions/pg_statement_cache_spec.rb +209 -0
- data/spec/extensions/prepared_statements_spec.rb +4 -0
- data/spec/extensions/pretty_table_spec.rb +6 -0
- data/spec/extensions/query_literals_spec.rb +168 -0
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +231 -11
- data/spec/extensions/schema_spec.rb +14 -2
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/sharding_spec.rb +6 -6
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +2 -1
- data/spec/extensions/sql_expr_spec.rb +28 -19
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/touch_spec.rb +1 -1
- data/spec/extensions/typecast_on_load_spec.rb +9 -1
- data/spec/integration/associations_test.rb +6 -6
- data/spec/integration/database_test.rb +1 -1
- data/spec/integration/dataset_test.rb +89 -26
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +3 -3
- data/spec/integration/plugin_test.rb +85 -22
- data/spec/integration/prepared_statement_test.rb +28 -8
- data/spec/integration/schema_test.rb +78 -7
- data/spec/integration/spec_helper.rb +1 -0
- data/spec/integration/timezone_test.rb +1 -1
- data/spec/integration/transaction_test.rb +4 -6
- data/spec/integration/type_test.rb +2 -2
- data/spec/model/associations_spec.rb +94 -8
- data/spec/model/base_spec.rb +4 -4
- data/spec/model/hooks_spec.rb +2 -2
- data/spec/model/model_spec.rb +19 -7
- data/spec/model/record_spec.rb +135 -58
- data/spec/model/spec_helper.rb +1 -0
- metadata +35 -7
|
@@ -143,9 +143,10 @@ as it's third argument. A simple example is:
|
|
|
143
143
|
on most databases.
|
|
144
144
|
:on_delete :: Specify the behavior of this foreign key column when the row with the primary key
|
|
145
145
|
it references is deleted , can be :restrict, :cascade, :set_null, or :set_default.
|
|
146
|
+
You can also use a string, which is used literally.
|
|
146
147
|
:on_update :: Specify the behavior of this foreign key column when the row with the primary key
|
|
147
|
-
it references modifies the value of the primary key
|
|
148
|
-
:
|
|
148
|
+
it references modifies the value of the primary key. Takes the same options as
|
|
149
|
+
:on_delete.
|
|
149
150
|
|
|
150
151
|
Like +primary_key+, if you provide +foreign_key+ with an array of symbols, it will not create a
|
|
151
152
|
column, but create a foreign key constraint:
|
|
@@ -253,6 +254,21 @@ and it creates an unnamed constraint
|
|
|
253
254
|
check{char_length(name) > 2}
|
|
254
255
|
end
|
|
255
256
|
|
|
257
|
+
== +create_join_table+
|
|
258
|
+
|
|
259
|
+
+create_join_table+ is a shortcut that you can use to create simple many-to-many join tables:
|
|
260
|
+
|
|
261
|
+
create_join_table(:artist_id=>:artists, :album_id=>:albums)
|
|
262
|
+
|
|
263
|
+
which expands to:
|
|
264
|
+
|
|
265
|
+
create_table(:albums_artists) do
|
|
266
|
+
foreign_key :album_id, :albums, :null=>false
|
|
267
|
+
foreign_key :artist_id, :artists, :null=>false
|
|
268
|
+
primary_key [:album_id, :artist_id]
|
|
269
|
+
index [:artist_id, :album_id]
|
|
270
|
+
end
|
|
271
|
+
|
|
256
272
|
== +alter_table+
|
|
257
273
|
|
|
258
274
|
+alter_table+ is used to alter existing tables, changing their columns, indexes,
|
data/doc/virtual_rows.rdoc
CHANGED
|
@@ -205,6 +205,55 @@ call, with an optional hash as the second argument: Here are some examples of us
|
|
|
205
205
|
ds.select{sum(:over, :args=>col1, :partition=>col2, :order=>col3){}}
|
|
206
206
|
# SELECT sum(col1) OVER (PARTITION BY col2 ORDER BY col3)
|
|
207
207
|
|
|
208
|
+
== Operators
|
|
209
|
+
|
|
210
|
+
VirtualRows use method_missing to handle almost all method calls. However, they
|
|
211
|
+
have special handling of some operator methods to make certain things easier. The
|
|
212
|
+
operators all use a prefix form.
|
|
213
|
+
|
|
214
|
+
=== Math Operators
|
|
215
|
+
|
|
216
|
+
The standard +, -, *, and / mathematical operators are defined:
|
|
217
|
+
|
|
218
|
+
ds.select{|o| o.-(1, o.a).as(b)}
|
|
219
|
+
ds.select{self.-(1, a).as(b)}
|
|
220
|
+
# SELECT (1 - a) AS b
|
|
221
|
+
|
|
222
|
+
=== Boolean Operators
|
|
223
|
+
|
|
224
|
+
The & and | methods are defined to use AND and OR:
|
|
225
|
+
|
|
226
|
+
ds.where{|o| o.&({:a=>:b}, :c)}
|
|
227
|
+
ds.where{self.&({:a=>:b}, :c)}
|
|
228
|
+
# WHERE ((a = b) AND c)
|
|
229
|
+
|
|
230
|
+
The ~ method is defined to do inversion:
|
|
231
|
+
|
|
232
|
+
ds.where{|o| o.~({:a=>1, :b=>2})}
|
|
233
|
+
ds.where{self.~({:a=>1, :b=>2})}
|
|
234
|
+
# WHERE ((a != 1) OR (b != 2))
|
|
235
|
+
|
|
236
|
+
=== Inequality Operators
|
|
237
|
+
|
|
238
|
+
The standard >, <, >=, and <= inequality operators are defined:
|
|
239
|
+
|
|
240
|
+
ds.where{|o| o.>(1, :c)}
|
|
241
|
+
ds.where{self.>(1, :c)}
|
|
242
|
+
# WHERE (1 > c)
|
|
243
|
+
|
|
244
|
+
== Literal Strings
|
|
245
|
+
|
|
246
|
+
The backtick operator can be used inside an instance-evaled
|
|
247
|
+
virtual row block to create a literal string:
|
|
248
|
+
|
|
249
|
+
ds.where{a > `some SQL`}
|
|
250
|
+
# WHERE (a > some SQL)
|
|
251
|
+
|
|
252
|
+
You can use this on a regular virtual row block too, but it
|
|
253
|
+
doesn't look as nice:
|
|
254
|
+
|
|
255
|
+
ds.where{|o| o.>(:a, o.`('some SQL')}
|
|
256
|
+
|
|
208
257
|
== Returning multiple values
|
|
209
258
|
|
|
210
259
|
It's common when using select and order virtual row blocks to want to
|
|
@@ -174,7 +174,7 @@ module Sequel
|
|
|
174
174
|
# REORG the related table whenever it is altered. This is not always
|
|
175
175
|
# required, but it is necessary for compatibilty with other Sequel
|
|
176
176
|
# code in many cases.
|
|
177
|
-
def alter_table(name, generator=nil
|
|
177
|
+
def alter_table(name, generator=nil)
|
|
178
178
|
res = super
|
|
179
179
|
reorg(name)
|
|
180
180
|
res
|
|
@@ -231,11 +231,16 @@ module Sequel
|
|
|
231
231
|
sql = ps.prepared_sql
|
|
232
232
|
synchronize(opts[:server]) do |conn|
|
|
233
233
|
unless conn.prepared_statements.fetch(ps_name, []).first == sql
|
|
234
|
-
log_yield("
|
|
234
|
+
log_yield("PREPARE #{ps_name}: #{sql}"){conn.prepare(sql, ps_name)}
|
|
235
235
|
end
|
|
236
236
|
args = args.map{|v| v.nil? ? nil : prepared_statement_arg(v)}
|
|
237
|
-
|
|
238
|
-
|
|
237
|
+
log_sql = "EXECUTE #{ps_name}"
|
|
238
|
+
if ps.log_sql
|
|
239
|
+
log_sql << " ("
|
|
240
|
+
log_sql << sql
|
|
241
|
+
log_sql << ")"
|
|
242
|
+
end
|
|
243
|
+
stmt = log_yield(log_sql, args){conn.execute_prepared(ps_name, *args)}
|
|
239
244
|
if block_given?
|
|
240
245
|
begin
|
|
241
246
|
yield(stmt)
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
|
@@ -343,13 +343,18 @@ module Sequel
|
|
|
343
343
|
if name and cps = conn.prepared_statements[name] and cps[0] == sql
|
|
344
344
|
cps = cps[1]
|
|
345
345
|
else
|
|
346
|
-
log_yield("
|
|
347
|
-
cps = log_yield("
|
|
346
|
+
log_yield("CLOSE #{name}"){cps[1].close} if cps
|
|
347
|
+
cps = log_yield("PREPARE#{" #{name}:" if name} #{sql}"){conn.prepareStatement(sql)}
|
|
348
348
|
conn.prepared_statements[name] = [sql, cps] if name
|
|
349
349
|
end
|
|
350
350
|
i = 0
|
|
351
351
|
args.each{|arg| set_ps_arg(cps, arg, i+=1)}
|
|
352
|
-
msg = "
|
|
352
|
+
msg = "EXECUTE#{" #{name}" if name}"
|
|
353
|
+
if ps.log_sql
|
|
354
|
+
msg << " ("
|
|
355
|
+
msg << sql
|
|
356
|
+
msg << ")"
|
|
357
|
+
end
|
|
353
358
|
begin
|
|
354
359
|
if block_given?
|
|
355
360
|
yield log_yield(msg, args){cps.executeQuery}
|
|
@@ -623,7 +628,7 @@ module Sequel
|
|
|
623
628
|
# Handle type conversions for common Java types.
|
|
624
629
|
class TYPE_TRANSLATOR
|
|
625
630
|
LF = "\n".freeze
|
|
626
|
-
def time(v) Sequel.string_to_time(v.to_string) end
|
|
631
|
+
def time(v) Sequel.string_to_time(v.to_string) + v.getTime.divmod(1000).last/1000.0 end
|
|
627
632
|
def date(v) Date.civil(v.getYear + 1900, v.getMonth + 1, v.getDate) end
|
|
628
633
|
def decimal(v) BigDecimal.new(v.to_string) end
|
|
629
634
|
def byte_array(v) Sequel::SQL::Blob.new(String.from_java_bytes(v)) end
|
|
@@ -25,7 +25,7 @@ module Sequel
|
|
|
25
25
|
|
|
26
26
|
# H2 uses an IDENTITY type
|
|
27
27
|
def serial_primary_key_options
|
|
28
|
-
{:primary_key => true, :type => :identity}
|
|
28
|
+
{:primary_key => true, :type => :identity, :identity=>true}
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
# H2 supports CREATE TABLE IF NOT EXISTS syntax.
|
|
@@ -114,6 +114,12 @@ module Sequel
|
|
|
114
114
|
def schema_column_type(db_type)
|
|
115
115
|
db_type == 'clob' ? :string : super
|
|
116
116
|
end
|
|
117
|
+
|
|
118
|
+
# Use BIGINT IDENTITY for identity columns that use bigint, fixes
|
|
119
|
+
# the case where primary_key :column, :type=>Bignum is used.
|
|
120
|
+
def type_literal_generic_bignum(column)
|
|
121
|
+
column[:identity] ? 'BIGINT IDENTITY' : super
|
|
122
|
+
end
|
|
117
123
|
end
|
|
118
124
|
|
|
119
125
|
# Dataset class for H2 datasets accessed via JDBC.
|
|
@@ -124,7 +130,7 @@ module Sequel
|
|
|
124
130
|
HSTAR = "H*".freeze
|
|
125
131
|
BITCOMP_OPEN = "((0 - ".freeze
|
|
126
132
|
BITCOMP_CLOSE = ") - 1)".freeze
|
|
127
|
-
ILIKE_PLACEHOLDER = "CAST(
|
|
133
|
+
ILIKE_PLACEHOLDER = ["CAST(".freeze, " AS VARCHAR_IGNORECASE)".freeze].freeze
|
|
128
134
|
TIME_FORMAT = "'%H:%M:%S'".freeze
|
|
129
135
|
|
|
130
136
|
# Emulate the case insensitive LIKE operator and the bitwise operators.
|
|
@@ -66,11 +66,6 @@ module Sequel
|
|
|
66
66
|
# Dataset class for MySQL datasets accessed via JDBC.
|
|
67
67
|
class Dataset < JDBC::Dataset
|
|
68
68
|
include Sequel::MySQL::DatasetMethods
|
|
69
|
-
|
|
70
|
-
# Use execute_insert to execute the replace_sql.
|
|
71
|
-
def replace(*args)
|
|
72
|
-
execute_insert(replace_sql(*args))
|
|
73
|
-
end
|
|
74
69
|
end
|
|
75
70
|
end
|
|
76
71
|
end
|
|
@@ -75,6 +75,49 @@ module Sequel
|
|
|
75
75
|
include Sequel::Postgres::DatasetMethods
|
|
76
76
|
APOS = Dataset::APOS
|
|
77
77
|
|
|
78
|
+
class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
|
|
79
|
+
# Convert Java::OrgPostgresqlJdbc4::Jdbc4Array to ruby arrays
|
|
80
|
+
def pg_array(v)
|
|
81
|
+
_pg_array(v.array)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Convert Java::OrgPostgresqlUtil::PGobject to ruby strings
|
|
85
|
+
def pg_object(v)
|
|
86
|
+
v.to_string
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
private
|
|
90
|
+
|
|
91
|
+
# Handle multi-dimensional Java arrays by recursively mapping them
|
|
92
|
+
# to ruby arrays.
|
|
93
|
+
def _pg_array(v)
|
|
94
|
+
v.to_ary.map do |i|
|
|
95
|
+
if i.respond_to?(:to_ary)
|
|
96
|
+
_pg_array(i)
|
|
97
|
+
else
|
|
98
|
+
i
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
PG_ARRAY_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:pg_array)
|
|
105
|
+
PG_OBJECT_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:pg_object)
|
|
106
|
+
|
|
107
|
+
# Handle PostgreSQL array and object types. Object types are just
|
|
108
|
+
# turned into strings, similarly to how the native adapter treats
|
|
109
|
+
# the types.
|
|
110
|
+
def convert_type_proc(v)
|
|
111
|
+
case v
|
|
112
|
+
when Java::OrgPostgresqlJdbc4::Jdbc4Array
|
|
113
|
+
PG_ARRAY_METHOD
|
|
114
|
+
when Java::OrgPostgresqlUtil::PGobject
|
|
115
|
+
PG_OBJECT_METHOD
|
|
116
|
+
else
|
|
117
|
+
super
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
78
121
|
# Add the shared PostgreSQL prepared statement methods
|
|
79
122
|
def prepare(*args)
|
|
80
123
|
ps = super
|
|
@@ -8,7 +8,26 @@ module Sequel
|
|
|
8
8
|
module DatabaseMethods
|
|
9
9
|
include Sequel::SQLite::DatabaseMethods
|
|
10
10
|
LAST_INSERT_ROWID = 'SELECT last_insert_rowid()'.freeze
|
|
11
|
+
FOREIGN_KEY_ERROR_RE = /query does not return ResultSet/.freeze
|
|
11
12
|
|
|
13
|
+
# Swallow pointless exceptions when the foreign key list pragma
|
|
14
|
+
# doesn't return any rows.
|
|
15
|
+
def foreign_key_list(table, opts={})
|
|
16
|
+
super
|
|
17
|
+
rescue Sequel::DatabaseError => e
|
|
18
|
+
raise unless e.message =~ FOREIGN_KEY_ERROR_RE
|
|
19
|
+
[]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Swallow pointless exceptions when the index list pragma
|
|
23
|
+
# doesn't return any rows.
|
|
24
|
+
def indexes(table, opts={})
|
|
25
|
+
super
|
|
26
|
+
rescue Sequel::DatabaseError => e
|
|
27
|
+
raise unless e.message =~ FOREIGN_KEY_ERROR_RE
|
|
28
|
+
{}
|
|
29
|
+
end
|
|
30
|
+
|
|
12
31
|
private
|
|
13
32
|
|
|
14
33
|
# Use last_insert_rowid() to get the last inserted id.
|
data/lib/sequel/adapters/mock.rb
CHANGED
|
@@ -44,6 +44,21 @@ module Sequel
|
|
|
44
44
|
'sqlite'=>'SQLite'
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
# Procs to run for specific database types to get the mock adapter
|
|
48
|
+
# to work with the shared adapter
|
|
49
|
+
SHARED_ADAPTER_SETUP = {
|
|
50
|
+
'postgres' => lambda do |db|
|
|
51
|
+
db.instance_eval do
|
|
52
|
+
@server_version = 90103
|
|
53
|
+
@primary_keys = {}
|
|
54
|
+
@primary_key_sequences = {}
|
|
55
|
+
def primary_key(table)
|
|
56
|
+
:id
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
}
|
|
61
|
+
|
|
47
62
|
# Set the autogenerated primary key integer
|
|
48
63
|
# to be returned when running an insert query.
|
|
49
64
|
# Argument types supported:
|
|
@@ -98,6 +113,9 @@ module Sequel
|
|
|
98
113
|
# instance an raise it wrapped in a DatabaseError.
|
|
99
114
|
attr_writer :numrows
|
|
100
115
|
|
|
116
|
+
# Mock the server version, useful when using the shared adapters
|
|
117
|
+
attr_accessor :server_version
|
|
118
|
+
|
|
101
119
|
# Additional options supported:
|
|
102
120
|
#
|
|
103
121
|
# :autoid :: Call #autoid= with the value
|
|
@@ -114,6 +132,9 @@ module Sequel
|
|
|
114
132
|
require "sequel/adapters/shared/#{opts[:host]}"
|
|
115
133
|
extend Sequel.const_get(mod_name)::DatabaseMethods
|
|
116
134
|
extend_datasets Sequel.const_get(mod_name)::DatasetMethods
|
|
135
|
+
if pr = SHARED_ADAPTER_SETUP[opts[:host]]
|
|
136
|
+
pr.call(self)
|
|
137
|
+
end
|
|
117
138
|
end
|
|
118
139
|
self.autoid = opts[:autoid]
|
|
119
140
|
self.columns = opts[:columns]
|
|
@@ -186,12 +207,12 @@ module Sequel
|
|
|
186
207
|
begin
|
|
187
208
|
if block
|
|
188
209
|
columns(ds, sql) if ds
|
|
189
|
-
_fetch(sql, ds._fetch || @fetch, &block)
|
|
210
|
+
_fetch(sql, (ds._fetch if ds) || @fetch, &block)
|
|
190
211
|
elsif meth = opts[:meth]
|
|
191
212
|
if meth == :numrows
|
|
192
|
-
_numrows(sql, ds.numrows || @numrows)
|
|
213
|
+
_numrows(sql, (ds.numrows if ds) || @numrows)
|
|
193
214
|
else
|
|
194
|
-
v = ds.autoid
|
|
215
|
+
v = ds.autoid if ds
|
|
195
216
|
_autoid(sql, v || @autoid, (ds if v))
|
|
196
217
|
end
|
|
197
218
|
end
|
|
@@ -43,6 +43,10 @@ module Sequel
|
|
|
43
43
|
|
|
44
44
|
# Mysql::Error messages that indicate the current connection should be disconnected
|
|
45
45
|
MYSQL_DATABASE_DISCONNECT_ERRORS = /\A(Commands out of sync; you can't run this command now|Can't connect to local MySQL server through socket|MySQL server has gone away|Lost connection to MySQL server during query)/
|
|
46
|
+
|
|
47
|
+
# Regular expression used for getting accurate number of rows
|
|
48
|
+
# matched by an update statement.
|
|
49
|
+
AFFECTED_ROWS_RE = /Rows matched:\s+(\d+)\s+Changed:\s+\d+\s+Warnings:\s+\d+/.freeze
|
|
46
50
|
|
|
47
51
|
set_adapter_scheme :mysql
|
|
48
52
|
|
|
@@ -155,6 +159,16 @@ module Sequel
|
|
|
155
159
|
@convert_tinyint_to_bool = v
|
|
156
160
|
end
|
|
157
161
|
|
|
162
|
+
# Return the number of matched rows when executing a delete/update statement.
|
|
163
|
+
def execute_dui(sql, opts={})
|
|
164
|
+
execute(sql, opts){|c| return affected_rows(c)}
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Return the last inserted id when executing an insert statement.
|
|
168
|
+
def execute_insert(sql, opts={})
|
|
169
|
+
execute(sql, opts){|c| return c.insert_id}
|
|
170
|
+
end
|
|
171
|
+
|
|
158
172
|
# Return the version of the MySQL server two which we are connecting.
|
|
159
173
|
def server_version(server=nil)
|
|
160
174
|
@server_version ||= (synchronize(server){|conn| conn.server_version if conn.respond_to?(:server_version)} || super)
|
|
@@ -167,7 +181,7 @@ module Sequel
|
|
|
167
181
|
# yield the connection if a block is given.
|
|
168
182
|
def _execute(conn, sql, opts)
|
|
169
183
|
begin
|
|
170
|
-
r = log_yield(sql){conn.query(sql)}
|
|
184
|
+
r = log_yield((log_sql = opts[:log_sql]) ? sql + log_sql : sql){conn.query(sql)}
|
|
171
185
|
if opts[:type] == :select
|
|
172
186
|
yield r if r
|
|
173
187
|
elsif block_given?
|
|
@@ -209,6 +223,18 @@ module Sequel
|
|
|
209
223
|
end
|
|
210
224
|
end
|
|
211
225
|
|
|
226
|
+
# Try to get an accurate number of rows matched using the query
|
|
227
|
+
# info. Fall back to affected_rows if there was no match, but
|
|
228
|
+
# that may be inaccurate.
|
|
229
|
+
def affected_rows(conn)
|
|
230
|
+
s = conn.info
|
|
231
|
+
if s && s =~ AFFECTED_ROWS_RE
|
|
232
|
+
$1.to_i
|
|
233
|
+
else
|
|
234
|
+
conn.affected_rows
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
212
238
|
# MySQL connections use the query method to execute SQL without a result
|
|
213
239
|
def connection_execute_method
|
|
214
240
|
:query
|
|
@@ -269,19 +295,10 @@ module Sequel
|
|
|
269
295
|
|
|
270
296
|
Database::DatasetClass = self
|
|
271
297
|
|
|
272
|
-
# Regular expression used for getting accurate number of rows
|
|
273
|
-
# matched by an update statement.
|
|
274
|
-
AFFECTED_ROWS_RE = /Rows matched:\s+(\d+)\s+Changed:\s+\d+\s+Warnings:\s+\d+/.freeze
|
|
275
|
-
|
|
276
|
-
# Delete rows matching this dataset
|
|
277
|
-
def delete
|
|
278
|
-
execute_dui(delete_sql){|c| return c.affected_rows}
|
|
279
|
-
end
|
|
280
|
-
|
|
281
298
|
# Yield all rows matching this dataset. If the dataset is set to
|
|
282
299
|
# split multiple statements, yield arrays of hashes one per statement
|
|
283
300
|
# instead of yielding results for all statements as hashes.
|
|
284
|
-
def fetch_rows(sql
|
|
301
|
+
def fetch_rows(sql)
|
|
285
302
|
execute(sql) do |r|
|
|
286
303
|
i = -1
|
|
287
304
|
cps = db.conversion_procs
|
|
@@ -298,7 +315,7 @@ module Sequel
|
|
|
298
315
|
yield_rows(r, cols){|h| s << h}
|
|
299
316
|
yield s
|
|
300
317
|
else
|
|
301
|
-
yield_rows(r, cols
|
|
318
|
+
yield_rows(r, cols){|h| yield h}
|
|
302
319
|
end
|
|
303
320
|
end
|
|
304
321
|
self
|
|
@@ -310,22 +327,6 @@ module Sequel
|
|
|
310
327
|
super
|
|
311
328
|
end
|
|
312
329
|
|
|
313
|
-
# Insert a new value into this dataset
|
|
314
|
-
def insert(*values)
|
|
315
|
-
execute_dui(insert_sql(*values)){|c| return c.insert_id}
|
|
316
|
-
end
|
|
317
|
-
|
|
318
|
-
# You can parse out the correct number of rows matched using the query info,
|
|
319
|
-
# even though affected_rows doesn't provide an accurate number.
|
|
320
|
-
def provides_accurate_rows_matched?
|
|
321
|
-
true
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
# Replace (update or insert) the matching row.
|
|
325
|
-
def replace(*args)
|
|
326
|
-
execute_dui(replace_sql(*args)){|c| return c.insert_id}
|
|
327
|
-
end
|
|
328
|
-
|
|
329
330
|
# Makes each yield arrays of rows, with each array containing the rows
|
|
330
331
|
# for a given result set. Does not work with graphing. So you can submit
|
|
331
332
|
# SQL with multiple statements and easily determine which statement
|
|
@@ -342,35 +343,13 @@ module Sequel
|
|
|
342
343
|
ds
|
|
343
344
|
end
|
|
344
345
|
|
|
345
|
-
# Update the matching rows.
|
|
346
|
-
def update(values={})
|
|
347
|
-
execute_dui(update_sql(values)){|c| return affected_rows(c)}
|
|
348
|
-
end
|
|
349
|
-
|
|
350
346
|
private
|
|
351
347
|
|
|
352
|
-
# Try to get an accurate number of rows matched using the query
|
|
353
|
-
# info. Fall back to affected_rows if there was no match, but
|
|
354
|
-
# that may be inaccurate.
|
|
355
|
-
def affected_rows(conn)
|
|
356
|
-
s = conn.info
|
|
357
|
-
if s && s =~ AFFECTED_ROWS_RE
|
|
358
|
-
$1.to_i
|
|
359
|
-
else
|
|
360
|
-
conn.affected_rows
|
|
361
|
-
end
|
|
362
|
-
end
|
|
363
|
-
|
|
364
348
|
# Set the :type option to :select if it hasn't been set.
|
|
365
349
|
def execute(sql, opts={}, &block)
|
|
366
350
|
super(sql, {:type=>:select}.merge(opts), &block)
|
|
367
351
|
end
|
|
368
352
|
|
|
369
|
-
# Set the :type option to :dui if it hasn't been set.
|
|
370
|
-
def execute_dui(sql, opts={}, &block)
|
|
371
|
-
super(sql, {:type=>:dui}.merge(opts), &block)
|
|
372
|
-
end
|
|
373
|
-
|
|
374
353
|
# Handle correct quoting of strings using ::MySQL.quote.
|
|
375
354
|
def literal_string_append(sql, v)
|
|
376
355
|
sql << "'"
|