viking-sequel 3.10.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.
- 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.
|