sequel 3.37.0 → 3.38.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. data/CHANGELOG +56 -0
  2. data/README.rdoc +82 -58
  3. data/Rakefile +6 -5
  4. data/bin/sequel +1 -1
  5. data/doc/active_record.rdoc +67 -52
  6. data/doc/advanced_associations.rdoc +33 -48
  7. data/doc/association_basics.rdoc +41 -51
  8. data/doc/cheat_sheet.rdoc +21 -21
  9. data/doc/core_extensions.rdoc +374 -0
  10. data/doc/dataset_basics.rdoc +5 -5
  11. data/doc/dataset_filtering.rdoc +47 -43
  12. data/doc/mass_assignment.rdoc +1 -1
  13. data/doc/migration.rdoc +4 -5
  14. data/doc/model_hooks.rdoc +3 -3
  15. data/doc/object_model.rdoc +31 -25
  16. data/doc/opening_databases.rdoc +19 -5
  17. data/doc/prepared_statements.rdoc +2 -2
  18. data/doc/querying.rdoc +109 -52
  19. data/doc/reflection.rdoc +6 -6
  20. data/doc/release_notes/3.38.0.txt +234 -0
  21. data/doc/schema_modification.rdoc +22 -13
  22. data/doc/sharding.rdoc +8 -9
  23. data/doc/sql.rdoc +154 -112
  24. data/doc/testing.rdoc +47 -7
  25. data/doc/thread_safety.rdoc +1 -1
  26. data/doc/transactions.rdoc +1 -1
  27. data/doc/validations.rdoc +1 -1
  28. data/doc/virtual_rows.rdoc +29 -43
  29. data/lib/sequel/adapters/do/postgres.rb +1 -4
  30. data/lib/sequel/adapters/jdbc.rb +14 -3
  31. data/lib/sequel/adapters/jdbc/db2.rb +9 -0
  32. data/lib/sequel/adapters/jdbc/derby.rb +41 -4
  33. data/lib/sequel/adapters/jdbc/jtds.rb +11 -0
  34. data/lib/sequel/adapters/jdbc/postgresql.rb +3 -6
  35. data/lib/sequel/adapters/mock.rb +10 -4
  36. data/lib/sequel/adapters/postgres.rb +1 -28
  37. data/lib/sequel/adapters/shared/mssql.rb +23 -13
  38. data/lib/sequel/adapters/shared/postgres.rb +46 -0
  39. data/lib/sequel/adapters/swift.rb +21 -13
  40. data/lib/sequel/adapters/swift/mysql.rb +1 -0
  41. data/lib/sequel/adapters/swift/postgres.rb +4 -5
  42. data/lib/sequel/adapters/swift/sqlite.rb +2 -1
  43. data/lib/sequel/adapters/tinytds.rb +14 -2
  44. data/lib/sequel/adapters/utils/pg_types.rb +5 -0
  45. data/lib/sequel/core.rb +29 -17
  46. data/lib/sequel/database/query.rb +1 -1
  47. data/lib/sequel/database/schema_generator.rb +3 -0
  48. data/lib/sequel/dataset/actions.rb +5 -6
  49. data/lib/sequel/dataset/query.rb +7 -7
  50. data/lib/sequel/dataset/sql.rb +5 -18
  51. data/lib/sequel/extensions/core_extensions.rb +8 -12
  52. data/lib/sequel/extensions/pg_array.rb +59 -33
  53. data/lib/sequel/extensions/pg_array_ops.rb +32 -4
  54. data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -1
  55. data/lib/sequel/extensions/pg_hstore.rb +32 -17
  56. data/lib/sequel/extensions/pg_hstore_ops.rb +32 -3
  57. data/lib/sequel/extensions/pg_inet.rb +1 -2
  58. data/lib/sequel/extensions/pg_interval.rb +0 -1
  59. data/lib/sequel/extensions/pg_json.rb +41 -23
  60. data/lib/sequel/extensions/pg_range.rb +36 -11
  61. data/lib/sequel/extensions/pg_range_ops.rb +32 -4
  62. data/lib/sequel/extensions/pg_row.rb +572 -0
  63. data/lib/sequel/extensions/pg_row_ops.rb +164 -0
  64. data/lib/sequel/extensions/query.rb +3 -3
  65. data/lib/sequel/extensions/schema_dumper.rb +7 -8
  66. data/lib/sequel/extensions/select_remove.rb +1 -1
  67. data/lib/sequel/model/base.rb +1 -0
  68. data/lib/sequel/no_core_ext.rb +1 -1
  69. data/lib/sequel/plugins/pg_row.rb +121 -0
  70. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  71. data/lib/sequel/plugins/validation_helpers.rb +31 -0
  72. data/lib/sequel/sql.rb +64 -44
  73. data/lib/sequel/version.rb +1 -1
  74. data/spec/adapters/mssql_spec.rb +37 -12
  75. data/spec/adapters/mysql_spec.rb +39 -75
  76. data/spec/adapters/oracle_spec.rb +11 -11
  77. data/spec/adapters/postgres_spec.rb +414 -237
  78. data/spec/adapters/spec_helper.rb +1 -1
  79. data/spec/adapters/sqlite_spec.rb +14 -14
  80. data/spec/core/database_spec.rb +6 -6
  81. data/spec/core/dataset_spec.rb +169 -205
  82. data/spec/core/expression_filters_spec.rb +182 -295
  83. data/spec/core/object_graph_spec.rb +6 -6
  84. data/spec/core/schema_spec.rb +14 -14
  85. data/spec/core/spec_helper.rb +1 -0
  86. data/spec/{extensions/core_extensions_spec.rb → core_extensions_spec.rb} +208 -14
  87. data/spec/extensions/columns_introspection_spec.rb +5 -5
  88. data/spec/extensions/hook_class_methods_spec.rb +28 -36
  89. data/spec/extensions/many_through_many_spec.rb +4 -4
  90. data/spec/extensions/pg_array_ops_spec.rb +15 -7
  91. data/spec/extensions/pg_array_spec.rb +81 -48
  92. data/spec/extensions/pg_auto_parameterize_spec.rb +2 -2
  93. data/spec/extensions/pg_hstore_ops_spec.rb +13 -9
  94. data/spec/extensions/pg_hstore_spec.rb +66 -65
  95. data/spec/extensions/pg_inet_spec.rb +2 -4
  96. data/spec/extensions/pg_interval_spec.rb +2 -3
  97. data/spec/extensions/pg_json_spec.rb +20 -18
  98. data/spec/extensions/pg_range_ops_spec.rb +11 -4
  99. data/spec/extensions/pg_range_spec.rb +30 -7
  100. data/spec/extensions/pg_row_ops_spec.rb +48 -0
  101. data/spec/extensions/pg_row_plugin_spec.rb +45 -0
  102. data/spec/extensions/pg_row_spec.rb +323 -0
  103. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  104. data/spec/extensions/query_literals_spec.rb +11 -11
  105. data/spec/extensions/query_spec.rb +3 -3
  106. data/spec/extensions/schema_dumper_spec.rb +20 -4
  107. data/spec/extensions/schema_spec.rb +18 -41
  108. data/spec/extensions/select_remove_spec.rb +4 -4
  109. data/spec/extensions/spec_helper.rb +4 -8
  110. data/spec/extensions/to_dot_spec.rb +5 -5
  111. data/spec/extensions/validation_class_methods_spec.rb +28 -16
  112. data/spec/integration/associations_test.rb +20 -20
  113. data/spec/integration/dataset_test.rb +98 -98
  114. data/spec/integration/eager_loader_test.rb +13 -27
  115. data/spec/integration/plugin_test.rb +5 -5
  116. data/spec/integration/prepared_statement_test.rb +22 -13
  117. data/spec/integration/schema_test.rb +28 -18
  118. data/spec/integration/spec_helper.rb +1 -1
  119. data/spec/integration/timezone_test.rb +2 -2
  120. data/spec/integration/type_test.rb +15 -6
  121. data/spec/model/association_reflection_spec.rb +1 -1
  122. data/spec/model/associations_spec.rb +4 -4
  123. data/spec/model/base_spec.rb +5 -5
  124. data/spec/model/eager_loading_spec.rb +15 -15
  125. data/spec/model/model_spec.rb +32 -32
  126. data/spec/model/record_spec.rb +16 -0
  127. data/spec/model/spec_helper.rb +2 -6
  128. data/spec/model/validations_spec.rb +1 -1
  129. metadata +16 -4
@@ -2,7 +2,7 @@
2
2
 
3
3
  == Introduction
4
4
 
5
- Datasets are probably the thing that separate Sequel from other database libraries. While most database libraries have specific support for updating all records or only a single record, Sequel's ability to represent SQL queries themselves as objects is what gives Sequel most of its power. However, if you haven't been exposed to the dataset concept before, it can be a little disorienting. This document aims to give a basic introduction to datasets and how to use them.
5
+ Datasets are the primary way Sequel uses to access the database. While most database libraries have specific support for updating all records or only a single record, Sequel's ability to represent SQL queries themselves as objects is what gives Sequel most of its power. However, if you haven't been exposed to the dataset concept before, it can be a little disorienting. This document aims to give a basic introduction to datasets and how to use them.
6
6
 
7
7
  == What a Dataset Represents
8
8
 
@@ -24,23 +24,23 @@ Here, DB represents your Sequel::Database object, and ds is your dataset, with t
24
24
 
25
25
  One of the core dataset ideas that should be understood is that datasets use a functional style of modification, in which methods called on the dataset return modified copies of the dataset, they don't modify the dataset themselves:
26
26
 
27
- ds2 = ds.filter(:id=>1)
27
+ ds2 = ds.where(:id=>1)
28
28
  ds2
29
29
  # SELECT * FROM posts WHERE id = 1
30
30
  ds
31
31
  # SELECT * FROM posts
32
32
 
33
- Note how ds itself is not modified. This is because ds.filter returns a modified copy of ds, instead of modifying ds itself. This makes using datasets both thread safe and easy to chain:
33
+ Note how ds itself is not modified. This is because ds.where returns a modified copy of ds, instead of modifying ds itself. This makes using datasets both thread safe and easy to chain:
34
34
 
35
35
  # Thread safe:
36
36
  100.times do |i|
37
37
  Thread.new do
38
- ds.filter(:id=>i).first
38
+ ds.where(:id=>i).first
39
39
  end
40
40
  end
41
41
 
42
42
  # Easy to chain:
43
- ds3 = ds.select(:id, :name).order(:name).filter{id < 100}
43
+ ds3 = ds.select(:id, :name).order(:name).where{id < 100}
44
44
  # SELECT id, name FROM posts WHERE id < 100 ORDER BY name
45
45
 
46
46
  Thread safety you don't really need to worry about, but chainability is core to how Sequel is generally used. Almost all dataset methods that affect the SQL produced return modified copies of the receiving dataset.
@@ -4,59 +4,63 @@ Sequel is very flexibile when it comes to filtering records. You can specify you
4
4
 
5
5
  == Filtering using a custom filter string
6
6
 
7
- If you wish to write your SQL by hand, you can just supply it to the dataset's #filter method:
7
+ If you wish to write your SQL by hand, you can just supply it to the dataset's #where method:
8
8
 
9
- items.filter('x < 10').sql
9
+ items.where('x < 10').sql
10
10
  #=> "SELECT * FROM items WHERE x < 10"
11
11
 
12
12
  In order to prevent SQL injection, you can replace literal values with question marks and supply the values as additional arguments:
13
13
 
14
- items.filter('category = ?', 'ruby').sql
14
+ items.where('category = ?', 'ruby').sql
15
15
  #=> "SELECT * FROM items WHERE category = 'ruby'"
16
16
 
17
17
  You can also use placeholders with :placeholder and a hash of placeholder values:
18
18
 
19
- items.filter('category = :category', :category=>'ruby').sql
19
+ items.where('category = :category', :category=>'ruby').sql
20
20
  #=> "SELECT * FROM items WHERE category = 'ruby'"
21
21
 
22
22
  === Specifying SQL functions
23
23
 
24
- Sequel also allows you to specify functions by using the Symbol#sql_function method:
24
+ Sequel also allows you to specify functions by using the Sequel.function method:
25
25
 
26
- items.literal(:avg.sql_function(:price)) #=> "avg(price)"
26
+ items.literal(Sequel.function(:avg, :price)) #=> "avg(price)"
27
27
 
28
28
  If you are specifying a filter/selection/order, you can use a virtual row block:
29
29
 
30
30
  items.select{avg(price)}
31
31
 
32
+ You can also use the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html] and the +sql_function+ method:
33
+
34
+ :avg.sql_function(:price)
35
+
32
36
  == Filtering using a hash
33
37
 
34
38
  If you just need to compare records against values, you can supply a hash:
35
39
 
36
- items.filter(:category => 'ruby').sql
40
+ items.where(:category => 'ruby').sql
37
41
  #=> "SELECT * FROM items WHERE (category = 'ruby')"
38
42
 
39
43
  Sequel can check for null values:
40
44
 
41
- items.filter(:category => nil).sql
45
+ items.where(:category => nil).sql
42
46
  #=> "SELECT * FROM items WHERE (category IS NULL)"
43
47
 
44
48
  Or compare two columns:
45
49
 
46
- items.filter(:x => :some_table__y).sql
50
+ items.where(:x => :some_table__y).sql
47
51
  #=> "SELECT * FROM items WHERE (x = some_table.y)"
48
52
 
49
53
  And also compare against multiple values:
50
54
 
51
- items.filter(:category => ['ruby', 'perl']).sql
55
+ items.where(:category => ['ruby', 'perl']).sql
52
56
  #=> "SELECT * FROM items WHERE (category IN ('ruby', 'perl'))"
53
57
 
54
58
  Ranges (both inclusive and exclusive) can also be used:
55
59
 
56
- items.filter(:price => 100..200).sql
60
+ items.where(:price => 100..200).sql
57
61
  #=> "SELECT * FROM items WHERE (price >= 100 AND price <= 200)"
58
62
 
59
- items.filter(:price => 100...200).sql
63
+ items.where(:price => 100...200).sql
60
64
  #=> "SELECT * FROM items WHERE (price >= 100 AND price < 200)"
61
65
 
62
66
  == Filtering using an array
@@ -64,119 +68,119 @@ Ranges (both inclusive and exclusive) can also be used:
64
68
  If you need to select multiple items from a dataset, you can supply an array:
65
69
 
66
70
  item_array = [1, 38, 47, 99]
67
- items.filter(:id => item_array).sql
71
+ items.where(:id => item_array).sql
68
72
  #=> "SELECT * FROM items WHERE (id IN (1, 38, 47, 99))"
69
73
 
70
74
  == Filtering using expressions
71
75
 
72
- Sequel allows you to use ruby expressions directly in the call to filter:
76
+ You can pass a block to where, which is evaluated in a special context:
73
77
 
74
- items.filter(:price * 2 < 50).sql
78
+ items.where{price * 2 < 50}.sql
75
79
  #=> "SELECT * FROM items WHERE ((price * 2) < 50)
76
80
 
77
- This works for the standard inequality and arithmetic operators (though you can't use the inequality operators directly on a symbol):
81
+ This works for the standard inequality and arithmetic operators:
78
82
 
79
- items.filter(:price + 100 < 200).sql
83
+ items.where{price + 100 < 200}.sql
80
84
  #=> "SELECT * FROM items WHERE ((price + 100) < 200)
81
85
 
82
- items.filter(:price - 100 > 200).sql
86
+ items.where{price - 100 > 200}.sql
83
87
  #=> "SELECT * FROM items WHERE ((price - 100) > 200)
84
88
 
85
- items.filter(:price * 100 <= 200).sql
89
+ items.where{price * 100 <= 200}.sql
86
90
  #=> "SELECT * FROM items WHERE ((price * 100) <= 200)
87
91
 
88
- items.filter(:price / 100 >= 200).sql
92
+ items.where{price / 100 >= 200}.sql
89
93
  #=> "SELECT * FROM items WHERE ((price / 100) >= 200)
90
94
 
91
95
  You use the overloaded bitwise and (&) and or (|) operators to combine expressions:
92
96
 
93
- items.filter((:price + 100 < 200) & (:price * 100 <= 200)).sql
97
+ items.where{(price + 100 < 200) & (price * 100 <= 200)}.sql
94
98
  #=> "SELECT * FROM items WHERE (((price + 100) < 200) AND ((price * 100) <= 200))
95
99
 
96
- items.filter((:price - 100 > 200) | (:price / 100 >= 200)).sql
100
+ items.where{(price - 100 > 200) | (price / 100 >= 200)}.sql
97
101
  #=> "SELECT * FROM items WHERE (((price - 100) > 200) OR ((price / 100) >= 200))
98
102
 
99
- To filter by equality, you use the standard hash, which can be combined with other operators:
103
+ To filter by equality, you use the standard hash, which can be combined with other expressions using Sequel.& and Sequel.|:
100
104
 
101
- items.filter({:category => 'ruby'} & (:price + 100 < 200)).sql
105
+ items.where{Sequel.&({:category => 'ruby'}, (price + 100 < 200))}.sql
102
106
  #=> "SELECT * FROM items WHERE ((category = 'ruby') AND ((price + 100) < 200))"
103
107
 
104
108
  This works with other hash values, such as arrays and ranges:
105
109
 
106
- items.filter({:category => ['ruby', 'other']} | (:price - 100 > 200)).sql
110
+ items.where{Sequel.|({:category => ['ruby', 'other']}, (:price - 100 > 200))}.sql
107
111
  #=> "SELECT * FROM items WHERE ((category IN ('ruby', 'other')) OR ((price - 100) <= 200))"
108
112
 
109
- items.filter({:price => (100..200)} & :active).sql
113
+ items.where{Sequel.&({:price => (100..200)}, :active)).sql
110
114
  #=> "SELECT * FROM items WHERE ((price >= 100 AND price <= 200) AND active)"
111
115
 
112
116
  === Negating conditions
113
117
 
114
- You can use the inversion operator (~) in most cases:
118
+ You can use the exclude method to exclude conditions:
115
119
 
116
- items.filter(~{:category => 'ruby'}).sql
120
+ items.exclude(:category => 'ruby').sql
117
121
  #=> "SELECT * FROM items WHERE (category != 'ruby')"
118
122
 
119
- items.filter{~:active}.sql
123
+ items.exclude(:active).sql
120
124
  #=> "SELECT * FROM items WHERE NOT active"
121
125
 
122
- items.filter(~(:price / 100 >= 200)).sql
126
+ items.exclude{price / 100 >= 200}.sql
123
127
  #=> "SELECT * FROM items WHERE ((price / 100) < 200)
124
128
 
125
129
  === Comparing against column references
126
130
 
127
131
  You can also compare against other columns:
128
132
 
129
- items.filter{credit > debit}.sql
133
+ items.where{credit > debit}.sql
130
134
  #=> "SELECT * FROM items WHERE (credit > debit)
131
135
 
132
136
  Or against SQL functions:
133
137
 
134
- items.filter{price - 100 < max(price)}.sql
138
+ items.where{price - 100 < max(price)}.sql
135
139
  #=> "SELECT * FROM items WHERE ((price - 100) < max(price))"
136
140
 
137
141
  == String search functions
138
142
 
139
- You can search SQL strings using the #like method:
143
+ You can search SQL strings using the Sequel.like method:
140
144
 
141
- items.filter(:name.like('Acme%')).sql
145
+ items.where(Sequel.like(:name, 'Acme%')).sql
142
146
  #=> "SELECT * FROM items WHERE (name LIKE 'Acme%')"
143
147
 
144
148
  You can specify a Regexp as a like argument, but this will probably only work
145
149
  on PostgreSQL and MySQL:
146
150
 
147
- items.filter(:name.like(/Acme.*/)).sql
151
+ items.where(Sequel.like(:name, /Acme.*/)).sql
148
152
  #=> "SELECT * FROM items WHERE (name ~ 'Acme.*')"
149
153
 
150
154
  Like can also take more than one argument:
151
155
 
152
- items.filter(:name.like('Acme%', /Beta.*/)).sql
156
+ items.where(Sequel.like(:name, 'Acme%', /Beta.*/)).sql
153
157
  #=> "SELECT * FROM items WHERE ((name LIKE 'Acme%') OR (name ~ 'Beta.*'))"
154
158
 
155
159
  == String concatenation
156
160
 
157
- You can concatenate SQL strings using Array#sql_string_join:
161
+ You can concatenate SQL strings using Sequel.join:
158
162
 
159
- items.filter([:name, :comment].sql_string_join.like('%acme%')).sql
163
+ items.where(Sequel.join([:name, :comment]).like('%acme%')).sql
160
164
  #=> "SELECT * FROM items WHERE ((name || comment) LIKE 'Acme%')"
161
165
 
162
166
  Array#sql_string_join also takes a join argument:
163
167
 
164
- items.filter([:name, :comment].sql_string_join(' ').like('%acme%')).sql
168
+ items.filter(Sequel.join([:name, :comment], ' ').like('%acme%')).sql
165
169
  #=> "SELECT * FROM items WHERE ((name || ' ' || comment) LIKE 'Acme%')"
166
170
 
167
171
  == Filtering using sub-queries
168
172
 
169
173
  One of the best features of Sequel is the ability to use datasets as sub-queries. Sub-queries can be very useful for filtering records, and many times provide a simpler alternative to table joins. Sub-queries can be used in all forms of filters:
170
174
 
171
- refs = consumer_refs.filter(:logged_in).select(:consumer_id)
172
- consumers.filter(:id => refs).sql
175
+ refs = consumer_refs.where(:logged_in).select(:consumer_id)
176
+ consumers.where(:id => refs).sql
173
177
  #=> "SELECT * FROM consumers WHERE (id IN (SELECT consumer_id FROM consumer_refs WHERE logged_in))"
174
178
 
175
179
  Note that if you are checking for the inclusion of a single column in a subselect, the subselect should only select a single column.
176
180
 
177
181
  == Using OR instead of AND
178
182
 
179
- By default, if you chain calls to +filter+, the conditions get ANDed together. If you want to use an OR for a condition, you can use the +or+ method:
183
+ By default, if you chain calls to +where+, the conditions get ANDed together. If you want to use an OR for a condition, you can use the +or+ method:
180
184
 
181
- items.filter(:name=>'Food').or(:vendor=>1).sql
185
+ items.where(:name=>'Food').or(:vendor=>1).sql
182
186
  #=> "SELECT * FROM items WHERE ((name = 'Food') OR (vendor = 1))"
@@ -25,7 +25,7 @@ To handle cases where different columns are allowed in different cases, you can
25
25
  # admin case
26
26
  post.set_only(params[:post], :title, :body, :deleted)
27
27
 
28
- In this case, only the <tt>title=</tt> and <tt>body=</tt> methods will be allowed in the mass assignment.
28
+ In this case, only the <tt>title=</tt> and <tt>body=</tt> methods will be allowed in the mass assignment in the user case, and only <tt>title=</tt>, <tt>body=</tt>, and <tt>deleted=</tt> will be allowed for mass assignment in the admin case.
29
29
 
30
30
  By default, if an invalid setter method call is attempted, Sequel raises a <tt>Sequel::Error</tt> exception. You can have Sequel silently ignore invalid calls by doing:
31
31
 
data/doc/migration.rdoc CHANGED
@@ -523,11 +523,10 @@ The main difference between the two is that <tt>-d</tt> will use the type method
523
523
  with the database independent ruby class types, while <tt>-D</tt> will use
524
524
  the +column+ method with string types.
525
525
 
526
- Note that Sequel cannot dump constraints other than primary key constraints,
527
- so it dumps foreign key columns as plain integers. If you are using any real
528
- database features such as foreign keys, constraints, or triggers, you should
529
- use your database's dump and restore programs instead of Sequel's schema
530
- dumper.
526
+ Note that Sequel cannot dump constraints other than primary key and possibly
527
+ foreign key constraints constraints. If you are using database features such
528
+ as constraints or triggers, you should use your database's dump and restore
529
+ programs instead of Sequel's schema dumper.
531
530
 
532
531
  You can take the migration created by the schema dumper to another computer
533
532
  with an empty database, and attempt to recreate the schema using:
data/doc/model_hooks.rdoc CHANGED
@@ -45,7 +45,7 @@ Sequel calls hooks in the following order when saving an existing object:
45
45
  * +before_save+
46
46
  * +around_update+
47
47
  * +before_update+
48
- * INSERT QUERY
48
+ * UPDATE QUERY
49
49
  * +after_update+
50
50
  * +after_save+
51
51
 
@@ -89,10 +89,10 @@ Sequel does not provide a simple way to turn off the running of save/create/upda
89
89
 
90
90
  However, you should note that there are plenty of ways to modify the database without saving a model object. One example is by using plain datasets, or one of the model's dataset methods:
91
91
 
92
- Album.filter(:name=>'RF').update(:copies_sold=>:copies_sold + 1)
92
+ Album.where(:name=>'RF').update(:copies_sold=>:copies_sold + 1)
93
93
  # UPDATE albums SET copies_sold = copies_sold + 1 WHERE name = 'RF'
94
94
 
95
- In this case, the +update+ method is called on the dataset returned by <tt>Album.filter</tt>. Even if there is only a single object with the name RF, this will not call any hooks. If you want model hooks to be called, you need to make sure to operate on a model object:
95
+ In this case, the +update+ method is called on the dataset returned by <tt>Album.where</tt>. Even if there is only a single object with the name RF, this will not call any hooks. If you want model hooks to be called, you need to make sure to operate on a model object:
96
96
 
97
97
  album = Album.first(:name=>'RF')
98
98
  album.update(:copies_sold=>album.copies_sold + 1)
@@ -204,6 +204,8 @@ If Sequel needs to represent an SQL concept that does not map directly to an exi
204
204
  ruby class, it will generally use a Sequel::SQL::Expression subclass to represent that
205
205
  concept.
206
206
 
207
+ Some of the examples below show examples that require the {core_extensions extension}[link:files/doc/core_extensions_rdoc.html].
208
+
207
209
  === Sequel::LiteralString
208
210
 
209
211
  Sequel::LiteralString is not actually a Sequel::SQL::Expression subclass. It is
@@ -215,7 +217,7 @@ as literal SQL code, instead of as an SQL string that needs to be escaped:
215
217
  The following shortcuts exist for creating Sequel::LiteralString objects:
216
218
 
217
219
  Sequel.lit("co'de")
218
- "co'de".lit
220
+ "co'de".lit # core_extensions extension
219
221
 
220
222
  === Sequel::SQL::Blob
221
223
 
@@ -228,7 +230,7 @@ than SQL strings do:
228
230
  The following shortcuts exist for creating Sequel::SQL::Blob objects:
229
231
 
230
232
  Sequel.blob("blob")
231
- "blob".to_sequel_blob
233
+ "blob".to_sequel_blob # core_extensions extension
232
234
 
233
235
  === Sequel::SQLTime
234
236
 
@@ -256,7 +258,7 @@ where they are required.
256
258
  The following shortcuts exist for creating Sequel::SQL::ValueList objects:
257
259
 
258
260
  Sequel.value_list([[1, 2], [3, 4]])
259
- [[1, 2], [3, 4]].sql_value_list
261
+ [[1, 2], [3, 4]].sql_value_list # core_extensions extension
260
262
 
261
263
  === Sequel::SQL::Identifier
262
264
 
@@ -268,8 +270,9 @@ automatic qualification or aliasing happens for them:
268
270
 
269
271
  The following shortcuts exist for creating Sequel::SQL::Identifier objects:
270
272
 
273
+ Sequel.expr(:column)
271
274
  Sequel.identifier(:col__umn)
272
- :col__umn.identifier
275
+ :col__umn.identifier # core_extensions extension
273
276
 
274
277
  === Sequel::SQL::QualifiedIdentifier
275
278
 
@@ -279,8 +282,9 @@ Sequel::SQL::QualifiedIdentifier objects represent qualified identifiers:
279
282
 
280
283
  The following shortcuts exist for creating Sequel::SQL::QualifiedIdentifier objects:
281
284
 
285
+ Sequel.expr(:table__column)
282
286
  Sequel.qualify(:table, :column)
283
- :column.qualify(:table)
287
+ :column.qualify(:table) # core_extensions extension
284
288
 
285
289
  === Sequel::SQL::AliasedExpression
286
290
 
@@ -291,8 +295,9 @@ is treated as an identifier, but the expression can be an arbitrary Sequel expre
291
295
 
292
296
  The following shortcuts exist for creating Sequel::SQL::AliasedExpression objects:
293
297
 
298
+ Sequel.expr(:column___alias)
294
299
  Sequel.as(:column, :alias)
295
- :column.as(:alias)
300
+ :column.as(:alias) # core_extensions extension
296
301
 
297
302
  === Sequel::SQL::ComplexExpression
298
303
 
@@ -309,13 +314,13 @@ There are separate subclasses for representing boolean operations such as AND an
309
314
  There are many shortcuts for creating Sequel::SQL::ComplexExpression objects:
310
315
 
311
316
  Sequel.or(:col1, :col2)
312
- :col1 | :col2
317
+ :col1 | :col2 # core_extensions extension
313
318
 
314
319
  Sequel.+(:column, 2)
315
- :column + 2
320
+ :column + 2 # core_extensions extension
316
321
 
317
322
  Sequel.join([:column, 'b'])
318
- :column + 'b'
323
+ :column + 'b' # core_extensions extension
319
324
 
320
325
  === Sequel::SQL::CaseExpression
321
326
 
@@ -339,8 +344,8 @@ The following shortcuts exist for creating Sequel::SQL::CaseExpression objects:
339
344
  Sequel.case({2=>1}, 0, :a)
340
345
  Sequel.case({{:a=>2}=>1}, 0)
341
346
 
342
- {2=>1}.case(0, :a)
343
- {{:a=>2}=>1}.case(0)
347
+ {2=>1}.case(0, :a) # core_extensions extension
348
+ {{:a=>2}=>1}.case(0) # core_extensions extension
344
349
 
345
350
  === Sequel::SQL::Cast
346
351
 
@@ -360,8 +365,8 @@ The following shortcuts exist for creating Sequel::SQL::Cast objects:
360
365
  Sequel.cast(:a, String)
361
366
  Sequel.cast(:a, :int4)
362
367
 
363
- :a.cast(String)
364
- :a.cast(:int4)
368
+ :a.cast(String) # core_extensions extension
369
+ :a.cast(:int4) # core_extensions extension
365
370
 
366
371
  === Sequel::SQL::ColumnAll
367
372
 
@@ -374,7 +379,8 @@ take arguments. Still, it's possible they are still useful in some code:
374
379
 
375
380
  The following shortcut exists for creating Sequel::SQL::Cast objects:
376
381
 
377
- :table.*
382
+ Sequel.expr(:table).*
383
+ :table.* # core_extensions extension
378
384
 
379
385
  === Sequel::SQL::Constant
380
386
 
@@ -399,7 +405,7 @@ name and any arguments:
399
405
  The following shortcuts exist for creating Sequel::SQL::Function objects:
400
406
 
401
407
  Sequel.function(:func, :a, 2)
402
- :func.sql_function(:a, 2)
408
+ :func.sql_function(:a, 2) # core_extensions extension
403
409
 
404
410
  === Sequel::SQL::JoinClause
405
411
 
@@ -436,8 +442,8 @@ objects:
436
442
  Sequel.lit(':b = :v', :b=>:a, :v=>1)
437
443
  Sequel.lit(['', ' = '], :a, 1)
438
444
 
439
- '? = ?'.lit(:a, 1)
440
- ':b = :v'.lit(:b=>:a, :v=>1)
445
+ '? = ?'.lit(:a, 1) # core_extensions extension
446
+ ':b = :v'.lit(:b=>:a, :v=>1) # core_extensions extension
441
447
 
442
448
  === Sequel::SQL::OrderedExpression
443
449
 
@@ -461,10 +467,10 @@ The following shortcuts exist for creating Sequel::SQL::OrderedExpression object
461
467
  Sequel.asc(:a, :nulls=>:first)
462
468
  Sequel.desc(:a, :nulls=>:last)
463
469
 
464
- :a.asc
465
- :a.desc
466
- :a.asc(:nulls=>:first)
467
- :a.desc(:nulls=>:last)
470
+ :a.asc # core_extensions extension
471
+ :a.desc # core_extensions extension
472
+ :a.asc(:nulls=>:first) # core_extensions extension
473
+ :a.desc(:nulls=>:last) # core_extensions extension
468
474
 
469
475
  === Sequel::SQL::Subscript
470
476
 
@@ -479,17 +485,17 @@ The following shortcuts exist for creating Sequel::SQL::Subscript objects:
479
485
  Sequel.subscript(:a, 1)
480
486
  Sequel.subscript(:a, 1, 2)
481
487
 
482
- :a.sql_subscript(1)
483
- :a.sql_subscript(1, 2)
488
+ :a.sql_subscript(1) # core_extensions extension
489
+ :a.sql_subscript(1, 2) # core_extensions extension
484
490
 
485
491
  === Sequel::SQL::VirtualRow
486
492
 
487
493
  Sequel::SQL::VirtualRow is a BasicObject subclass that is the backbone behind the
488
494
  block expression support:
489
495
 
490
- DB[:table].filter{a < 1}
496
+ DB[:table].where{a < 1}
491
497
 
492
- In the above code, the block is instance-evaled instead a VirtualRow instance.
498
+ In the above code, the block is instance-evaled inside a VirtualRow instance.
493
499
 
494
500
  These objects are usually not instantiated manually. See the
495
501
  {Virtual Row Guide}[link:files/doc/virtual_rows_rdoc.html] for details.