sequel 3.43.0 → 3.44.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +32 -0
- data/doc/association_basics.rdoc +10 -3
- data/doc/release_notes/3.37.0.txt +1 -1
- data/doc/release_notes/3.44.0.txt +152 -0
- data/lib/sequel/adapters/ado.rb +0 -6
- data/lib/sequel/adapters/db2.rb +0 -3
- data/lib/sequel/adapters/dbi.rb +0 -6
- data/lib/sequel/adapters/ibmdb.rb +0 -3
- data/lib/sequel/adapters/jdbc.rb +8 -12
- data/lib/sequel/adapters/jdbc/as400.rb +2 -18
- data/lib/sequel/adapters/jdbc/derby.rb +10 -0
- data/lib/sequel/adapters/jdbc/h2.rb +10 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +10 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +5 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +2 -4
- data/lib/sequel/adapters/mock.rb +5 -0
- data/lib/sequel/adapters/mysql2.rb +4 -13
- data/lib/sequel/adapters/odbc.rb +0 -5
- data/lib/sequel/adapters/oracle.rb +3 -5
- data/lib/sequel/adapters/postgres.rb +2 -1
- data/lib/sequel/adapters/shared/access.rb +10 -0
- data/lib/sequel/adapters/shared/cubrid.rb +9 -0
- data/lib/sequel/adapters/shared/db2.rb +10 -0
- data/lib/sequel/adapters/shared/mssql.rb +10 -0
- data/lib/sequel/adapters/shared/mysql.rb +14 -0
- data/lib/sequel/adapters/shared/oracle.rb +15 -0
- data/lib/sequel/adapters/shared/postgres.rb +26 -2
- data/lib/sequel/adapters/shared/sqlite.rb +15 -0
- data/lib/sequel/adapters/tinytds.rb +5 -32
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +2 -37
- data/lib/sequel/core.rb +3 -3
- data/lib/sequel/database/misc.rb +40 -4
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_methods.rb +33 -12
- data/lib/sequel/dataset/actions.rb +51 -2
- data/lib/sequel/dataset/features.rb +0 -6
- data/lib/sequel/dataset/sql.rb +1 -1
- data/lib/sequel/exceptions.rb +22 -7
- data/lib/sequel/extensions/columns_introspection.rb +30 -5
- data/lib/sequel/extensions/pg_auto_parameterize.rb +9 -0
- data/lib/sequel/model/associations.rb +50 -37
- data/lib/sequel/model/base.rb +30 -1
- data/lib/sequel/plugins/eager_each.rb +17 -21
- data/lib/sequel/plugins/identity_map.rb +2 -1
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +1 -1
- data/lib/sequel/sql.rb +4 -2
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +32 -2
- data/spec/adapters/sqlite_spec.rb +20 -0
- data/spec/core/database_spec.rb +40 -0
- data/spec/core/dataset_spec.rb +91 -4
- data/spec/core/mock_adapter_spec.rb +2 -1
- data/spec/core/schema_generator_spec.rb +4 -0
- data/spec/core/schema_spec.rb +9 -3
- data/spec/extensions/association_dependencies_spec.rb +3 -3
- data/spec/extensions/columns_introspection_spec.rb +28 -2
- data/spec/extensions/eager_each_spec.rb +0 -1
- data/spec/extensions/identity_map_spec.rb +3 -2
- data/spec/extensions/migration_spec.rb +6 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +2 -2
- data/spec/extensions/rcte_tree_spec.rb +2 -2
- data/spec/extensions/single_table_inheritance_spec.rb +3 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +1 -1
- data/spec/extensions/validation_class_methods_spec.rb +8 -0
- data/spec/integration/associations_test.rb +4 -4
- data/spec/integration/database_test.rb +68 -20
- data/spec/integration/dataset_test.rb +48 -0
- data/spec/integration/schema_test.rb +25 -1
- data/spec/model/associations_spec.rb +21 -8
- data/spec/model/dataset_methods_spec.rb +58 -18
- metadata +4 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,35 @@
|
|
1
|
+
=== 3.44.0 (2013-02-04)
|
2
|
+
|
3
|
+
* Speedup mysql2 adapter with identifier output method fetch speed by up to 50% (jeremyevans)
|
4
|
+
|
5
|
+
* Speedup tinytds adapter fetch speed by up to 60% (jeremyevans)
|
6
|
+
|
7
|
+
* Expand columns_introspection extension to consider cached schema values in the database (jeremyevans)
|
8
|
+
|
9
|
+
* Expand columns_introspection extension to handle subselects (jeremyevans)
|
10
|
+
|
11
|
+
* Have #last and #paged_each for model datasets order by the model's primary key by default (jeremyevans)
|
12
|
+
|
13
|
+
* Improve emulated offset support to handle subqueries (jeremyevans)
|
14
|
+
|
15
|
+
* Remove use of Object#extend from the eager_each plugin (jeremyevans)
|
16
|
+
|
17
|
+
* Add support for temporary views on SQLite and PostgreSQL via the :temp option to create_view (chanks, jeremyevans)
|
18
|
+
|
19
|
+
* Emulate Database#create_or_replace_view if not supported directly (jeremyevans)
|
20
|
+
|
21
|
+
* Add Dataset#paged_each, for processing entire datasets without keeping all rows in memory (jeremyevans)
|
22
|
+
|
23
|
+
* Add Sequel::ConstraintViolation exception class and subclasses for easier exception handling (jeremyevans)
|
24
|
+
|
25
|
+
* Fix use of identity_map plugin with many_to_many associations with right composite keys (chanks) (#603)
|
26
|
+
|
27
|
+
* Increase virtual row performance by using a shared VirtualRow instance (jeremyevans)
|
28
|
+
|
29
|
+
* Allow the :dataset association option to accept the association reflection as an argument (jeremyevans)
|
30
|
+
|
31
|
+
* Improve association method performance by caching intermediate dataset (jeremyevans)
|
32
|
+
|
1
33
|
=== 3.43.0 (2013-01-08)
|
2
34
|
|
3
35
|
* Move the #meta_def support for Database, Dataset, and Model to the meta_def extension (jeremyevans)
|
data/doc/association_basics.rdoc
CHANGED
@@ -1007,14 +1007,21 @@ in additon to the :clone option.
|
|
1007
1007
|
==== :dataset
|
1008
1008
|
|
1009
1009
|
This is generally only specified for custom associations that aren't based on
|
1010
|
-
primary/foreign key relationships. It should be a proc that is
|
1010
|
+
primary/foreign key relationships. It should be a proc that is instance_execed
|
1011
1011
|
to get the base dataset to use before the other options are applied.
|
1012
1012
|
|
1013
|
+
If the proc accepts an argument, it is passed the related association reflection.
|
1014
|
+
For best performance, it's recommended that custom associations call the
|
1015
|
+
+associated_dataset+ method on the association reflection as the starting point
|
1016
|
+
for the dataset to return. The +associated_dataset+ method will return a
|
1017
|
+
dataset based on the associated class with most of the association options
|
1018
|
+
already applied, and the proc should return a modified copy of this dataset.
|
1019
|
+
|
1013
1020
|
Here's an example of an association of songs to artists through lyrics, where
|
1014
1021
|
the artist can perform any one of four tasks for the lyric:
|
1015
1022
|
|
1016
|
-
Album.one_to_many :songs, :dataset=>(proc do
|
1017
|
-
|
1023
|
+
Album.one_to_many :songs, :dataset=>(proc do |r|
|
1024
|
+
r.associated_dataset.select_all(:songs).
|
1018
1025
|
join(Lyric, :id=>:lyricid,
|
1019
1026
|
id=>[:composer_id, :arranger_id, :vocalist_id, :lyricist_id])
|
1020
1027
|
end)
|
@@ -0,0 +1,152 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* Dataset#paged_each has been added, for processing entire datasets
|
4
|
+
without keeping all rows in memory, even if the underlying driver
|
5
|
+
keeps all query results in memory. This is implemented using
|
6
|
+
limits and offsets, and requires an order (model datasets use a
|
7
|
+
default order by primary key). It defaults to fetching 1000
|
8
|
+
rows at a time, but that can be changed via the :rows_per_fetch
|
9
|
+
option.
|
10
|
+
|
11
|
+
This method is drop-in compatible for each. Previously, the
|
12
|
+
pagination extension's each_page method could be used for a
|
13
|
+
similar purpose, but users of each_page are now encouraged to
|
14
|
+
switch to paged_each.
|
15
|
+
|
16
|
+
* Sequel now recognizes constraint violation exceptions on most
|
17
|
+
databases, and will raise specific exceptions for different
|
18
|
+
types of constraint violations, instead of the generic
|
19
|
+
Sequel::DatabaseError:
|
20
|
+
|
21
|
+
* Sequel::ConstraintViolation (generic superclass)
|
22
|
+
* Sequel::CheckConstraintViolation
|
23
|
+
* Sequel::NotNullConstraintViolation
|
24
|
+
* Sequel::ForeignKeyConstraintViolation
|
25
|
+
* Sequel::UniqueConstraintViolation
|
26
|
+
* Sequel::Postgres::ExclusionConstraintViolation
|
27
|
+
|
28
|
+
* The :dataset association option can now take accept an optional
|
29
|
+
association reflection option. Instead of doing:
|
30
|
+
|
31
|
+
Album.one_to_many :artists,
|
32
|
+
:dataset=>{Artist...}
|
33
|
+
|
34
|
+
you can now do:
|
35
|
+
|
36
|
+
Album.one_to_many :artists,
|
37
|
+
:dataset=>{|r| r.associated_dataset...}
|
38
|
+
|
39
|
+
This second form will preform better.
|
40
|
+
|
41
|
+
* Temporary views are now supported on PostgreSQL and SQLite using
|
42
|
+
the :temp option to create_view.
|
43
|
+
|
44
|
+
= Other Improvements
|
45
|
+
|
46
|
+
* Row fetching speed in the tinytds adapter has been increased by
|
47
|
+
up to 60%.
|
48
|
+
|
49
|
+
* Row fetching speed in the mysql2 adapter when using an identifier
|
50
|
+
output method has been increased by up to 50%.
|
51
|
+
|
52
|
+
* On databases where offsets are emulated via the ROW_NUMBER window
|
53
|
+
function (Oracle, DB2, Microsoft SQL Server), using an offset in
|
54
|
+
a subselect is now supported. For example, the following code
|
55
|
+
previously didn't work correctly with emulated offsets:
|
56
|
+
|
57
|
+
# Second 5 rows ordered by column2 of the second 10 rows ordered
|
58
|
+
# by column 1.
|
59
|
+
DB[:table].order(:column1).limit(10, 10).
|
60
|
+
from_self.order(:column2).limit(5, 5)
|
61
|
+
|
62
|
+
Row processing speed has been increased slightly for all adapters
|
63
|
+
that supported databases where offsets are emulated.
|
64
|
+
|
65
|
+
* Association method performance has improved by caching an
|
66
|
+
intermediate dataset. This can close to triple the performance
|
67
|
+
of the association_dataset method, and increase the performance
|
68
|
+
of the association method by close to 30%.
|
69
|
+
|
70
|
+
* Virtual Row performance has increased about 30% in the typical
|
71
|
+
case by using a shared VirtualRow instance.
|
72
|
+
|
73
|
+
* Database#create_or_replace_view is now emulated on databases that
|
74
|
+
don't support it directly by dropping the view before attempting
|
75
|
+
to create it.
|
76
|
+
|
77
|
+
* The columns_introspection extension can now introspect for simple
|
78
|
+
select * queries from subselects, and it can now use the cached
|
79
|
+
schema information in the database for simple select * queries
|
80
|
+
from tables.
|
81
|
+
|
82
|
+
* The identity_map plugin now works correctly with many-to-many
|
83
|
+
right-side composite keys.
|
84
|
+
|
85
|
+
* Dataset#last for Model datasets now works even if you don't specify
|
86
|
+
an order explicitly, giving the last entry by primary key. Note
|
87
|
+
that Dataset#first for model datasets still does not order by
|
88
|
+
default.
|
89
|
+
|
90
|
+
* The eager_each plugin no longer uses Object#extend at runtime.
|
91
|
+
|
92
|
+
* Database#remove_cached_schema is now thread-safe on non-GVL ruby
|
93
|
+
implementations.
|
94
|
+
|
95
|
+
* Connection errors in the jdbc adapter now provide slightly more
|
96
|
+
helpful messages.
|
97
|
+
|
98
|
+
* Sequel now uses the standard offset emulation code in the
|
99
|
+
jdbc/as400 adapter, instead of custom offset emulation code
|
100
|
+
specific to that adapter.
|
101
|
+
|
102
|
+
* Database#create_view with a dataset now works correctly when using
|
103
|
+
the pg_auto_parameterize extension.
|
104
|
+
|
105
|
+
* Database#columns no longer calls the row_proc.
|
106
|
+
|
107
|
+
* Dataset#schema_and_table no longer turns a literal string into a
|
108
|
+
non-literal string.
|
109
|
+
|
110
|
+
* The oracle adapter now works with a :prefetch_rows=>nil option,
|
111
|
+
which explicitly disables prefetching.
|
112
|
+
|
113
|
+
* The mock mssql adapter now sets a server_version so that more
|
114
|
+
parts of it work.
|
115
|
+
|
116
|
+
= Backwards Compatibility
|
117
|
+
|
118
|
+
* Offset emulation via ROW_NUMBER works by moving the query to a
|
119
|
+
subselect that also selects from the ROW_NUMBER window function,
|
120
|
+
and filtering on the ROW_NUMBER in the main query. Previously, the
|
121
|
+
ROW_NUMBER was also present in the output columns, and some
|
122
|
+
adapter code was needed to hide that fact. Now, the outer select
|
123
|
+
selects all of the inner columns in the subselect except for the
|
124
|
+
ROW_NUMBER, reducing the adapter code needed. This has the side
|
125
|
+
effect of potentially requiring a query (or multiple queries for
|
126
|
+
multiple subselects) to determine the columns to use. The
|
127
|
+
columns_introspection extension may reduce the number of queries
|
128
|
+
needed.
|
129
|
+
|
130
|
+
* The correlated_subquery eager limit strategy is no longer supported
|
131
|
+
on Microsoft SQL Server for many_*_many associations. As the
|
132
|
+
window_function eager limit strategy is supported there, there is
|
133
|
+
no reason to use the correlated_subquery strategy.
|
134
|
+
|
135
|
+
* The public AssociationReflection#_dataset_method method has been
|
136
|
+
removed.
|
137
|
+
|
138
|
+
* The private _*_dataset methods for associations (e.g.
|
139
|
+
_albums_dataset) have been removed.
|
140
|
+
|
141
|
+
* The private Dataset#offset_returns_row_number_column? method has
|
142
|
+
been removed.
|
143
|
+
|
144
|
+
* :conditions options for associations are now added to the
|
145
|
+
association dataset before the foreign key filters, instead of
|
146
|
+
after. This should have no effect unless you were introspecting
|
147
|
+
the dataset's opts or sql and acting on it.
|
148
|
+
|
149
|
+
* The added abilities in the columns_introspection plugin to use
|
150
|
+
cached schema for introspection can now cause it to return
|
151
|
+
incorrect results if the table's schema has changed since it was
|
152
|
+
cached by Sequel.
|
data/lib/sequel/adapters/ado.rb
CHANGED
@@ -132,16 +132,10 @@ module Sequel
|
|
132
132
|
def fetch_rows(sql)
|
133
133
|
execute(sql) do |s|
|
134
134
|
columns = cols = s.Fields.extend(Enumerable).map{|column| output_identifier(column.Name)}
|
135
|
-
if opts[:offset] && offset_returns_row_number_column?
|
136
|
-
rn = row_number_column
|
137
|
-
columns = columns.dup
|
138
|
-
columns.delete(rn)
|
139
|
-
end
|
140
135
|
@columns = columns
|
141
136
|
s.getRows.transpose.each do |r|
|
142
137
|
row = {}
|
143
138
|
cols.each{|c| row[c] = r.shift}
|
144
|
-
row.delete(rn) if rn
|
145
139
|
yield row
|
146
140
|
end unless s.eof
|
147
141
|
end
|
data/lib/sequel/adapters/db2.rb
CHANGED
@@ -181,12 +181,10 @@ module Sequel
|
|
181
181
|
|
182
182
|
def fetch_rows(sql)
|
183
183
|
execute(sql) do |sth|
|
184
|
-
offset = @opts[:offset]
|
185
184
|
db = @db
|
186
185
|
i = 1
|
187
186
|
column_info = get_column_info(sth)
|
188
187
|
cols = column_info.map{|c| c.at(1)}
|
189
|
-
cols.delete(row_number_column) if offset
|
190
188
|
@columns = cols
|
191
189
|
errors = [DB2CLI::SQL_NO_DATA_FOUND, DB2CLI::SQL_ERROR]
|
192
190
|
until errors.include?(rc = DB2CLI.SQLFetch(sth))
|
@@ -202,7 +200,6 @@ module Sequel
|
|
202
200
|
v
|
203
201
|
end
|
204
202
|
end
|
205
|
-
row.delete(row_number_column) if offset
|
206
203
|
yield row
|
207
204
|
end
|
208
205
|
end
|
data/lib/sequel/adapters/dbi.rb
CHANGED
@@ -88,16 +88,10 @@ module Sequel
|
|
88
88
|
execute(sql) do |s|
|
89
89
|
begin
|
90
90
|
columns = cols = s.column_names.map{|c| output_identifier(c)}
|
91
|
-
if opts[:offset] && offset_returns_row_number_column?
|
92
|
-
rn = row_number_column
|
93
|
-
columns = columns.dup
|
94
|
-
columns.delete(rn)
|
95
|
-
end
|
96
91
|
@columns = columns
|
97
92
|
s.fetch do |r|
|
98
93
|
row = {}
|
99
94
|
cols.each{|c| row[c] = r.shift}
|
100
|
-
row.delete(rn) if rn
|
101
95
|
yield row
|
102
96
|
end
|
103
97
|
ensure
|
@@ -408,7 +408,6 @@ module Sequel
|
|
408
408
|
# Fetch the rows from the database and yield plain hashes.
|
409
409
|
def fetch_rows(sql)
|
410
410
|
execute(sql) do |stmt|
|
411
|
-
offset = @opts[:offset]
|
412
411
|
columns = []
|
413
412
|
convert = convert_smallint_to_bool
|
414
413
|
cps = db.conversion_procs
|
@@ -421,7 +420,6 @@ module Sequel
|
|
421
420
|
columns << [key, cps[type]]
|
422
421
|
end
|
423
422
|
cols = columns.map{|c| c.at(0)}
|
424
|
-
cols.delete(row_number_column) if offset
|
425
423
|
@columns = cols
|
426
424
|
|
427
425
|
while res = stmt.fetch_array
|
@@ -429,7 +427,6 @@ module Sequel
|
|
429
427
|
res.zip(columns).each do |v, (k, pr)|
|
430
428
|
row[k] = ((pr ? pr.call(v) : v) if v)
|
431
429
|
end
|
432
|
-
row.delete(row_number_column) if offset
|
433
430
|
yield row
|
434
431
|
end
|
435
432
|
end
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -237,8 +237,10 @@ module Sequel
|
|
237
237
|
raise(Sequel::DatabaseError, 'driver.new.connect returned nil: probably bad JDBC connection string') unless c
|
238
238
|
c
|
239
239
|
rescue JavaSQL::SQLException, NativeException, StandardError => e2
|
240
|
-
|
241
|
-
|
240
|
+
unless e2.message == e.message
|
241
|
+
e2.message << "\n#{e.class.name}: #{e.message}"
|
242
|
+
end
|
243
|
+
raise e2
|
242
244
|
end
|
243
245
|
end
|
244
246
|
end
|
@@ -742,17 +744,13 @@ module Sequel
|
|
742
744
|
i = 0
|
743
745
|
meta.getColumnCount.times{cols << [output_identifier(meta.getColumnLabel(i+=1)), i]}
|
744
746
|
columns = cols.map{|c| c.at(0)}
|
745
|
-
if opts[:offset] && offset_returns_row_number_column?
|
746
|
-
rn = row_number_column
|
747
|
-
columns.delete(rn)
|
748
|
-
end
|
749
747
|
@columns = columns
|
750
748
|
ct = @convert_types
|
751
749
|
if (ct.nil? ? db.convert_types : ct)
|
752
750
|
cols.each{|c| c << nil}
|
753
|
-
process_result_set_convert(cols, result,
|
751
|
+
process_result_set_convert(cols, result, &block)
|
754
752
|
else
|
755
|
-
process_result_set_no_convert(cols, result,
|
753
|
+
process_result_set_no_convert(cols, result, &block)
|
756
754
|
end
|
757
755
|
ensure
|
758
756
|
result.close
|
@@ -776,7 +774,7 @@ module Sequel
|
|
776
774
|
# the result of as the column's conversion proc to speed up
|
777
775
|
# later processing. If the conversion proc exists, call it
|
778
776
|
# and return the result, otherwise, return the object.
|
779
|
-
def process_result_set_convert(cols, result
|
777
|
+
def process_result_set_convert(cols, result)
|
780
778
|
while result.next
|
781
779
|
row = {}
|
782
780
|
cols.each do |n, i, p|
|
@@ -798,18 +796,16 @@ module Sequel
|
|
798
796
|
v
|
799
797
|
end
|
800
798
|
end
|
801
|
-
row.delete(rn) if rn
|
802
799
|
yield row
|
803
800
|
end
|
804
801
|
end
|
805
802
|
|
806
803
|
# Yield rows without calling any conversion procs. This
|
807
804
|
# may yield Java values and not ruby values.
|
808
|
-
def process_result_set_no_convert(cols, result
|
805
|
+
def process_result_set_no_convert(cols, result)
|
809
806
|
while result.next
|
810
807
|
row = {}
|
811
808
|
cols.each{|n, i| row[n] = result.getObject(i)}
|
812
|
-
row.delete(rn) if rn
|
813
809
|
yield row
|
814
810
|
end
|
815
811
|
end
|
@@ -38,29 +38,13 @@ module Sequel
|
|
38
38
|
|
39
39
|
# Dataset class for AS400 datasets accessed via JDBC.
|
40
40
|
class Dataset < JDBC::Dataset
|
41
|
+
include EmulateOffsetWithRowNumber
|
42
|
+
|
41
43
|
WILDCARD = Sequel::LiteralString.new('*').freeze
|
42
44
|
FETCH_FIRST_ROW_ONLY = " FETCH FIRST ROW ONLY".freeze
|
43
45
|
FETCH_FIRST = " FETCH FIRST ".freeze
|
44
46
|
ROWS_ONLY = " ROWS ONLY".freeze
|
45
47
|
|
46
|
-
# AS400 needs to use a couple of subselects for queries with offsets.
|
47
|
-
def select_sql
|
48
|
-
return super unless o = @opts[:offset]
|
49
|
-
l = @opts[:limit]
|
50
|
-
order = @opts[:order]
|
51
|
-
dsa1 = dataset_alias(1)
|
52
|
-
dsa2 = dataset_alias(2)
|
53
|
-
rn = row_number_column
|
54
|
-
irn = Sequel::SQL::Identifier.new(rn).qualify(dsa2)
|
55
|
-
subselect_sql(unlimited.
|
56
|
-
from_self(:alias=>dsa1).
|
57
|
-
select_more(Sequel::SQL::QualifiedIdentifier.new(dsa1, WILDCARD),
|
58
|
-
Sequel::SQL::WindowFunction.new(SQL::Function.new(:ROW_NUMBER), Sequel::SQL::Window.new(:order=>order)).as(rn)).
|
59
|
-
from_self(:alias=>dsa2).
|
60
|
-
select(Sequel::SQL::QualifiedIdentifier.new(dsa2, WILDCARD)).
|
61
|
-
where(l ? ((irn > o) & (irn <= l + o)) : (irn > o))) # Leave off limit in case of limit(nil, offset)
|
62
|
-
end
|
63
|
-
|
64
48
|
# Modify the sql to limit the number of rows returned
|
65
49
|
def select_limit_sql(sql)
|
66
50
|
if l = @opts[:limit]
|
@@ -104,6 +104,16 @@ module Sequel
|
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
107
|
+
DATABASE_ERROR_REGEXPS = {
|
108
|
+
/The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index/ => UniqueConstraintViolation,
|
109
|
+
/violation of foreign key constraint/ => ForeignKeyConstraintViolation,
|
110
|
+
/The check constraint .+ was violated/ => CheckConstraintViolation,
|
111
|
+
/cannot accept a NULL value/ => NotNullConstraintViolation,
|
112
|
+
}.freeze
|
113
|
+
def database_error_regexps
|
114
|
+
DATABASE_ERROR_REGEXPS
|
115
|
+
end
|
116
|
+
|
107
117
|
# Use IDENTITY_VAL_LOCAL() to get the last inserted id.
|
108
118
|
def last_insert_id(conn, opts={})
|
109
119
|
statement(conn) do |stmt|
|
@@ -96,6 +96,16 @@ module Sequel
|
|
96
96
|
uri == 'jdbc:h2:mem:' ? o.merge(:max_connections=>1) : o
|
97
97
|
end
|
98
98
|
|
99
|
+
DATABASE_ERROR_REGEXPS = {
|
100
|
+
/Unique index or primary key violation/ => UniqueConstraintViolation,
|
101
|
+
/Referential integrity constraint violation/ => ForeignKeyConstraintViolation,
|
102
|
+
/Check constraint violation/ => CheckConstraintViolation,
|
103
|
+
/NULL not allowed for column/ => NotNullConstraintViolation,
|
104
|
+
}.freeze
|
105
|
+
def database_error_regexps
|
106
|
+
DATABASE_ERROR_REGEXPS
|
107
|
+
end
|
108
|
+
|
99
109
|
# Use IDENTITY() to get the last inserted id.
|
100
110
|
def last_insert_id(conn, opts={})
|
101
111
|
statement(conn) do |stmt|
|
@@ -52,6 +52,16 @@ module Sequel
|
|
52
52
|
"#{create_table_prefix_sql(name, options)} AS (#{sql}) WITH DATA"
|
53
53
|
end
|
54
54
|
|
55
|
+
DATABASE_ERROR_REGEXPS = {
|
56
|
+
/integrity constraint violation: unique constraint or index violation/ => UniqueConstraintViolation,
|
57
|
+
/integrity constraint violation: foreign key/ => ForeignKeyConstraintViolation,
|
58
|
+
/integrity constraint violation: check constraint/ => CheckConstraintViolation,
|
59
|
+
/integrity constraint violation: NOT NULL check constraint/ => NotNullConstraintViolation,
|
60
|
+
}.freeze
|
61
|
+
def database_error_regexps
|
62
|
+
DATABASE_ERROR_REGEXPS
|
63
|
+
end
|
64
|
+
|
55
65
|
# Use IDENTITY() to get the last inserted id.
|
56
66
|
def last_insert_id(conn, opts={})
|
57
67
|
statement(conn) do |stmt|
|