sequel 4.10.0 → 4.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +58 -0
  3. data/doc/association_basics.rdoc +1 -1
  4. data/doc/cheat_sheet.rdoc +0 -1
  5. data/doc/core_extensions.rdoc +2 -2
  6. data/doc/dataset_filtering.rdoc +5 -5
  7. data/doc/model_hooks.rdoc +9 -0
  8. data/doc/object_model.rdoc +7 -13
  9. data/doc/opening_databases.rdoc +3 -1
  10. data/doc/querying.rdoc +8 -8
  11. data/doc/release_notes/4.11.0.txt +147 -0
  12. data/doc/sql.rdoc +11 -7
  13. data/doc/virtual_rows.rdoc +4 -5
  14. data/lib/sequel/adapters/ibmdb.rb +24 -16
  15. data/lib/sequel/adapters/jdbc/h2.rb +5 -0
  16. data/lib/sequel/adapters/jdbc/hsqldb.rb +5 -0
  17. data/lib/sequel/adapters/mock.rb +14 -2
  18. data/lib/sequel/adapters/shared/access.rb +6 -9
  19. data/lib/sequel/adapters/shared/cubrid.rb +5 -0
  20. data/lib/sequel/adapters/shared/db2.rb +5 -0
  21. data/lib/sequel/adapters/shared/firebird.rb +5 -0
  22. data/lib/sequel/adapters/shared/mssql.rb +23 -16
  23. data/lib/sequel/adapters/shared/mysql.rb +12 -2
  24. data/lib/sequel/adapters/shared/oracle.rb +31 -15
  25. data/lib/sequel/adapters/shared/postgres.rb +28 -4
  26. data/lib/sequel/adapters/shared/sqlanywhere.rb +5 -0
  27. data/lib/sequel/adapters/shared/sqlite.rb +12 -1
  28. data/lib/sequel/ast_transformer.rb +9 -7
  29. data/lib/sequel/connection_pool.rb +10 -4
  30. data/lib/sequel/database/features.rb +15 -0
  31. data/lib/sequel/database/schema_generator.rb +2 -2
  32. data/lib/sequel/database/schema_methods.rb +21 -3
  33. data/lib/sequel/database/transactions.rb +8 -4
  34. data/lib/sequel/dataset/actions.rb +13 -7
  35. data/lib/sequel/dataset/features.rb +7 -0
  36. data/lib/sequel/dataset/query.rb +28 -11
  37. data/lib/sequel/dataset/sql.rb +90 -14
  38. data/lib/sequel/extensions/constraint_validations.rb +2 -2
  39. data/lib/sequel/extensions/date_arithmetic.rb +1 -1
  40. data/lib/sequel/extensions/eval_inspect.rb +12 -6
  41. data/lib/sequel/extensions/pg_array_ops.rb +11 -2
  42. data/lib/sequel/extensions/pg_json.rb +130 -23
  43. data/lib/sequel/extensions/pg_json_ops.rb +196 -28
  44. data/lib/sequel/extensions/to_dot.rb +5 -7
  45. data/lib/sequel/model/associations.rb +0 -50
  46. data/lib/sequel/plugins/class_table_inheritance.rb +49 -21
  47. data/lib/sequel/plugins/many_through_many.rb +10 -11
  48. data/lib/sequel/plugins/serialization.rb +4 -1
  49. data/lib/sequel/plugins/sharding.rb +0 -9
  50. data/lib/sequel/plugins/single_table_inheritance.rb +4 -2
  51. data/lib/sequel/plugins/timestamps.rb +2 -2
  52. data/lib/sequel/sql.rb +166 -44
  53. data/lib/sequel/version.rb +1 -1
  54. data/spec/adapters/postgres_spec.rb +199 -133
  55. data/spec/core/connection_pool_spec.rb +6 -0
  56. data/spec/core/database_spec.rb +12 -0
  57. data/spec/core/dataset_spec.rb +58 -3
  58. data/spec/core/expression_filters_spec.rb +67 -5
  59. data/spec/core/mock_adapter_spec.rb +8 -4
  60. data/spec/core/schema_spec.rb +7 -0
  61. data/spec/core_extensions_spec.rb +14 -0
  62. data/spec/extensions/class_table_inheritance_spec.rb +23 -3
  63. data/spec/extensions/core_refinements_spec.rb +14 -0
  64. data/spec/extensions/eval_inspect_spec.rb +8 -4
  65. data/spec/extensions/pg_array_ops_spec.rb +6 -0
  66. data/spec/extensions/pg_json_ops_spec.rb +99 -0
  67. data/spec/extensions/pg_json_spec.rb +104 -4
  68. data/spec/extensions/serialization_spec.rb +19 -0
  69. data/spec/extensions/single_table_inheritance_spec.rb +11 -3
  70. data/spec/extensions/timestamps_spec.rb +10 -0
  71. data/spec/extensions/to_dot_spec.rb +8 -4
  72. data/spec/integration/database_test.rb +1 -1
  73. data/spec/integration/dataset_test.rb +9 -0
  74. data/spec/integration/schema_test.rb +27 -0
  75. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d32a56c879a430a1257dd8e5f13e7346a4fe52bc
4
- data.tar.gz: 5dd875255c904b9b4a26e8b62c8beb1e31c20a59
3
+ metadata.gz: ced6249de982434d96b02340853663f604357771
4
+ data.tar.gz: 2f34bc5dff2cb2e0ffa1c613252291a52a0b5876
5
5
  SHA512:
6
- metadata.gz: 1377c4ecd45ba6af86ac084cddcaa444d02055606c4296633edf333f3f67c630d4dbf3283b18eed57a054ef6c017b6aa86424cbe9c0da0de60fe56809a874ca2
7
- data.tar.gz: 18257e8bbfae77001b6e94eca09f63615cfcf78169eb98d75fef94bcb8027b90948a44af43389de2e6dd2c0e17ddc70b1b0314df78f487b442bde0fc8b58ede0
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)
@@ -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
@@ -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, ...}], ...]
@@ -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
 
@@ -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
 
@@ -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.
@@ -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) # "column" AS "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::WindowFunction.
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
@@ -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 proc called after a new connection is made, with the connection object (default: nil)
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)
@@ -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.
@@ -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