sequel 4.39.0 → 4.40.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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +34 -0
  3. data/README.rdoc +8 -4
  4. data/doc/active_record.rdoc +1 -1
  5. data/doc/advanced_associations.rdoc +7 -7
  6. data/doc/association_basics.rdoc +7 -7
  7. data/doc/cheat_sheet.rdoc +5 -3
  8. data/doc/core_extensions.rdoc +3 -3
  9. data/doc/dataset_filtering.rdoc +1 -1
  10. data/doc/object_model.rdoc +16 -7
  11. data/doc/postgresql.rdoc +3 -3
  12. data/doc/querying.rdoc +3 -3
  13. data/doc/release_notes/4.40.0.txt +179 -0
  14. data/doc/security.rdoc +2 -1
  15. data/doc/sql.rdoc +34 -18
  16. data/doc/testing.rdoc +1 -0
  17. data/doc/virtual_rows.rdoc +11 -2
  18. data/lib/sequel/adapters/jdbc/derby.rb +7 -1
  19. data/lib/sequel/adapters/jdbc/h2.rb +15 -1
  20. data/lib/sequel/adapters/oracle.rb +9 -5
  21. data/lib/sequel/adapters/postgres.rb +0 -1
  22. data/lib/sequel/adapters/shared/cubrid.rb +11 -11
  23. data/lib/sequel/adapters/shared/db2.rb +4 -8
  24. data/lib/sequel/adapters/shared/mssql.rb +41 -28
  25. data/lib/sequel/adapters/shared/mysql.rb +9 -6
  26. data/lib/sequel/adapters/shared/oracle.rb +16 -5
  27. data/lib/sequel/adapters/shared/postgres.rb +84 -45
  28. data/lib/sequel/adapters/shared/sqlanywhere.rb +29 -15
  29. data/lib/sequel/adapters/shared/sqlite.rb +6 -6
  30. data/lib/sequel/core.rb +61 -10
  31. data/lib/sequel/database/connecting.rb +2 -1
  32. data/lib/sequel/database/features.rb +7 -0
  33. data/lib/sequel/database/query.rb +1 -1
  34. data/lib/sequel/database/schema_methods.rb +30 -3
  35. data/lib/sequel/database/transactions.rb +4 -2
  36. data/lib/sequel/dataset/actions.rb +1 -1
  37. data/lib/sequel/dataset/graph.rb +6 -1
  38. data/lib/sequel/dataset/query.rb +14 -7
  39. data/lib/sequel/dataset/sql.rb +2 -2
  40. data/lib/sequel/extensions/core_extensions.rb +2 -1
  41. data/lib/sequel/extensions/pg_row.rb +2 -2
  42. data/lib/sequel/extensions/s.rb +57 -0
  43. data/lib/sequel/extensions/set_overrides.rb +5 -1
  44. data/lib/sequel/extensions/sql_expr.rb +1 -0
  45. data/lib/sequel/extensions/symbol_aref.rb +71 -0
  46. data/lib/sequel/extensions/symbol_aref_refinement.rb +41 -0
  47. data/lib/sequel/extensions/symbol_as.rb +23 -0
  48. data/lib/sequel/extensions/symbol_as_refinement.rb +35 -0
  49. data/lib/sequel/model/base.rb +3 -3
  50. data/lib/sequel/plugins/class_table_inheritance.rb +14 -3
  51. data/lib/sequel/plugins/column_select.rb +4 -2
  52. data/lib/sequel/plugins/dataset_associations.rb +12 -4
  53. data/lib/sequel/plugins/insert_returning_select.rb +1 -1
  54. data/lib/sequel/plugins/mssql_optimistic_locking.rb +1 -1
  55. data/lib/sequel/plugins/prepared_statements.rb +1 -0
  56. data/lib/sequel/sql.rb +40 -8
  57. data/lib/sequel/version.rb +1 -1
  58. data/spec/adapters/firebird_spec.rb +3 -3
  59. data/spec/adapters/mssql_spec.rb +40 -40
  60. data/spec/adapters/mysql_spec.rb +5 -5
  61. data/spec/adapters/oracle_spec.rb +4 -4
  62. data/spec/adapters/postgres_spec.rb +135 -124
  63. data/spec/adapters/spec_helper.rb +1 -0
  64. data/spec/adapters/sqlite_spec.rb +6 -6
  65. data/spec/core/dataset_spec.rb +2 -2
  66. data/spec/core/expression_filters_spec.rb +43 -2
  67. data/spec/core/schema_spec.rb +35 -1
  68. data/spec/core_extensions_spec.rb +27 -0
  69. data/spec/extensions/class_table_inheritance_spec.rb +8 -0
  70. data/spec/extensions/column_select_spec.rb +8 -0
  71. data/spec/extensions/core_refinements_spec.rb +1 -1
  72. data/spec/extensions/dataset_associations_spec.rb +9 -0
  73. data/spec/extensions/insert_returning_select_spec.rb +20 -0
  74. data/spec/extensions/prepared_statements_spec.rb +7 -0
  75. data/spec/extensions/s_spec.rb +60 -0
  76. data/spec/extensions/symbol_aref_refinement_spec.rb +28 -0
  77. data/spec/extensions/symbol_as_refinement_spec.rb +21 -0
  78. data/spec/integration/associations_test.rb +62 -57
  79. data/spec/integration/dataset_test.rb +54 -54
  80. data/spec/integration/eager_loader_test.rb +7 -7
  81. data/spec/integration/plugin_test.rb +20 -20
  82. data/spec/integration/prepared_statement_test.rb +1 -1
  83. data/spec/integration/schema_test.rb +21 -0
  84. data/spec/integration/spec_helper.rb +1 -0
  85. metadata +12 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: faeae955d80275ae969500515f7a62f6db3ee1d2
4
- data.tar.gz: 69e8bed296f9a6044bdbecfb29317562f2890bb8
3
+ metadata.gz: 7036daa139080700c287bce9f5c7c2d068d5476e
4
+ data.tar.gz: cd75becb35bf05f4a74b70c6468bbfbd214359e5
5
5
  SHA512:
6
- metadata.gz: 6f87b9f699854635a13c664b49e0a9be073a6f1daf1dc00ccfa7c352d211939d514a39b5a057f4fd90a5f8ed7737ea8afc2f54afcbd68d0b8ca07babeed88e22
7
- data.tar.gz: 9ff3136d2113273d89d4dd1552aa5ba30bea4e39edbfc4535f2762d35e6c21badfd5131e1f726be4d534b9f2f5960e498f9d7e3944e858716b7180c2a23c06ba
6
+ metadata.gz: 46cb6f09318eab28fa222d4e37484bb5781d1f94cbe4e341dd2c70c521819513e3f877e74a31dd90b998fa35abeea4ab1366e67a3bd883f85d8eec531f1841c3
7
+ data.tar.gz: 71ec283114e83204a544ccdc22fd5f73cad5cd403e6c2c17d55318a6dccbe1ae5b131d62ff9cd6a3552047f4808bc41bce1f04755d123ece61a16020aa7dffe9
data/CHANGELOG CHANGED
@@ -1,3 +1,37 @@
1
+ === 4.40.0 (2016-10-28)
2
+
3
+ * Make column_select plugin not raise an exception if the model's table does not exist (jeremyevans)
4
+
5
+ * Make dataset_associations plugin correctly handle (many|one)_through_many associations with single join table (jeremyevans) (#1253)
6
+
7
+ * Add s extension, with adds Sequel::S module that includes private #S method for calling Sequel.expr, including use as refinement (jeremyevans)
8
+
9
+ * Add symbol_as and symbol_as_refinement extensions so that :column.as(:alias) is treated as Sequel.as(:column, :alias) (jeremyevans)
10
+
11
+ * Add symbol_aref and symbol_aref_refinement extensions so that :table[:column] is treated as Sequel.qualify(:table, :column) (jeremyevans)
12
+
13
+ * Add Sequel.split_symbols=, to support the disabling of splitting symbols with double/triple underscores (jeremyevans)
14
+
15
+ * Make SQL::QualifiedIdentifier convert SQL::Identifier arguments to strings, fixing Sequel[:schema][:table] usage in schema methods (jeremyevans)
16
+
17
+ * Do not attempt to combine non-associative operators (jeremyevans) (#1246)
18
+
19
+ * Automatically add NOT NULL to columns when adding primary keys if the database doesn't handle it (jeremyevans)
20
+
21
+ * Make prepared_statements plugin correctly handle lookup on joined datasets (jeremyevans) (#1244)
22
+
23
+ * Make Database#tables with :qualify=>true option handle table names with double underscores correctly (jeremyevans) (#1241)
24
+
25
+ * Add SQL::Identifier#[] and SQL::QualifiedIdentifier#[] for creating qualified identifiers (jeremyevans)
26
+
27
+ * Add support for Dataset#insert_conflict :conflict_where option, for a predicate to use in ON CONFLICT clauses (chanks) (#1240)
28
+
29
+ * Freeze Dataset::NON_SQL_OPTIONS, add private Dataset#non_sql_options, fixing thread safety issues during require (jeremyevans)
30
+
31
+ * Make the callable returned by Database#rollback_checker thread safe (jeremyevans)
32
+
33
+ * Make lazy_attributes and dataset_associations plugins work if insert_returning_select plugin is loaded before on model with no dataset (jeremyevans)
34
+
1
35
  === 4.39.0 (2016-10-01)
2
36
 
3
37
  * Make active_model plugin use rollback_checker instead of after_rollback hook (jeremyevans)
@@ -453,14 +453,14 @@ Ruby strings are generally treated as SQL strings:
453
453
  === Qualifying identifiers (column/table names)
454
454
 
455
455
  An identifier in SQL is a name that represents a column, table, or schema.
456
- Identifiers can be qualified by using the double underscore special notation <tt>:table__column</tt>:
456
+ By default, identifiers can be qualified by using the double underscore special notation <tt>:table__column</tt>:
457
457
 
458
458
  items.literal(:items__price)
459
459
  # items.price
460
460
 
461
- Another way to qualify columns is to use the <tt>Sequel.qualify</tt> method:
461
+ Another way to qualify columns is to use the <tt>Sequel[][]</tt> method:
462
462
 
463
- items.literal(Sequel.qualify(:items, :price))
463
+ items.literal(Sequel[:items][:price])
464
464
  # items.price
465
465
 
466
466
  While it is more common to qualify column identifiers with table identifiers, you can also qualify table identifiers with schema identifiers
@@ -471,7 +471,7 @@ to select from a qualified table:
471
471
 
472
472
  === Identifier aliases
473
473
 
474
- You can also alias identifiers by using the triple underscore special notation <tt>:column___alias</tt> or <tt>:table__column___alias</tt>:
474
+ By default, you can also alias identifiers by using the triple underscore special notation <tt>:column___alias</tt> or <tt>:table__column___alias</tt>:
475
475
 
476
476
  items.literal(:price___p)
477
477
  # price AS p
@@ -488,6 +488,10 @@ You can use the <tt>Sequel.as</tt> method to alias arbitrary expressions, not ju
488
488
  items.literal(Sequel.as(DB[:posts].select{max(id)}, :p))
489
489
  # (SELECT max(id) FROM posts) AS p
490
490
 
491
+ You can turn off the splitting of symbols containing double and triple underscores, and treat all symbols as regular identifiers, by using:
492
+
493
+ Sequel.split_symbols = false
494
+
491
495
  == Sequel Models
492
496
 
493
497
  A model class wraps a dataset, and an instance of that class wraps a single record in the dataset.
@@ -260,7 +260,7 @@ You just use:
260
260
  At the instance level, this means that if you select columns that aren't in the models table, you need to use <tt>Model#[]</tt> to access them:
261
261
 
262
262
  album = Album.join(:artist, :id=>:artist_id).
263
- select(:albums__id, :albums__name, :artists__name___artist).first
263
+ select{[albums[:id], albums[:name], artists[:name].as(:artist)]}.first
264
264
  # SELECT albums.id, albums.name, artists.name AS artist
265
265
 
266
266
  album.artist # Error!
@@ -50,12 +50,12 @@ These can be used like this:
50
50
 
51
51
  # Only returns albums that have sold more than 500,000 copies
52
52
  Artist.one_to_many :gold_albums, :class=>:Album, \
53
- :graph_block=>proc{|j,lj,js| Sequel.qualify(j, :copies_sold) > 500000}
53
+ :graph_block=>proc{|j,lj,js| Sequel[j][:copies_sold] > 500000}
54
54
 
55
55
  # Handles the case where the tables are associated by a case insensitive name string
56
56
  Artist.one_to_many :albums, :key=>:artist_name, \
57
57
  :graph_only_conditions=>nil, \
58
- :graph_block=>proc{|j,lj,js| {Sequel.function(:lower, Sequel.qualify(j, :artist_name))=>Sequel.function(:lower, Sequel.qualify(lj, :name))}}
58
+ :graph_block=>proc{|j,lj,js| {Sequel.function(:lower, Sequel[j][:artist_name])=>Sequel.function(:lower, Sequel[lj][:name])}}
59
59
 
60
60
  # Handles the case where both key columns have the name artist_name, and you want to use
61
61
  # a JOIN USING
@@ -73,8 +73,8 @@ ordered by the albums name, you can do:
73
73
 
74
74
  albums = Artist.
75
75
  eager_graph(:albums).
76
- where(Sequel.like(:albums__name, 'A%')).
77
- order(:albums__name).
76
+ where{Sequel.like(albums[:name], 'A%')}.
77
+ order{albums[:name]}.
78
78
  all
79
79
 
80
80
  For lazy loading (e.g. Model[1].association), the <tt>:dataset</tt> option can be used
@@ -780,16 +780,16 @@ What you want to do is get all songs for a given artist, ordered by the song's
780
780
  name, with no duplicates?
781
781
 
782
782
  class Artist < Sequel::Model
783
- one_to_many :songs, :order=>:songs__name, \
783
+ one_to_many :songs, :order=>Sequel[:songs][:name], \
784
784
  :dataset=>proc{Song.select_all(:songs).join(Lyric, :id=>:lyric_id, id=>[:composer_id, :arranger_id, :vocalist_id, :lyricist_id])}, \
785
785
  :eager_loader=>(proc do |eo|
786
786
  h = eo[:id_map]
787
787
  ids = h.keys
788
788
  eo[:rows].each{|r| r.associations[:songs] = []}
789
789
  Song.select_all(:songs).
790
- select_append(:lyrics__composer_id, :lyrics__arranger_id, :lyrics__vocalist_id, :lyrics__lyricist_id).
790
+ select_append{[lyrics[:composer_id], lyrics[:arranger_id], lyrics[:vocalist_id], lyrics[:lyricist_id]}.
791
791
  join(Lyric, :id=>:lyric_id){Sequel.or(:composer_id=>ids, :arranger_id=>ids, :vocalist_id=>ids, :lyricist_id=>ids)}.
792
- order(:songs__name).all do |song|
792
+ order{songs[:name]}.all do |song|
793
793
  [:composer_id, :arranger_id, :vocalist_id, :lyricist_id].each do |x|
794
794
  recs = h[song.values.delete(x)]
795
795
  recs.each{|r| r.associations[:songs] << song} if recs
@@ -993,7 +993,7 @@ columns that have the same name in both the join table and the associated
993
993
  table. Example:
994
994
 
995
995
  Artist.one_to_many :albums, :select=>[:id, :name]
996
- Album.many_to_many :tags, :select=>[Sequel[:tags].*, :albums_tags__number]
996
+ Album.many_to_many :tags, :select=>[Sequel[:tags].*, Sequel[:albums_tags][:number]]
997
997
 
998
998
  ==== :limit
999
999
 
@@ -1332,11 +1332,11 @@ association based on dependent associations:
1332
1332
 
1333
1333
  Artist.one_to_many :albums_with_short_tracks, :class=>:Album,
1334
1334
  :eager_graph=>:tracks do |ds|
1335
- ds.where{tracks__seconds < 120}
1335
+ ds.where{tracks[:seconds] < 120}
1336
1336
  end
1337
1337
  Artist.one_to_many :albums_by_track_name, :class=>:Album,
1338
1338
  :eager_graph=>:tracks do |ds|
1339
- ds.order(:tracks__name)
1339
+ ds.order{tracks[:name]}
1340
1340
  end
1341
1341
 
1342
1342
  You can also use a hash or array of arguments for :eager_graph, similar to
@@ -1364,7 +1364,7 @@ via eager_graph. This is useful to specify conditions that can't be specified
1364
1364
  in a hash or array of two element arrays.
1365
1365
 
1366
1366
  Artist.one_to_many :gold_albums, :class=>:Album,
1367
- :graph_block=>proc{|j,lj,js| Sequel.qualify(j, :copies_sold) > 500000}
1367
+ :graph_block=>proc{|j,lj,js| Sequel[j][:copies_sold] > 500000}
1368
1368
 
1369
1369
  ==== :graph_join_type
1370
1370
 
@@ -1396,8 +1396,8 @@ where the artist's name differs in case:
1396
1396
 
1397
1397
  Artist.one_to_many :albums, :key=>:artist_name,
1398
1398
  :graph_only_conditions=>nil,
1399
- :graph_block=>proc{|j,lj,js| {Sequel.function(:lower, Sequel.qualify(j, :artist_name))=>
1400
- Sequel.function(:lower, Sequel.qualify(lj, :name))}}
1399
+ :graph_block=>proc{|j,lj,js| {Sequel.function(:lower, Sequel[j][:artist_name])=>
1400
+ Sequel.function(:lower, Sequel[lj][:name])}}
1401
1401
 
1402
1402
  Note how :graph_only_conditions is set to nil to ignore any existing conditions,
1403
1403
  and :graph_block is used to set up the case insensitive comparison.
@@ -1504,7 +1504,7 @@ has received a bachelor's degree (degree starting with B):
1504
1504
 
1505
1505
  Person.many_to_many :bachelor_degree_colleges, :class=>:College,
1506
1506
  :join_table=>:degrees_received,
1507
- :graph_join_table_block=>proc{|j,lj,js| Sequel.qualify(j, :degree).like('B%')}
1507
+ :graph_join_table_block=>proc{|j,lj,js| Sequel[j][:degree].like('B%')}
1508
1508
 
1509
1509
  This should be done when graphing the join table, instead of when graphing the
1510
1510
  final table, as :degree is a column of the join table.
@@ -129,7 +129,7 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
129
129
  # SELECT * FROM items
130
130
  # LEFT OUTER JOIN categories ON categories.id = items.category_id
131
131
 
132
- DB[:items].join(:categories, :id => :category_id).join(:groups, :id => :items__group_id)
132
+ DB[:items].join(:categories, :id => :category_id).join(:groups, :id => Sequel[:items][:group_id])
133
133
  # SELECT * FROM items
134
134
  # INNER JOIN categories ON categories.id = items.category_id
135
135
  # INNER JOIN groups ON groups.id = items.group_id
@@ -170,8 +170,10 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
170
170
  == Aliasing
171
171
 
172
172
  DB[:items].select(Sequel.as(:name, :item_name))
173
- DB[:items].select(:name___item_name)
174
- DB[:items___items_table].select(:items_table__name___item_name)
173
+ DB[:items].select{name.as(:item_name)}
174
+ # SELECT name AS item_name FROM items
175
+
176
+ DB[Sequel[:items].as(:items_table)].select{items_table[:name].as(:item_name)}
175
177
  # SELECT items_table.name AS item_name FROM items AS items_table
176
178
 
177
179
  == Transactions
@@ -170,11 +170,11 @@ Symbol#qualify qualifies the identifier (e.g. a column) with a another identifie
170
170
 
171
171
  :column.qualify(:table) # SQL: table.column
172
172
 
173
- Alternative: Sequel.qualify:
173
+ Alternative: Sequel[][]:
174
174
 
175
- Sequel.qualify(:table, :column)
175
+ Sequel[:table][:column]
176
176
 
177
- Note the reversed order of the arguments. For the Symbol#qualify method, the argument is the qualifier, while for Sequel.qualify, the qualifier is the first argument.
177
+ Note the reversed order of the arguments. For the Symbol#qualify method, the argument is the qualifier, while for Sequel[][], the first [] is the qualifier, and the second [] is the identifier.
178
178
 
179
179
  ==== like
180
180
 
@@ -47,7 +47,7 @@ Sequel can check for null values:
47
47
 
48
48
  Or compare two columns:
49
49
 
50
- items.where(:x => :some_table__y).sql
50
+ items.where{{:x => some_table[:y]}}.sql
51
51
  #=> "SELECT * FROM items WHERE (x = some_table.y)"
52
52
 
53
53
  And also compare against multiple values:
@@ -126,21 +126,29 @@ For example, ruby symbols represent SQL identifiers (tables, columns, schemas):
126
126
  :table # "table"
127
127
  :column # "column"
128
128
 
129
- However, they can also represent qualified identifiers by including a double
130
- underscore inside a symbol:
129
+ By default, Sequel supports splitting symbols using double or triple underscores
130
+ to represent qualified and aliased identifiers. A symbol with a double underscore
131
+ is treated as a qualified identifier:
131
132
 
132
133
  :table__column # "table"."column"
133
134
 
134
- They can also represent an aliased identifier by including a triple underscore
135
- inside a symbol:
135
+ A symbol with a triple underscore is treated as an aliased identifier:
136
136
 
137
137
  :column___alias # "column" AS "alias"
138
138
 
139
- You can combine both qualification and aliasing by using a double underscore
140
- and a triple underscore:
139
+ A symbol with a double underscore followed by a triple underscore is treated
140
+ as an aliased qualified identifer:
141
141
 
142
142
  :table__column___alias # "table"."column" AS "alias"
143
143
 
144
+ By allowing the creation of qualified and aliased identifiers via symbols,
145
+ Sequel makes it simpler to represent more SQL expressions. However, if you
146
+ are using double or triple underscores in your own identifiers, Sequel's
147
+ automatic splitting of identifiers can be problematic, in which case you
148
+ may want to turn them off via:
149
+
150
+ Sequel.split_symbols = false
151
+
144
152
  === Integer, Float, BigDecimal, String, Date, Time, DateTime
145
153
 
146
154
  Ruby's Integer, Float, BigDecimal, String, Date, Time, and DateTime classes
@@ -283,6 +291,7 @@ Sequel::SQL::QualifiedIdentifier objects represent qualified identifiers:
283
291
  The following shortcuts exist for creating Sequel::SQL::QualifiedIdentifier objects:
284
292
 
285
293
  Sequel[:table__column]
294
+ Sequel[:table][:column]
286
295
  Sequel.qualify(:table, :column)
287
296
  :column.qualify(:table) # core_extensions extension
288
297
 
@@ -302,7 +311,7 @@ The following shortcuts exist for creating Sequel::SQL::AliasedExpression object
302
311
  Sequel[:column___alias]
303
312
  Sequel.as(:column, :alias)
304
313
  Sequel.as(:column, :alias, [:column_alias1, :column_alias2])
305
- :column.as(:alias) # core_extensions extension
314
+ :column.as(:alias) # core_extensions or symbol_as extension
306
315
 
307
316
  === Sequel::SQL::ComplexExpression
308
317
 
@@ -160,7 +160,7 @@ Sequel has built in support for creating and dropping PostgreSQL schemas, proced
160
160
  DB.drop_function(:set_updated_at)
161
161
  # DROP FUNCTION set_updated_at()
162
162
 
163
- DB.create_trigger(:table, :trg_updated_at, :set_updated_at, :events=>:update, :each_row=>true, :when => {:new__updated_at => :old__updated_at})
163
+ DB.create_trigger(:table, :trg_updated_at, :set_updated_at, :events=>:update, :each_row=>true, :when => {Sequel[:new][:updated_at] => Sequel[:old][:updated_at]})
164
164
  # CREATE TRIGGER trg_updated_at BEFORE UPDATE ON "table" FOR EACH ROW WHEN ("new"."updated_at" = "old"."updated_at") EXECUTE PROCEDURE set_updated_at()
165
165
  DB.drop_trigger(:table, :trg_updated_at)
166
166
  # DROP TRIGGER trg_updated_at ON "table"
@@ -231,7 +231,7 @@ If you want to update the existing row instead of ignoring the constraint violat
231
231
  can pass an +:update+ option with a hash of values to update. You must pass either the
232
232
  +:target+ or +:constraint+ options when passing the +:update+ option:
233
233
 
234
- DB[:table].insert_conflict(:target=>:a, :update=>{:b=>:excluded__b}).insert(:a=>1, :b=>2)
234
+ DB[:table].insert_conflict(:target=>:a, :update=>{:b=>Sequel[:excluded][:b]}).insert(:a=>1, :b=>2)
235
235
  # INSERT INTO TABLE (a, b) VALUES (1, 2)
236
236
  # ON CONFLICT (a) DO UPDATE SET b = excluded.b
237
237
 
@@ -240,7 +240,7 @@ Additionally, if you only want to do the update in certain cases, you can specif
240
240
  conditions, the constraint violation will be ignored, but the row will not be updated:
241
241
 
242
242
  DB[:table].insert_conflict(:constraint=>:table_a_uidx,
243
- :update=>{:b=>:excluded__b}, :update_where=>{:table__status_id=>1}).insert(:a=>1, :b=>2)
243
+ :update=>{:b=>Sequel[:excluded][:b]}, :update_where=>{Sequel[:table][:status_id]=>1}).insert(:a=>1, :b=>2)
244
244
  # INSERT INTO TABLE (a, b) VALUES (1, 2)
245
245
  # ON CONFLICT ON CONSTRAINT table_a_uidx
246
246
  # DO UPDATE SET b = excluded.b WHERE (table.status_id = 1)
@@ -804,7 +804,7 @@ is wrong as the foreign key <tt>tracks.album_id</tt> refers to <tt>albums.id</tt
804
804
  <tt>artists.id</tt>. To fix this, you need to explicitly qualify when joining:
805
805
 
806
806
  Album.join(:artists, :id=>:artist_id).
807
- join(:tracks, :album_id=>:albums__id)
807
+ join(:tracks, :album_id=>Sequel[:albums][:id])
808
808
  # SELECT * FROM albums
809
809
  # INNER JOIN artists ON artists.id = albums.artist_id
810
810
  # INNER JOIN tracks ON tracks.album_id = albums.id
@@ -876,7 +876,7 @@ and artists tables, but only want albums where the artist's name
876
876
  comes before the album's name.
877
877
 
878
878
  Album.join(:artists, :id=>:artist_id) do |j, lj, js|
879
- Sequel.qualify(j, :name) < Sequel.qualify(lj, :name)
879
+ Sequel[j][:name] < Sequel[lj][:name]
880
880
  end
881
881
  # SELECT * FROM albums INNER JOIN artists
882
882
  # ON artists.id = albums.artist_id
@@ -904,7 +904,7 @@ number of old albums.
904
904
  Using multiple FROM tables and setting conditions in the WHERE clause is
905
905
  an old-school way of joining tables:
906
906
 
907
- DB.from(:albums, :artists).where(:artists__id=>:albums__artist_id)
907
+ DB.from(:albums, :artists).where{{artists[:id]=>albums[:artist_id]}}
908
908
  # SELECT * FROM albums, artists WHERE artists.id = albums.artist_id
909
909
 
910
910
  === Using the current dataset in a subselect
@@ -0,0 +1,179 @@
1
+ = New Features
2
+
3
+ * A Sequel.split_symbols setting has been added. This setting is
4
+ true by default, so there is no change to backwards compatibility
5
+ by default. However, users can now do:
6
+
7
+ Sequel.split_symbols = false
8
+
9
+ to disable the splitting of symbols. This will make Sequel no
10
+ longer treat symbols with double or triple underscores as qualified
11
+ or aliased identifiers, instead treating them as plain identifiers.
12
+ It will also make Sequel no longer treat virtual row methods with
13
+ double underscores as qualified identifiers. Examples:
14
+
15
+ # Sequel.split_symbols = true
16
+ :column # "column"
17
+ :table__column # "table"."column"
18
+ :column___alias # "column" AS "alias"
19
+ :table__column___alias # "table"."column" AS "alias"
20
+ Sequel.expr{table__column} # "table"."column"
21
+
22
+ # Sequel.split_symbols = false
23
+ :column # "column"
24
+ :table__column # "table__column"
25
+ :column___alias # "column___alias"
26
+ :table__column___alias # "table__column___alias"
27
+ Sequel.expr{table__column} # "table__column"
28
+
29
+ Disabling symbol splitting can make things much easier if leading
30
+ trailing, double, or triple underscores are used in identifiers
31
+ in your database.
32
+
33
+ Disabling symbol splitting makes Sequel simpler, even if it does
34
+ make it slightly less easy to create qualified and aliased
35
+ identifiers. It is possible that the symbol splitting will be
36
+ disabled by default starting in Sequel 5.
37
+
38
+ Note that due to Database symbol literal caching, you should not
39
+ change the Sequel.split_symbols setting after creating a
40
+ Database instance.
41
+
42
+ * SQL::Identifier#[] and SQL::QualifiedIdentifier#[] have been added
43
+ for creating qualified identifiers. This makes it easier and more
44
+ natural to create qualified identifiers from existing identifiers.
45
+ Previously, you could do:
46
+
47
+ Sequel[:column].qualify(:table)
48
+
49
+ You can now use the more natural:
50
+
51
+ Sequel[:table][:column]
52
+
53
+ This can also be used in virtual rows:
54
+
55
+ Sequel.expr{table[:column]}
56
+
57
+ This offers a easy way to create qualified identifers when symbol
58
+ splitting has been disabled.
59
+
60
+ * A symbol_aref extension has been added, allowing the use of
61
+ Symbol#[] to create qualified identifiers if passed a Symbol,
62
+ SQL::Identifier, or SQL::QualifiedIdentifier. This doesn't
63
+ break any existing ruby behavior, as ruby currrently raises
64
+ an exception in such cases. Example:
65
+
66
+ :table[:column] # "table"."column"
67
+
68
+ This extension can make it easier to create qualified identifiers
69
+ if symbol splitting is disabled.
70
+
71
+ A symbol_aref_refinement extension has also been added, which
72
+ adds a refinement version of the extension that can be enabled via:
73
+
74
+ using Sequel::SymbolAref
75
+
76
+ * A symbol_as extension has been added, which adds the Symbol#as method
77
+ to create aliased identifiers. This was previously part of the core
78
+ extensions, but has been separated so it can be included by itself.
79
+ Example:
80
+
81
+ :column.as(:alias) # "column" AS "alias"
82
+
83
+ This extension can make it easier to create aliased identifiers if
84
+ symbol splitting is disabled.
85
+
86
+ A symbol_as_refinement extension has also been added, which
87
+ adds a refinement version of the extension that can be enabled via:
88
+
89
+ using Sequel::SymbolAs
90
+
91
+ * An s extension has been added, which adds the Sequel::S module,
92
+ containing a private #S method that calls Sequel.expr. You can
93
+ include this module in any module or class where you would like the
94
+ S method to be available:
95
+
96
+ class Album < Sequel::Model
97
+ extend Sequel::S
98
+ one_to_many :tracks, :order=>S(:number).desc
99
+ end
100
+
101
+ You can include this in Object if you want the S method to be
102
+ available globally:
103
+
104
+ Object.send(:include, Sequel::S)
105
+
106
+ Sequel::S also works if it is used as a refinement, adding the S
107
+ method to Object while the refinement is active:
108
+
109
+ using Sequel::S
110
+
111
+ This extension can make it easier to create qualified and aliased
112
+ identifiers if symbol splitting is disabled:
113
+
114
+ S(:table)[:column]
115
+ S(:column).as(:alias)
116
+
117
+ * Dataset#insert_conflict on PostgreSQL now supports a :conflict_where
118
+ option, allowing for the handling of insert conflicts when using a
119
+ partial unique index:
120
+
121
+ DB[:table].insert_conflict(:target=>:a,
122
+ :conflict_where=>{:c=>true}).insert(:a=>1, :b=>2)
123
+ # INSERT INTO TABLE (a, b) VALUES (1, 2)
124
+ # ON CONFLICT (a) WHERE (c IS TRUE) DO NOTHING
125
+
126
+ = Other Improvements
127
+
128
+ * Sequel no longer attempts to combine arguments for non-associative
129
+ operators, as doing so leads to invalid code in cases such as:
130
+
131
+ Sequel.expr{column1 - (column2 - 1)}
132
+
133
+ * Sequel now automatically adds NOT NULL constraints on columns when
134
+ adding a primary key constraint on the columns, if the database
135
+ doesn't handle that situation correctly.
136
+
137
+ * Database#rollback_checker now returns a thread-safe object.
138
+
139
+ * SQL::QualifiedIdentifier#initialize now converts SQL::Identifier
140
+ arguments to strings, fixing usage of such objects in the
141
+ schema methods.
142
+
143
+ * The prepared_statements plugin now correctly handles lookup by
144
+ primary key on models with joined datasets.
145
+
146
+ * The dataset_associations plugin now handles many_through_many and
147
+ one_through_many associations that use a single join table. Note
148
+ there is no reason to create such associations, as many_to_many
149
+ and one_through_one associations will work for such cases.
150
+
151
+ * The insert_returning_select plugin now handles cases where the
152
+ model doesn't have a valid dataset, fixing usage with the
153
+ lazy_attributes and dataset_associations plugins, and potentially
154
+ other plugins.
155
+
156
+ * The column_select plugin no longer raises an exception if the
157
+ model's table does not exist.
158
+
159
+ * The class_table_inheritance plugin now works when the
160
+ prepared_statements plugin is also used.
161
+
162
+ * Some adapters now avoid thread-safety issues during loading on
163
+ ruby implementations without a GVL by avoiding the modification of
164
+ shared datastructures.
165
+
166
+ * When using Database#tables with the :qualify=>true option on
167
+ PostgreSQL, table names with double or triple underscores are
168
+ now handled correctly.
169
+
170
+ = Backwards Compatibility
171
+
172
+ * The following Dataset constants are now frozen: NON_SQL_OPTIONS,
173
+ ACTION_METHODS, QUERY_METHODS, CONDITIONED_JOIN_TYPES,
174
+ UNCONDITIONED_JOIN_TYPES, and JOIN_METHODS. Of these,
175
+ NON_SQL_OPTIONS was previously modified in a non-thread-safe manner
176
+ by some adapters. External adapters should switch to having the
177
+ adapter's dataset non_sql_options method return an array of options
178
+ that do not affect the SELECT SQL for the adapter's datasets, rather
179
+ than modifying NON_SQL_OPTIONS.