sequel 4.10.0 → 4.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +58 -0
- data/doc/association_basics.rdoc +1 -1
- data/doc/cheat_sheet.rdoc +0 -1
- data/doc/core_extensions.rdoc +2 -2
- data/doc/dataset_filtering.rdoc +5 -5
- data/doc/model_hooks.rdoc +9 -0
- data/doc/object_model.rdoc +7 -13
- data/doc/opening_databases.rdoc +3 -1
- data/doc/querying.rdoc +8 -8
- data/doc/release_notes/4.11.0.txt +147 -0
- data/doc/sql.rdoc +11 -7
- data/doc/virtual_rows.rdoc +4 -5
- data/lib/sequel/adapters/ibmdb.rb +24 -16
- data/lib/sequel/adapters/jdbc/h2.rb +5 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +5 -0
- data/lib/sequel/adapters/mock.rb +14 -2
- data/lib/sequel/adapters/shared/access.rb +6 -9
- data/lib/sequel/adapters/shared/cubrid.rb +5 -0
- data/lib/sequel/adapters/shared/db2.rb +5 -0
- data/lib/sequel/adapters/shared/firebird.rb +5 -0
- data/lib/sequel/adapters/shared/mssql.rb +23 -16
- data/lib/sequel/adapters/shared/mysql.rb +12 -2
- data/lib/sequel/adapters/shared/oracle.rb +31 -15
- data/lib/sequel/adapters/shared/postgres.rb +28 -4
- data/lib/sequel/adapters/shared/sqlanywhere.rb +5 -0
- data/lib/sequel/adapters/shared/sqlite.rb +12 -1
- data/lib/sequel/ast_transformer.rb +9 -7
- data/lib/sequel/connection_pool.rb +10 -4
- data/lib/sequel/database/features.rb +15 -0
- data/lib/sequel/database/schema_generator.rb +2 -2
- data/lib/sequel/database/schema_methods.rb +21 -3
- data/lib/sequel/database/transactions.rb +8 -4
- data/lib/sequel/dataset/actions.rb +13 -7
- data/lib/sequel/dataset/features.rb +7 -0
- data/lib/sequel/dataset/query.rb +28 -11
- data/lib/sequel/dataset/sql.rb +90 -14
- data/lib/sequel/extensions/constraint_validations.rb +2 -2
- data/lib/sequel/extensions/date_arithmetic.rb +1 -1
- data/lib/sequel/extensions/eval_inspect.rb +12 -6
- data/lib/sequel/extensions/pg_array_ops.rb +11 -2
- data/lib/sequel/extensions/pg_json.rb +130 -23
- data/lib/sequel/extensions/pg_json_ops.rb +196 -28
- data/lib/sequel/extensions/to_dot.rb +5 -7
- data/lib/sequel/model/associations.rb +0 -50
- data/lib/sequel/plugins/class_table_inheritance.rb +49 -21
- data/lib/sequel/plugins/many_through_many.rb +10 -11
- data/lib/sequel/plugins/serialization.rb +4 -1
- data/lib/sequel/plugins/sharding.rb +0 -9
- data/lib/sequel/plugins/single_table_inheritance.rb +4 -2
- data/lib/sequel/plugins/timestamps.rb +2 -2
- data/lib/sequel/sql.rb +166 -44
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +199 -133
- data/spec/core/connection_pool_spec.rb +6 -0
- data/spec/core/database_spec.rb +12 -0
- data/spec/core/dataset_spec.rb +58 -3
- data/spec/core/expression_filters_spec.rb +67 -5
- data/spec/core/mock_adapter_spec.rb +8 -4
- data/spec/core/schema_spec.rb +7 -0
- data/spec/core_extensions_spec.rb +14 -0
- data/spec/extensions/class_table_inheritance_spec.rb +23 -3
- data/spec/extensions/core_refinements_spec.rb +14 -0
- data/spec/extensions/eval_inspect_spec.rb +8 -4
- data/spec/extensions/pg_array_ops_spec.rb +6 -0
- data/spec/extensions/pg_json_ops_spec.rb +99 -0
- data/spec/extensions/pg_json_spec.rb +104 -4
- data/spec/extensions/serialization_spec.rb +19 -0
- data/spec/extensions/single_table_inheritance_spec.rb +11 -3
- data/spec/extensions/timestamps_spec.rb +10 -0
- data/spec/extensions/to_dot_spec.rb +8 -4
- data/spec/integration/database_test.rb +1 -1
- data/spec/integration/dataset_test.rb +9 -0
- data/spec/integration/schema_test.rb +27 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ced6249de982434d96b02340853663f604357771
|
4
|
+
data.tar.gz: 2f34bc5dff2cb2e0ffa1c613252291a52a0b5876
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8df573b48f64deb1af7958cdf2d09e75a5f8adb2709519e04f51cabc2b18f7b08e3da857261b0faec876e476b1a3bd961517f82d79bfb33ee9a236dfc066d899
|
7
|
+
data.tar.gz: becb87b9aecc164e06e48a4b5f86eb983ad9e3d09851155f50c935f0e17bccd26d57987dfdcc4635c4531d1cc07a1e753a20998b55c6fa9921e89c58310bc3dd
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,61 @@
|
|
1
|
+
=== 4.11.0 (2014-06-03)
|
2
|
+
|
3
|
+
* Add :model_map option to class_table_inheritance plugin so class names don't need to be stored in the database (jeremyevans)
|
4
|
+
|
5
|
+
* Set version when using for MySQL/SQLite emulation in the mock adapter (jeremyevans)
|
6
|
+
|
7
|
+
* Add support for CUBRID/SQLAnywhere emulation to the mock adapter (jeremyevans)
|
8
|
+
|
9
|
+
* Add support for the jsonb operators added in PostgreSQL 9.4 to the pg_json_ops extension (jeremyevans)
|
10
|
+
|
11
|
+
* Add support for new json/jsonb functions added in PostgreSQL 9.4 to the pg_json_ops extension (jeremyevans)
|
12
|
+
|
13
|
+
* Add support for the PostgreSQL 9.4+ jsonb type to the pg_json_ops extension (jeremyevans)
|
14
|
+
|
15
|
+
* Add support for derived column lists to Sequel.as and SQL::AliasMethods#as (jeremyevans)
|
16
|
+
|
17
|
+
* Support connecting to a DB2 catalog name in the ibmdb adapter (calh) (#821)
|
18
|
+
|
19
|
+
* Fix warnings in some cases in the ibmdb adapter (calh) (#820)
|
20
|
+
|
21
|
+
* Add SQL::Function#with_ordinality for creating set returning functions WITH ORDINALITY (jeremyevans)
|
22
|
+
|
23
|
+
* Add SQL::Function#filter for creating filtered aggregate function calls (jeremyevans)
|
24
|
+
|
25
|
+
* Add SQL::Function#within_group for creating ordered-set and hypothetical-set aggregate functions (jeremyevans)
|
26
|
+
|
27
|
+
* Add SQL::Function#lateral, for creating set returning functions that will be preceded by LATERAL (jeremyevans)
|
28
|
+
|
29
|
+
* Add SQL::Function#quoted and #unquoted methods, to enable/disable quoting of function names (jeremyevans)
|
30
|
+
|
31
|
+
* Deprecate Dataset#{window,emulated,}_function_sql_append (jeremyevans)
|
32
|
+
|
33
|
+
* Deprecate SQL::WindowFunction and SQL::EmulatedFunction classes, switch to using options on SQL::Function (jeremyevans)
|
34
|
+
|
35
|
+
* Only modify changed_columns if deserialized value changes in the serialization plugin (jeremyevans) (#818)
|
36
|
+
|
37
|
+
* Support PostgreSQL 9.4+ jsonb type in the pg_json extension (jeremyevans)
|
38
|
+
|
39
|
+
* Allow Postgres::ArrayOp#unnest to accept arguments in the pg_array_ops extension (jeremyevans)
|
40
|
+
|
41
|
+
* Add Postgres::ArrayOp#cardinality to the pg_array_ops extension (jeremyevans)
|
42
|
+
|
43
|
+
* Add :check option to Database#create_view for WITH [LOCAL] CHECK OPTION support (jeremyevans)
|
44
|
+
|
45
|
+
* Add :concurrently option to Database#refresh_view on PostgreSQL to support concurrent refresh of materialized views (jeremyevans)
|
46
|
+
|
47
|
+
* Call the :after_connect Database option proc with both the connection and server/shard if it accepts 2 arguments (pedro, jeremyevans) (#813)
|
48
|
+
|
49
|
+
* Make multiple plugins set values before validation instead of before create, works better with auto_validations (jeremyevans)
|
50
|
+
|
51
|
+
* Support a default Dataset#import slice size, set to 500 on SQLite (jeremyevans) (#810)
|
52
|
+
|
53
|
+
* Make :read_only transaction option be per-savepoint on PostgreSQL (jeremyevans) (#807)
|
54
|
+
|
55
|
+
* Add :rank option to Dataset#full_text_search on PostgreSQL, to order by the ranking (jeremyevans) (#809)
|
56
|
+
|
57
|
+
* Remove methods deprecated in 4.10.0 (jeremyevans)
|
58
|
+
|
1
59
|
=== 4.10.0 (2014-05-01)
|
2
60
|
|
3
61
|
* Make Model.include API same as Module.include (ged) (#803)
|
data/doc/association_basics.rdoc
CHANGED
@@ -360,7 +360,7 @@ it can be further filtered, ordered, etc.:
|
|
360
360
|
order(:copies_sold).
|
361
361
|
limit(10)
|
362
362
|
# SELECT * FROM albums
|
363
|
-
# WHERE ((artist_id = 20) AND (name LIKE 'A%'))
|
363
|
+
# WHERE ((artist_id = 20) AND (name LIKE 'A%' ESCAPE '\'))
|
364
364
|
# ORDER BY copies_sold LIMIT 10
|
365
365
|
|
366
366
|
Records retrieved using the +_dataset+ method are not cached in the
|
data/doc/cheat_sheet.rdoc
CHANGED
@@ -216,6 +216,5 @@ Savepoints can be used if the database supports it:
|
|
216
216
|
|
217
217
|
dataset.sql # "SELECT * FROM items"
|
218
218
|
dataset.delete_sql # "DELETE FROM items"
|
219
|
-
dataset.where(:name => 'sequel').exists # "EXISTS ( SELECT * FROM items WHERE name = 'sequel' )"
|
220
219
|
dataset.columns #=> array of columns in the result set, does a SELECT
|
221
220
|
DB.schema(:items) => [[:id, {:type=>:integer, ...}], [:name, {:type=>:string, ...}], ...]
|
data/doc/core_extensions.rdoc
CHANGED
@@ -164,7 +164,7 @@ Note the reversed order of the arguments. For the Symbol#qualify method, the ar
|
|
164
164
|
|
165
165
|
Symbol#like returns a case sensitive LIKE expression between the identifier and the given argument:
|
166
166
|
|
167
|
-
:a.like('b%') # SQL: a LIKE 'b%'
|
167
|
+
:a.like('b%') # SQL: a LIKE 'b%' ESCAPE '\'
|
168
168
|
|
169
169
|
Alternative: Sequel.like:
|
170
170
|
|
@@ -174,7 +174,7 @@ Alternative: Sequel.like:
|
|
174
174
|
|
175
175
|
Symbol#ilike returns a case insensitive LIKE expression between the identifier and the given argument:
|
176
176
|
|
177
|
-
:a.ilike('b%') # SQL: a ILIKE 'b%'
|
177
|
+
:a.ilike('b%') # SQL: a ILIKE 'b%' ESCAPE '\'
|
178
178
|
|
179
179
|
Alternative: Sequel.ilike:
|
180
180
|
|
data/doc/dataset_filtering.rdoc
CHANGED
@@ -143,12 +143,12 @@ Or against SQL functions:
|
|
143
143
|
You can search SQL strings in a case sensitive manner using the Sequel.like method:
|
144
144
|
|
145
145
|
items.where(Sequel.like(:name, 'Acme%')).sql
|
146
|
-
#=> "SELECT * FROM items WHERE (name LIKE 'Acme%')"
|
146
|
+
#=> "SELECT * FROM items WHERE (name LIKE 'Acme%' ESCAPE '\')"
|
147
147
|
|
148
148
|
You can search SQL strings in a case insensitive manner using the Sequel.ilike method:
|
149
149
|
|
150
150
|
items.where(Sequel.ilike(:name, 'Acme%')).sql
|
151
|
-
#=> "SELECT * FROM items WHERE (name ILIKE 'Acme%')"
|
151
|
+
#=> "SELECT * FROM items WHERE (name ILIKE 'Acme%' ESCAPE '\')"
|
152
152
|
|
153
153
|
You can specify a Regexp as a like argument, but this will probably only work
|
154
154
|
on PostgreSQL and MySQL:
|
@@ -159,19 +159,19 @@ on PostgreSQL and MySQL:
|
|
159
159
|
Like can also take more than one argument:
|
160
160
|
|
161
161
|
items.where(Sequel.like(:name, 'Acme%', /Beta.*/)).sql
|
162
|
-
#=> "SELECT * FROM items WHERE ((name LIKE 'Acme%') OR (name ~ 'Beta.*'))"
|
162
|
+
#=> "SELECT * FROM items WHERE ((name LIKE 'Acme%' ESCAPE '\') OR (name ~ 'Beta.*'))"
|
163
163
|
|
164
164
|
== String concatenation
|
165
165
|
|
166
166
|
You can concatenate SQL strings using Sequel.join:
|
167
167
|
|
168
168
|
items.where(Sequel.join([:name, :comment]).like('%acme%')).sql
|
169
|
-
#=> "SELECT * FROM items WHERE ((name || comment) LIKE 'Acme%')"
|
169
|
+
#=> "SELECT * FROM items WHERE ((name || comment) LIKE 'Acme%' ESCAPE '\')"
|
170
170
|
|
171
171
|
Sequel.join also takes a join argument:
|
172
172
|
|
173
173
|
items.filter(Sequel.join([:name, :comment], ' ').like('%acme%')).sql
|
174
|
-
#=> "SELECT * FROM items WHERE ((name || ' ' || comment) LIKE 'Acme%')"
|
174
|
+
#=> "SELECT * FROM items WHERE ((name || ' ' || comment) LIKE 'Acme%' ESCAPE '\')"
|
175
175
|
|
176
176
|
== Filtering using sub-queries
|
177
177
|
|
data/doc/model_hooks.rdoc
CHANGED
@@ -81,6 +81,15 @@ If you aren't using transactions when saving or destroying model objects, and th
|
|
81
81
|
|
82
82
|
The purpose of these hooks is dealing with external systems that are interacting with the same database. For example, let's say you have a model that stores a picture, and you have a background job library that makes thumbnails of all of the pictures. So when a model object is created, you want to add a background job that will create the thumbnail for the picture. If you used after_save for this and transactions are being used, you are subject to a race condition where the background job library will check the database table for the record before the transaction that saved the record commits, and it won't be able to see the record's data. Using after_commit, you are guaranteed that the background job library will not get notified of the record until after the transaction commits and the data is viewable.
|
83
83
|
|
84
|
+
Note that when using the after_commit or after_rollback hooks, you don't know whether the saved object was newly created or updated. If you only want to run an action after commit of a newly created record, you need to use the Database's after_commit inside the model's after_create hook:
|
85
|
+
|
86
|
+
class Album < Sequel::Model
|
87
|
+
def after_create
|
88
|
+
super
|
89
|
+
db.after_commit{update_external_cache}
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
84
93
|
== Running Hooks
|
85
94
|
|
86
95
|
Sequel does not provide a simple way to turn off the running of save/create/update hooks. If you attempt to save a model object, the save hooks are always called. All model instance methods that modify the database call save in some manner, so you can be sure that if you define the hooks, they will be called when you save the object.
|
data/doc/object_model.rdoc
CHANGED
@@ -291,12 +291,17 @@ The following shortcuts exist for creating Sequel::SQL::QualifiedIdentifier obje
|
|
291
291
|
Sequel::SQL::AliasedExpression objects represent aliased expressions in SQL. The alias
|
292
292
|
is treated as an identifier, but the expression can be an arbitrary Sequel expression:
|
293
293
|
|
294
|
-
Sequel::SQL::AliasedExpression.new(:column, :alias)
|
294
|
+
Sequel::SQL::AliasedExpression.new(:column, :alias)
|
295
|
+
# "column" AS "alias"
|
296
|
+
|
297
|
+
Sequel::SQL::AliasedExpression.new(:table, :alias, [:column_alias1, :column_alias2])
|
298
|
+
# "table" AS "alias"("column_alias1", "column_alias2")
|
295
299
|
|
296
300
|
The following shortcuts exist for creating Sequel::SQL::AliasedExpression objects:
|
297
301
|
|
298
302
|
Sequel.expr(:column___alias)
|
299
303
|
Sequel.as(:column, :alias)
|
304
|
+
Sequel.as(:column, :alias, [:column_alias1, :column_alias2])
|
300
305
|
:column.as(:alias) # core_extensions extension
|
301
306
|
|
302
307
|
=== Sequel::SQL::ComplexExpression
|
@@ -534,7 +539,7 @@ These objects are usually not instantiated manually. See the
|
|
534
539
|
|
535
540
|
=== Sequel::SQL::Window
|
536
541
|
|
537
|
-
Sequel::SQL::Window objects represent the windows used by Sequel::SQL::
|
542
|
+
Sequel::SQL::Window objects represent the windows used by Sequel::SQL::Function.
|
538
543
|
They use a hash-based API, supporting the :frame, :order, :partition, and :window
|
539
544
|
options:
|
540
545
|
|
@@ -544,17 +549,6 @@ options:
|
|
544
549
|
Sequel::SQL::Window.new(:parition=>:a, :frame=>:all)
|
545
550
|
# (PARTITION BY "a" ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
|
546
551
|
|
547
|
-
=== Sequel::SQL::WindowFunction
|
548
|
-
|
549
|
-
Sequel::SQL::WindowFunction objects represent SQL window function calls. These
|
550
|
-
just combine a Sequel::SQL::Function with a Sequel::SQL::Window:
|
551
|
-
|
552
|
-
function = Sequel::SQL::Function.new(:f, 1)
|
553
|
-
window = Sequel::SQL::Window.new(:order=>:a)
|
554
|
-
Sequel::SQL::WindowFunction.new(function, window) # f(1) OVER (ORDER BY "a")
|
555
|
-
|
556
|
-
Virtual rows offer a shortcut for creating Sequel::SQL::Window objects.
|
557
|
-
|
558
552
|
=== Sequel::SQL::Wrapper
|
559
553
|
|
560
554
|
Sequel::SQL::Wrapper objects wrap arbitrary objects so that they can be used
|
data/doc/opening_databases.rdoc
CHANGED
@@ -78,7 +78,9 @@ These options are shared by all adapters unless otherwise noted.
|
|
78
78
|
|
79
79
|
The following options can be specified and are passed to the database's internal connection pool.
|
80
80
|
|
81
|
-
:after_connect :: A
|
81
|
+
:after_connect :: A callable object called after each new connection is made, with the
|
82
|
+
connection object (and server argument if the callable accepts 2 arguments),
|
83
|
+
useful for customizations that you want to apply to all connections (default: nil).
|
82
84
|
:max_connections :: The maximum size of the connection pool (default: 4 connections on most databases)
|
83
85
|
:pool_sleep_time :: The number of seconds to sleep before trying to acquire a connection again (default: 0.001 seconds)
|
84
86
|
:pool_timeout :: The number of seconds to wait if a connection cannot be acquired before raising an error (default: 5 seconds)
|
data/doc/querying.rdoc
CHANGED
@@ -63,7 +63,7 @@ Any options you pass to +first+ will be used as a filter:
|
|
63
63
|
=> #<Artist @values={:name=>"YJM", :id=>1}>
|
64
64
|
|
65
65
|
artist = Artist.first(Sequel.like(:name, 'Y%'))
|
66
|
-
# SELECT * FROM artists WHERE (name LIKE 'Y%') LIMIT 1
|
66
|
+
# SELECT * FROM artists WHERE (name LIKE 'Y%' ESCAPE '\') LIMIT 1
|
67
67
|
=> #<Artist @values={:name=>"YJM", :id=>1}>
|
68
68
|
|
69
69
|
If there is no matching row, +first+ will return nil. If you want to
|
@@ -273,7 +273,7 @@ Let's say we are only interested in the artists whose names
|
|
273
273
|
start with "A":
|
274
274
|
|
275
275
|
ds2 = ds1.where(Sequel.like(:name, 'A%'))
|
276
|
-
# SELECT * FROM artists WHERE name LIKE 'A%'
|
276
|
+
# SELECT * FROM artists WHERE name LIKE 'A%' ESCAPE '\'
|
277
277
|
|
278
278
|
Here we see that +where+ returns a dataset that adds a +WHERE+
|
279
279
|
clause to the query. It's important to note that +where+ does
|
@@ -282,7 +282,7 @@ not modify the receiver:
|
|
282
282
|
ds1
|
283
283
|
# SELECT * FROM artists
|
284
284
|
ds2
|
285
|
-
# SELECT * FROM artists WHERE name LIKE 'A%'
|
285
|
+
# SELECT * FROM artists WHERE name LIKE 'A%' ESCAPE '\'
|
286
286
|
|
287
287
|
In Sequel, most dataset methods that you will be using will
|
288
288
|
not modify the dataset itself, so you can freely use the dataset in multiple
|
@@ -293,7 +293,7 @@ Let's say we only want to select the id and name columns, and that
|
|
293
293
|
we want to order by name:
|
294
294
|
|
295
295
|
ds3 = ds.order(:name).select(:id, :name)
|
296
|
-
# SELECT id, name FROM artists WHERE name LIKE 'A%' ORDER BY name
|
296
|
+
# SELECT id, name FROM artists WHERE name LIKE 'A%' ESCAPE '\' ORDER BY name
|
297
297
|
|
298
298
|
Note how you don't need to assign the returned value of order to a variable,
|
299
299
|
and then call select on that. Because order just returns a dataset, you can
|
@@ -403,7 +403,7 @@ expressions are instances of subclasses of Sequel::SQL::Expression. You've
|
|
403
403
|
already seen an example earlier:
|
404
404
|
|
405
405
|
Artist.where(Sequel.like(:name, 'Y%'))
|
406
|
-
# SELECT * FROM artists WHERE name LIKE 'Y%'
|
406
|
+
# SELECT * FROM artists WHERE name LIKE 'Y%' ESCAPE '\'
|
407
407
|
|
408
408
|
In this case Sequel.like returns a Sequel::SQL::BooleanExpression object,
|
409
409
|
which is used directly in the filter.
|
@@ -415,7 +415,7 @@ object. In most cases, the SQL::Expression returned supports the & operator for
|
|
415
415
|
+AND+, the | operator for +OR+, and the ~ operator for inversion:
|
416
416
|
|
417
417
|
Artist.where(Sequel.like(:name, 'Y%') & (Sequel.expr(:b=>1) | Sequel.~(:c=>3)))
|
418
|
-
# SELECT * FROM artists WHERE name LIKE 'Y%' AND (b = 1 OR c != 3)
|
418
|
+
# SELECT * FROM artists WHERE name LIKE 'Y%' ESCAPE '\' AND (b = 1 OR c != 3)
|
419
419
|
|
420
420
|
You can combine these expression operators with the virtual row support:
|
421
421
|
|
@@ -493,7 +493,7 @@ So to do a NOT IN with an array:
|
|
493
493
|
Or to use the NOT LIKE operator:
|
494
494
|
|
495
495
|
Artist.exclude(Sequel.like(:name, '%J%'))
|
496
|
-
# SELECT * FROM artists WHERE name NOT LIKE '%J%'
|
496
|
+
# SELECT * FROM artists WHERE name NOT LIKE '%J%' ESCAPE '\'
|
497
497
|
|
498
498
|
=== Removing
|
499
499
|
|
@@ -982,7 +982,7 @@ If you just want to know whether the current dataset would return any rows, use
|
|
982
982
|
=> true
|
983
983
|
|
984
984
|
Album.where(Sequel.like(:name, 'R%')).empty?
|
985
|
-
# SELECT 1 FROM albums WHERE name LIKE 'R%' LIMIT 1
|
985
|
+
# SELECT 1 FROM albums WHERE name LIKE 'R%' ESCAPE '\' LIMIT 1
|
986
986
|
=> false
|
987
987
|
|
988
988
|
== Aggregate Calculations
|
@@ -0,0 +1,147 @@
|
|
1
|
+
= New SQL Function Features
|
2
|
+
|
3
|
+
* SQL::Function now supports an options hash for functions.
|
4
|
+
Unfortunately, since SQL::Function#initialize does not support
|
5
|
+
an options hash, you need to use SQL::Function.new! to create
|
6
|
+
a function with an options hash. You can also call methods on
|
7
|
+
the SQL::Function instance, which will return a new SQL::Function
|
8
|
+
with the appropriate option set.
|
9
|
+
|
10
|
+
* SQL::Function#quoted has been added, which will return a new
|
11
|
+
SQL::Function instance that will quote the function name (if
|
12
|
+
the database supports quoting function names).
|
13
|
+
|
14
|
+
* SQL::Function#unquoted has been added, which will return a new
|
15
|
+
SQL::Function instance that will not quote the function name.
|
16
|
+
|
17
|
+
* SQL::Function#lateral has been added, which will return a new
|
18
|
+
SQL::Function instance that will be preceded by LATERAL when
|
19
|
+
literalized, useful for set-returning functions.
|
20
|
+
|
21
|
+
* SQL::Function#within_group has been added, for creating
|
22
|
+
ordered-set and hypothetical-set functions that use WITHIN GROUP.
|
23
|
+
|
24
|
+
* SQL::Function#filter has been added, for creating filtered
|
25
|
+
aggregate function calls using FILTER.
|
26
|
+
|
27
|
+
* SQL::Function#with_ordinality has been added, for creating set
|
28
|
+
returning functions that also include a row number for every
|
29
|
+
row in the set, using WITH ORDINALITY.
|
30
|
+
|
31
|
+
= New PostgreSQL Features
|
32
|
+
|
33
|
+
* The jsonb type added in 9.4 is now supported in the pg_json
|
34
|
+
extension. To create a jsonb type manually, you need to call
|
35
|
+
Sequel.pg_jsonb.
|
36
|
+
|
37
|
+
The new json and jsonb functions and operators added in 9.4 are
|
38
|
+
now supported in the pg_json_ops extension. You can use the jsonb
|
39
|
+
functions and operators by creating a Postgres::JSONBOp using
|
40
|
+
Sequel.pg_jsonb_op.
|
41
|
+
|
42
|
+
* Database#full_text_search now takes a :rank option to order by the
|
43
|
+
ranking.
|
44
|
+
|
45
|
+
* Database#refresh_view now supports a :concurrently option, to
|
46
|
+
refresh a materialized view concurrently, supported on 9.4+.
|
47
|
+
|
48
|
+
* Postgres::ArrayOp#cardinality has been added to the pg_array_ops
|
49
|
+
extension, for easy use of the cardinality method added in 9.4.
|
50
|
+
|
51
|
+
* Postgres::ArrayOp#unnest in the pg_array_ops extension now accepts
|
52
|
+
arguments. PostgreSQL 9.4+ supports this if unnest is used in the
|
53
|
+
FROM clause.
|
54
|
+
|
55
|
+
= Other New Features
|
56
|
+
|
57
|
+
* Sequel now supports derived column lists (table aliases that include
|
58
|
+
column aliases) via Sequel.as and SQL::AliasedMethods#as:
|
59
|
+
|
60
|
+
Sequel.as(:table, :alias, [:c1, :c2])
|
61
|
+
# table AS alias(c1, c2)
|
62
|
+
|
63
|
+
Not all databases support this, but it is in SQL92 and Sequel now
|
64
|
+
supports it by default. Derived column lists make it easier to
|
65
|
+
alias columns when using set-returning functions.
|
66
|
+
|
67
|
+
Dataset#from_self now supports derived column lists via the new
|
68
|
+
:column_aliases option (which requires the :alias option to take
|
69
|
+
effect).
|
70
|
+
|
71
|
+
* Database#create_view now supports a :check option, to use
|
72
|
+
WITH CHECK OPTION. You can also use :check=>:local for
|
73
|
+
WITH LOCAL CHECK OPTION. These clauses make it so when you are
|
74
|
+
inserting into/updating the view, you can only modify rows in the
|
75
|
+
underlying table if the result would be returned by the view.
|
76
|
+
|
77
|
+
* The :after_connect Database option proc now can accept two
|
78
|
+
arguments. If the arity of the proc is 2, Sequel will pass both
|
79
|
+
the connection object and the shard symbol.
|
80
|
+
|
81
|
+
* The class_table_inheritance plugin now supports a :model_map
|
82
|
+
option similar to the single_table_inheritance plugin, allowing
|
83
|
+
use of the plugin without storing ruby class names in the database.
|
84
|
+
Note that if you use this option, you must set the correct value
|
85
|
+
for the kind column manually when creating the row.
|
86
|
+
|
87
|
+
* Support for CUBRID/SQLAnywhere emulation has been added to the
|
88
|
+
mock adapter.
|
89
|
+
|
90
|
+
= Other Improvements
|
91
|
+
|
92
|
+
* Dataset#import now supports a default slice size, which Sequel
|
93
|
+
sets to 500 on SQLite as that is the limit that SQLite supports in
|
94
|
+
a single statement.
|
95
|
+
|
96
|
+
* The serialization plugin now only modifies changed_columns in the
|
97
|
+
setter method if the deserialized value has changed, similar to
|
98
|
+
how Sequel's standard column setters work. Note that if you are
|
99
|
+
mutating the deserialized value (i.e. not calling the setter
|
100
|
+
method), you still need to use the
|
101
|
+
serialization_modification_detection plugin.
|
102
|
+
|
103
|
+
* Plugins that set column values for new objects before creation now
|
104
|
+
use before_validation instead of before_create, which works better
|
105
|
+
when the auto_validations plugin is used.
|
106
|
+
|
107
|
+
* The :read_only transaction option is now applied per-savepoint on
|
108
|
+
PostgreSQL. Note that this allows you to have a READ ONLY
|
109
|
+
savepoint in a READ WRITE transaction, it does not allow you to
|
110
|
+
have a READ WRITE savepoint in a READ ONLY transaction.
|
111
|
+
|
112
|
+
* In the ibm_db adapter, fix warnings when using certain column names.
|
113
|
+
|
114
|
+
* Support connecting to a DB2 catalog name in the ibm_db adapter, by
|
115
|
+
providing a :database option without a :host or :port option.
|
116
|
+
|
117
|
+
* The mock adapter now sets an emulated version when using MySQL and
|
118
|
+
SQLite. Additionally, the emulated version for PostgreSQL and
|
119
|
+
Microsoft SQL Server has been updated.
|
120
|
+
|
121
|
+
= Backwards Compatibility
|
122
|
+
|
123
|
+
* External adapters that override Dataset#as_sql_append now need to
|
124
|
+
have the method accept two arguments.
|
125
|
+
|
126
|
+
* Model.eager_loading_dataset, .apply_association_dataset_opts, and
|
127
|
+
.def_{add_method,association_dataset_methods,remove_methods} have
|
128
|
+
been removed (they were deprecated in 4.10.0).
|
129
|
+
|
130
|
+
* SQL::WindowFunction and SQL::EmulatedFunction classes are now
|
131
|
+
deprecated, as well as Dataset methods that literalize instances of
|
132
|
+
these classes. These classes are replaced by using options on
|
133
|
+
SQL::Function instances.
|
134
|
+
|
135
|
+
* Passing a table_alias argument when creating an SQL::JoinClause
|
136
|
+
manually is no longer supported. You now need to pass the table as
|
137
|
+
an SQL::AliasedExpression if the table needs to be aliased.
|
138
|
+
|
139
|
+
* ASTTransformer no longer transforms the table alias for
|
140
|
+
SQL::JoinClause. This is for consistency with
|
141
|
+
SQL::AliasedExpression.
|
142
|
+
|
143
|
+
* SQL standard casts are now used in Database#full_text_search, which
|
144
|
+
can break tests that expect specific SQL.
|
145
|
+
|
146
|
+
* The to_dot extension now uses slightly different output for
|
147
|
+
SQL::Function and SQL::JoinClause instances.
|
data/doc/sql.rdoc
CHANGED
@@ -178,6 +178,10 @@ You can also use the <tt>Sequel.as</tt> method to create an alias, and the +as+
|
|
178
178
|
Sequel.as(:column, :alias) # "column" AS "alias"
|
179
179
|
Sequel.qualify(:table, :column).as(:alias) # "table"."column" AS "alias"
|
180
180
|
|
181
|
+
If you want to use a derived column list, you can provide an array of column aliases:
|
182
|
+
|
183
|
+
Sequel.as(:table, :alias, [:c1, :c2]) # "table" AS "alias"("c1", "c2")
|
184
|
+
|
181
185
|
=== Functions
|
182
186
|
|
183
187
|
The easiest way to use SQL functions is via a virtual row:
|
@@ -452,19 +456,19 @@ Just like ruby's <tt>String#join</tt>, you can provide an argument for a string
|
|
452
456
|
|
453
457
|
For the LIKE operator, Sequel defines the +like+ and +ilike+ methods on most Sequel-specific expression objects:
|
454
458
|
|
455
|
-
Sequel.expr(:name).like('A%') # ("name" LIKE 'A%')
|
456
|
-
Sequel.expr(:name).ilike('A%') # ("name" ILIKE 'A%')
|
459
|
+
Sequel.expr(:name).like('A%') # ("name" LIKE 'A%' ESCAPE '\')
|
460
|
+
Sequel.expr(:name).ilike('A%') # ("name" ILIKE 'A%' ESCAPE '\')
|
457
461
|
|
458
462
|
You can also use the <tt>Sequel.like</tt> and <tt>Sequel.ilike</tt> methods:
|
459
463
|
|
460
|
-
Sequel.like(:name, 'A%') # ("name" LIKE 'A%')
|
461
|
-
Sequel.ilike(:name, 'A%') # ("name" ILIKE 'A%')
|
464
|
+
Sequel.like(:name, 'A%') # ("name" LIKE 'A%' ESCAPE '\')
|
465
|
+
Sequel.ilike(:name, 'A%') # ("name" ILIKE 'A%' ESCAPE '\')
|
462
466
|
|
463
467
|
Note the above syntax for ilike, while Sequel's default, is specific to PostgreSQL. However, most other adapters override the behavior. For example, on MySQL, Sequel uses LIKE BINARY for +like+, and LIKE for +ilike+. If the database supports both case sensitive and case insensitive LIKE, then +like+ will use a case sensitive LIKE, and +ilike+ will use a case insensitive LIKE.
|
464
468
|
|
465
469
|
Inverting the LIKE operator works like other inversions:
|
466
470
|
|
467
|
-
~Sequel.like(:name, 'A%') # ("name" NOT LIKE 'A%')
|
471
|
+
~Sequel.like(:name, 'A%') # ("name" NOT LIKE 'A%' ESCAPE '\')
|
468
472
|
|
469
473
|
Sequel also supports SQL regular expressions on MySQL and PostgreSQL. You can use these by passing a ruby regular expression to +like+ or +ilike+, or by making the regular expression a hash value:
|
470
474
|
|
@@ -553,12 +557,12 @@ If you don't want to select from any FROM tables, just call dataset:
|
|
553
557
|
Once you have your dataset object, you build queries by chaining methods, usually with one method per clause in the query:
|
554
558
|
|
555
559
|
DB[:albums].select(:id, :name).where(Sequel.like(:name, 'A%')).order(:name)
|
556
|
-
# SELECT id, name FROM albums WHERE (name LIKE 'A%') ORDER BY name
|
560
|
+
# SELECT id, name FROM albums WHERE (name LIKE 'A%' ESCAPE '\') ORDER BY name
|
557
561
|
|
558
562
|
Note that the order of your method chain is not usually important unless you have multiple methods that affect the same clause:
|
559
563
|
|
560
564
|
DB[:albums].order(:name).where(Sequel.like(:name, 'A%')).select(:id, :name)
|
561
|
-
# SELECT id, name FROM albums WHERE (name LIKE 'A%') ORDER BY name
|
565
|
+
# SELECT id, name FROM albums WHERE (name LIKE 'A%' ESCAPE '\') ORDER BY name
|
562
566
|
|
563
567
|
=== Using the Same Dataset for SELECT, INSERT, UPDATE, and DELETE
|
564
568
|
|