sequel 5.18.0 → 5.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +40 -0
- data/doc/opening_databases.rdoc +5 -2
- data/doc/release_notes/5.19.0.txt +28 -0
- data/doc/release_notes/5.20.0.txt +89 -0
- data/doc/sharding.rdoc +12 -0
- data/doc/transactions.rdoc +38 -0
- data/lib/sequel/adapters/jdbc.rb +7 -2
- data/lib/sequel/adapters/mysql2.rb +2 -2
- data/lib/sequel/adapters/shared/postgres.rb +8 -8
- data/lib/sequel/adapters/shared/sqlite.rb +3 -1
- data/lib/sequel/adapters/sqlanywhere.rb +33 -17
- data/lib/sequel/adapters/sqlite.rb +20 -13
- data/lib/sequel/connection_pool.rb +0 -5
- data/lib/sequel/database/misc.rb +10 -9
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +1 -1
- data/lib/sequel/database/transactions.rb +57 -5
- data/lib/sequel/dataset/actions.rb +6 -5
- data/lib/sequel/dataset/graph.rb +2 -2
- data/lib/sequel/dataset/placeholder_literalizer.rb +4 -1
- data/lib/sequel/dataset/prepared_statements.rb +1 -1
- data/lib/sequel/dataset/query.rb +1 -1
- data/lib/sequel/extensions/constraint_validations.rb +14 -0
- data/lib/sequel/extensions/pg_enum.rb +23 -15
- data/lib/sequel/extensions/schema_dumper.rb +1 -1
- data/lib/sequel/model/associations.rb +38 -12
- data/lib/sequel/model/base.rb +1 -1
- data/lib/sequel/model/plugins.rb +104 -0
- data/lib/sequel/plugins/association_dependencies.rb +3 -3
- data/lib/sequel/plugins/association_pks.rb +14 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +1 -0
- data/lib/sequel/plugins/composition.rb +13 -9
- data/lib/sequel/plugins/finder.rb +2 -2
- data/lib/sequel/plugins/hook_class_methods.rb +17 -5
- data/lib/sequel/plugins/inverted_subsets.rb +2 -2
- data/lib/sequel/plugins/json_serializer.rb +3 -3
- data/lib/sequel/plugins/nested_attributes.rb +1 -1
- data/lib/sequel/plugins/pg_array_associations.rb +8 -4
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +61 -32
- data/lib/sequel/plugins/prepared_statements.rb +1 -1
- data/lib/sequel/plugins/prepared_statements_safe.rb +1 -1
- data/lib/sequel/plugins/subset_conditions.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +5 -3
- data/lib/sequel/plugins/validation_helpers.rb +2 -2
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +40 -0
- data/spec/core/database_spec.rb +73 -2
- data/spec/core/schema_spec.rb +7 -1
- data/spec/extensions/class_table_inheritance_spec.rb +30 -8
- data/spec/extensions/constraint_validations_spec.rb +20 -2
- data/spec/extensions/core_refinements_spec.rb +1 -1
- data/spec/extensions/hook_class_methods_spec.rb +22 -0
- data/spec/extensions/migration_spec.rb +13 -0
- data/spec/extensions/pg_auto_constraint_validations_spec.rb +8 -0
- data/spec/extensions/pg_enum_spec.rb +5 -0
- data/spec/extensions/s_spec.rb +1 -1
- data/spec/extensions/schema_dumper_spec.rb +4 -2
- data/spec/integration/plugin_test.rb +15 -0
- data/spec/integration/transaction_test.rb +50 -0
- data/spec/model/associations_spec.rb +84 -4
- data/spec/model/plugins_spec.rb +111 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e092b5439a78eec1bb50a0bbc8a62c1d84ee5b27b9c5f034c250b632d03e17af
|
4
|
+
data.tar.gz: 231708d52405407b11113c55d5fdcd95e7d6155b0a8283f736876569ced6e4b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c2d7e19056e53f2d780f57f5da3c4675531f9678c6a54e922e0d59895bd2e485f12ee0b2644ed801c832a53653f75531d849cb7d60dcd9fb6a4edbfa8cb4c0b
|
7
|
+
data.tar.gz: 701b041185cc57c1966ea3b4be040e26a9e0aabfd6df45f0192f5b0b51133bfb94629f0634fa6edfc513a1c9193d455cb6222b388683d638e474b344e663ca50
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,43 @@
|
|
1
|
+
=== 5.20.0 (2019-05-01)
|
2
|
+
|
3
|
+
* Fix reversing of alter_table add_foreign_key when :type option is used (jeremyevans) (#1615)
|
4
|
+
|
5
|
+
* Switch from using instance_exec to define_method for model associations and in some plugins (jeremyevans)
|
6
|
+
|
7
|
+
* Fix Database#server_version when using mysql2 adapter with mysql driver on MariaDB 10+ database (v-kolesnikov) (#1614)
|
8
|
+
|
9
|
+
* Make one_to_one setter method handle models that use joined datasets (jeremyevans) (#1612)
|
10
|
+
|
11
|
+
* Make auto_validations plugin work with the class_table_inheritance plugin (jeremyevans) (#1611)
|
12
|
+
|
13
|
+
* Avoid use of instance_exec for PlaceholderLiteralString#with_dataset (jeremyevans)
|
14
|
+
|
15
|
+
* Recognize float unsigned database types as float (keeguon, jeremyevans) (#1609)
|
16
|
+
|
17
|
+
* Support :savepoint options to Database#{after_commit,after_rollback} for making the hooks handle savepoints (jeremyevans)
|
18
|
+
|
19
|
+
* Avoid use of instance_exec in association_dependencies plugin (jeremyevans)
|
20
|
+
|
21
|
+
* Add pg_auto_constraint_validation_override to the pg_auto_constraint_validations plugin, for customizing columns and error message per constraint (jeremyevans)
|
22
|
+
|
23
|
+
* Make Database#check_constraints on PostgreSQL also include constraints where the related columns are not known (jeremyevans)
|
24
|
+
|
25
|
+
=== 5.19.0 (2019-04-02)
|
26
|
+
|
27
|
+
* Use more optimized approach to merging hashes in ruby 2.5+ (jeremyevans)
|
28
|
+
|
29
|
+
* Use SQLite extended result codes when using ruby-sqlite3 1.4.0+ (jeremyevans)
|
30
|
+
|
31
|
+
* Recognize additional SQLite extended result codes in the shared sqlite adapter (jeremyevans)
|
32
|
+
|
33
|
+
* Add Database#rename_enum_value to the pg_enum extension (AlexWayfer) (#1603)
|
34
|
+
|
35
|
+
* Make Database#drop_table delete constraint validations metadata for that table if using the constraint_validations extension (jeremyevans)
|
36
|
+
|
37
|
+
* Speed up row fetching in the sqlite adapter (jeremyevans)
|
38
|
+
|
39
|
+
* Speed up row fetching and type conversion in the sqlanywhere adapter (jeremyevans)
|
40
|
+
|
1
41
|
=== 5.18.0 (2019-03-01)
|
2
42
|
|
3
43
|
* Use singleton .call methods on plain objects instead of procs/methods for faster type conversion (jeremyevans)
|
data/doc/opening_databases.rdoc
CHANGED
@@ -187,9 +187,8 @@ For Derby, H2, HSQLDB, JTDS, MySQL, Postgres, SQLite3
|
|
187
187
|
the adapters can use the `jdbc-*` gem, for the others you need to have the `.jar` in your CLASSPATH
|
188
188
|
or load the Java class manually before calling Sequel.connect.
|
189
189
|
|
190
|
-
|
191
190
|
Note that when using a JDBC adapter, the best way to use Sequel
|
192
|
-
is via Sequel.connect, NOT Sequel.jdbc. Use the JDBC connection
|
191
|
+
is via Sequel.connect using a connection string, NOT Sequel.jdbc. Use the JDBC connection
|
193
192
|
string when connecting, which will be in a different format than
|
194
193
|
the native connection string. The connection string should start
|
195
194
|
with 'jdbc:'. For PostgreSQL, use 'jdbc:postgresql:', and for
|
@@ -201,6 +200,10 @@ Sequel does no preprocessing of JDBC connection strings, it passes them directly
|
|
201
200
|
So if you have problems getting a connection string to work, look up the
|
202
201
|
documentation for the JDBC driver.
|
203
202
|
|
203
|
+
The jdbc adapter does not handle common options such as +:host+,
|
204
|
+
+:user+, and +:port+. If you must use a hash of options when connecting,
|
205
|
+
provide the full JDBC connection string as the :uri option.
|
206
|
+
|
204
207
|
Example connection strings:
|
205
208
|
|
206
209
|
jdbc:sqlite::memory:
|
@@ -0,0 +1,28 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A Database#rename_enum_value method has been added to the pg_enum
|
4
|
+
extension. It is supported on PostgreSQL 10+:
|
5
|
+
|
6
|
+
DB.rename_enum_value(:enum_type, 'old_name', 'new_name')
|
7
|
+
|
8
|
+
= Other Improvements
|
9
|
+
|
10
|
+
* The performance of row fetching and type conversion in the
|
11
|
+
sqlanywhere adapter has been improved.
|
12
|
+
|
13
|
+
* The performance of row fetching in the sqlite adapter has been
|
14
|
+
improved.
|
15
|
+
|
16
|
+
* Calling Database#drop_table now drops any constraint validations
|
17
|
+
metadata for the table if using the constraint_validations
|
18
|
+
extension. However, modifying the table using Database#alter_table
|
19
|
+
does not affect the constraint validations metadata.
|
20
|
+
|
21
|
+
* The sqlite adapter when used with ruby-sqlite3 1.4.0+ now uses
|
22
|
+
SQLite extended result codes for a more accurate determination of
|
23
|
+
specific database errors types.
|
24
|
+
|
25
|
+
* Performance for typecasting to decimal and floats has been improved
|
26
|
+
slightly.
|
27
|
+
|
28
|
+
* Performance when merging hashes has been improved slightly.
|
@@ -0,0 +1,89 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* Database#after_commit and #after_rollback transaction hook methods
|
4
|
+
now support a :savepoint option. Using the :savepoint option makes
|
5
|
+
the hooks savepoint-aware, so after_commit will only be called if
|
6
|
+
all enclosing savepoints and the transaction are committed, and
|
7
|
+
after_rollback will be called when any of the enclosing savepoints
|
8
|
+
are rolled back (which may be before transaction commit/rollback).
|
9
|
+
Examples:
|
10
|
+
|
11
|
+
x = nil
|
12
|
+
DB.transaction do # BEGIN
|
13
|
+
DB.transaction(savepoint: true) do # SAVEPOINT
|
14
|
+
DB.after_commit(savepoint: true){x = 1}
|
15
|
+
DB.after_rollback(savepoint: true){x = 2}
|
16
|
+
x # nil
|
17
|
+
end # RELEASE SAVEPOINT
|
18
|
+
x # nil
|
19
|
+
end # COMMIT
|
20
|
+
x # 1
|
21
|
+
|
22
|
+
x = nil
|
23
|
+
DB.transaction do # BEGIN
|
24
|
+
DB.transaction(savepoint: true) do # SAVEPOINT
|
25
|
+
DB.after_commit(savepoint: true){x = 1}
|
26
|
+
DB.after_rollback(savepoint: true){x = 2}
|
27
|
+
x # nil
|
28
|
+
raise Sequel::Rollback
|
29
|
+
end # ROLLBACK TO SAVEPOINT
|
30
|
+
x # 2
|
31
|
+
end # COMMIT
|
32
|
+
x # 2
|
33
|
+
|
34
|
+
x = nil
|
35
|
+
DB.transaction do # BEGIN
|
36
|
+
DB.transaction(savepoint: true) do # SAVEPOINT
|
37
|
+
DB.after_commit(savepoint: true){x = 1}
|
38
|
+
DB.after_rollback(savepoint: true){x = 2}
|
39
|
+
end # RELEASE SAVEPOINT
|
40
|
+
x # nil
|
41
|
+
raise Sequel::Rollback
|
42
|
+
end
|
43
|
+
x # 2
|
44
|
+
|
45
|
+
* The pg_auto_constraint_validations plugin now supports a
|
46
|
+
pg_auto_constraint_validation_override method for overriding
|
47
|
+
the columns and message for a specific constraint. This is
|
48
|
+
useful if the database cannot determine the columns (due
|
49
|
+
to the constraint containing a database function call), or
|
50
|
+
if you would like to customize the message per constraint.
|
51
|
+
|
52
|
+
= Other Improvements
|
53
|
+
|
54
|
+
* The one_to_one association setter now works with models that use
|
55
|
+
joined datasets, such as child models when using the
|
56
|
+
class_table_inheritance plugin.
|
57
|
+
|
58
|
+
* Database#check_constraints on PostgreSQL now also includes CHECK
|
59
|
+
constraints where the related columns are not known. The :columns
|
60
|
+
entry in the hash will be an empty array in such cases. The
|
61
|
+
exclusion of such constraints in previous versions was not
|
62
|
+
intentional, and the documentation implied that all CHECK
|
63
|
+
constraints were returned.
|
64
|
+
|
65
|
+
* Many cases where instance_exec was previously used on model
|
66
|
+
instances have been changed so that instance methods are defined
|
67
|
+
and called instead. This avoids the creation of singleton classes
|
68
|
+
for model instances, and can significantly improve performance in
|
69
|
+
some cases. This affects all associations as well as the
|
70
|
+
following plugins:
|
71
|
+
|
72
|
+
* composition
|
73
|
+
* hook_class_methods
|
74
|
+
* validation_class_methods
|
75
|
+
|
76
|
+
Other cases where instance_exec is now avoided and a different
|
77
|
+
approach is used:
|
78
|
+
|
79
|
+
* association_dependencies plugin
|
80
|
+
* PlaceholderLiteralString#with_dataset
|
81
|
+
|
82
|
+
* The auto_validations plugin now works with child models when using
|
83
|
+
the class_table_inheritance plugin.
|
84
|
+
|
85
|
+
* Database#server_version now works correctly in the mysql2 adapter
|
86
|
+
when using the MySQL driver with MariaDB 10+.
|
87
|
+
|
88
|
+
* The float unsigned type is now recognized and supported in the
|
89
|
+
schema parser and schema_dumper extension.
|
data/doc/sharding.rdoc
CHANGED
@@ -268,3 +268,15 @@ the Database, just remove that option. If you are setting:
|
|
268
268
|
Sequel.single_threaded = true
|
269
269
|
|
270
270
|
just remove or comment out that code.
|
271
|
+
|
272
|
+
== JDBC
|
273
|
+
|
274
|
+
If you are using the jdbc adapter, note that it does not handle separate
|
275
|
+
options such as +:host+, +:user+, and +:port+. If you would like to use
|
276
|
+
the +:servers+ option when connecting to a JDBC database, each hash value in
|
277
|
+
the +servers+ option should contain a +:uri+ key with a JDBC connection string
|
278
|
+
for that shard as the value. Example:
|
279
|
+
|
280
|
+
DB=Sequel.connect('jdbc:postgresql://primary_server/database',
|
281
|
+
servers: {read_only: {uri: 'jdbc:postgresql://replica_server/database'}})
|
282
|
+
|
data/doc/transactions.rdoc
CHANGED
@@ -169,6 +169,44 @@ If you want the current savepoint and potentially enclosing savepoints to be rol
|
|
169
169
|
end # ROLLBACK TO SAVEPOINT
|
170
170
|
end # ROLLBACK
|
171
171
|
|
172
|
+
=== Savepoint Hooks
|
173
|
+
|
174
|
+
When using savepoints, you can use the +:savepoint+ option to +after_commit+ or +after_rollback+ to use a savepoint hook. For +after_commit+, this will only run the hook after transaction commit if all enclosing savepoints are released (not rolled back). For +after_rollback+, this will run the hook after any enclosing savepoint is rolled back (before transaction commit), or after the transaction is rolled back if all enclosing savepoints are released:
|
175
|
+
|
176
|
+
x = nil
|
177
|
+
DB.transaction do # BEGIN
|
178
|
+
DB.transaction(savepoint: true) do # SAVEPOINT
|
179
|
+
DB.after_commit(savepoint: true){x = 1}
|
180
|
+
DB.after_rollback(savepoint: true){x = 2}
|
181
|
+
x # nil
|
182
|
+
end # RELEASE SAVEPOINT
|
183
|
+
x # nil
|
184
|
+
end # COMMIT
|
185
|
+
x # 1
|
186
|
+
|
187
|
+
x = nil
|
188
|
+
DB.transaction do # BEGIN
|
189
|
+
DB.transaction(savepoint: true) do # SAVEPOINT
|
190
|
+
DB.after_commit(savepoint: true){x = 1}
|
191
|
+
DB.after_rollback(savepoint: true){x = 2}
|
192
|
+
x # nil
|
193
|
+
raise Sequel::Rollback
|
194
|
+
end # ROLLBACK TO SAVEPOINT
|
195
|
+
x # 2
|
196
|
+
end # COMMIT
|
197
|
+
x # 2
|
198
|
+
|
199
|
+
x = nil
|
200
|
+
DB.transaction do # BEGIN
|
201
|
+
DB.transaction(savepoint: true) do # SAVEPOINT
|
202
|
+
DB.after_commit(savepoint: true){x = 1}
|
203
|
+
DB.after_rollback(savepoint: true){x = 2}
|
204
|
+
end # RELEASE SAVEPOINT
|
205
|
+
x # nil
|
206
|
+
raise Sequel::Rollback
|
207
|
+
end
|
208
|
+
x # 2
|
209
|
+
|
172
210
|
== Prepared Transactions / Two-Phase Commit
|
173
211
|
|
174
212
|
Sequel supports database prepared transactions on PostgreSQL, MySQL, and H2. With prepared transactions, at the end of the transaction, the transaction is not immediately committed (it acts like a rollback). Later, you can call +commit_prepared_transaction+ to commit the transaction or +rollback_prepared_transaction+ to roll the transaction back. Prepared transactions are usually used with distributed databases to make sure all databases commit the same transaction or none of them do.
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -254,7 +254,9 @@ module Sequel
|
|
254
254
|
log_connection_yield(sql, conn){stmt.execute(sql)}
|
255
255
|
when :insert
|
256
256
|
log_connection_yield(sql, conn){execute_statement_insert(stmt, sql)}
|
257
|
-
|
257
|
+
opts = Hash[opts]
|
258
|
+
opts[:stmt] = stmt
|
259
|
+
last_insert_id(conn, opts)
|
258
260
|
else
|
259
261
|
log_connection_yield(sql, conn){stmt.executeUpdate(sql)}
|
260
262
|
end
|
@@ -449,7 +451,10 @@ module Sequel
|
|
449
451
|
log_connection_yield(msg, conn, args){cps.execute}
|
450
452
|
when :insert
|
451
453
|
log_connection_yield(msg, conn, args){execute_prepared_statement_insert(cps)}
|
452
|
-
|
454
|
+
opts = Hash[opts]
|
455
|
+
opts[:prepared] = true
|
456
|
+
opts[:stmt] = cps
|
457
|
+
last_insert_id(conn, opts)
|
453
458
|
else
|
454
459
|
log_connection_yield(msg, conn, args){cps.executeUpdate}
|
455
460
|
end
|
@@ -78,8 +78,8 @@ module Sequel
|
|
78
78
|
end
|
79
79
|
|
80
80
|
# Return the version of the MySQL server to which we are connecting.
|
81
|
-
def server_version(
|
82
|
-
@server_version ||= (
|
81
|
+
def server_version(_server=nil)
|
82
|
+
@server_version ||= super()
|
83
83
|
end
|
84
84
|
|
85
85
|
private
|
@@ -220,24 +220,22 @@ module Sequel
|
|
220
220
|
# A hash of metadata for CHECK constraints on the table.
|
221
221
|
# Keys are CHECK constraint name symbols. Values are hashes with the following keys:
|
222
222
|
# :definition :: An SQL fragment for the definition of the constraint
|
223
|
-
# :columns :: An array of column symbols for the columns referenced in the constraint
|
223
|
+
# :columns :: An array of column symbols for the columns referenced in the constraint,
|
224
|
+
# can be an empty array if the database cannot deteremine the column symbols.
|
224
225
|
def check_constraints(table)
|
225
226
|
m = output_identifier_meth
|
226
227
|
|
227
228
|
rows = metadata_dataset.
|
228
229
|
from{pg_constraint.as(:co)}.
|
229
|
-
|
230
|
+
left_join(Sequel[:pg_attribute].as(:att), :attrelid=>:conrelid, :attnum=>SQL::Function.new(:ANY, Sequel[:co][:conkey])).
|
230
231
|
where(:conrelid=>regclass_oid(table), :contype=>'c').
|
231
232
|
select{[co[:conname].as(:constraint), att[:attname].as(:column), pg_get_constraintdef(co[:oid]).as(:definition)]}
|
232
233
|
|
233
234
|
hash = {}
|
234
235
|
rows.each do |row|
|
235
236
|
constraint = m.call(row[:constraint])
|
236
|
-
|
237
|
-
|
238
|
-
else
|
239
|
-
hash[constraint] = {:definition=>row[:definition], :columns=>[m.call(row[:column])]}
|
240
|
-
end
|
237
|
+
entry = hash[constraint] ||= {:definition=>row[:definition], :columns=>[]}
|
238
|
+
entry[:columns] << m.call(row[:column]) if row[:column]
|
241
239
|
end
|
242
240
|
|
243
241
|
hash
|
@@ -1733,7 +1731,9 @@ module Sequel
|
|
1733
1731
|
def _import(columns, values, opts=OPTS)
|
1734
1732
|
if @opts[:returning]
|
1735
1733
|
statements = multi_insert_sql(columns, values)
|
1736
|
-
|
1734
|
+
trans_opts = Hash[opts]
|
1735
|
+
trans_opts[:server] = @opts[:server]
|
1736
|
+
@db.transaction(trans_opts) do
|
1737
1737
|
statements.map{|st| returning_fetch_rows(st)}
|
1738
1738
|
end.first.map{|v| v.length == 1 ? v.values.first : v}
|
1739
1739
|
elsif opts[:return] == :primary_key
|
@@ -323,7 +323,7 @@ module Sequel
|
|
323
323
|
case sqlite_error_code(exception)
|
324
324
|
when 1299
|
325
325
|
NotNullConstraintViolation
|
326
|
-
when 2067
|
326
|
+
when 1555, 2067, 2579
|
327
327
|
UniqueConstraintViolation
|
328
328
|
when 787
|
329
329
|
ForeignKeyConstraintViolation
|
@@ -331,6 +331,8 @@ module Sequel
|
|
331
331
|
CheckConstraintViolation
|
332
332
|
when 19
|
333
333
|
ConstraintViolation
|
334
|
+
when 517
|
335
|
+
SerializationFailure
|
334
336
|
else
|
335
337
|
super
|
336
338
|
end
|
@@ -17,21 +17,34 @@ module Sequel
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
20
|
+
boolean = Object.new
|
21
|
+
def boolean.call(s)
|
22
|
+
s.to_i != 0
|
23
|
+
end
|
24
|
+
|
25
|
+
date = Object.new
|
26
|
+
def date.call(s)
|
27
|
+
::Date.strptime(s)
|
28
|
+
end
|
29
|
+
|
30
|
+
decimal = Object.new
|
31
|
+
class << decimal
|
32
|
+
alias call BigDecimal
|
33
|
+
public :call
|
34
|
+
end
|
35
|
+
|
36
|
+
time = Object.new
|
37
|
+
def time.call(s)
|
38
|
+
::Sequel.string_to_time(s)
|
39
|
+
end
|
27
40
|
|
28
41
|
SQLANYWHERE_TYPES = {}
|
29
42
|
{
|
30
|
-
[0, 484] =>
|
31
|
-
[384] =>
|
32
|
-
[388] =>
|
33
|
-
[500] =>
|
34
|
-
[524, 528] =>
|
43
|
+
[0, 484] => decimal,
|
44
|
+
[384] => date,
|
45
|
+
[388] => time,
|
46
|
+
[500] => boolean,
|
47
|
+
[524, 528] => ::Sequel::SQL::Blob
|
35
48
|
}.each do |k,v|
|
36
49
|
k.each{|n| SQLANYWHERE_TYPES[n] = v}
|
37
50
|
end
|
@@ -153,17 +166,20 @@ module Sequel
|
|
153
166
|
else
|
154
167
|
cps[type]
|
155
168
|
end
|
156
|
-
col_infos << [
|
169
|
+
col_infos << [output_identifier(name), cp]
|
157
170
|
end
|
158
171
|
|
159
|
-
self.columns = col_infos.map
|
172
|
+
self.columns = col_infos.map(&:first)
|
173
|
+
max = col_infos.length
|
160
174
|
|
161
175
|
if rs
|
162
176
|
while api.sqlany_fetch_next(rs) == 1
|
177
|
+
i = -1
|
163
178
|
h = {}
|
164
|
-
|
165
|
-
|
166
|
-
|
179
|
+
while (i+=1) < max
|
180
|
+
name, cp = col_infos[i]
|
181
|
+
v = api.sqlany_get_column(rs, i)[1]
|
182
|
+
h[name] = cp && v ? cp.call(v) : v
|
167
183
|
end
|
168
184
|
yield h
|
169
185
|
end
|
@@ -5,7 +5,7 @@ require_relative 'shared/sqlite'
|
|
5
5
|
|
6
6
|
module Sequel
|
7
7
|
module SQLite
|
8
|
-
FALSE_VALUES = (%w'0 false f no n' + [0]).freeze
|
8
|
+
FALSE_VALUES = (%w'0 false f no n'.each(&:freeze) + [0]).freeze
|
9
9
|
|
10
10
|
blob = Object.new
|
11
11
|
def blob.call(s)
|
@@ -77,6 +77,10 @@ module Sequel
|
|
77
77
|
k.each{|n| SQLITE_TYPES[n] = v}
|
78
78
|
end
|
79
79
|
SQLITE_TYPES.freeze
|
80
|
+
|
81
|
+
sqlite_version = SQLite3::VERSION.split('.').map(&:to_i)[0..1]
|
82
|
+
sqlite_version = sqlite_version[0] * 100 + sqlite_version[1]
|
83
|
+
USE_EXTENDED_RESULT_CODES = sqlite_version >= 104
|
80
84
|
|
81
85
|
class Database < Sequel::Database
|
82
86
|
include ::Sequel::SQLite::DatabaseMethods
|
@@ -109,6 +113,10 @@ module Sequel
|
|
109
113
|
sqlite3_opts[:readonly] = typecast_value_boolean(opts[:readonly]) if opts.has_key?(:readonly)
|
110
114
|
db = ::SQLite3::Database.new(opts[:database].to_s, sqlite3_opts)
|
111
115
|
db.busy_timeout(opts.fetch(:timeout, 5000))
|
116
|
+
|
117
|
+
if USE_EXTENDED_RESULT_CODES
|
118
|
+
db.extended_result_codes = true
|
119
|
+
end
|
112
120
|
|
113
121
|
connection_pragmas.each{|s| log_connection_yield(s, db){db.execute_batch(s)}}
|
114
122
|
|
@@ -279,13 +287,12 @@ module Sequel
|
|
279
287
|
Dataset
|
280
288
|
end
|
281
289
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
#end
|
290
|
+
if USE_EXTENDED_RESULT_CODES
|
291
|
+
# Support SQLite exception codes if ruby-sqlite3 supports them.
|
292
|
+
def sqlite_error_code(exception)
|
293
|
+
exception.code if exception.respond_to?(:code)
|
294
|
+
end
|
295
|
+
end
|
289
296
|
end
|
290
297
|
|
291
298
|
class Dataset < Sequel::Dataset
|
@@ -318,18 +325,18 @@ module Sequel
|
|
318
325
|
|
319
326
|
def fetch_rows(sql)
|
320
327
|
execute(sql) do |result|
|
321
|
-
i = -1
|
322
328
|
cps = db.conversion_procs
|
323
329
|
type_procs = result.types.map{|t| cps[base_type_name(t)]}
|
324
|
-
|
325
|
-
|
330
|
+
j = -1
|
331
|
+
cols = result.columns.map{|c| [output_identifier(c), type_procs[(j+=1)]]}
|
326
332
|
self.columns = cols.map(&:first)
|
333
|
+
max = cols.length
|
327
334
|
result.each do |values|
|
328
335
|
row = {}
|
329
336
|
i = -1
|
330
337
|
while (i += 1) < max
|
331
|
-
name,
|
332
|
-
v = values[
|
338
|
+
name, type_proc = cols[i]
|
339
|
+
v = values[i]
|
333
340
|
if type_proc && v
|
334
341
|
v = type_proc.call(v)
|
335
342
|
end
|