sequel 3.36.1 → 3.37.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +84 -0
- data/Rakefile +13 -0
- data/bin/sequel +12 -16
- data/doc/advanced_associations.rdoc +36 -67
- data/doc/association_basics.rdoc +11 -16
- data/doc/release_notes/3.37.0.txt +338 -0
- data/doc/schema_modification.rdoc +4 -0
- data/lib/sequel/adapters/jdbc/h2.rb +1 -1
- data/lib/sequel/adapters/jdbc/postgresql.rb +26 -8
- data/lib/sequel/adapters/mysql2.rb +4 -3
- data/lib/sequel/adapters/odbc/mssql.rb +2 -2
- data/lib/sequel/adapters/postgres.rb +4 -60
- data/lib/sequel/adapters/shared/mssql.rb +2 -1
- data/lib/sequel/adapters/shared/mysql.rb +0 -5
- data/lib/sequel/adapters/shared/postgres.rb +68 -2
- data/lib/sequel/adapters/shared/sqlite.rb +17 -1
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +12 -1
- data/lib/sequel/adapters/utils/pg_types.rb +76 -0
- data/lib/sequel/core.rb +13 -0
- data/lib/sequel/database/misc.rb +41 -1
- data/lib/sequel/database/schema_generator.rb +23 -10
- data/lib/sequel/database/schema_methods.rb +26 -4
- data/lib/sequel/dataset/graph.rb +2 -1
- data/lib/sequel/dataset/query.rb +62 -2
- data/lib/sequel/extensions/_pretty_table.rb +7 -3
- data/lib/sequel/extensions/arbitrary_servers.rb +5 -4
- data/lib/sequel/extensions/blank.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +13 -2
- data/lib/sequel/extensions/core_extensions.rb +6 -0
- data/lib/sequel/extensions/eval_inspect.rb +158 -0
- data/lib/sequel/extensions/inflector.rb +4 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -4
- data/lib/sequel/extensions/migration.rb +4 -1
- data/lib/sequel/extensions/named_timezones.rb +4 -0
- data/lib/sequel/extensions/null_dataset.rb +4 -0
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pg_array.rb +219 -168
- data/lib/sequel/extensions/pg_array_ops.rb +7 -2
- data/lib/sequel/extensions/pg_auto_parameterize.rb +10 -4
- data/lib/sequel/extensions/pg_hstore.rb +3 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +7 -2
- data/lib/sequel/extensions/pg_inet.rb +28 -3
- data/lib/sequel/extensions/pg_interval.rb +192 -0
- data/lib/sequel/extensions/pg_json.rb +21 -9
- data/lib/sequel/extensions/pg_range.rb +487 -0
- data/lib/sequel/extensions/pg_range_ops.rb +122 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +3 -2
- data/lib/sequel/extensions/pretty_table.rb +12 -1
- data/lib/sequel/extensions/query.rb +4 -0
- data/lib/sequel/extensions/query_literals.rb +6 -6
- data/lib/sequel/extensions/schema_dumper.rb +39 -38
- data/lib/sequel/extensions/select_remove.rb +4 -0
- data/lib/sequel/extensions/server_block.rb +3 -2
- data/lib/sequel/extensions/split_array_nil.rb +65 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -0
- data/lib/sequel/extensions/string_date_time.rb +4 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +9 -3
- data/lib/sequel/extensions/to_dot.rb +4 -0
- data/lib/sequel/model/associations.rb +150 -91
- data/lib/sequel/plugins/identity_map.rb +2 -2
- data/lib/sequel/plugins/list.rb +1 -0
- data/lib/sequel/plugins/many_through_many.rb +33 -32
- data/lib/sequel/plugins/nested_attributes.rb +11 -3
- data/lib/sequel/plugins/rcte_tree.rb +2 -2
- data/lib/sequel/plugins/schema.rb +1 -1
- data/lib/sequel/sql.rb +14 -14
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/mysql_spec.rb +25 -0
- data/spec/adapters/postgres_spec.rb +572 -28
- data/spec/adapters/sqlite_spec.rb +16 -1
- data/spec/core/database_spec.rb +61 -2
- data/spec/core/dataset_spec.rb +92 -0
- data/spec/core/expression_filters_spec.rb +12 -0
- data/spec/extensions/arbitrary_servers_spec.rb +1 -1
- data/spec/extensions/boolean_readers_spec.rb +25 -25
- data/spec/extensions/eval_inspect_spec.rb +58 -0
- data/spec/extensions/json_serializer_spec.rb +0 -6
- data/spec/extensions/list_spec.rb +1 -1
- data/spec/extensions/looser_typecasting_spec.rb +7 -7
- data/spec/extensions/many_through_many_spec.rb +81 -0
- data/spec/extensions/nested_attributes_spec.rb +21 -4
- data/spec/extensions/pg_array_ops_spec.rb +1 -11
- data/spec/extensions/pg_array_spec.rb +181 -90
- data/spec/extensions/pg_auto_parameterize_spec.rb +3 -3
- data/spec/extensions/pg_hstore_spec.rb +1 -3
- data/spec/extensions/pg_inet_spec.rb +6 -1
- data/spec/extensions/pg_interval_spec.rb +73 -0
- data/spec/extensions/pg_json_spec.rb +5 -9
- data/spec/extensions/pg_range_ops_spec.rb +49 -0
- data/spec/extensions/pg_range_spec.rb +372 -0
- data/spec/extensions/pg_statement_cache_spec.rb +1 -2
- data/spec/extensions/query_literals_spec.rb +1 -2
- data/spec/extensions/schema_dumper_spec.rb +48 -89
- data/spec/extensions/serialization_spec.rb +1 -5
- data/spec/extensions/server_block_spec.rb +2 -2
- data/spec/extensions/spec_helper.rb +12 -2
- data/spec/extensions/split_array_nil_spec.rb +24 -0
- data/spec/integration/associations_test.rb +4 -4
- data/spec/integration/database_test.rb +2 -2
- data/spec/integration/dataset_test.rb +4 -4
- data/spec/integration/eager_loader_test.rb +6 -6
- data/spec/integration/plugin_test.rb +2 -2
- data/spec/integration/spec_helper.rb +2 -2
- data/spec/model/association_reflection_spec.rb +5 -0
- data/spec/model/associations_spec.rb +156 -49
- data/spec/model/eager_loading_spec.rb +137 -2
- data/spec/model/model_spec.rb +10 -10
- metadata +15 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,87 @@
|
|
1
|
+
=== 3.37.0 (2012-07-02)
|
2
|
+
|
3
|
+
* Allow specifying eager_graph alias base on a per-call basis using an AliasedExpression (jeremyevans)
|
4
|
+
|
5
|
+
* Allow bin/sequel to respect multiple -l options for logging to multiple files (jeremyevans)
|
6
|
+
|
7
|
+
* Correctly handle cases where SCOPE_IDENTITY is nil in the odbc/mssql adapter (stnoonan, jeremyevans)
|
8
|
+
|
9
|
+
* Add pg_interval extension, for returning interval types as ActiveSupport::Duration instances (jeremyevans)
|
10
|
+
|
11
|
+
* Save a new one_to_one associated object once instead of twice in the nested_attributes plugin (jeremyevans)
|
12
|
+
|
13
|
+
* Don't add unnecessary filter condition when passing a new object to a one_to_one setter method (jeremyevans)
|
14
|
+
|
15
|
+
* Differentiate between column references and method references in many_through_many associations (jeremyevans)
|
16
|
+
|
17
|
+
* Use :qualify=>:deep option when joining tables in model association datasets (jeremyevans)
|
18
|
+
|
19
|
+
* Support :qualify=>:deep option to Dataset#join_table to qualify subexpressions in the expression tree (jeremyevans)
|
20
|
+
|
21
|
+
* Support :qualify=>false option to Dataset#join_table to not automatically qualify keys/values (jeremyevans)
|
22
|
+
|
23
|
+
* Make filter by associations support use column references and method references correctly (jeremyevans)
|
24
|
+
|
25
|
+
* Call super in list plugin before_create (jeremyevans) (#504)
|
26
|
+
|
27
|
+
* Do not automatically cast String to text in pg_auto_parameterize extension (jeremyevans)
|
28
|
+
|
29
|
+
* Support alter_table validate_constraint on PostgreSQL for validating constraints previously declared with NOT VALID (jeremyevans)
|
30
|
+
|
31
|
+
* Support :not_valid option when adding foreign key constraints on PostgreSQL (jeremyevans)
|
32
|
+
|
33
|
+
* Support exclusion constraints on PostgreSQL (jeremyevans)
|
34
|
+
|
35
|
+
* Allow for overriding the create/alter table generators used per Database object (jeremyevans)
|
36
|
+
|
37
|
+
* Make casting to Date/(Time/DateTime) use date/datetime functions on SQLite (jeremyevans)
|
38
|
+
|
39
|
+
* Add pg_range_ops extension for DSL support for PostgreSQL range operators and functions (jeremyevans)
|
40
|
+
|
41
|
+
* The json library is now required when running the plugin/extension specs (jeremyevans)
|
42
|
+
|
43
|
+
* Use change migrations instead of up/down migrations in the schema_dumper (jeremyevans)
|
44
|
+
|
45
|
+
* Dump unsigned integer columns with a check >= 0 constraint in the schema_dumper (stu314)
|
46
|
+
|
47
|
+
* Switch the :key_hash entry to the association :eager_loader option to use the method symbol(s) instead of the column symbol(s) (jeremyevans)
|
48
|
+
|
49
|
+
* Add :id_map entry to the hash passed to the association :eager_loader option, for easier custom eager loading (jeremyevans)
|
50
|
+
|
51
|
+
* Fix dumping of non-integer foreign key columns in the schema_dumper (jeremyevans) (#502)
|
52
|
+
|
53
|
+
* Add nested_attributes :fields option to be a proc that is called with the associated object (chanks) (#498)
|
54
|
+
|
55
|
+
* Add split_array_nil extension, for compiling :col=>[1, nil] to col IN (1) OR col IS NULL (jeremyevans)
|
56
|
+
|
57
|
+
* Add Database#extension and Dataset#extension for loading extension modules into objects automatically (jeremyevans)
|
58
|
+
|
59
|
+
* Respect an existing dataset limit when updating on Microsoft SQL Server (jeremyevans)
|
60
|
+
|
61
|
+
* Add pg_range extension, for dealing with PostgreSQL 9.2+ range types (jeremyevans)
|
62
|
+
|
63
|
+
* Make pg_array extension convert array members when typecasting Array to PGArray (jeremyevans)
|
64
|
+
|
65
|
+
* Make jdbc/postgres adapter convert array type elements (e.g. date[] arrays are returned as arrays of Date instances) (jeremyevans)
|
66
|
+
|
67
|
+
* Make the pg_inet extension handle inet[]/cidr[]/macaddr[] types when used with the pg_array extension (jeremyevans)
|
68
|
+
|
69
|
+
* Make the pg_json extension handle json[] type when used with the pg_array extension (jeremyevans)
|
70
|
+
|
71
|
+
* Fix schema parsing of h2 clob types (jeremyevans)
|
72
|
+
|
73
|
+
* Make the pg_array extension handle array types for scalar types handled by the native postgres adapter (jeremyevans)
|
74
|
+
|
75
|
+
* Generalize handling of array types in the pg_array extension, allowing easy support of custom array types (jeremyevans)
|
76
|
+
|
77
|
+
* Remove type conversion of int2vector and money types on PostgreSQL, since previous conversions were wrong (jeremyevans)
|
78
|
+
|
79
|
+
* Add eval_inspect extension, which makes Sequel::SQL::Expression#inspect attempt to return a string suitable for eval (jeremyevans)
|
80
|
+
|
81
|
+
* When emulating offset with ROW_NUMBER, default to ordering by all columns if no specific order is given (stnoonan, jeremyevans) (#490)
|
82
|
+
|
83
|
+
* Work around JRuby 1.6 ruby 1.9 mode bug in Time -> SQLTime conversion (jeremyevans)
|
84
|
+
|
1
85
|
=== 3.36.1 (2012-06-01)
|
2
86
|
|
3
87
|
* Fix jdbc adapter when DriverManager#getConnection fails (aportnov) (#488)
|
data/Rakefile
CHANGED
@@ -138,6 +138,19 @@ begin
|
|
138
138
|
%w'postgres sqlite mysql informix oracle firebird mssql db2'.each do |adapter|
|
139
139
|
spec_with_cov.call("spec_#{adapter}", ["spec/adapters/#{adapter}_spec.rb"] + Dir["spec/integration/*_test.rb"], "Run #{adapter} specs"){|t| t.rcov_opts.concat(%w'--exclude "lib/sequel/([a-z_]+\.rb|connection_pool|database|dataset|model|extensions|plugins)"')}
|
140
140
|
end
|
141
|
+
|
142
|
+
task :spec_travis=>[:spec, :spec_plugin, :spec_sqlite] do
|
143
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
144
|
+
ENV['SEQUEL_PG_SPEC_DB'] = "jdbc:postgresql://localhost/sequel_test?user=postgres"
|
145
|
+
ENV['SEQUEL_MY_SPEC_DB'] = "jdbc:mysql://localhost/sequel_test?user=root"
|
146
|
+
else
|
147
|
+
ENV['SEQUEL_PG_SPEC_DB'] = "postgres://localhost/sequel_test?user=postgres"
|
148
|
+
ENV['SEQUEL_MY_SPEC_DB'] = "mysql2://localhost/sequel_test?user=root"
|
149
|
+
end
|
150
|
+
|
151
|
+
Rake::Task['spec_postgres'].invoke
|
152
|
+
Rake::Task['spec_mysql'].invoke
|
153
|
+
end
|
141
154
|
|
142
155
|
desc "Run model specs without the associations code"
|
143
156
|
task :spec_model_no_assoc do
|
data/bin/sequel
CHANGED
@@ -4,18 +4,17 @@ require 'rubygems'
|
|
4
4
|
require 'optparse'
|
5
5
|
require 'sequel'
|
6
6
|
|
7
|
-
db_opts = {:test=>true}
|
8
7
|
copy_databases = nil
|
9
8
|
dump_migration = nil
|
10
9
|
dump_schema = nil
|
11
|
-
echo = nil
|
12
10
|
env = nil
|
13
|
-
logfile = nil
|
14
11
|
migrate_dir = nil
|
15
12
|
migrate_ver = nil
|
16
13
|
backtrace = nil
|
14
|
+
test = true
|
17
15
|
load_dirs = []
|
18
16
|
exclusive_options = []
|
17
|
+
loggers = []
|
19
18
|
|
20
19
|
opts = OptionParser.new do |opts|
|
21
20
|
opts.banner = "Sequel: The Database Toolkit for Ruby"
|
@@ -54,7 +53,8 @@ opts = OptionParser.new do |opts|
|
|
54
53
|
end
|
55
54
|
|
56
55
|
opts.on("-E", "--echo", "echo SQL statements") do
|
57
|
-
|
56
|
+
require 'logger'
|
57
|
+
loggers << Logger.new($stdout)
|
58
58
|
end
|
59
59
|
|
60
60
|
opts.on("-I", "--include dir", "specify $LOAD_PATH directory") do |v|
|
@@ -62,7 +62,8 @@ opts = OptionParser.new do |opts|
|
|
62
62
|
end
|
63
63
|
|
64
64
|
opts.on("-l", "--log logfile", "log SQL statements to log file") do |v|
|
65
|
-
|
65
|
+
require 'logger'
|
66
|
+
loggers << Logger.new(v)
|
66
67
|
end
|
67
68
|
|
68
69
|
opts.on("-L", "--load-dir DIR", "loads all *.rb under specifed directory") do |v|
|
@@ -79,7 +80,7 @@ opts = OptionParser.new do |opts|
|
|
79
80
|
end
|
80
81
|
|
81
82
|
opts.on("-N", "--no-test-connection", "do not test the connection") do
|
82
|
-
|
83
|
+
test = false
|
83
84
|
end
|
84
85
|
|
85
86
|
opts.on("-r", "--require lib", "require the library, before executing your script") do |v|
|
@@ -112,26 +113,21 @@ end
|
|
112
113
|
error_proc["Error: Must specify -m if using -M"] if migrate_ver && !migrate_dir
|
113
114
|
error_proc["Error: Cannot specify #{exclusive_options.map{|v| "-#{v}"}.join(' and ')} together"] if exclusive_options.length > 1
|
114
115
|
|
115
|
-
if logfile || echo
|
116
|
-
require 'logger'
|
117
|
-
db_opts[:loggers] = []
|
118
|
-
db_opts[:loggers] << Logger.new(logfile) if logfile
|
119
|
-
db_opts[:loggers] << Logger.new($stdout) if echo
|
120
|
-
end
|
121
|
-
|
122
116
|
connect_proc = lambda do |database|
|
123
117
|
db = if database.nil? || database.empty?
|
124
|
-
Sequel.connect('mock:///'
|
118
|
+
Sequel.connect('mock:///')
|
125
119
|
elsif File.exist?(database)
|
126
120
|
require 'yaml'
|
127
121
|
env ||= "development"
|
128
122
|
db_config = YAML.load_file(database)
|
129
123
|
db_config = db_config[env] || db_config[env.to_sym] || db_config
|
130
124
|
db_config.keys.each{|k| db_config[k.to_sym] = db_config.delete(k)}
|
131
|
-
Sequel.connect(db_config
|
125
|
+
Sequel.connect(db_config)
|
132
126
|
else
|
133
|
-
Sequel.connect(database
|
127
|
+
Sequel.connect(database)
|
134
128
|
end
|
129
|
+
db.loggers = loggers
|
130
|
+
db.test_connection if test
|
135
131
|
db
|
136
132
|
end
|
137
133
|
|
@@ -75,19 +75,15 @@ option. Though it can often be verbose (compared to other things in Sequel),
|
|
75
75
|
it allows you complete control over how to eagerly load associations for a
|
76
76
|
group of objects.
|
77
77
|
|
78
|
-
:eager_loader should be a proc that takes
|
79
|
-
|
78
|
+
:eager_loader should be a proc that takes a single hash argument, which will
|
79
|
+
have at least the following keys:
|
80
80
|
|
81
|
-
:
|
81
|
+
:id_map :: A mapping of key values to arrays of current model instances,
|
82
|
+
usage described below
|
82
83
|
:rows :: An array of model objects
|
83
84
|
:associations :: A hash of dependent associations to eagerly load
|
84
85
|
:self :: The dataset that is doing the eager loading
|
85
|
-
|
86
|
-
If the proc takes three arguments, it gets passed the :key_hash, :rows,
|
87
|
-
and :associations values. The only way to get the :self value is to
|
88
|
-
accept one argument. The 3 argument procs are allowed for backwards
|
89
|
-
compatibility, and it is recommended to use the 1 argument proc format
|
90
|
-
for new code.
|
86
|
+
:eager_block :: A dynamic callback for this eager load.
|
91
87
|
|
92
88
|
Since you are given all of the records, you can do things like filter on
|
93
89
|
associations that are specified by multiple keys, or do multiple
|
@@ -98,13 +94,12 @@ associations cache for all objects in the array of records. The hash
|
|
98
94
|
of dependent associations is available for you to cascade the eager
|
99
95
|
loading down multiple levels, but it is up to you to use it.
|
100
96
|
|
101
|
-
The
|
102
|
-
association loaders and is also available to you. It is a hash with keys
|
103
|
-
foreign/primary key
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
give an example. Let's say you have the following associations
|
97
|
+
The id_map is a performance enhancement that is used by the default
|
98
|
+
association loaders and is also available to you. It is a hash with keys
|
99
|
+
foreign/primary key values, and values being arrays of current model
|
100
|
+
objects having the foreign/primary key value associated with the key.
|
101
|
+
This may be hard to visualize, so I'll give an example. Let's say you
|
102
|
+
have the following associations
|
108
103
|
|
109
104
|
Album.many_to_one :artist
|
110
105
|
Album.one_to_many :tracks
|
@@ -113,53 +108,30 @@ and the following two albums in the database:
|
|
113
108
|
|
114
109
|
album1 = Album.create(:artist_id=>3) # id: 1
|
115
110
|
album2 = Album.create(:artist_id=>3) # id: 2
|
111
|
+
album3 = Album.create(:artist_id=>2) # id: 3
|
116
112
|
|
117
113
|
If you try to eager load this dataset:
|
118
114
|
|
119
115
|
Album.eager(:artist, :tracks).all
|
120
116
|
|
121
|
-
Then the
|
122
|
-
|
123
|
-
{:id=>{1=>[album1], 2=>[album2]}, :artist_id=>{3=>[album1, album2]}}
|
124
|
-
|
125
|
-
Let's break down the reason for the makeup of this key_hash. The hash has keys for
|
126
|
-
each of foreign/primary keys used in the association. In this case, the artist
|
127
|
-
association needs the artist_id foreign key (since it is a many_to_one), and the
|
128
|
-
tracks association needs the id primary key (since it is a one_to_many).
|
129
|
-
|
130
|
-
If you only eagerly loaded the artist association:
|
131
|
-
|
132
|
-
Album.eager(:artist).all
|
133
|
-
|
134
|
-
Then the key_hash would only contain artist_id information:
|
135
|
-
|
136
|
-
{:artist_id=>{3=>[album1, album2]}}
|
137
|
-
|
138
|
-
Likewise, if you only eagerly loaded the tracks association:
|
139
|
-
|
140
|
-
Album.eager(:tracks).all
|
141
|
-
|
142
|
-
Then the key_hash would only contain id information:
|
143
|
-
|
144
|
-
{:id=>{1=>[album1], 2=>[album2]}}
|
145
|
-
|
146
|
-
Now, the eager loader for the artist association is only going to care about the
|
147
|
-
value of the artist_id key in the hash, so it's going to do the equivalent of:
|
117
|
+
Then the id_map provided to the artist :eager_loader proc would be:
|
148
118
|
|
149
|
-
|
119
|
+
{3=>[album1, album2], 2=>[album3]}
|
150
120
|
|
151
|
-
The
|
152
|
-
album objects. Since
|
153
|
-
|
121
|
+
The artist id_map contains a mapping of artist_id values to arrays of
|
122
|
+
album objects. Since both album1 and album2 have the same artist_id,
|
123
|
+
the are both in the array related to that key. album3 has a different
|
124
|
+
artist_id, so it is in a different array. Eager loading of artists is
|
125
|
+
done by looking for any artist having one of the keys in the hash:
|
154
126
|
|
155
|
-
artists = Artist.where(:id=>
|
127
|
+
artists = Artist.where(:id=>id_map.keys).all
|
156
128
|
|
157
129
|
When the artists are retrieved, you can iterate over them, find entries
|
158
130
|
with matching keys, and manually associate them to the albums:
|
159
131
|
|
160
132
|
artists.each do |artist|
|
161
133
|
# Find related albums using the artist_id_map
|
162
|
-
if albums =
|
134
|
+
if albums = id_map[artist.id]
|
163
135
|
# Iterate over the albums
|
164
136
|
albums.each do |album|
|
165
137
|
# Manually set the artist association for each album
|
@@ -168,15 +140,14 @@ with matching keys, and manually associate them to the albums:
|
|
168
140
|
end
|
169
141
|
end
|
170
142
|
|
171
|
-
|
172
|
-
value of the id key in the hash:
|
143
|
+
The id_map provided to the tracks :eager_loader proc would be:
|
173
144
|
|
174
|
-
|
145
|
+
{1=>[album1], 2=>[album2], 3=>[album3]}
|
175
146
|
|
176
147
|
Now the id_map contains a mapping of id values to arrays of album objects (in this
|
177
148
|
case each array only has a single object, because id is the primary key). So when
|
178
149
|
looking for tracks to eagerly load, you only need to look for ones that have an
|
179
|
-
album_id of
|
150
|
+
album_id with one of the keys in the hash:
|
180
151
|
|
181
152
|
tracks = Track.where(:album_id=>id_map.keys).all
|
182
153
|
|
@@ -213,9 +184,9 @@ So putting everything together, the artist eager loader looks like:
|
|
213
184
|
|
214
185
|
:eager_loader=>(proc do |eo_opts|
|
215
186
|
eo_opts[:rows].each{|album| album.associations[:artist] = nil}
|
216
|
-
|
217
|
-
Artist.where(:id=>
|
218
|
-
if albums =
|
187
|
+
id_map = eo_opts[:id_map]
|
188
|
+
Artist.where(:id=>id_map.keys).all do |artist|
|
189
|
+
if albums = id_map[artist.id]
|
219
190
|
albums.each do |album|
|
220
191
|
album.associations[:artist] = artist
|
221
192
|
end
|
@@ -227,7 +198,7 @@ and the tracks eager loader looks like:
|
|
227
198
|
|
228
199
|
:eager_loader=>(proc do |eo_opts|
|
229
200
|
eo_opts[:rows].each{|album| album.associations[:tracks] = []}
|
230
|
-
id_map = eo_opts[:
|
201
|
+
id_map = eo_opts[:id_map]
|
231
202
|
Track.where(:id=>id_map.keys).all do |tracks|
|
232
203
|
if albums = id_map[track.album_id]
|
233
204
|
albums.each do |album|
|
@@ -245,14 +216,12 @@ the custom eager loaders described later in this page are more complex.
|
|
245
216
|
Basically, the eager loading steps can be broken down into:
|
246
217
|
|
247
218
|
1. Set default association values (nil/[]) for each of the current objects
|
248
|
-
2.
|
249
|
-
|
250
|
-
3.
|
251
|
-
|
252
|
-
4. Iterating over the returned associated objects, indexing into the custom key
|
253
|
-
map using the foreign/primary key value in the associated object to get
|
219
|
+
2. Return just related associated objects by filtering the associated class
|
220
|
+
to include only rows with keys present in the id_map.
|
221
|
+
3. Iterating over the returned associated objects, indexing into the id_map
|
222
|
+
using the foreign/primary key value in the associated object to get
|
254
223
|
current values associated to that specific object.
|
255
|
-
|
224
|
+
4. For each of those current values, updating the cached association value to
|
256
225
|
include that specific object.
|
257
226
|
|
258
227
|
Using the :eager_loader proc, you should be able to eagerly load all associations
|
@@ -631,7 +600,7 @@ name, with no duplicates?
|
|
631
600
|
one_to_many :songs, :order=>:songs__name, \
|
632
601
|
:dataset=>proc{Song.select(:songs.*).join(Lyric, :id=>:lyric_id, id=>[:composer_id, :arranger_id, :vocalist_id, :lyricist_id])}, \
|
633
602
|
:eager_loader=>(proc do |eo|
|
634
|
-
h = eo[:
|
603
|
+
h = eo[:id_map]
|
635
604
|
ids = h.keys
|
636
605
|
eo[:rows].each{|r| r.associations[:songs] = []}
|
637
606
|
Song.select(:songs.*, :lyrics__composer_id, :lyrics__arranger_id, :lyrics__vocalist_id, :lyrics__lyricist_id)\
|
@@ -662,11 +631,11 @@ associated tickets.
|
|
662
631
|
:dataset=>proc{Ticket.filter(:project_id=>id).select{sum(hours).as(hours)}},
|
663
632
|
:eager_loader=>(proc do |eo|
|
664
633
|
eo[:rows].each{|p| p.associations[:ticket_hours] = nil}
|
665
|
-
Ticket.filter(:project_id=>eo[:
|
634
|
+
Ticket.filter(:project_id=>eo[:id_map].keys).
|
666
635
|
group(:project_id).
|
667
636
|
select{[project_id, sum(hours).as(hours)]}.
|
668
637
|
all do |t|
|
669
|
-
p = eo[:
|
638
|
+
p = eo[:id_map][t.values.delete(:project_id)].first
|
670
639
|
p.associations[:ticket_hours] = t
|
671
640
|
end
|
672
641
|
end)
|
data/doc/association_basics.rdoc
CHANGED
@@ -473,7 +473,7 @@ associations (ones without conditions).
|
|
473
473
|
== Name Collisions
|
474
474
|
|
475
475
|
Because associations create instance methods, it's possible to override
|
476
|
-
existing instance methods if you name an
|
476
|
+
existing instance methods if you name an association the same as an
|
477
477
|
existing method. For example, <tt>values</tt> and <tt>associations</tt>
|
478
478
|
would be bad association names.
|
479
479
|
|
@@ -1050,7 +1050,7 @@ Column in associated table that :right_key points to, as a symbol.
|
|
1050
1050
|
Defaults to primary key of the associated table.
|
1051
1051
|
|
1052
1052
|
Tag.set_primary_key :tid
|
1053
|
-
Album.many_to_many :tags # :
|
1053
|
+
Album.many_to_many :tags # :right_primary_key=>:tid
|
1054
1054
|
|
1055
1055
|
Can use an array of symbols for a composite key association.
|
1056
1056
|
|
@@ -1135,8 +1135,6 @@ Called after removing an object from the association:
|
|
1135
1135
|
|
1136
1136
|
Called before the _<i>association</i>= method is called to modify the objects:
|
1137
1137
|
|
1138
|
-
Called before removing an object from the association:
|
1139
|
-
|
1140
1138
|
class Album
|
1141
1139
|
# Don't associate the album with an artist if the year the album was
|
1142
1140
|
# released is less than the year the artist/band started.
|
@@ -1223,13 +1221,9 @@ For many details and examples of custom eager loaders, please see the
|
|
1223
1221
|
==== :eager_loader_key
|
1224
1222
|
|
1225
1223
|
A symbol for the key column to use to populate the key hash for the eager
|
1226
|
-
loader.
|
1227
|
-
|
1228
|
-
|
1229
|
-
eagerly load any associated objects for that association. If you have a
|
1230
|
-
custom eager loader and aren't sure of a good value to use here, and you
|
1231
|
-
aren't using the key_hash (first argument to the eager_loader proc), then
|
1232
|
-
you can probably use the primary key column of the model.
|
1224
|
+
loader. Generally does not need to be set manually, defaults to the key
|
1225
|
+
method used. Can be set to nil to not populate the key hash (better for
|
1226
|
+
performance if a custom eager loader does not use the key_hash).
|
1233
1227
|
|
1234
1228
|
==== :eager_block
|
1235
1229
|
|
@@ -1340,6 +1334,11 @@ This is mostly useful if you have associations with the same name in many models
|
|
1340
1334
|
to be able to easily tell which table alias corresponds to which association when eagerly
|
1341
1335
|
graphing multiple associations with the same name.
|
1342
1336
|
|
1337
|
+
You can override this option on a per-graph basis by specifying the association as an
|
1338
|
+
SQL::AliasedExpression instead of a symbol:
|
1339
|
+
|
1340
|
+
Album.eager_graph(Sequel.as(:artist, :a))
|
1341
|
+
|
1343
1342
|
==== :eager_grapher
|
1344
1343
|
|
1345
1344
|
Sets up a custom grapher to use when eager loading the objects via eager_graph.
|
@@ -1465,13 +1464,9 @@ aliases defined with <tt>Model.def_column_alias</tt>:
|
|
1465
1464
|
def_column_alias(:obj_id, :object_id)
|
1466
1465
|
end
|
1467
1466
|
class Obj < Sequel::Model
|
1468
|
-
|
1467
|
+
one_to_many :things, :key=>:object_id, :key_method=>:obj_id
|
1469
1468
|
end
|
1470
1469
|
|
1471
|
-
Note that for eager loading purposes, you generally need to set the
|
1472
|
-
<tt>:eager_loader_key</tt> option as well, specifying the underlying
|
1473
|
-
column(s) to use.
|
1474
|
-
|
1475
1470
|
==== :key_column [+many_to_one+]
|
1476
1471
|
|
1477
1472
|
Like the :key option, but :key references the method name, while
|
@@ -0,0 +1,338 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* Database#extension and Dataset#extension have been added and
|
4
|
+
make it much easier to use extensions that just define modules,
|
5
|
+
where you previously had to manually extend a Database or
|
6
|
+
Dataset object with the module to get the extension's behavior.
|
7
|
+
These methods operate similarly to model plugins, where you just
|
8
|
+
specify the extension symbol, except that you can specify multiple
|
9
|
+
extensions at once:
|
10
|
+
|
11
|
+
DB.extension(:pg_array, :pg_hstore)
|
12
|
+
|
13
|
+
For databases, these modify the Database itself (and
|
14
|
+
potentially all of its datasets). Dataset#extension operates
|
15
|
+
like other dataset methods, returning a modified clone of
|
16
|
+
the dataset with the extension added:
|
17
|
+
|
18
|
+
dataset = dataset.extension(:columns_introspection)
|
19
|
+
|
20
|
+
Dataset#extension! has also been added for modifying the
|
21
|
+
receiver instead of returning a clone.
|
22
|
+
|
23
|
+
Not all extensions are usable by Database#extension or
|
24
|
+
Dataset#extension, the extension has to have specific support
|
25
|
+
for it. The following extensions support both
|
26
|
+
Database#extension and Dataset#extension:
|
27
|
+
|
28
|
+
* columns_introspection
|
29
|
+
* query_literals
|
30
|
+
* split_array_nil
|
31
|
+
|
32
|
+
The following extensions support just Database#extension:
|
33
|
+
|
34
|
+
* arbitrary_servers
|
35
|
+
* looser_typecasting
|
36
|
+
* pg_array
|
37
|
+
* pg_auto_parameterize
|
38
|
+
* pg_hstore
|
39
|
+
* pg_inet
|
40
|
+
* pg_interval
|
41
|
+
* pg_json
|
42
|
+
* pg_range
|
43
|
+
* pg_statement_cache
|
44
|
+
* server_block
|
45
|
+
|
46
|
+
Any user that was loading these extensions with Sequel.extension
|
47
|
+
and then manually extending objects with the extension's module
|
48
|
+
is encouraged to switch to Database#extension and/or
|
49
|
+
Dataset#extension.
|
50
|
+
|
51
|
+
* Dataset join methods now respect a :qualify=>:deep option
|
52
|
+
to do deep qualification of expressions, allowing qualification
|
53
|
+
of subexpressions in the expression tree. This can allow you
|
54
|
+
to do things like:
|
55
|
+
|
56
|
+
DB[:a].join(:b, {:c.cast(Integer)=>:d.cast(Integer)},
|
57
|
+
:qualify=>:deep)
|
58
|
+
# SELECT * FROM a INNER JOIN b
|
59
|
+
# ON (CAST(b.c AS INTEGER) = CAST(a.d AS INTEGER))
|
60
|
+
|
61
|
+
For backwards compatibility, by default Sequel will only do
|
62
|
+
automatic qualification if the arguments are simple symbols.
|
63
|
+
This may change in a future version, if automatic qualification
|
64
|
+
of only symbols is desired, switch to using :qualify=>:symbol.
|
65
|
+
|
66
|
+
You can also choose to do no automatic qualification using the
|
67
|
+
:qualify=>false option.
|
68
|
+
|
69
|
+
* All of Sequel's model associations now work with key expressions
|
70
|
+
that are not simple column references, without creating a fully
|
71
|
+
custom association. So you can create associations where the
|
72
|
+
primary/foreign key values are stored in PostgreSQL array or
|
73
|
+
hstore columns, for example.
|
74
|
+
|
75
|
+
* The pg_array extension has now been made more generic, so that it
|
76
|
+
is easy to support array types for any scalar type that is
|
77
|
+
currently supported. All scalar types that Sequel's postgres
|
78
|
+
adapter supports now have corresponding array types supported in
|
79
|
+
the pg_array extension. So if you load the pg_array extension and
|
80
|
+
return a date array column, the returned values will be arrays of
|
81
|
+
ruby Date objects.
|
82
|
+
|
83
|
+
Other pg_* extensions that add support for PostgreSQL-specific
|
84
|
+
scalar types now support array versions of those types if the
|
85
|
+
pg_array extension is loaded first.
|
86
|
+
|
87
|
+
* A pg_range extension has been added, making it easy to deal
|
88
|
+
with PostgreSQL 9.2+'s range types. As ruby's Range class does
|
89
|
+
not support all PostgreSQL range type values (such as empty ranges,
|
90
|
+
unbounded ranges, or ranges with an exlusive beginning), range
|
91
|
+
types are returned as instances of Sequel::Postgres::PGRange, which
|
92
|
+
has an API similar to Range. You can turn a PGRange into a Range
|
93
|
+
using PGRange#to_range, assuming that the range type value does not
|
94
|
+
use features that are incompatible with ruby's Range class.
|
95
|
+
|
96
|
+
The pg_range extension supports all range types supported by
|
97
|
+
default in PostgreSQL 9.2, and makes it easy to support custom
|
98
|
+
range types.
|
99
|
+
|
100
|
+
* A pg_range_ops extension has been added, which adds DSL support for
|
101
|
+
PostgreSQL range operators and functions, similar to the
|
102
|
+
pg_array_ops and pg_hstore_ops extensions.
|
103
|
+
|
104
|
+
* A pg_interval extension has been added, which makes Sequel return
|
105
|
+
PostgreSQL interval types as instances of ActiveSupport::Duration.
|
106
|
+
This is useful if you want to take the interval value and use it in
|
107
|
+
calculations in ruby (assuming you load the appropriate parts of
|
108
|
+
ActiveSupport).
|
109
|
+
|
110
|
+
* A split_array_nil extension has been added, which changes how Sequel
|
111
|
+
compiles IN/NOT IN expressions with arrays with nil values.
|
112
|
+
|
113
|
+
where(:col=>[1, nil])
|
114
|
+
# Default:
|
115
|
+
# WHERE (col IN (1, NULL))
|
116
|
+
# with split_array_nil extension:
|
117
|
+
# WHERE ((col IN (1)) OR (col IS NULL))
|
118
|
+
|
119
|
+
exclude(:col=>[1, nil])
|
120
|
+
# Default:
|
121
|
+
# WHERE (col NOT IN (1, NULL))
|
122
|
+
# with split_array_nil extension:
|
123
|
+
# WHERE ((col NOT IN (1)) AND (col IS NOT NULL))
|
124
|
+
|
125
|
+
* The nested_attributes plugin now allows the :fields option to
|
126
|
+
be a proc, which is called with the associated object and should
|
127
|
+
return an array of allowable fields.
|
128
|
+
|
129
|
+
* You can now specify the graph alias base when using eager_graph on
|
130
|
+
a per-call basis. Previously, it could only be set on a per
|
131
|
+
association basis. This is helpful if you have multiple
|
132
|
+
associations to the same class, and are cascading the eager graph to
|
133
|
+
dependent associations of that class for both of the associations.
|
134
|
+
Previously, there was no way to manually give descriptive names to
|
135
|
+
the tables in the cascaded associations, but you can now do so
|
136
|
+
by passing the association as an Sequel::SQL::AliasedExpression
|
137
|
+
instance instead of a plain Symbol. Here's a usage example:
|
138
|
+
|
139
|
+
ds = Game.eager_graph(:winner=>:players.as(:winning_players),
|
140
|
+
:loser=>:players.as(:losing_players)).
|
141
|
+
where(:winning_players__name=>'A',
|
142
|
+
:losing_players__name=>'B')
|
143
|
+
|
144
|
+
* many_through_many associations now differentiate between column
|
145
|
+
references and method references, by supporting the
|
146
|
+
:left_primary_key_column and :right_primary_key_method options that
|
147
|
+
many_to_many associations support.
|
148
|
+
|
149
|
+
* Custom :eager_loader procs that accept a single hash argument now
|
150
|
+
have an additional entry passed in the hash, :id_map, which is
|
151
|
+
easier to use than the :key_hash entry (which is still present for
|
152
|
+
backwards compatibility). Anyone with custom :eager_loader procs is
|
153
|
+
encouraged to switch from using :key_hash to :id_map.
|
154
|
+
|
155
|
+
* You can now override the create_table/alter_table schema generators
|
156
|
+
per database/adapter. This allows for database specific generator
|
157
|
+
subclasses, which have methods for unique features for that
|
158
|
+
database.
|
159
|
+
|
160
|
+
* You can now setup exclusion constraints on PostgreSQL using the
|
161
|
+
create_table and alter_table schema generators:
|
162
|
+
|
163
|
+
DB.create_table(:t) do
|
164
|
+
...
|
165
|
+
exclusion_constraint([[:col1, '&&'], [:col2, '=']])
|
166
|
+
# EXCLUDE USING gist (col1 WITH &&, col2 WITH =)
|
167
|
+
end
|
168
|
+
|
169
|
+
One common use for exclusion constraints is to make sure that no two
|
170
|
+
rows have overlapping values/ranges/circles.
|
171
|
+
|
172
|
+
* When adding foreign key constraints to an existing table on
|
173
|
+
PostgreSQL, you can use the :not_valid option to mark the constraint
|
174
|
+
as not yet valid. This will make it so that future changes to the
|
175
|
+
table need to respect the foreign key constraint, but existing rows
|
176
|
+
do not. After cleaning up the existing data, you can then use the
|
177
|
+
alter_table validate_constraint method to mark the constraint as
|
178
|
+
valid.
|
179
|
+
|
180
|
+
* An eval_inspect extension has been added that attempts to do
|
181
|
+
do the following for Sequel::SQL::Expression instances:
|
182
|
+
|
183
|
+
eval(obj.inspect) == obj # => true
|
184
|
+
|
185
|
+
There are a lot of cases that this extension does not handle, but
|
186
|
+
it does a decent job in most cases. This is currently only used
|
187
|
+
internally in a specific case in the schema_dumper extension.
|
188
|
+
|
189
|
+
= Other Improvements
|
190
|
+
|
191
|
+
* The filter by associations support now respects the method
|
192
|
+
reference vs column reference distinction that other parts of the
|
193
|
+
association code have respected since 3.32.0.
|
194
|
+
|
195
|
+
* In the nested_attributes plugin, new one_to_one associated
|
196
|
+
values are saved once instead of twice. Previously it attempted to
|
197
|
+
save them before they were associated to the current model object,
|
198
|
+
which can violate some validations/constraints.
|
199
|
+
|
200
|
+
* When saving an associated object in the one_to_one association
|
201
|
+
setter method, Sequel no longer adds an unnecessary filter
|
202
|
+
condition when nullifying the foreign key for existing rows
|
203
|
+
in the associated table.
|
204
|
+
|
205
|
+
* The list plugin's before_create method now calls super, which
|
206
|
+
fixes usage when other plugins that define before_create are loaded
|
207
|
+
before it.
|
208
|
+
|
209
|
+
* In the pg_array extension, when typecasting an Array to PGArray,
|
210
|
+
a recursive map is done on the input array to convert each value
|
211
|
+
in the input array to the expected type, using the typecasting
|
212
|
+
method that would be used for the scalar value. For example, for
|
213
|
+
model objects, where ids is an integer array column:
|
214
|
+
|
215
|
+
model.set(:ids=>['1', '2']).ids.to_a # => [1, 2]
|
216
|
+
|
217
|
+
* The pg_array extension now correctly handles bytea arrays used
|
218
|
+
in bound variables.
|
219
|
+
|
220
|
+
* The pg_array extension no longer uses the JSON-based parser for
|
221
|
+
floating point types, since it doesn't handle NaN and Infinity
|
222
|
+
values correctly.
|
223
|
+
|
224
|
+
* When typecasting in the pg_array extension, PGArray values are
|
225
|
+
only returned verbatim if they have a matching database type.
|
226
|
+
Otherwise, the underlying array is rewrapped in a new PGArray
|
227
|
+
value with the correct database type.
|
228
|
+
|
229
|
+
* H2 clob types are now recognized as strings instead of blobs.
|
230
|
+
Previously the code attempted to do this, but it didn't do so
|
231
|
+
correctly.
|
232
|
+
|
233
|
+
* The jdbc/postgres adapter now converts scalar values of
|
234
|
+
the array to the appropriate type. Previously, if you retrieved
|
235
|
+
a date array, you got back a ruby array of JavaSQL::SQL::Date
|
236
|
+
instances. Now, you get back a ruby array of ruby Date instances.
|
237
|
+
|
238
|
+
* The schema_dumper extension now dumps migrations as change
|
239
|
+
migrations, instead of separate up/down migrations, resulting in
|
240
|
+
simpler code.
|
241
|
+
|
242
|
+
* When dumping non-integer foreign keys in the schema dumper, an
|
243
|
+
explicit type is now used. Previously, the column would have been
|
244
|
+
dumped as an integer column.
|
245
|
+
|
246
|
+
* When dumping unsigned integer columns in the schema dumper, add a
|
247
|
+
column > 0 constraint in the dumped migration.
|
248
|
+
|
249
|
+
* On Microsoft SQL Server, when updating a dataset with a limit,
|
250
|
+
the limit is now respected.
|
251
|
+
|
252
|
+
* When emulating offset using the ROW_NUMBER window function,
|
253
|
+
do not require that the dataset be ordered. If an order is
|
254
|
+
not provided, default to ordering on all of the columns in
|
255
|
+
the dataset. If you want to override the default order used
|
256
|
+
in such a case, you need to override the default_offset_order
|
257
|
+
method for the dataset.
|
258
|
+
|
259
|
+
* On SQLite, casting to Date/Time/DateTime now calls an SQLite
|
260
|
+
date/datetime function instead of using a cast, as SQLite treats
|
261
|
+
such a cast as a cast to integer.
|
262
|
+
|
263
|
+
* When using JRuby 1.6 in ruby 1.9 mode and typecasting a time
|
264
|
+
column, workaround a bug where Time#nsec is 0 even though
|
265
|
+
Time#usec is not.
|
266
|
+
|
267
|
+
* The odbc/mssql adapter now correctly handles the case where
|
268
|
+
SCOPE_IDENTITY returns NULL after an insert.
|
269
|
+
|
270
|
+
* bin/sequel now accepts multiple -l options for logging to multiple
|
271
|
+
output files.
|
272
|
+
|
273
|
+
* In addition to Sequel's rigorous pre-push testing, Sequel now
|
274
|
+
also uses TravisCI for continuous integration testing across
|
275
|
+
a wider range of ruby implementations.
|
276
|
+
|
277
|
+
= Backwards Compatibility
|
278
|
+
|
279
|
+
* The keys in the :key_hash entry passed to the :eager_loader proc
|
280
|
+
are now method references instead of column references. For most
|
281
|
+
associations, they are the same thing, but for associations using
|
282
|
+
the :key_column/:primary_key_column/:left_primary_key_column
|
283
|
+
options, the values could be different. If you were using one
|
284
|
+
of those options and had a custom eager_loader, you should switch
|
285
|
+
from indexing into the :key_hash option to just using the :id_map
|
286
|
+
option.
|
287
|
+
|
288
|
+
* The :key_hash entry passed to the :eager_loader proc is now no
|
289
|
+
longer guaranteed to contain key maps for associations other than
|
290
|
+
the one currently being eagerly loaded. Previously, it contained
|
291
|
+
key maps for all associations that were being eagerly loaded. If
|
292
|
+
you have a custom :eager_loader proc that accessed a key map for
|
293
|
+
a separate association that was being loaded concurrently, you'll
|
294
|
+
now have to build the key map manually if it doesn't exist.
|
295
|
+
|
296
|
+
* If you previously explicitly specified an :eager_loader_key option
|
297
|
+
when defining an association, you may need to change it so that it
|
298
|
+
is a method reference instead of a column reference, or possibly
|
299
|
+
just omit the option.
|
300
|
+
|
301
|
+
* If you have a custom :eager_loader proc for an association where
|
302
|
+
the default :eager_loader_key option references a method that
|
303
|
+
the model does not respond to (or raises an exception), you may
|
304
|
+
need to specify the :eager_loader_key=>nil option.
|
305
|
+
|
306
|
+
* In the pg_auto_parameterize extension, String values are no longer
|
307
|
+
automatically casted to text. This is because the default type of
|
308
|
+
a string literal in PostgreSQL is unknown, not text. This makes it
|
309
|
+
much less likely to require manual casts, but has the potential to
|
310
|
+
break existing code relying on the automatic cast to text. As a
|
311
|
+
work around, any query that can no longer be automatically
|
312
|
+
parameterized after this query just needs to add manual casting
|
313
|
+
to text.
|
314
|
+
|
315
|
+
* Sequel now raises an exception if you attempt to clone associations
|
316
|
+
with different types, except if one type is one_to_many and the
|
317
|
+
other is one_to_one. Cloning from other types was usually a bug,
|
318
|
+
and raising an exception early will make it much easier to track
|
319
|
+
such bugs down.
|
320
|
+
|
321
|
+
* When running the plugin/extension and PostgreSQL adapter specs,
|
322
|
+
a json library is now required.
|
323
|
+
|
324
|
+
* The json/postgres adapter array typecasting internals have been
|
325
|
+
modified, if you were relying on the internals, you may need to
|
326
|
+
update your code.
|
327
|
+
|
328
|
+
* The pg_array extension internals changed significantly. PGArray
|
329
|
+
no longer has any subclasses by default, as parsing is now done
|
330
|
+
in separate objects. Anyone relying on the pg_array internals
|
331
|
+
will need to update their code.
|
332
|
+
|
333
|
+
* The postgres adapter no longer sets up type conversion of int2vector
|
334
|
+
and money types, since in both cases the conversion was incorrect in
|
335
|
+
most cases. These types will now be returned as strings. If you are
|
336
|
+
relying on the conversion, you'll need to add your own custom type
|
337
|
+
procs.
|
338
|
+
|