sequel 3.43.0 → 3.44.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 +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|
|