sequel 5.8.0 → 5.9.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 +30 -0
- data/doc/release_notes/5.9.0.txt +99 -0
- data/doc/testing.rdoc +10 -10
- data/lib/sequel/adapters/ado.rb +1 -1
- data/lib/sequel/adapters/amalgalite.rb +1 -1
- data/lib/sequel/adapters/jdbc.rb +19 -7
- data/lib/sequel/adapters/jdbc/oracle.rb +1 -1
- data/lib/sequel/adapters/jdbc/postgresql.rb +0 -5
- data/lib/sequel/adapters/postgres.rb +3 -3
- data/lib/sequel/adapters/shared/access.rb +5 -6
- data/lib/sequel/adapters/shared/mysql.rb +28 -2
- data/lib/sequel/adapters/shared/postgres.rb +16 -6
- data/lib/sequel/adapters/shared/sqlite.rb +1 -1
- data/lib/sequel/adapters/sqlanywhere.rb +1 -1
- data/lib/sequel/adapters/sqlite.rb +2 -2
- data/lib/sequel/connection_pool.rb +2 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +12 -4
- data/lib/sequel/connection_pool/threaded.rb +19 -7
- data/lib/sequel/core.rb +1 -1
- data/lib/sequel/database/connecting.rb +6 -6
- data/lib/sequel/database/misc.rb +3 -3
- data/lib/sequel/database/query.rb +2 -2
- data/lib/sequel/database/schema_generator.rb +9 -3
- data/lib/sequel/database/schema_methods.rb +12 -5
- data/lib/sequel/dataset/features.rb +5 -0
- data/lib/sequel/dataset/misc.rb +1 -1
- data/lib/sequel/dataset/prepared_statements.rb +4 -4
- data/lib/sequel/dataset/query.rb +5 -0
- data/lib/sequel/dataset/sql.rb +8 -6
- data/lib/sequel/extensions/escaped_like.rb +100 -0
- data/lib/sequel/extensions/eval_inspect.rb +3 -1
- data/lib/sequel/extensions/looser_typecasting.rb +3 -3
- data/lib/sequel/extensions/pg_extended_date_support.rb +23 -10
- data/lib/sequel/model/associations.rb +18 -4
- data/lib/sequel/model/base.rb +9 -2
- data/lib/sequel/plugins/defaults_setter.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/nested_attributes.rb +2 -2
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +2 -2
- data/lib/sequel/plugins/rcte_tree.rb +5 -7
- data/lib/sequel/plugins/sharding.rb +2 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +1 -1
- data/lib/sequel/plugins/tree.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/sql.rb +2 -2
- data/lib/sequel/version.rb +4 -1
- data/spec/adapters/mysql_spec.rb +24 -0
- data/spec/adapters/postgres_spec.rb +9 -9
- data/spec/adapters/sqlite_spec.rb +10 -10
- data/spec/core/connection_pool_spec.rb +22 -0
- data/spec/core/database_spec.rb +6 -6
- data/spec/core/dataset_spec.rb +16 -5
- data/spec/core/expression_filters_spec.rb +1 -1
- data/spec/core/schema_spec.rb +1 -1
- data/spec/core/version_spec.rb +7 -0
- data/spec/extensions/connection_expiration_spec.rb +20 -2
- data/spec/extensions/connection_validator_spec.rb +20 -3
- data/spec/extensions/escaped_like_spec.rb +40 -0
- data/spec/extensions/eval_inspect_spec.rb +1 -1
- data/spec/extensions/nested_attributes_spec.rb +6 -0
- data/spec/extensions/pg_array_spec.rb +13 -13
- data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -1
- data/spec/extensions/pg_range_spec.rb +1 -1
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/sql_expr_spec.rb +1 -1
- data/spec/extensions/string_agg_spec.rb +1 -1
- data/spec/extensions/timestamps_spec.rb +2 -2
- data/spec/extensions/validation_helpers_spec.rb +1 -1
- data/spec/integration/associations_test.rb +12 -0
- data/spec/integration/dataset_test.rb +21 -0
- data/spec/integration/type_test.rb +4 -4
- data/spec/model/base_spec.rb +9 -0
- data/spec/model/eager_loading_spec.rb +25 -0
- data/spec/model/record_spec.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49e114f3c425c0cdcd798fdcb170ac2112fada51077235f8e53b3d9a3940954a
|
4
|
+
data.tar.gz: db61fd6ab89b98c48fd2461f500db1f35afd2624808721733a8efbdc4c14a9ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff2793a7d47c0fe5ff7669ef248cd2c66bd1761f36a9ca0d2742adb8ee59be88a12264df0155864e7ac34f2795ff8f1a633d4e97fc87bcd9bb7976e93b67615b
|
7
|
+
data.tar.gz: a5996916449312e4a83ecc1e4bdaf2a3789c98321fa622389d675b3b6caf5cc84ce9e413198c2d875d0963ac07b7f3b59f2e80cd50b7eb9f45110b1f87263489
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,33 @@
|
|
1
|
+
=== 5.9.0 (2018-06-01)
|
2
|
+
|
3
|
+
* Support generated columns on MySQL 5.7+ and MariaDB 5.2+ (wjordan, jeremyevans) (#1517)
|
4
|
+
|
5
|
+
* Add escaped_like extension for creation of LIKE expressions with placeholders in the pattern without access to a dataset (jeremyevans)
|
6
|
+
|
7
|
+
* Modify jdbc adapter exception handling to work around ::NativeException deprecation in JRuby 9.2 (jeremyevans)
|
8
|
+
|
9
|
+
* Work around broken BC date handling in JRuby 9.2.0.0 (jeremyevans)
|
10
|
+
|
11
|
+
* Switch use of BigDecimal.new() to BigDecimal(), since the former is deprecated (jeremyevans)
|
12
|
+
|
13
|
+
* Add Sequel::VERSION_NUMBER for easier version comparisons (jeremyevans)
|
14
|
+
|
15
|
+
* Add Model.has_dataset? to determine if the model class has a dataset (AlexWayfer) (#1508)
|
16
|
+
|
17
|
+
* Support use of LIKE with ANY function on PostgreSQL by avoiding unnecessary use of ESCAPE syntax (jeremyevans)
|
18
|
+
|
19
|
+
* Disconnect connections left allocated by dead threads instead of returning the connections to the pool (jeremyevans)
|
20
|
+
|
21
|
+
* Make both threaded connection pools avoid disconnecting connections while holding the connection pool mutex (jeremyevans)
|
22
|
+
|
23
|
+
* Don't deadlock when disconnecting connections in the sharded_threaded connection pool when using connection_validator or connection_expiration extensions (jeremyevans)
|
24
|
+
|
25
|
+
* Don't modify hash argument passed in Model.nested_attributes in the nested_attributes plugin (jeremyevans)
|
26
|
+
|
27
|
+
* Avoid unnecessary hash creation in many places (jeremyevans)
|
28
|
+
|
29
|
+
* Fix duplicate objects in nested associations when eager_graphing cascaded many_to_one=>one_to_many associations (jeremyevans)
|
30
|
+
|
1
31
|
=== 5.8.0 (2018-05-01)
|
2
32
|
|
3
33
|
* Don't mark SQLAnywhere as supporting WITH in INSERT statement (jeremyevans)
|
@@ -0,0 +1,99 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* An escaped_like extension has been added, for the creation of
|
4
|
+
LIKE/ILIKE expressions with placeholders in patterns without
|
5
|
+
access to a dataset. This adds escaped_like and escaped_ilike
|
6
|
+
methods to the same Sequel expression objects that support like
|
7
|
+
and ilike. These methods take two arguments, the first being
|
8
|
+
the pattern, with ? placeholders, and the second being the
|
9
|
+
placeholder value (which can be an array for multiple
|
10
|
+
placeholders):
|
11
|
+
|
12
|
+
Sequel.extension :escaped_like
|
13
|
+
DB[:table].where{string_column.escaped_like('?%', user_input)}
|
14
|
+
# user_input is 'foo':
|
15
|
+
# SELECT * FROM table WHERE string_column LIKE 'foo%'
|
16
|
+
# user_input is '%foo':
|
17
|
+
# SELECT * FROM table WHERE string_column LIKE '\%foo%'
|
18
|
+
|
19
|
+
* Generated columns on MySQL 5.7+ and MariaDB 5.2+ are now supported
|
20
|
+
using the :generated_always_as option when creating the column.
|
21
|
+
The :generated_type option can also be used to specify the type of
|
22
|
+
generated column (virtual or stored). Examples:
|
23
|
+
|
24
|
+
DB.add_column :t, :c, Integer, generated_always_as: Sequel[:a]+'b'
|
25
|
+
# ALTER TABLE `t` ADD COLUMN `c` varchar(255)
|
26
|
+
# GENERATED ALWAYS AS (CONCAT(`a`, 'b'))
|
27
|
+
|
28
|
+
DB.add_column :t, :c, Integer, generated_always_as: Sequel[:a]+'b',
|
29
|
+
generated_type: :virtual
|
30
|
+
# ALTER TABLE `t` ADD COLUMN `c` varchar(255)
|
31
|
+
# GENERATED ALWAYS AS (CONCAT(`a`, 'b')) VIRTUAL
|
32
|
+
|
33
|
+
DB.add_column :t, :c, Integer, generated_always_as: Sequel[:a]+'b',
|
34
|
+
generated_type: :stored
|
35
|
+
# ALTER TABLE `t` ADD COLUMN `c` varchar(255)
|
36
|
+
# GENERATED ALWAYS AS (CONCAT(`a`, 'b')) STORED
|
37
|
+
|
38
|
+
* Sequel::Model.has_dataset? has been added for checking whether the
|
39
|
+
model class has an associated dataset. This will generally be true
|
40
|
+
for most model classes, but will be false for abstract model
|
41
|
+
classes (such as Sequel::Model itself).
|
42
|
+
|
43
|
+
* Sequel::VERSION_NUMBER has been added for easier future version
|
44
|
+
comparisons. The version number for 5.9.0 is 50090.
|
45
|
+
|
46
|
+
= Other Improvements
|
47
|
+
|
48
|
+
* When disconnecting connections in the threaded connection pools,
|
49
|
+
the disconnection is performed without holding the connection
|
50
|
+
pool mutex, since disconnection may block.
|
51
|
+
|
52
|
+
* The sharded threaded connection pool no longer deadlocks when
|
53
|
+
disconnecting connections if the connection_validator or
|
54
|
+
connection_expiration extension is used.
|
55
|
+
|
56
|
+
* If a thread dies and does not check a connection back into the
|
57
|
+
connection pool, Sequel now disconnects the connection when it
|
58
|
+
detects the dead thread, instead of assuming the connection is
|
59
|
+
safe to be reused.
|
60
|
+
|
61
|
+
* When using eager_graph with cascaded associations, a unique
|
62
|
+
object is now used instead of a shared object in cases where
|
63
|
+
using a shared object may cause further cascaded associated
|
64
|
+
objects to be duplicated.
|
65
|
+
|
66
|
+
* On PostgreSQL, the ESCAPE modifier to the LIKE/ILIKE operators is
|
67
|
+
no longer used, since the default ESCAPE value is the one Sequel
|
68
|
+
uses. This change was made in order to allow the LIKE/ILIKE
|
69
|
+
operators to work with the ANY function, as PostgreSQL does not
|
70
|
+
support the use of the ESCAPE modifier in such cases.
|
71
|
+
|
72
|
+
* A hash argument passed to Model.nested_attributes in the
|
73
|
+
nested_attributes plugin is now no longer modified.
|
74
|
+
|
75
|
+
* Internal data structures for eager and eager_graph datasets are now
|
76
|
+
frozen to avoid unintentional modification.
|
77
|
+
|
78
|
+
* Nondeterministic behavior in Database#foreign_key_list with the
|
79
|
+
:reverse option on PostgreSQL is now avoided by using an
|
80
|
+
unambiguous order.
|
81
|
+
|
82
|
+
* Performance has been improved slightly by avoiding unnecessary
|
83
|
+
hash allocations.
|
84
|
+
|
85
|
+
* Performance has been improved slightly by using while instead
|
86
|
+
of Kernel#loop.
|
87
|
+
|
88
|
+
* BigDecimal() is now used instead of BigDecimal.new(), as the
|
89
|
+
latter has been deprecated.
|
90
|
+
|
91
|
+
* The jdbc adapter now avoids referencing ::NativeException on JRuby
|
92
|
+
9.2+, since JRuby has deprecated it. It is still used on older
|
93
|
+
versions of JRuby, since some JRuby 1.7 code may still require it.
|
94
|
+
|
95
|
+
* Sequel now works around multiple Date/Time conversion bugs in
|
96
|
+
JRuby 9.2.0.0 for BC dates in the pg_extended_date_support
|
97
|
+
extension. These bugs have already been fixed in JRuby, and
|
98
|
+
the workarounds will be removed after the release of JRuby
|
99
|
+
9.2.1.0.
|
data/doc/testing.rdoc
CHANGED
@@ -13,7 +13,7 @@ These run each test in its own transaction, the recommended way to test.
|
|
13
13
|
require 'minitest/hooks/default'
|
14
14
|
class Minitest::HooksSpec
|
15
15
|
def around
|
16
|
-
|
16
|
+
DB.transaction(:rollback=>:always, :auto_savepoint=>true){super}
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -21,7 +21,7 @@ These run each test in its own transaction, the recommended way to test.
|
|
21
21
|
|
22
22
|
class Minitest::Spec
|
23
23
|
def run(*args, &block)
|
24
|
-
|
24
|
+
DB.transaction(:rollback=>:always, :auto_savepoint=>true){super}
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -30,7 +30,7 @@ These run each test in its own transaction, the recommended way to test.
|
|
30
30
|
# Use this class as the base class for your tests
|
31
31
|
class SequelTestCase < Minitest::Test
|
32
32
|
def run(*args, &block)
|
33
|
-
|
33
|
+
DB.transaction(:rollback=>:always, :auto_savepoint=>true){super}
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -46,7 +46,7 @@ These run each test in its own transaction, the recommended way to test.
|
|
46
46
|
|
47
47
|
You can use the Sequel.transaction method to run a transaction on multiple databases, rolling all of them back. Instead of:
|
48
48
|
|
49
|
-
|
49
|
+
DB.transaction(:rollback=>:always)
|
50
50
|
|
51
51
|
Use Sequel.transaction with an array of databases:
|
52
52
|
|
@@ -66,11 +66,11 @@ Example:
|
|
66
66
|
require 'minitest/hooks/default'
|
67
67
|
class Minitest::HooksSpec
|
68
68
|
def around
|
69
|
-
|
69
|
+
DB.transaction(:rollback=>:always, :savepoint=>true, :auto_savepoint=>true){super}
|
70
70
|
end
|
71
71
|
|
72
72
|
def around_all
|
73
|
-
|
73
|
+
DB.transaction(:rollback=>:always){super}
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
@@ -90,9 +90,9 @@ The order in which you delete/truncate the tables is important if you are using
|
|
90
90
|
|
91
91
|
describe "some test suite" do
|
92
92
|
after do
|
93
|
-
[:table1, :table2].each{|x|
|
93
|
+
[:table1, :table2].each{|x| DB.from(x).truncate}
|
94
94
|
# or
|
95
|
-
[:table1, :table2].each{|x|
|
95
|
+
[:table1, :table2].each{|x| DB.from(x).delete}
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
@@ -100,9 +100,9 @@ The order in which you delete/truncate the tables is important if you are using
|
|
100
100
|
|
101
101
|
class SomeTestClass < Minitest::Test
|
102
102
|
def teardown
|
103
|
-
[:table1, :table2].each{|x|
|
103
|
+
[:table1, :table2].each{|x| DB.from(x).truncate}
|
104
104
|
# or
|
105
|
-
[:table1, :table2].each{|x|
|
105
|
+
[:table1, :table2].each{|x| DB.from(x).delete}
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
data/lib/sequel/adapters/ado.rb
CHANGED
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -17,7 +17,19 @@ module Sequel
|
|
17
17
|
# Contains procs keyed on subadapter type that extend the
|
18
18
|
# given database object so it supports the correct database type.
|
19
19
|
DATABASE_SETUP = {}
|
20
|
+
|
21
|
+
# Create custom NativeException alias for nicer access, and also so that
|
22
|
+
# JRuby 9.2+ so it doesn't use the deprecated ::NativeException
|
23
|
+
NativeException = java.lang.Exception
|
20
24
|
|
25
|
+
# Default database error classes
|
26
|
+
DATABASE_ERROR_CLASSES = [NativeException]
|
27
|
+
if JRUBY_VERSION < '9.2'
|
28
|
+
# On JRuby <9.2, still include ::NativeException, as it is still needed in some cases
|
29
|
+
DATABASE_ERROR_CLASSES << ::NativeException
|
30
|
+
end
|
31
|
+
DATABASE_ERROR_CLASSES.freeze
|
32
|
+
|
21
33
|
# Allow loading the necessary JDBC support via a gem.
|
22
34
|
def self.load_gem(name)
|
23
35
|
begin
|
@@ -68,7 +80,7 @@ module Sequel
|
|
68
80
|
end
|
69
81
|
def RubyBigDecimal(r, i)
|
70
82
|
if v = r.getBigDecimal(i)
|
71
|
-
BigDecimal
|
83
|
+
::Kernel::BigDecimal(v.to_string)
|
72
84
|
end
|
73
85
|
end
|
74
86
|
def RubyBlob(r, i)
|
@@ -168,7 +180,7 @@ module Sequel
|
|
168
180
|
last_insert_id(conn, opts)
|
169
181
|
end
|
170
182
|
end
|
171
|
-
rescue
|
183
|
+
rescue *DATABASE_ERROR_CLASSES => e
|
172
184
|
raise_error(e)
|
173
185
|
ensure
|
174
186
|
cps.close
|
@@ -189,7 +201,7 @@ module Sequel
|
|
189
201
|
JavaSQL::DriverManager.setLoginTimeout(opts[:login_timeout]) if opts[:login_timeout]
|
190
202
|
raise StandardError, "skipping regular connection" if opts[:jdbc_properties]
|
191
203
|
JavaSQL::DriverManager.getConnection(*args)
|
192
|
-
rescue
|
204
|
+
rescue StandardError, *DATABASE_ERROR_CLASSES => e
|
193
205
|
raise e unless driver
|
194
206
|
# If the DriverManager can't get the connection - use the connect
|
195
207
|
# method of the driver. (This happens under Tomcat for instance)
|
@@ -203,7 +215,7 @@ module Sequel
|
|
203
215
|
c = driver.new.connect(args[0], props)
|
204
216
|
raise(Sequel::DatabaseError, 'driver.new.connect returned nil: probably bad JDBC connection string') unless c
|
205
217
|
c
|
206
|
-
rescue
|
218
|
+
rescue StandardError, *DATABASE_ERROR_CLASSES => e2
|
207
219
|
if e2.respond_to?(:message=) && e2.message != e.message
|
208
220
|
e2.message = "#{e2.message}\n#{e.class.name}: #{e.message}"
|
209
221
|
end
|
@@ -355,7 +367,7 @@ module Sequel
|
|
355
367
|
end
|
356
368
|
|
357
369
|
def database_error_classes
|
358
|
-
|
370
|
+
DATABASE_ERROR_CLASSES
|
359
371
|
end
|
360
372
|
|
361
373
|
def database_exception_sqlstate(exception, opts)
|
@@ -436,7 +448,7 @@ module Sequel
|
|
436
448
|
log_connection_yield(msg, conn, args){cps.executeUpdate}
|
437
449
|
end
|
438
450
|
end
|
439
|
-
rescue
|
451
|
+
rescue *DATABASE_ERROR_CLASSES => e
|
440
452
|
raise_error(e)
|
441
453
|
ensure
|
442
454
|
cps.close unless name
|
@@ -661,7 +673,7 @@ module Sequel
|
|
661
673
|
def statement(conn)
|
662
674
|
stmt = conn.createStatement
|
663
675
|
yield stmt
|
664
|
-
rescue
|
676
|
+
rescue *DATABASE_ERROR_CLASSES => e
|
665
677
|
raise_error(e)
|
666
678
|
ensure
|
667
679
|
stmt.close if stmt
|
@@ -135,11 +135,6 @@ module Sequel
|
|
135
135
|
|
136
136
|
private
|
137
137
|
|
138
|
-
DATABASE_ERROR_CLASSES = [NativeException].freeze
|
139
|
-
def database_error_classes
|
140
|
-
DATABASE_ERROR_CLASSES
|
141
|
-
end
|
142
|
-
|
143
138
|
def disconnect_error?(exception, opts)
|
144
139
|
super || exception.message =~ /\A(This connection has been closed\.|FATAL: terminating connection due to administrator command|An I\/O error occurred while sending to the backend\.)\z/
|
145
140
|
end
|
@@ -271,7 +271,7 @@ module Sequel
|
|
271
271
|
def error_info(e)
|
272
272
|
e = e.wrapped_exception if e.is_a?(DatabaseError)
|
273
273
|
r = e.result
|
274
|
-
|
274
|
+
{
|
275
275
|
:schema => r.error_field(::PG::PG_DIAG_SCHEMA_NAME),
|
276
276
|
:table => r.error_field(::PG::PG_DIAG_TABLE_NAME),
|
277
277
|
:column => r.error_field(::PG::PG_DIAG_COLUMN_NAME),
|
@@ -449,7 +449,7 @@ module Sequel
|
|
449
449
|
raise Error, 'calling #listen with :loop requires a block' unless block
|
450
450
|
loop_call = l.respond_to?(:call)
|
451
451
|
catch(:stop) do
|
452
|
-
|
452
|
+
while true
|
453
453
|
t = timeout_block ? [timeout_block.call] : []
|
454
454
|
conn.wait_for_notify(*t, &block)
|
455
455
|
l.call(conn) if loop_call
|
@@ -712,7 +712,7 @@ module Sequel
|
|
712
712
|
yield_hash_rows(res, cols){|h| yield h}
|
713
713
|
return if res.ntuples < rows_per_fetch
|
714
714
|
end
|
715
|
-
|
715
|
+
while true
|
716
716
|
execute(fetch_sql) do |res|
|
717
717
|
yield_hash_rows(res, cols){|h| yield h}
|
718
718
|
return if res.ntuples < rows_per_fetch
|
@@ -109,12 +109,6 @@ module Sequel
|
|
109
109
|
complex_expression_sql_append(sql, :LIKE, args)
|
110
110
|
when :'NOT ILIKE'
|
111
111
|
complex_expression_sql_append(sql, :'NOT LIKE', args)
|
112
|
-
when :LIKE, :'NOT LIKE'
|
113
|
-
sql << '('
|
114
|
-
literal_append(sql, args[0])
|
115
|
-
sql << ' ' << op.to_s << ' '
|
116
|
-
literal_append(sql, args[1])
|
117
|
-
sql << ')'
|
118
112
|
when :'!='
|
119
113
|
sql << '('
|
120
114
|
literal_append(sql, args[0])
|
@@ -240,6 +234,11 @@ module Sequel
|
|
240
234
|
end
|
241
235
|
end
|
242
236
|
|
237
|
+
# Access doesn't support ESCAPE for LIKE.
|
238
|
+
def requires_like_escape?
|
239
|
+
false
|
240
|
+
end
|
241
|
+
|
243
242
|
# Access requires parentheses when joining more than one table
|
244
243
|
def select_from_sql(sql)
|
245
244
|
if f = @opts[:from]
|
@@ -19,7 +19,7 @@ module Sequel
|
|
19
19
|
include Sequel::Database::SplitAlterTable
|
20
20
|
|
21
21
|
CAST_TYPES = {String=>:CHAR, Integer=>:SIGNED, Time=>:DATETIME, DateTime=>:DATETIME, Numeric=>:DECIMAL, BigDecimal=>:DECIMAL, File=>:BINARY}.freeze
|
22
|
-
COLUMN_DEFINITION_ORDER = [:collate, :null, :default, :unique, :primary_key, :auto_increment, :references].freeze
|
22
|
+
COLUMN_DEFINITION_ORDER = [:generated, :collate, :null, :default, :unique, :primary_key, :auto_increment, :references].freeze
|
23
23
|
|
24
24
|
# Set the default charset used for CREATE TABLE. You can pass the
|
25
25
|
# :charset option to create_table to override this setting.
|
@@ -137,6 +137,11 @@ module Sequel
|
|
137
137
|
true
|
138
138
|
end
|
139
139
|
|
140
|
+
# Generated columns are supported in MariaDB 5.2.0+ and MySQL 5.7.6+.
|
141
|
+
def supports_generated_columns?
|
142
|
+
server_version >= (mariadb? ? 50200 : 50706)
|
143
|
+
end
|
144
|
+
|
140
145
|
# MySQL 5+ supports prepared transactions (two-phase commit) using XA
|
141
146
|
def supports_prepared_transactions?
|
142
147
|
server_version >= 50000
|
@@ -331,6 +336,23 @@ module Sequel
|
|
331
336
|
end
|
332
337
|
end
|
333
338
|
|
339
|
+
# Add generation clause SQL fragment to column creation SQL.
|
340
|
+
def column_definition_generated_sql(sql, column)
|
341
|
+
if (generated_expression = column[:generated_always_as])
|
342
|
+
sql << " GENERATED ALWAYS AS (#{literal(generated_expression)})"
|
343
|
+
case (type = column[:generated_type])
|
344
|
+
when nil
|
345
|
+
# none, database default
|
346
|
+
when :virtual
|
347
|
+
sql << " VIRTUAL"
|
348
|
+
when :stored
|
349
|
+
sql << (mariadb? ? " PERSISTENT" : " STORED")
|
350
|
+
else
|
351
|
+
raise Error, "unsupported :generated_type option: #{type.inspect}"
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
334
356
|
def column_definition_order
|
335
357
|
COLUMN_DEFINITION_ORDER
|
336
358
|
end
|
@@ -473,7 +495,11 @@ module Sequel
|
|
473
495
|
metadata_dataset.with_sql("DESCRIBE ?", table).map do |row|
|
474
496
|
extra = row.delete(:Extra)
|
475
497
|
if row[:primary_key] = row.delete(:Key) == 'PRI'
|
476
|
-
row[:auto_increment] = !!(extra.to_s =~ /auto_increment/
|
498
|
+
row[:auto_increment] = !!(extra.to_s =~ /auto_increment/i)
|
499
|
+
end
|
500
|
+
if supports_generated_columns?
|
501
|
+
# Extra field contains VIRTUAL or PERSISTENT for generated columns
|
502
|
+
row[:generated] = !!(extra.to_s =~ /VIRTUAL|STORED|PERSISTENT/i)
|
477
503
|
end
|
478
504
|
row[:allow_null] = row.delete(:Null) == 'YES'
|
479
505
|
row[:default] = row.delete(:Default)
|