sequel 4.7.0 → 4.8.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.
- checksums.yaml +4 -4
- data/CHANGELOG +46 -0
- data/README.rdoc +25 -1
- data/doc/active_record.rdoc +1 -1
- data/doc/advanced_associations.rdoc +143 -17
- data/doc/association_basics.rdoc +80 -59
- data/doc/release_notes/4.8.0.txt +175 -0
- data/lib/sequel/adapters/odbc.rb +1 -1
- data/lib/sequel/adapters/odbc/mssql.rb +4 -2
- data/lib/sequel/adapters/shared/postgres.rb +19 -3
- data/lib/sequel/adapters/shared/sqlite.rb +3 -3
- data/lib/sequel/ast_transformer.rb +1 -1
- data/lib/sequel/dataset/actions.rb +1 -1
- data/lib/sequel/dataset/graph.rb +23 -9
- data/lib/sequel/dataset/misc.rb +2 -2
- data/lib/sequel/dataset/sql.rb +3 -3
- data/lib/sequel/extensions/columns_introspection.rb +1 -1
- data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +1 -1
- data/lib/sequel/extensions/pg_array_ops.rb +6 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +7 -0
- data/lib/sequel/extensions/pg_json_ops.rb +5 -0
- data/lib/sequel/extensions/query.rb +8 -2
- data/lib/sequel/extensions/to_dot.rb +1 -1
- data/lib/sequel/model/associations.rb +476 -152
- data/lib/sequel/plugins/class_table_inheritance.rb +11 -3
- data/lib/sequel/plugins/dataset_associations.rb +21 -18
- data/lib/sequel/plugins/many_through_many.rb +87 -20
- data/lib/sequel/plugins/nested_attributes.rb +12 -0
- data/lib/sequel/plugins/pg_array_associations.rb +31 -12
- data/lib/sequel/plugins/single_table_inheritance.rb +9 -1
- data/lib/sequel/sql.rb +1 -0
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +2 -2
- data/spec/adapters/postgres_spec.rb +7 -0
- data/spec/core/object_graph_spec.rb +250 -196
- data/spec/extensions/core_refinements_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +100 -6
- data/spec/extensions/many_through_many_spec.rb +1002 -19
- data/spec/extensions/nested_attributes_spec.rb +24 -0
- data/spec/extensions/pg_array_associations_spec.rb +17 -12
- data/spec/extensions/pg_array_spec.rb +4 -2
- data/spec/extensions/spec_helper.rb +1 -1
- data/spec/integration/associations_test.rb +1003 -48
- data/spec/integration/dataset_test.rb +12 -5
- data/spec/integration/prepared_statement_test.rb +1 -1
- data/spec/integration/type_test.rb +1 -1
- data/spec/model/associations_spec.rb +467 -130
- data/spec/model/eager_loading_spec.rb +332 -5
- metadata +5 -3
@@ -0,0 +1,175 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A one_through_one association type has been added. This is similar
|
4
|
+
to the many_to_many association type in that it uses a join table,
|
5
|
+
but it returns a single record instead of an array of records.
|
6
|
+
This is designed for cases where the foreign key in the join table
|
7
|
+
that references the current table has a unique constraint, or where
|
8
|
+
you want to use an order to just pick the first matching record.
|
9
|
+
|
10
|
+
Similarly, the many_through_many plugin now also offers a
|
11
|
+
one_through_many association.
|
12
|
+
|
13
|
+
* An association_join method has been added to model datasets, for
|
14
|
+
setting up joins based on associations. This basically does the
|
15
|
+
same join that eager_graph would do, but does not make the other
|
16
|
+
changes that eager_graph makes.
|
17
|
+
|
18
|
+
Unlike eager_graph (which uses LEFT OUTER JOINs by default),
|
19
|
+
association_join uses INNER JOINs, but there are also
|
20
|
+
association_*_join methods (e.g. association_left_join) for
|
21
|
+
using different join types.
|
22
|
+
|
23
|
+
Similar to eager_graph, you can use cascading of associations or
|
24
|
+
multiple associations.
|
25
|
+
|
26
|
+
Album.association_join(:artist, :tracks)
|
27
|
+
Artist.association_left_join(:albums=>:tracks)
|
28
|
+
|
29
|
+
* Dataset#eager_graph_with_options has been added for model
|
30
|
+
datasets. It currently supports a :join_type option, for
|
31
|
+
overriding the type of join to use on a per-call basis, as well
|
32
|
+
as a :limit_strategy option. The API is similar to eager_graph,
|
33
|
+
except that the associations to eagerly load are passed in as
|
34
|
+
a single argument, and it takes an options hash.
|
35
|
+
|
36
|
+
The :limit_strategy option works similarly to the
|
37
|
+
:eager_limit_strategy option when eagerly loading. If set to
|
38
|
+
true and the database supports window functions, it will join
|
39
|
+
the current dataset to a subquery that uses a window function
|
40
|
+
to correctly restrict the join to only those objects that fall
|
41
|
+
within the association's limit/offset.
|
42
|
+
|
43
|
+
The :limit_strategy option is not on by default. It is possible
|
44
|
+
for it to perform significantly worse than the default strategy
|
45
|
+
(which uses array slicing in ruby). The :limit_strategy
|
46
|
+
significantly changes the SQL used, and can change the results
|
47
|
+
of the query if any filters/orders related to the association
|
48
|
+
are used.
|
49
|
+
|
50
|
+
It's recommended you only use the :limit_strategy option if you
|
51
|
+
are experiencing a bottleneck and you have benchmarked that it
|
52
|
+
is faster and still produces the desired results.
|
53
|
+
|
54
|
+
Artist.eager_graph_with_options(:first_10_albums,
|
55
|
+
:limit_strategy=>true)
|
56
|
+
# SELECT artists.id, artists.name,
|
57
|
+
# first_10_albums.id AS first_10_albums_id,
|
58
|
+
# first_10_albums.name AS first_10_albums_name,
|
59
|
+
# first_10_albums.artist_id,
|
60
|
+
# first_10_albums.release_date
|
61
|
+
# FROM artists
|
62
|
+
# LEFT OUTER JOIN (
|
63
|
+
# SELECT id, name, artist_id, release_date
|
64
|
+
# FROM (
|
65
|
+
# SELECT *, row_number() OVER (PARTITION BY tracks.album_id)
|
66
|
+
# AS x_sequel_row_number_x
|
67
|
+
# FROM albums
|
68
|
+
# ) AS t1 WHERE (x_sequel_row_number_x <= 10)
|
69
|
+
# ) AS first_10_albums ON (first_10_albums.artist_id = artists.id)
|
70
|
+
|
71
|
+
* Dataset#full_text_search on PostgreSQL now supports :plain and
|
72
|
+
:phrase options. :plain takes the search terms as a single
|
73
|
+
string, and searches for rows where all terms are used.
|
74
|
+
:phrase is similar to :plain, but also adds a substring search
|
75
|
+
to ensure that the string given appears verbatim in the text.
|
76
|
+
|
77
|
+
* A :graph_order association option has been added, for using a
|
78
|
+
different order when using eager_graph. This is mostly
|
79
|
+
designed for cases where :order should be qualified in other
|
80
|
+
cases, but using a qualification breaks eager_graph because the
|
81
|
+
correct qualifier is not known until runtime.
|
82
|
+
|
83
|
+
* SQL::AliasedExpression#alias has been added as an alias for #aliaz.
|
84
|
+
|
85
|
+
= Other Improvements
|
86
|
+
|
87
|
+
* Sequel will now automatically use an eager limit strategy for
|
88
|
+
*_one associations that use an :order option. For associations
|
89
|
+
that are truly one-to-one, an :order option is not needed, so it
|
90
|
+
only makes sense to have an :order option if the association
|
91
|
+
could theoretically return multiple results (in which case an
|
92
|
+
eager limit strategy is helpful).
|
93
|
+
|
94
|
+
* The queries that Sequel uses to filter by associations when
|
95
|
+
those associations have conditions are now simpler and easier
|
96
|
+
for the database to execute.
|
97
|
+
|
98
|
+
* The queries that Sequel uses for dataset associations now handle
|
99
|
+
cases where unqualified identifiers were used in the receiving
|
100
|
+
dataset that would be made ambiguous by a join.
|
101
|
+
|
102
|
+
* A limit strategy is now used when filtering by associations if
|
103
|
+
the association has a limit and the database supports window
|
104
|
+
functions. This allows Sequel to setup a correct filter in
|
105
|
+
such cases.
|
106
|
+
|
107
|
+
Artist.where(:first_10_albums=>Album[1]).all
|
108
|
+
# SELECT *
|
109
|
+
# FROM artists
|
110
|
+
# WHERE (artists.id IN (
|
111
|
+
# SELECT albums.artist_id
|
112
|
+
# FROM albums
|
113
|
+
# WHERE ((albums.artist_id IS NOT NULL) AND (albums.id IN (
|
114
|
+
# SELECT id FROM (
|
115
|
+
# SELECT albums.id, row_number() OVER
|
116
|
+
# (PARTITION BY albums.artist_id ORDER BY release_date)
|
117
|
+
# AS x_sequel_row_number_x
|
118
|
+
# FROM albums
|
119
|
+
# ) AS t1
|
120
|
+
# WHERE (x_sequel_row_number_x <= 10)
|
121
|
+
# )) AND (albums.id = 1))))
|
122
|
+
|
123
|
+
* A limit strategy is now used in the dataset_associations plugin
|
124
|
+
if the association has a limit and the database supports window
|
125
|
+
functions. This makes the resulting datasets return correct
|
126
|
+
results.
|
127
|
+
|
128
|
+
Artist.first_10_albums
|
129
|
+
# SELECT *
|
130
|
+
# FROM albums
|
131
|
+
# WHERE ((albums.artist_id IN (
|
132
|
+
# SELECT artists.id FROM artists)
|
133
|
+
# ) AND (albums.id IN (
|
134
|
+
# SELECT id FROM (
|
135
|
+
# SELECT albums.id, row_number() OVER
|
136
|
+
# (PARTITION BY albums.artist_id ORDER BY release_date)
|
137
|
+
# AS x_sequel_row_number_x
|
138
|
+
# FROM albums
|
139
|
+
# ) AS t1
|
140
|
+
# WHERE (x_sequel_row_number_x <= 10)
|
141
|
+
# )))
|
142
|
+
# ORDER BY release_date
|
143
|
+
|
144
|
+
* You can now pass symbols with embedded qualifiers or aliases,
|
145
|
+
as well as SQL::Identifier, SQL::QualifiedIdentifier, and
|
146
|
+
SQL::AliasedExpression objects as the first argument to
|
147
|
+
Dataset#graph.
|
148
|
+
|
149
|
+
* The nested_attributes plugin now automatically handles presence
|
150
|
+
validations on foreign keys when creating associated objects.
|
151
|
+
It now sets the foreign key value (or a placeholder value)
|
152
|
+
before validating such objects.
|
153
|
+
|
154
|
+
* Offsets on *_one associations are now respected when using
|
155
|
+
eager_graph.
|
156
|
+
|
157
|
+
* eager graphing *_many associations with offsets no longer breaks
|
158
|
+
if there are no associated results.
|
159
|
+
|
160
|
+
* Database#register_array_type in the pg_array extension now works
|
161
|
+
correctly if there is no existing scalar conversion proc for
|
162
|
+
the type.
|
163
|
+
|
164
|
+
* Unique, foreign key, and not null constraint violations are now
|
165
|
+
recognized correctly on SQLite 3.8.2+.
|
166
|
+
|
167
|
+
* The odbc adapter now returns fractional seconds in timestamps.
|
168
|
+
|
169
|
+
* The obdc/mssql adapter now inputs timestamps with 3 decimal
|
170
|
+
places.
|
171
|
+
|
172
|
+
= Backwards Compatibility
|
173
|
+
|
174
|
+
* The private Model.apply_window_function_eager_limit_strategy
|
175
|
+
method has been removed.
|
data/lib/sequel/adapters/odbc.rb
CHANGED
@@ -127,7 +127,7 @@ module Sequel
|
|
127
127
|
# ODBCColumn#mapSqlTypeToGenericType and Column#klass.
|
128
128
|
case v
|
129
129
|
when ::ODBC::TimeStamp
|
130
|
-
db.to_application_timestamp([v.year, v.month, v.day, v.hour, v.minute, v.second])
|
130
|
+
db.to_application_timestamp([v.year, v.month, v.day, v.hour, v.minute, v.second, v.fraction])
|
131
131
|
when ::ODBC::Time
|
132
132
|
Sequel::SQLTime.create(v.hour, v.minute, v.second)
|
133
133
|
when ::ODBC::Date
|
@@ -32,10 +32,12 @@ module Sequel
|
|
32
32
|
class Dataset < ODBC::Dataset
|
33
33
|
include Sequel::MSSQL::DatasetMethods
|
34
34
|
|
35
|
+
# Use ODBC format, not Microsoft format, as the ODBC layer does
|
36
|
+
# some translation. MSSQL version is over-ridden to allow 3 millisecond decimal places
|
37
|
+
TIMESTAMP_FORMAT="{ts '%Y-%m-%d %H:%M:%S%N'}".freeze
|
38
|
+
|
35
39
|
private
|
36
40
|
|
37
|
-
# Use ODBC format, not Microsoft format, as the ODBC layer does
|
38
|
-
# some translation.
|
39
41
|
def default_timestamp_format
|
40
42
|
TIMESTAMP_FORMAT
|
41
43
|
end
|
@@ -1193,12 +1193,28 @@ module Sequel
|
|
1193
1193
|
lock_style(:share)
|
1194
1194
|
end
|
1195
1195
|
|
1196
|
-
#
|
1197
|
-
#
|
1196
|
+
# Run a full text search on PostgreSQL. By default, searching for the inclusion
|
1197
|
+
# of any of the terms in any of the cols.
|
1198
|
+
#
|
1199
|
+
# Options:
|
1200
|
+
# :language :: The language to use for the search (default: 'simple')
|
1201
|
+
# :plain :: Whether a plain search should be used (default: false). In this case,
|
1202
|
+
# terms should be a single string, and it will do a search where cols
|
1203
|
+
# contains all of the words in terms. This ignores search operators in terms.
|
1204
|
+
# :phrase :: Similar to :plain, but also adding an ILIKE filter to ensure that
|
1205
|
+
# returned rows also include the exact phrase used.
|
1198
1206
|
def full_text_search(cols, terms, opts = OPTS)
|
1199
1207
|
lang = opts[:language] || 'simple'
|
1200
1208
|
terms = terms.join(' | ') if terms.is_a?(Array)
|
1201
|
-
|
1209
|
+
to_tsquery = (opts[:phrase] || opts[:plain]) ? 'plainto_tsquery' : 'to_tsquery'
|
1210
|
+
|
1211
|
+
ds = where(Sequel.lit(["(to_tsvector(", "::regconfig, ", ") @@ #{to_tsquery}(", "::regconfig, ", "))"], lang, full_text_string_join(cols), lang, terms))
|
1212
|
+
|
1213
|
+
if opts[:phrase]
|
1214
|
+
ds = ds.grep(cols, "%#{escape_like(terms)}%", :case_insensitive=>true)
|
1215
|
+
end
|
1216
|
+
|
1217
|
+
ds
|
1202
1218
|
end
|
1203
1219
|
|
1204
1220
|
# Insert given values into the database.
|
@@ -332,10 +332,10 @@ module Sequel
|
|
332
332
|
end
|
333
333
|
|
334
334
|
DATABASE_ERROR_REGEXPS = {
|
335
|
-
/(is|are) not unique\z/ => UniqueConstraintViolation,
|
336
|
-
/foreign key constraint failed\z/ => ForeignKeyConstraintViolation,
|
335
|
+
/(is|are) not unique\z|UNIQUE constraint failed: .+\z/ => UniqueConstraintViolation,
|
336
|
+
/foreign key constraint failed\z|FOREIGN KEY constraint failed\z/ => ForeignKeyConstraintViolation,
|
337
337
|
/\A(SQLITE ERROR 19 \(CONSTRAINT\) : )?constraint failed\z/ => ConstraintViolation,
|
338
|
-
/may not be NULL\z/ => NotNullConstraintViolation,
|
338
|
+
/may not be NULL\z|NOT NULL constraint failed: .+\z/ => NotNullConstraintViolation,
|
339
339
|
}.freeze
|
340
340
|
def database_error_regexps
|
341
341
|
DATABASE_ERROR_REGEXPS
|
@@ -33,7 +33,7 @@ module Sequel
|
|
33
33
|
when SQL::OrderedExpression
|
34
34
|
SQL::OrderedExpression.new(v(o.expression), o.descending, :nulls=>o.nulls)
|
35
35
|
when SQL::AliasedExpression
|
36
|
-
SQL::AliasedExpression.new(v(o.expression), o.
|
36
|
+
SQL::AliasedExpression.new(v(o.expression), o.alias)
|
37
37
|
when SQL::CaseExpression
|
38
38
|
args = [v(o.conditions), v(o.default)]
|
39
39
|
args << v(o.expression) if o.expression?
|
data/lib/sequel/dataset/graph.rb
CHANGED
@@ -26,7 +26,7 @@ module Sequel
|
|
26
26
|
#
|
27
27
|
# Arguments:
|
28
28
|
# dataset :: Can be a symbol (specifying a table), another dataset,
|
29
|
-
# or an
|
29
|
+
# or an SQL::Identifier, SQL::QualifiedIdentifier, or SQL::AliasedExpression.
|
30
30
|
# join_conditions :: Any condition(s) allowed by +join_table+.
|
31
31
|
# block :: A block that is passed to +join_table+.
|
32
32
|
#
|
@@ -50,22 +50,36 @@ module Sequel
|
|
50
50
|
# Allow the use of a dataset or symbol as the first argument
|
51
51
|
# Find the table name/dataset based on the argument
|
52
52
|
table_alias = options[:table_alias]
|
53
|
+
table = dataset
|
54
|
+
create_dataset = true
|
55
|
+
|
53
56
|
case dataset
|
54
57
|
when Symbol
|
55
|
-
table
|
56
|
-
|
57
|
-
table_alias ||= table
|
58
|
-
when
|
58
|
+
# let alias be the same as the table name (sans any optional schema)
|
59
|
+
# unless alias explicitly given in the symbol using ___ notation
|
60
|
+
table_alias ||= split_symbol(table).compact.last
|
61
|
+
when Dataset
|
59
62
|
if dataset.simple_select_all?
|
60
63
|
table = dataset.opts[:from].first
|
61
64
|
table_alias ||= table
|
62
65
|
else
|
63
|
-
table = dataset
|
64
66
|
table_alias ||= dataset_alias((@opts[:num_dataset_sources] || 0)+1)
|
65
67
|
end
|
68
|
+
create_dataset = false
|
69
|
+
when SQL::Identifier
|
70
|
+
table_alias ||= table.value
|
71
|
+
when SQL::QualifiedIdentifier
|
72
|
+
table_alias ||= split_qualifiers(table).last
|
73
|
+
when SQL::AliasedExpression
|
74
|
+
return graph(table.expression, join_conditions, {:table_alias=>table.alias}.merge(options), &block)
|
66
75
|
else
|
67
76
|
raise Error, "The dataset argument should be a symbol or dataset"
|
68
77
|
end
|
78
|
+
table_alias = table_alias.to_sym
|
79
|
+
|
80
|
+
if create_dataset
|
81
|
+
dataset = db.from(table)
|
82
|
+
end
|
69
83
|
|
70
84
|
# Raise Sequel::Error with explanation that the table alias has been used
|
71
85
|
raise_alias_error = lambda do
|
@@ -76,8 +90,8 @@ module Sequel
|
|
76
90
|
# Only allow table aliases that haven't been used
|
77
91
|
raise_alias_error.call if @opts[:graph] && @opts[:graph][:table_aliases] && @opts[:graph][:table_aliases].include?(table_alias)
|
78
92
|
|
79
|
-
# Use a from_self if this is already a joined table
|
80
|
-
ds = (!@opts[:graph] && (@opts[:from].length > 1 || @opts[:join])) ? from_self(:alias=>options[:from_self_alias] || first_source) : self
|
93
|
+
# Use a from_self if this is already a joined table (or from_self specifically disabled for graphs)
|
94
|
+
ds = (@opts[:graph_from_self] != false && !@opts[:graph] && (@opts[:from].length > 1 || @opts[:join])) ? from_self(:alias=>options[:from_self_alias] || first_source) : self
|
81
95
|
|
82
96
|
# Join the table early in order to avoid cloning the dataset twice
|
83
97
|
ds = ds.join_table(options[:join_type] || :left_outer, table, join_conditions, :table_alias=>table_alias, :implicit_qualifier=>options[:implicit_qualifier], :qualify=>options[:qualify], &block)
|
@@ -121,7 +135,7 @@ module Sequel
|
|
121
135
|
column = column.value if column.is_a?(SQL::Identifier)
|
122
136
|
column.to_sym
|
123
137
|
when SQL::AliasedExpression
|
124
|
-
column = sel.
|
138
|
+
column = sel.alias
|
125
139
|
column = column.value if column.is_a?(SQL::Identifier)
|
126
140
|
column.to_sym
|
127
141
|
else
|
data/lib/sequel/dataset/misc.rb
CHANGED
@@ -97,7 +97,7 @@ module Sequel
|
|
97
97
|
end
|
98
98
|
case s = source.first
|
99
99
|
when SQL::AliasedExpression
|
100
|
-
s.
|
100
|
+
s.alias
|
101
101
|
when Symbol
|
102
102
|
_, _, aliaz = split_symbol(s)
|
103
103
|
aliaz ? aliaz.to_sym : s
|
@@ -178,7 +178,7 @@ module Sequel
|
|
178
178
|
c_table, column, aliaz = split_symbol(c)
|
179
179
|
[c_table ? SQL::QualifiedIdentifier.new(c_table, column.to_sym) : column.to_sym, aliaz]
|
180
180
|
when SQL::AliasedExpression
|
181
|
-
[c.expression, c.
|
181
|
+
[c.expression, c.alias]
|
182
182
|
when SQL::JoinClause
|
183
183
|
[c.table, c.table_alias]
|
184
184
|
else
|
data/lib/sequel/dataset/sql.rb
CHANGED
@@ -298,7 +298,7 @@ module Sequel
|
|
298
298
|
# SQL fragment for AliasedExpression
|
299
299
|
def aliased_expression_sql_append(sql, ae)
|
300
300
|
literal_append(sql, ae.expression)
|
301
|
-
as_sql_append(sql, ae.
|
301
|
+
as_sql_append(sql, ae.alias)
|
302
302
|
end
|
303
303
|
|
304
304
|
# SQL fragment for Array
|
@@ -801,7 +801,7 @@ module Sequel
|
|
801
801
|
when SQL::QualifiedIdentifier
|
802
802
|
alias_symbol(sym.column)
|
803
803
|
when SQL::AliasedExpression
|
804
|
-
alias_alias_symbol(sym.
|
804
|
+
alias_alias_symbol(sym.alias)
|
805
805
|
else
|
806
806
|
raise Error, "Invalid alias for alias_symbol: #{sym.inspect}"
|
807
807
|
end
|
@@ -1183,7 +1183,7 @@ module Sequel
|
|
1183
1183
|
schema, table, t_alias = split_symbol(table)
|
1184
1184
|
t_alias ||= Sequel::SQL::QualifiedIdentifier.new(schema, table) if schema
|
1185
1185
|
when Sequel::SQL::AliasedExpression
|
1186
|
-
t_alias = table.
|
1186
|
+
t_alias = table.alias
|
1187
1187
|
end
|
1188
1188
|
c_table = t_alias || table
|
1189
1189
|
end
|
@@ -185,7 +185,7 @@ module Sequel
|
|
185
185
|
|
186
186
|
if soid = opts[:scalar_oid]
|
187
187
|
raise Error, "can't provide both a converter and :scalar_oid option to register" if converter
|
188
|
-
|
188
|
+
converter = type_procs[soid]
|
189
189
|
end
|
190
190
|
|
191
191
|
array_type = (opts[:array_type] || db_type).to_s.dup.freeze
|
@@ -42,6 +42,8 @@
|
|
42
42
|
# ia.any # ANY(int_array_column)
|
43
43
|
# ia.all # ALL(int_array_column)
|
44
44
|
# ia.dims # array_dims(int_array_column)
|
45
|
+
# ia.hstore # hstore(int_array_column)
|
46
|
+
# ia.hstore(:a) # hstore(int_array_column, a)
|
45
47
|
# ia.length # array_length(int_array_column, 1)
|
46
48
|
# ia.length(2) # array_length(int_array_column, 2)
|
47
49
|
# ia.lower # array_lower(int_array_column, 1)
|
@@ -57,6 +59,10 @@
|
|
57
59
|
# If you are also using the pg_array extension, you should load it before
|
58
60
|
# loading this extension. Doing so will allow you to use PGArray#op to get
|
59
61
|
# an ArrayOp, allowing you to perform array operations on array literals.
|
62
|
+
#
|
63
|
+
# In order for #hstore to automatically wrap the returned value correctly in
|
64
|
+
# an HStoreOp, you need to load the pg_hstore_ops extension.
|
65
|
+
|
60
66
|
module Sequel
|
61
67
|
module Postgres
|
62
68
|
# The ArrayOp class is a simple container for a single object that
|
@@ -58,6 +58,13 @@
|
|
58
58
|
# If you are also using the pg_hstore extension, you should load it before
|
59
59
|
# loading this extension. Doing so will allow you to use HStore#op to get
|
60
60
|
# an HStoreOp, allowing you to perform hstore operations on hstore literals.
|
61
|
+
#
|
62
|
+
# Some of these methods will accept ruby arrays and convert them automatically to
|
63
|
+
# PostgreSQL arrays if you have the pg_array extension loaded. Some of these methods
|
64
|
+
# will accept ruby hashes and convert them automatically to PostgreSQL hstores if the
|
65
|
+
# pg_hstore extension is loaded. Methods representing expressions that return
|
66
|
+
# PostgreSQL arrays will have the returned expression automatically wrapped in a
|
67
|
+
# Postgres::ArrayOp if the pg_array_ops extension is loaded.
|
61
68
|
|
62
69
|
module Sequel
|
63
70
|
module Postgres
|
@@ -49,6 +49,11 @@
|
|
49
49
|
# loading this extension. Doing so will allow you to use JSONHash#op and
|
50
50
|
# JSONArray#op to get a JSONOp, allowing you to perform json operations
|
51
51
|
# on json literals.
|
52
|
+
#
|
53
|
+
# In order to get the automatic conversion from a ruby array to a PostgreSQL array
|
54
|
+
# (as shown in the #[] and #get_text examples above), you need to load the pg_array
|
55
|
+
# extension.
|
56
|
+
|
52
57
|
module Sequel
|
53
58
|
module Postgres
|
54
59
|
# The JSONOp class is a simple container for a single object that
|