viking-sequel 3.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +3134 -0
- data/COPYING +19 -0
- data/README.rdoc +723 -0
- data/Rakefile +193 -0
- data/bin/sequel +196 -0
- data/doc/advanced_associations.rdoc +644 -0
- data/doc/cheat_sheet.rdoc +218 -0
- data/doc/dataset_basics.rdoc +106 -0
- data/doc/dataset_filtering.rdoc +158 -0
- data/doc/opening_databases.rdoc +296 -0
- data/doc/prepared_statements.rdoc +104 -0
- data/doc/reflection.rdoc +84 -0
- data/doc/release_notes/1.0.txt +38 -0
- data/doc/release_notes/1.1.txt +143 -0
- data/doc/release_notes/1.3.txt +101 -0
- data/doc/release_notes/1.4.0.txt +53 -0
- data/doc/release_notes/1.5.0.txt +155 -0
- data/doc/release_notes/2.0.0.txt +298 -0
- data/doc/release_notes/2.1.0.txt +271 -0
- data/doc/release_notes/2.10.0.txt +328 -0
- data/doc/release_notes/2.11.0.txt +215 -0
- data/doc/release_notes/2.12.0.txt +534 -0
- data/doc/release_notes/2.2.0.txt +253 -0
- data/doc/release_notes/2.3.0.txt +88 -0
- data/doc/release_notes/2.4.0.txt +106 -0
- data/doc/release_notes/2.5.0.txt +137 -0
- data/doc/release_notes/2.6.0.txt +157 -0
- data/doc/release_notes/2.7.0.txt +166 -0
- data/doc/release_notes/2.8.0.txt +171 -0
- data/doc/release_notes/2.9.0.txt +97 -0
- data/doc/release_notes/3.0.0.txt +221 -0
- data/doc/release_notes/3.1.0.txt +406 -0
- data/doc/release_notes/3.10.0.txt +286 -0
- data/doc/release_notes/3.2.0.txt +268 -0
- data/doc/release_notes/3.3.0.txt +192 -0
- data/doc/release_notes/3.4.0.txt +325 -0
- data/doc/release_notes/3.5.0.txt +510 -0
- data/doc/release_notes/3.6.0.txt +366 -0
- data/doc/release_notes/3.7.0.txt +179 -0
- data/doc/release_notes/3.8.0.txt +151 -0
- data/doc/release_notes/3.9.0.txt +233 -0
- data/doc/schema.rdoc +36 -0
- data/doc/sharding.rdoc +113 -0
- data/doc/virtual_rows.rdoc +205 -0
- data/lib/sequel.rb +1 -0
- data/lib/sequel/adapters/ado.rb +90 -0
- data/lib/sequel/adapters/ado/mssql.rb +30 -0
- data/lib/sequel/adapters/amalgalite.rb +176 -0
- data/lib/sequel/adapters/db2.rb +139 -0
- data/lib/sequel/adapters/dbi.rb +113 -0
- data/lib/sequel/adapters/do.rb +188 -0
- data/lib/sequel/adapters/do/mysql.rb +49 -0
- data/lib/sequel/adapters/do/postgres.rb +91 -0
- data/lib/sequel/adapters/do/sqlite.rb +40 -0
- data/lib/sequel/adapters/firebird.rb +283 -0
- data/lib/sequel/adapters/informix.rb +77 -0
- data/lib/sequel/adapters/jdbc.rb +587 -0
- data/lib/sequel/adapters/jdbc/as400.rb +58 -0
- data/lib/sequel/adapters/jdbc/h2.rb +133 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +57 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +78 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +50 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +108 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +55 -0
- data/lib/sequel/adapters/mysql.rb +421 -0
- data/lib/sequel/adapters/odbc.rb +143 -0
- data/lib/sequel/adapters/odbc/mssql.rb +42 -0
- data/lib/sequel/adapters/openbase.rb +64 -0
- data/lib/sequel/adapters/oracle.rb +131 -0
- data/lib/sequel/adapters/postgres.rb +504 -0
- data/lib/sequel/adapters/shared/mssql.rb +490 -0
- data/lib/sequel/adapters/shared/mysql.rb +498 -0
- data/lib/sequel/adapters/shared/oracle.rb +195 -0
- data/lib/sequel/adapters/shared/postgres.rb +830 -0
- data/lib/sequel/adapters/shared/progress.rb +44 -0
- data/lib/sequel/adapters/shared/sqlite.rb +389 -0
- data/lib/sequel/adapters/sqlite.rb +224 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +84 -0
- data/lib/sequel/connection_pool.rb +99 -0
- data/lib/sequel/connection_pool/sharded_single.rb +84 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +211 -0
- data/lib/sequel/connection_pool/single.rb +29 -0
- data/lib/sequel/connection_pool/threaded.rb +150 -0
- data/lib/sequel/core.rb +293 -0
- data/lib/sequel/core_sql.rb +241 -0
- data/lib/sequel/database.rb +1079 -0
- data/lib/sequel/database/schema_generator.rb +327 -0
- data/lib/sequel/database/schema_methods.rb +203 -0
- data/lib/sequel/database/schema_sql.rb +320 -0
- data/lib/sequel/dataset.rb +32 -0
- data/lib/sequel/dataset/actions.rb +441 -0
- data/lib/sequel/dataset/features.rb +86 -0
- data/lib/sequel/dataset/graph.rb +254 -0
- data/lib/sequel/dataset/misc.rb +119 -0
- data/lib/sequel/dataset/mutation.rb +64 -0
- data/lib/sequel/dataset/prepared_statements.rb +227 -0
- data/lib/sequel/dataset/query.rb +709 -0
- data/lib/sequel/dataset/sql.rb +996 -0
- data/lib/sequel/exceptions.rb +51 -0
- data/lib/sequel/extensions/blank.rb +43 -0
- data/lib/sequel/extensions/inflector.rb +242 -0
- data/lib/sequel/extensions/looser_typecasting.rb +21 -0
- data/lib/sequel/extensions/migration.rb +239 -0
- data/lib/sequel/extensions/named_timezones.rb +61 -0
- data/lib/sequel/extensions/pagination.rb +100 -0
- data/lib/sequel/extensions/pretty_table.rb +82 -0
- data/lib/sequel/extensions/query.rb +52 -0
- data/lib/sequel/extensions/schema_dumper.rb +271 -0
- data/lib/sequel/extensions/sql_expr.rb +122 -0
- data/lib/sequel/extensions/string_date_time.rb +46 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +48 -0
- data/lib/sequel/metaprogramming.rb +9 -0
- data/lib/sequel/model.rb +120 -0
- data/lib/sequel/model/associations.rb +1514 -0
- data/lib/sequel/model/base.rb +1069 -0
- data/lib/sequel/model/default_inflections.rb +45 -0
- data/lib/sequel/model/errors.rb +39 -0
- data/lib/sequel/model/exceptions.rb +21 -0
- data/lib/sequel/model/inflections.rb +162 -0
- data/lib/sequel/model/plugins.rb +70 -0
- data/lib/sequel/plugins/active_model.rb +59 -0
- data/lib/sequel/plugins/association_dependencies.rb +103 -0
- data/lib/sequel/plugins/association_proxies.rb +41 -0
- data/lib/sequel/plugins/boolean_readers.rb +53 -0
- data/lib/sequel/plugins/caching.rb +141 -0
- data/lib/sequel/plugins/class_table_inheritance.rb +214 -0
- data/lib/sequel/plugins/composition.rb +138 -0
- data/lib/sequel/plugins/force_encoding.rb +72 -0
- data/lib/sequel/plugins/hook_class_methods.rb +126 -0
- data/lib/sequel/plugins/identity_map.rb +116 -0
- data/lib/sequel/plugins/instance_filters.rb +98 -0
- data/lib/sequel/plugins/instance_hooks.rb +57 -0
- data/lib/sequel/plugins/lazy_attributes.rb +77 -0
- data/lib/sequel/plugins/many_through_many.rb +208 -0
- data/lib/sequel/plugins/nested_attributes.rb +206 -0
- data/lib/sequel/plugins/optimistic_locking.rb +81 -0
- data/lib/sequel/plugins/rcte_tree.rb +281 -0
- data/lib/sequel/plugins/schema.rb +66 -0
- data/lib/sequel/plugins/serialization.rb +166 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +74 -0
- data/lib/sequel/plugins/subclasses.rb +45 -0
- data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
- data/lib/sequel/plugins/timestamps.rb +87 -0
- data/lib/sequel/plugins/touch.rb +118 -0
- data/lib/sequel/plugins/typecast_on_load.rb +72 -0
- data/lib/sequel/plugins/validation_class_methods.rb +405 -0
- data/lib/sequel/plugins/validation_helpers.rb +223 -0
- data/lib/sequel/sql.rb +1020 -0
- data/lib/sequel/timezones.rb +161 -0
- data/lib/sequel/version.rb +12 -0
- data/lib/sequel_core.rb +1 -0
- data/lib/sequel_model.rb +1 -0
- data/spec/adapters/firebird_spec.rb +407 -0
- data/spec/adapters/informix_spec.rb +97 -0
- data/spec/adapters/mssql_spec.rb +403 -0
- data/spec/adapters/mysql_spec.rb +1019 -0
- data/spec/adapters/oracle_spec.rb +286 -0
- data/spec/adapters/postgres_spec.rb +969 -0
- data/spec/adapters/spec_helper.rb +51 -0
- data/spec/adapters/sqlite_spec.rb +432 -0
- data/spec/core/connection_pool_spec.rb +808 -0
- data/spec/core/core_sql_spec.rb +417 -0
- data/spec/core/database_spec.rb +1662 -0
- data/spec/core/dataset_spec.rb +3827 -0
- data/spec/core/expression_filters_spec.rb +595 -0
- data/spec/core/object_graph_spec.rb +296 -0
- data/spec/core/schema_generator_spec.rb +159 -0
- data/spec/core/schema_spec.rb +830 -0
- data/spec/core/spec_helper.rb +56 -0
- data/spec/core/version_spec.rb +7 -0
- data/spec/extensions/active_model_spec.rb +76 -0
- data/spec/extensions/association_dependencies_spec.rb +127 -0
- data/spec/extensions/association_proxies_spec.rb +50 -0
- data/spec/extensions/blank_spec.rb +67 -0
- data/spec/extensions/boolean_readers_spec.rb +92 -0
- data/spec/extensions/caching_spec.rb +250 -0
- data/spec/extensions/class_table_inheritance_spec.rb +252 -0
- data/spec/extensions/composition_spec.rb +194 -0
- data/spec/extensions/force_encoding_spec.rb +117 -0
- data/spec/extensions/hook_class_methods_spec.rb +470 -0
- data/spec/extensions/identity_map_spec.rb +202 -0
- data/spec/extensions/inflector_spec.rb +181 -0
- data/spec/extensions/instance_filters_spec.rb +55 -0
- data/spec/extensions/instance_hooks_spec.rb +133 -0
- data/spec/extensions/lazy_attributes_spec.rb +153 -0
- data/spec/extensions/looser_typecasting_spec.rb +39 -0
- data/spec/extensions/many_through_many_spec.rb +884 -0
- data/spec/extensions/migration_spec.rb +332 -0
- data/spec/extensions/named_timezones_spec.rb +72 -0
- data/spec/extensions/nested_attributes_spec.rb +396 -0
- data/spec/extensions/optimistic_locking_spec.rb +100 -0
- data/spec/extensions/pagination_spec.rb +99 -0
- data/spec/extensions/pretty_table_spec.rb +91 -0
- data/spec/extensions/query_spec.rb +85 -0
- data/spec/extensions/rcte_tree_spec.rb +205 -0
- data/spec/extensions/schema_dumper_spec.rb +357 -0
- data/spec/extensions/schema_spec.rb +127 -0
- data/spec/extensions/serialization_spec.rb +209 -0
- data/spec/extensions/single_table_inheritance_spec.rb +96 -0
- data/spec/extensions/spec_helper.rb +91 -0
- data/spec/extensions/sql_expr_spec.rb +89 -0
- data/spec/extensions/string_date_time_spec.rb +93 -0
- data/spec/extensions/subclasses_spec.rb +52 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
- data/spec/extensions/thread_local_timezones_spec.rb +45 -0
- data/spec/extensions/timestamps_spec.rb +150 -0
- data/spec/extensions/touch_spec.rb +155 -0
- data/spec/extensions/typecast_on_load_spec.rb +69 -0
- data/spec/extensions/validation_class_methods_spec.rb +984 -0
- data/spec/extensions/validation_helpers_spec.rb +438 -0
- data/spec/integration/associations_test.rb +281 -0
- data/spec/integration/database_test.rb +26 -0
- data/spec/integration/dataset_test.rb +963 -0
- data/spec/integration/eager_loader_test.rb +734 -0
- data/spec/integration/model_test.rb +130 -0
- data/spec/integration/plugin_test.rb +814 -0
- data/spec/integration/prepared_statement_test.rb +213 -0
- data/spec/integration/schema_test.rb +361 -0
- data/spec/integration/spec_helper.rb +73 -0
- data/spec/integration/timezone_test.rb +55 -0
- data/spec/integration/transaction_test.rb +122 -0
- data/spec/integration/type_test.rb +96 -0
- data/spec/model/association_reflection_spec.rb +175 -0
- data/spec/model/associations_spec.rb +2633 -0
- data/spec/model/base_spec.rb +418 -0
- data/spec/model/dataset_methods_spec.rb +78 -0
- data/spec/model/eager_loading_spec.rb +1391 -0
- data/spec/model/hooks_spec.rb +240 -0
- data/spec/model/inflector_spec.rb +26 -0
- data/spec/model/model_spec.rb +593 -0
- data/spec/model/plugins_spec.rb +236 -0
- data/spec/model/record_spec.rb +1500 -0
- data/spec/model/spec_helper.rb +97 -0
- data/spec/model/validations_spec.rb +153 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec_config.rb.example +10 -0
- metadata +346 -0
@@ -0,0 +1,298 @@
|
|
1
|
+
Blockless Filter Expressions
|
2
|
+
----------------------------
|
3
|
+
|
4
|
+
Before 2.0.0, in order to specify complex SQL expressions, you
|
5
|
+
either had to resort to writing the SQL yourself in a string or
|
6
|
+
using an expression inside a block that was parsed by ParseTree.
|
7
|
+
Because ParseTree was required, only ruby 1.8.* was supported, and
|
8
|
+
supporting other ruby versions (ruby 1.9, JRuby, Rubinius) would
|
9
|
+
never be possible.
|
10
|
+
|
11
|
+
With 2.0.0, you no longer need to use a block to write complex SQL
|
12
|
+
expressions. The basics of the blockless filters are the usual
|
13
|
+
arithmetic, inequality, and binary operators:
|
14
|
+
|
15
|
+
+ = addition
|
16
|
+
- = subtraction
|
17
|
+
* = multiplication
|
18
|
+
/ = division
|
19
|
+
> = greater than
|
20
|
+
< = less than
|
21
|
+
>= = greater than or equal to
|
22
|
+
<= = less than or equal to
|
23
|
+
~ = negation
|
24
|
+
& = AND
|
25
|
+
| = OR
|
26
|
+
|
27
|
+
You can use these operators on Symbols, LiteralStrings, and other
|
28
|
+
Sequel::SQL::Expressions. Note that there is no equal operator or
|
29
|
+
not equal operator, to specify those, you use a Hash.
|
30
|
+
|
31
|
+
Here are some examples:
|
32
|
+
|
33
|
+
# Ruby code => SQL WHERE clause
|
34
|
+
:active => active
|
35
|
+
~:active => NOT active
|
36
|
+
~~:active => active
|
37
|
+
~~~:active => NOT active
|
38
|
+
:is_true[] => is_true()
|
39
|
+
~:is_true[] => NOT is_true()
|
40
|
+
:x > 100 => (x > 100)
|
41
|
+
:x < 100.01 => (x < 100.01)
|
42
|
+
:x <= 0 => (x <= 0)
|
43
|
+
:x >= 1 => (x >= 1)
|
44
|
+
~(:x > 100) => (x <= 100)
|
45
|
+
{:x => 100} => (x = 100)
|
46
|
+
{:x => 'a'} => (x = 'a')
|
47
|
+
{:x => nil} => (x IS NULL)
|
48
|
+
~{:x => 100} => (x != 100)
|
49
|
+
~{:x => 'a'} => (x != 'a')
|
50
|
+
~{:x => nil} => (x IS NOT NULL)
|
51
|
+
{:x => /a/} => (x ~ 'blah') # Default, MySQL different
|
52
|
+
~{:x => /a/} => (x !~ 'blah') # Default, MySQL different
|
53
|
+
:x.like('a') => (x LIKE 'a')
|
54
|
+
~:x.like('a') => (x NOT LIKE 'a')
|
55
|
+
:x.like(/a/) => (x ~ 'a') # Default, MySQL different
|
56
|
+
~:x.like('a', /b/) => ((x NOT LIKE 'a') AND (x !~ 'b')) # Default
|
57
|
+
~{:x => 1..5} => ((x < 1) OR (x > 5))
|
58
|
+
~{:x => DB[:items].select(:i)} => (x NOT IN (SELECT i FROM items))
|
59
|
+
~{:x => [1,2,3]} => (x NOT IN (1, 2, 3))
|
60
|
+
:x + 1 > 100 => ((x + 1) > 100)
|
61
|
+
(:x * :y) < 100.01 => ((x * y) < 100.01)
|
62
|
+
(:x - :y/2) >= 100 => ((x - (y / 2)) >= 100)
|
63
|
+
(((:x - :y)/(:x + :y))*:z) <= 100 => ((((x - y) / (x + y)) * z) <=
|
64
|
+
100)
|
65
|
+
~((((:x - :y)/(:x + :y))*:z) <= 100) => ((((x - y) / (x + y)) * z) >
|
66
|
+
100)
|
67
|
+
:x & :y => (x AND y)
|
68
|
+
:x & :y & :z => ((x AND y) AND z)
|
69
|
+
:x & {:y => :z} => (x AND (y = z))
|
70
|
+
{:y => :z} & :x => ((y = z) AND x)
|
71
|
+
{:x => :a} & {:y => :z} => ((x = a) AND (y = z))
|
72
|
+
(:x > 200) & (:y < 200) => ((x > 200) AND (y < 200))
|
73
|
+
:x | :y => (x OR y)
|
74
|
+
:x | :y | :z => ((x OR y) OR z)
|
75
|
+
:x | {:y => :z} => (x OR (y = z))
|
76
|
+
{:y => :z} | :x => ((y = z) OR x)
|
77
|
+
{:x => :a} | {:y => :z} => ((x = a) OR (y = z))
|
78
|
+
(:x > 200) | (:y < 200) => ((x > 200) OR (y < 200))
|
79
|
+
(:x | :y) & :z => ((x OR y) AND z)
|
80
|
+
:x | (:y & :z) => (x OR (y AND z))
|
81
|
+
(:x & :w) | (:y & :z) => ((x AND w) OR (y AND z))
|
82
|
+
~((:x | :y) & :z) => ((NOT x AND NOT y) OR NOT z)
|
83
|
+
~((:x & :w) | (:y & :z)) => ((NOT x OR NOT w) AND (NOT y OR NOT z))
|
84
|
+
~((:x > 200) | (:y & :z)) => ((x <= 200) AND (NOT y OR NOT z))
|
85
|
+
~('x'.lit + 1 > 100) => ((x + 1) <= 100)
|
86
|
+
'x'.lit.like(/a/) => (x ~ 'a') # (x ~ \'a\')
|
87
|
+
|
88
|
+
None of these require blocks, you can use any directly in a call to
|
89
|
+
filter:
|
90
|
+
|
91
|
+
DB[:items].filter((:price * :tax) - :discount > 100)
|
92
|
+
# => SELECT * FROM items WHERE (((price * tax) - discount) > 100)
|
93
|
+
DB[:items].filter(:active & ~:archived)
|
94
|
+
# => SELECT * FROM items WHERE (active AND NOT archived)
|
95
|
+
|
96
|
+
SQL String Concatenation
|
97
|
+
------------------------
|
98
|
+
|
99
|
+
Sequel now has support for expressing SQL string concatenation in an
|
100
|
+
easy way:
|
101
|
+
|
102
|
+
[:name, :title].sql_string_join(" - ")
|
103
|
+
# SQL: name || ' - ' || title
|
104
|
+
|
105
|
+
You can use this in selecting columns, creating filters, ordering
|
106
|
+
datasets, and possibly elsewhere.
|
107
|
+
|
108
|
+
Schema Reflection Support/Typecasting on Assignment
|
109
|
+
---------------------------------------------------
|
110
|
+
|
111
|
+
When used with PostgreSQL, MySQL, or SQLite, Sequel now has the
|
112
|
+
ability to get information from the database's schema in regards
|
113
|
+
to column types:
|
114
|
+
|
115
|
+
DB.schema(:artist)
|
116
|
+
=> [[:id, {:type=>:integer, :db_type=>"integer", :max_chars=>0
|
117
|
+
:numeric_precision=>32, :allow_null=>false,
|
118
|
+
:default=>"nextval('artist_id_seq'::regclass)"}], [:name,
|
119
|
+
{:type=>:string, :default=>nil, :db_type=>"text",
|
120
|
+
:numeric_precision=>0, :allow_null=>true, :max_chars=>0}]]
|
121
|
+
|
122
|
+
Models now use this information to typecast values on attribute
|
123
|
+
assignment. For example, if you have an integer column named number
|
124
|
+
and a text (e.g. varchar) column named title:
|
125
|
+
|
126
|
+
1.5.1:
|
127
|
+
model.number = '1'
|
128
|
+
model.number # => '1'
|
129
|
+
model.title = 1
|
130
|
+
model.title # => 1
|
131
|
+
2.0.0:
|
132
|
+
model.number = '1'
|
133
|
+
model.number # => 1
|
134
|
+
model.title = 1
|
135
|
+
model.title # => '1'
|
136
|
+
|
137
|
+
Typecasting can be turned off on a global, per class, and per object
|
138
|
+
basis:
|
139
|
+
|
140
|
+
Sequel::Model.typecast_on_assignment = false # Global
|
141
|
+
Album.typecast_on_assignment = false # Per Class
|
142
|
+
Album.new.typecast_on_assignment = false # Per Object
|
143
|
+
|
144
|
+
Typecasting is somewhat strict, it does not allow obviously bogus
|
145
|
+
data to be used:
|
146
|
+
|
147
|
+
model.number = 'a' # Raises error
|
148
|
+
|
149
|
+
This is in contrast to how some other ORMs handle the situation:
|
150
|
+
|
151
|
+
model.number = 'a'
|
152
|
+
model.number # => 0
|
153
|
+
|
154
|
+
If Sequel is being used with a web framework and you want to display
|
155
|
+
friendly error messages to the user, you should probably turn
|
156
|
+
typecasting off and set up the necessary validations in your models.
|
157
|
+
|
158
|
+
Model Association Improvements
|
159
|
+
------------------------------
|
160
|
+
|
161
|
+
Associations can now be eagerly loaded even if they have a block,
|
162
|
+
though the block should not rely on being evaluated in the context
|
163
|
+
of an instance. This allows you filter on associations when eagerly
|
164
|
+
loading:
|
165
|
+
|
166
|
+
Artist.one_to_many :albums_with_10_tracks, :class=>:Album do |ds|
|
167
|
+
ds.filter(:num_tracks => 10)
|
168
|
+
end
|
169
|
+
Artist.filter(:name.like('A%)).eager(:albums_with_10_tracks).all
|
170
|
+
# SELECT * FROM artists WHERE (name LIKE 'A%')
|
171
|
+
# SELECT albums.* FROM albums WHERE ((artist_id IN (...)) AND
|
172
|
+
# (num_tracks = 10))
|
173
|
+
|
174
|
+
Associations now have a remove_all_ method for removing all
|
175
|
+
associated objects in a single query:
|
176
|
+
|
177
|
+
Artist.many_to_many :albums
|
178
|
+
Artist[1].remove_all_albums
|
179
|
+
# DELETE FROM albums_artists WHERE artist_id = 1
|
180
|
+
|
181
|
+
Artist.one_to_many :albums
|
182
|
+
Artist[1].remove_all_albums
|
183
|
+
# UPDATE albums SET artist_id = NULL WHERE artist_id = 1
|
184
|
+
|
185
|
+
All associations can specify a :select option to change which columns
|
186
|
+
are selected. Previously only many to many associations suppported
|
187
|
+
this.
|
188
|
+
|
189
|
+
The SQL used when eagerly loading through eager_graph can be
|
190
|
+
modified via the :graph_join_type, :graph_conditions, and
|
191
|
+
:graph_join_conditions options.
|
192
|
+
|
193
|
+
:graph_join_type changes the join type from the default of
|
194
|
+
:left_outer. This can be useful if you do not want any
|
195
|
+
albums that don't have an artist in the result set:
|
196
|
+
|
197
|
+
Album.many_to_one :artist, :graph_join_type=>:inner
|
198
|
+
Album.eager_graph(:artist).sql
|
199
|
+
# SELECT ... FROM albums INNER JOIN artists ...
|
200
|
+
|
201
|
+
:graph_conditions adds conditions on the join to the table you are
|
202
|
+
joining, the eager_graph equivalent of an association block argument
|
203
|
+
in eager. It takes either a hash or an array where all elements
|
204
|
+
are arrays of length two, similar to join_table, where key symbols
|
205
|
+
specify columns in the joined table and value symbols specify
|
206
|
+
columns in the last joined or primary table:
|
207
|
+
|
208
|
+
Album.many_to_one :artist, :graph_conditions=>{:active=>true}
|
209
|
+
Album.eager_graph(:artist).sql
|
210
|
+
# SELECT ... FROM albums LEFT OUTER JOIN artists ON ((artists.id =
|
211
|
+
# albums.artist_id) AND (artists.active = 't'))
|
212
|
+
|
213
|
+
:graph_join_table_conditions exists for many to many associations only,
|
214
|
+
and operates the same as :graph_conditions, except it specifies a
|
215
|
+
condition on the many to many join table instead of the associated
|
216
|
+
model's table. This is necessary if the join table is also model
|
217
|
+
table with other columns on which you may want to filter:
|
218
|
+
|
219
|
+
Album.many_to_many :genres, :join_table=>:ag, \
|
220
|
+
:graph_join_table_conditions=>{:active=>true}
|
221
|
+
Album.eager_graph(:genres).sql
|
222
|
+
# SELECT ... FROM albums LEFT OUTER JOIN ag ON ((ag.album_id =
|
223
|
+
albums.id) AND (ag.active = 't')) LEFT OUTER JOIN genres ON
|
224
|
+
(genres.id = ag.genre_id)
|
225
|
+
|
226
|
+
Other Small Improvements
|
227
|
+
------------------------
|
228
|
+
|
229
|
+
* Dataset#invert returns a dataset that matches all records not
|
230
|
+
matching the current filter.
|
231
|
+
* Dataset#unfiltered returns a dataset that has any filters removed.
|
232
|
+
* Dataset#last_page? and Dataset#first_page? for paginated datasets.
|
233
|
+
* The sequel command line tool now support an -E or --echo argument
|
234
|
+
that logs all SQL to the standard output. It also can take a path
|
235
|
+
to a yaml file with database connection options, in addition to a
|
236
|
+
database URL.
|
237
|
+
* Databases can now have multiple SQL loggers, so you can log to the
|
238
|
+
standard output as well as a file.
|
239
|
+
* SQL identifiers (columns and tables) are now quoted by default (you
|
240
|
+
can turn this off via Sequel.quote_identifiers = false if need be).
|
241
|
+
* Sequel.connect now takes an optional block that will disconnect the
|
242
|
+
database when the block finishes.
|
243
|
+
* AlterTableGenerator now has add_primary_key and add_foreign_key
|
244
|
+
methods.
|
245
|
+
* Running the specs without ParseTree installed skips the specs that
|
246
|
+
require ParseTree.
|
247
|
+
* You can use an array of arrays instead of a hash when specifying
|
248
|
+
conditions, which may be necessary in certain situations where
|
249
|
+
you would be using the same hash key more than once.
|
250
|
+
* Almost all documentation for Sequel was updated for 2.0.0, so if you
|
251
|
+
found Sequel documentation lacking before, check out the new RDoc
|
252
|
+
pages.
|
253
|
+
* There have been many minor refactoring improvements, the code
|
254
|
+
should now be easier to read and follow.
|
255
|
+
* Sequel now has no external dependencies.
|
256
|
+
* Sequel::Models now have before_validation and after_validation
|
257
|
+
hooks.
|
258
|
+
* Sequel::Model hooks that return false cause the methods that call
|
259
|
+
them (such as save) to return false.
|
260
|
+
* Sequel::Models can now load their schema on first instantiation,
|
261
|
+
instead of when they are created, via
|
262
|
+
Sequel::Model.lazy_load_schema=. This is helpful for certain
|
263
|
+
web frameworks that reload all models on every request.
|
264
|
+
* Hook methods that use blocks can now include an optional tag,
|
265
|
+
which allows them to work well with web frameworks that load source
|
266
|
+
files every time they are modified.
|
267
|
+
|
268
|
+
The PostgreSQL adapter has been rewritten and now supports ruby-pg.
|
269
|
+
There have also been improvements in the following adapters: DBI,
|
270
|
+
MySQL, SQLite, Oracle, and MSSQL.
|
271
|
+
|
272
|
+
All of the methods that have been deprecated in 1.5.0 have now been
|
273
|
+
removed. If you are want to upgrade to Sequel 2.0.0 from version 1.4.0
|
274
|
+
or previous, upgrade to 1.5.1 first, fix all of the deprecation
|
275
|
+
warnings that show up, and then upgrade to 2.0.0.
|
276
|
+
|
277
|
+
There were some backwards incompatible changes made in 2.0.0 beyond the
|
278
|
+
removal of deprecated methods. These are:
|
279
|
+
|
280
|
+
* Inflector is no longer used, the inflection methods were moved
|
281
|
+
directly into String (where they belong because inflections only
|
282
|
+
make sense for strings). So to override singularization
|
283
|
+
or pluralization rules, use String.inflections instead of
|
284
|
+
Inflector.inflections.
|
285
|
+
* MySQL tinyints are now returned as boolean values instead of
|
286
|
+
integers. MySQL doesn't have a boolean type, and usually it
|
287
|
+
is recommended to use tinyint for a boolean column.
|
288
|
+
* You can no longer pass an array to Dataset#order or Dataset#select,
|
289
|
+
you need to pass each argument separately (the * operator is your
|
290
|
+
friend).
|
291
|
+
* You must use '?' instead of '(?)' when interpolating an array
|
292
|
+
argument into a string (e.g. filter('x IN ?', [1,2,3]))
|
293
|
+
* You must pass an explicit table alias argument to join_table and
|
294
|
+
related methods, you can no longer include the table alias
|
295
|
+
inside the table argument.
|
296
|
+
* sqlite:// URLs now operate the same as file:// URLs (2 slashes
|
297
|
+
for a relative path, 3 for an absolute path).
|
298
|
+
|
@@ -0,0 +1,271 @@
|
|
1
|
+
Model Improvements
|
2
|
+
------------------
|
3
|
+
|
4
|
+
* one_to_many/many_to_many associations now support a :limit option,
|
5
|
+
adding a limit/offset to the records returned. This was possible
|
6
|
+
before using a block, so it is just added for convenience.
|
7
|
+
|
8
|
+
* Associations now support a :read_only option, which doesn't create
|
9
|
+
methods that modify the database.
|
10
|
+
|
11
|
+
* Associations now support a :graph_select option, which allows
|
12
|
+
specifying the columns of associated models to include when using
|
13
|
+
eager_graph.
|
14
|
+
|
15
|
+
* one_to_many associations now have a :one_to_one option. When used
|
16
|
+
it creates a getter and setter method similar to many_to_one. This
|
17
|
+
fills the same role as ActiveRecord's has_one, but it is
|
18
|
+
implemented as a couple of convenience methods over one_to_many, so
|
19
|
+
it still requires that you specify the association name as a
|
20
|
+
plural.
|
21
|
+
|
22
|
+
* Model datasets now have to_hash augmented so that it can be called
|
23
|
+
without any arguments, in which case it yields an identity map (a
|
24
|
+
hash with keys being primary key values and values being model
|
25
|
+
instances).
|
26
|
+
|
27
|
+
* The Model.set_sti_key method was added, for easily setting up
|
28
|
+
single table inheritance. It should be called only in the parent
|
29
|
+
class.
|
30
|
+
|
31
|
+
* Calls to def_dataset_method with a block are now cached and
|
32
|
+
reapplied to the new dataset if set_dataset is called afterward,
|
33
|
+
or in a subclass.
|
34
|
+
|
35
|
+
* All validation methods can now be made conditional via an :if
|
36
|
+
option, which takes either a symbol (which specifies an instance
|
37
|
+
method) or a proc (which is instance_evaled).
|
38
|
+
|
39
|
+
* Model#set and Model#update have been added back, they are now
|
40
|
+
aliases of #set_with_params and #update_with_params.
|
41
|
+
|
42
|
+
* Models now have set_only/set_except/update_only/update_except
|
43
|
+
instance methods that take a hash (like you would provide to
|
44
|
+
set or update) and additional arguments specifying which columns
|
45
|
+
to allow or disallow.
|
46
|
+
|
47
|
+
* Models now have a set_allowed_columns and set_restricted_columns
|
48
|
+
methods, which operate similarly to ActiveRecord's attr_accessible
|
49
|
+
and attr_protected. It is recommend that you use the set_only or
|
50
|
+
update_only instead of these methods, though. You can ignore the
|
51
|
+
allowed or restricted columns by using #set_all or #update_all.
|
52
|
+
|
53
|
+
* The primary key column(s) is restricted by default. To allow it to
|
54
|
+
be set via new/set/update, use:
|
55
|
+
|
56
|
+
Sequel::Model.unrestrict_primary_key # Global
|
57
|
+
Artist.unrestrict_primary_key # Per Class
|
58
|
+
|
59
|
+
* It is now easy to override the one_to_many/many_to_many association
|
60
|
+
methods that modify the database (add_/remove_/remove_all_), as
|
61
|
+
they have been broken into two methods, one that handles the
|
62
|
+
caching features and a private one (prepended with an _) that
|
63
|
+
handles the database changes (and which you can easily override
|
64
|
+
without worrying about the caching).
|
65
|
+
|
66
|
+
Table Joining
|
67
|
+
-------------
|
68
|
+
|
69
|
+
Dataset#join_table got a nice overhaul. You can now use any join
|
70
|
+
type your database allows:
|
71
|
+
|
72
|
+
DB[:artist].join_table(:natural, :albums)
|
73
|
+
DB[:numbers].join_table(:cross, :numbers)
|
74
|
+
|
75
|
+
You can now specify the conditions as
|
76
|
+
|
77
|
+
* String: "a.b = c.d" # ON a.b = c.d
|
78
|
+
* Expression :x < :y # ON x < y
|
79
|
+
* Array of Symbols: [:x, :y, :z] # USING (x, y, z)
|
80
|
+
* nil # no conditions, used for NATURAL or CROSS joins
|
81
|
+
|
82
|
+
Dataset#join_table also takes a block that yields three arguments:
|
83
|
+
|
84
|
+
* join_table_alias - The alias/name of the table currently being
|
85
|
+
joined
|
86
|
+
* last_join_table_alias - The alias name of the last table joined
|
87
|
+
(if there was one) or the first FROM table (if not).
|
88
|
+
* joins - An array of JoinClause objects for all previous joins in
|
89
|
+
the query.
|
90
|
+
|
91
|
+
Using the block you can specify conditions for complex joins without
|
92
|
+
needing to know in advance what table aliases will be used.
|
93
|
+
|
94
|
+
Expanded SQL Syntax Support
|
95
|
+
---------------------------
|
96
|
+
|
97
|
+
SQL Case statements are now supported directly using hashes or
|
98
|
+
arrays:
|
99
|
+
|
100
|
+
{:x > 1 => 1}.case(0)
|
101
|
+
# CASE WHEN x > 1 THEN 1 ELSE 0 END
|
102
|
+
[[{:x=>1}, 0], [:x < 1, 1], [:x > 1, 2]].case(-1)
|
103
|
+
# CASE WHEN x = 1 THEN 0 WHEN x < 1 THEN 1 WHEN x > 1 THEN 2
|
104
|
+
ELSE -1 END
|
105
|
+
|
106
|
+
You should use an array instead of a hash for multiple conditions
|
107
|
+
unless all conditions are orthogonal.
|
108
|
+
|
109
|
+
The SQL extract function has special syntax:
|
110
|
+
|
111
|
+
EXTRACT(day FROM date)
|
112
|
+
|
113
|
+
This syntax is now supported via the following ruby code:
|
114
|
+
|
115
|
+
:date.extract(:day)
|
116
|
+
|
117
|
+
Other Notable Changes
|
118
|
+
---------------------
|
119
|
+
|
120
|
+
* The sequel command line tool can now run migrations. The -m
|
121
|
+
option specifies the directory holding the migration files,
|
122
|
+
and the -M options specifies the version to which to migrate.
|
123
|
+
|
124
|
+
* The PostgreSQL adapter supports nested transactions/savepoints.
|
125
|
+
|
126
|
+
* The schema parser now understands decimal fields, and will
|
127
|
+
typecast to BigDecimal.
|
128
|
+
|
129
|
+
* PostgreSQL's numeric type is now recognized and returned as
|
130
|
+
BigDecimal.
|
131
|
+
|
132
|
+
* HAVING now comes before ORDER BY, which most databases seem to
|
133
|
+
prefer. If your database wants HAVING after ORDER BY, please
|
134
|
+
let us know.
|
135
|
+
|
136
|
+
* Symbol#qualify now exists, to specify the table name for a given
|
137
|
+
symbol, similar to the use of #as to specify an alias. This is
|
138
|
+
mainly helpful in conjuction with the #join_table block, as that
|
139
|
+
provides the table aliases to use to qualify the columns inside
|
140
|
+
the block.
|
141
|
+
|
142
|
+
* BitwiseMethods (&, |, ^, ~, <<, >>) have been added to the
|
143
|
+
NumericExpression class, so you can do the following:
|
144
|
+
|
145
|
+
(x + 1) ^ 10 # SQL: (x + 1) ^ 10
|
146
|
+
~(x + 1) # SQL: ~(x + 1)
|
147
|
+
|
148
|
+
Usually, &, |, and ~ operate in a logical manner, but for
|
149
|
+
NumericExpressions, they take on their usual bitwise meaning,
|
150
|
+
since logical operations only make sense for booleans.
|
151
|
+
|
152
|
+
* #cast_numeric and #cast_string exist for Symbols, Strings, and
|
153
|
+
other Sequel Expressions, which return the results casted and
|
154
|
+
wrapped in either NumericExpression or StringExpression, so you
|
155
|
+
can use the BitwiseMethods (&, |, ^, ~, <<, >>) or
|
156
|
+
StringConcatenationMethods (+) directly.
|
157
|
+
|
158
|
+
# Dataset#to_hash can take only one argument, in which case it uses
|
159
|
+
that argument to specify the key, and uses the entire hash for the
|
160
|
+
value.
|
161
|
+
|
162
|
+
# Dataset#graph can now take an array of columns to select from the
|
163
|
+
joined table via the :select option.
|
164
|
+
|
165
|
+
# Dataset#filter and similar methods now combine the block and
|
166
|
+
regular argument conditions if both are given, instead of ignoring
|
167
|
+
the regular argument conditions.
|
168
|
+
|
169
|
+
# Dataset#filter(false) can now be used to make sure that no records
|
170
|
+
are returned. Dataset#filter(true) also works, but it's a no-op.
|
171
|
+
Before, these raised errors.
|
172
|
+
|
173
|
+
# Dataset#count does a subquery for a dataset using DISTINCT, since
|
174
|
+
the otherwise it would yield a count for the query without
|
175
|
+
DISTINCT.
|
176
|
+
|
177
|
+
ParseTree Support Officially Deprecated
|
178
|
+
---------------------------------------
|
179
|
+
|
180
|
+
The support for ParseTree-based block filters has officially been
|
181
|
+
deprecated and will be removed in Sequel 2.2. To use the
|
182
|
+
expression filters (which don't require ParseTree) inside blocks,
|
183
|
+
use:
|
184
|
+
|
185
|
+
SEQUEL_NO_PARSE_TREE = true
|
186
|
+
require 'sequel'
|
187
|
+
# OR
|
188
|
+
require 'sequel'
|
189
|
+
Sequel.use_parse_tree = false
|
190
|
+
|
191
|
+
This is the default if ParseTree cannot be loaded. If ParseTree
|
192
|
+
can be loaded, it remains the default, in order not to immediately
|
193
|
+
break existing code.
|
194
|
+
|
195
|
+
With this set, you can use the expression filters inside of blocks:
|
196
|
+
|
197
|
+
dataset.filter{((:x + 1) & 10 < :y) & :z}
|
198
|
+
|
199
|
+
That doesn't gain you all that much, but there are some methods
|
200
|
+
that feed block arguments into filter, such as the following:
|
201
|
+
|
202
|
+
dataset.first(5){((:x + 1) & 10 < :y) & :z}
|
203
|
+
|
204
|
+
Which will get you the first 5 records matching the condition.
|
205
|
+
|
206
|
+
Backwards Incompatible Changes
|
207
|
+
------------------------------
|
208
|
+
|
209
|
+
* To change the datetime classe used from Time to DateTime, you
|
210
|
+
now use:
|
211
|
+
|
212
|
+
Sequel.datetime_class = DateTime # instead of Sequel.time_class
|
213
|
+
|
214
|
+
* Models now raise errors if you try to access a missing or
|
215
|
+
restricted method via new/set/update, instead of just silently
|
216
|
+
skipping that parameter. To get the old behavior:
|
217
|
+
|
218
|
+
Sequel::Model.strict_param_setting = false
|
219
|
+
|
220
|
+
* The association_dataset method now takes into account the :eager
|
221
|
+
option and the block argument, where it didn't before. It also
|
222
|
+
takes into account the new :limit option.
|
223
|
+
|
224
|
+
* Association methods now raise errors in most cases if the model
|
225
|
+
doesn't have a valid primary key.
|
226
|
+
|
227
|
+
* Dataset#join_table used to allow a symbol as a conditions argument
|
228
|
+
as a shortcut for a hash:
|
229
|
+
|
230
|
+
DB[:artist].join(:albums, :artist_id)
|
231
|
+
# ON albums.artist_id = artists.id
|
232
|
+
|
233
|
+
With the changes to #join_table, this no longer works. It would
|
234
|
+
now be interpreted as a boolean column:
|
235
|
+
|
236
|
+
DB[:artist].join(:albums, :artist_id)
|
237
|
+
# ON artists.id
|
238
|
+
|
239
|
+
Use the following slightly longer version for the old behavior:
|
240
|
+
|
241
|
+
DB[:artist].join(:albums, :artist_id=>:id)
|
242
|
+
# ON albums.artist_id = artists.id
|
243
|
+
|
244
|
+
* MySQL users need to be careful when upgrading, the following code
|
245
|
+
will once again cause an error:
|
246
|
+
|
247
|
+
DB[:artists].each{|artist| DB[:albums].each{|album| ...}}
|
248
|
+
|
249
|
+
To fix it, change the code to:
|
250
|
+
|
251
|
+
DB[:artists].all{|artist| DB[:albums].each{|album| ...}}
|
252
|
+
|
253
|
+
The issue is the MySQL adapter doesn't release the database
|
254
|
+
connection while running each, and the second call to each gets the
|
255
|
+
same database connection (while the other query is still running),
|
256
|
+
because it is in the same thread. Using #all for the outside query
|
257
|
+
ensures that the database connection is released before the block is
|
258
|
+
called.
|
259
|
+
|
260
|
+
The reason for this change was that the workaround provided for
|
261
|
+
MySQL could potentially cause issues with transactions for all
|
262
|
+
adapters.
|
263
|
+
|
264
|
+
* String#asc and String#desc are no longer defined, as ordering on a
|
265
|
+
plain string column should be a no-op. They are still defined
|
266
|
+
on LiteralStrings.
|
267
|
+
|
268
|
+
* You can no longer abuse the SQL::Function syntax to use a table
|
269
|
+
alias with specified columns (e.g. :table[:col1, :col2, :col3])
|
270
|
+
or to cast to types (e.g. :x.cast_as(:varchar[20])). Use a
|
271
|
+
LiteralString in both cases.
|