postgres_ext 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +4 -0
- data/CHANGELOG.md +22 -0
- data/README.md +12 -240
- data/docs/indexes.md +19 -0
- data/docs/migrations.md +76 -0
- data/docs/querying.md +138 -0
- data/docs/type_casting.md +51 -0
- data/lib/postgres_ext/active_record/connection_adapters/postgres_adapter.rb +10 -4
- data/lib/postgres_ext/active_record/relation/predicate_builder.rb +71 -0
- data/lib/postgres_ext/active_record/relation/query_methods.rb +84 -0
- data/lib/postgres_ext/active_record/relation.rb +2 -0
- data/lib/postgres_ext/active_record.rb +1 -0
- data/lib/postgres_ext/arel/nodes/contained_within.rb +12 -0
- data/lib/postgres_ext/arel/predications.rb +12 -0
- data/lib/postgres_ext/arel/visitors/to_sql.rb +15 -0
- data/lib/postgres_ext/arel/visitors/visitor.rb +14 -8
- data/lib/postgres_ext/arel/visitors.rb +1 -0
- data/lib/postgres_ext/version.rb +1 -1
- data/postgres_ext.gemspec +2 -2
- data/spec/arel/inet_spec.rb +25 -2
- data/spec/columns/array_spec.rb +39 -0
- data/spec/dummy/db/migrate/20120501163758_create_people.rb +3 -5
- data/spec/dummy/db/schema.rb +11 -7
- data/spec/migrations/array_spec.rb +23 -7
- data/spec/migrations/citext_spec.rb +27 -0
- data/spec/queries/array_queries_spec.rb +57 -0
- data/spec/queries/contains_querie_spec.rb +36 -0
- data/spec/queries/sanity_spec.rb +23 -0
- data/spec/schema_dumper/citext_spec.rb +17 -0
- metadata +26 -8
data/.travis.yml
CHANGED
@@ -8,7 +8,11 @@ rvm:
|
|
8
8
|
before_script:
|
9
9
|
- psql -c 'create database postgres_ext_test;' -U postgres
|
10
10
|
- cp spec/dummy/config/database.yml.example spec/dummy/config/database.yml
|
11
|
+
- RAILS_ENV=test rake db:migrate
|
11
12
|
|
12
13
|
notifications:
|
13
14
|
email:
|
14
15
|
- git@danmcclain.net
|
16
|
+
campfire:
|
17
|
+
rooms:
|
18
|
+
- secure: "yVESPleawl+fzvnzXw/W7rULyCjMEq3gPc3cEqcqM2SBBtEIDNXto2zoTAoR\nC5yqhijr+UtmVMsI7CxVK3XvfkmCJZN9P4DP0uas8XYx5DsSabCdPN0h3pka\nbaDCMCInU5QF4WswL2iuyLsOJeKDRwxh09adsHi1HpMgf0nTKPA="
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
## 0.2.0
|
2
|
+
|
3
|
+
* Introduces extensions to `ActiveRecord::Relation.where` to simplify
|
4
|
+
Array and INET/CIDR queries - Dan McClain (@danmcclain)
|
5
|
+
* Fixes `where(:array => [1,2])` to use equailty instead of IN clauses
|
6
|
+
- Dan McClain (@danmcclain)
|
7
|
+
* Adds Arel predicates for more network comparisons - Patrick Muldoon
|
8
|
+
(@doon)
|
9
|
+
* Adds support for citext in migrations/schema.rb - Jonathan Younger
|
10
|
+
(@daikini)
|
11
|
+
* Fixes text character encoding for text columns - Andy Monat (@amonat)
|
12
|
+
* Cleans up alias_method_chains for better interoperability - Raido
|
13
|
+
Paaslepp (@legendetm)
|
14
|
+
* Doc updates - Dan McClain, Caleb Woods (@danmcclain @calebwoods)
|
15
|
+
|
16
|
+
## 0.1.0
|
17
|
+
|
18
|
+
* Performs PostgreSQL version check before attempting to dumpe
|
19
|
+
extensions - Dan McClain (@danmcclain)
|
20
|
+
* Fixes issues with schema dumper when indexes have no index_opclass -
|
21
|
+
Mario Visic (@mariovisic)
|
22
|
+
|
1
23
|
## 0.0.10
|
2
24
|
|
3
25
|
* Fixes parsing of number arrays when they are set from a string array - Alexey Noskov (@alno)
|
data/README.md
CHANGED
@@ -5,10 +5,13 @@ Adds support for missing PostgreSQL data types to ActiveRecord.
|
|
5
5
|
[![Build Status](https://secure.travis-ci.org/dockyard/postgres_ext.png?branch=master)](http://travis-ci.org/dockyard/postgres_ext)
|
6
6
|
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/dockyard/postgres_ext)
|
7
7
|
|
8
|
-
##
|
8
|
+
## Looking for help? ##
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
If it is a bug [please open an issue on
|
11
|
+
Github](https://github.com/dockyard/party_foul/issues). If you need help using
|
12
|
+
the gem please ask the question on
|
13
|
+
[Stack Overflow](http://stackoverflow.com). Be sure to tag the
|
14
|
+
question with `DockYard` so we can find it.
|
12
15
|
|
13
16
|
## Installation
|
14
17
|
|
@@ -29,11 +32,12 @@ Or install it yourself as:
|
|
29
32
|
Just `require 'postgres_ext'` and use ActiveRecord as you normally would! postgres\_ext extends
|
30
33
|
ActiveRecord's data type handling.
|
31
34
|
|
32
|
-
* [Migration/Schema.rb support](
|
33
|
-
* [Type Casting support](
|
34
|
-
* [Querying PostgreSQL datatypes](
|
35
|
+
* [Migration/Schema.rb support](docs/migrations.md)
|
36
|
+
* [Type Casting support](docs/type_casting.md)
|
37
|
+
* [Querying PostgreSQL datatypes](docs/querying.md)
|
38
|
+
* [Indexes](docs/indexes.md)
|
35
39
|
|
36
|
-
|
40
|
+
## Usage Notes
|
37
41
|
Avoid the use of in place operators (ie `Array#<<`). These changes are
|
38
42
|
*not* tracked by Rails ([this issue](https://github.com/rails/rails/issues/6954))
|
39
43
|
explains why). In place modifications also modify the default object.
|
@@ -64,7 +68,7 @@ The supported way of modifying `a.names`:
|
|
64
68
|
|
65
69
|
```ruby
|
66
70
|
a = Item.new
|
67
|
-
a.names += 'foo'
|
71
|
+
a.names += ['foo']
|
68
72
|
|
69
73
|
b = Item.new
|
70
74
|
puts b.names
|
@@ -74,240 +78,8 @@ puts b.names
|
|
74
78
|
As a result, in place operators are discouraged and will not be
|
75
79
|
supported in postgres\_ext at this time.
|
76
80
|
|
77
|
-
## Migration/Schema.rb support
|
78
81
|
|
79
|
-
### INET
|
80
82
|
|
81
|
-
```ruby
|
82
|
-
create_table :testing do |t|
|
83
|
-
t.inet :inet_column
|
84
|
-
# or
|
85
|
-
t.inet :inet_column_1, :inet_column_2
|
86
|
-
# or
|
87
|
-
t.column :inet_column, :inet
|
88
|
-
end
|
89
|
-
```
|
90
|
-
|
91
|
-
### CIDR
|
92
|
-
|
93
|
-
```ruby
|
94
|
-
create_table :testing do |t|
|
95
|
-
t.cidr :cidr_column
|
96
|
-
# or
|
97
|
-
t.cidr :cidr_column_1, :cidr_column_2
|
98
|
-
# or
|
99
|
-
t.column :cidr_column, :cidr
|
100
|
-
end
|
101
|
-
```
|
102
|
-
|
103
|
-
### MACADDR
|
104
|
-
|
105
|
-
```ruby
|
106
|
-
create_table :testing do |t|
|
107
|
-
t.macaddr :macaddr_column
|
108
|
-
# or
|
109
|
-
t.macaddr :macaddr_column_1, :macaddr_column_2
|
110
|
-
# or
|
111
|
-
t.column :macaddr_column, :macaddr
|
112
|
-
end
|
113
|
-
```
|
114
|
-
|
115
|
-
### UUID
|
116
|
-
|
117
|
-
```ruby
|
118
|
-
create_table :testing do |t|
|
119
|
-
t.uuid :uuid_column
|
120
|
-
# or
|
121
|
-
t.uuid :uuid_column_1, :uuid_column_2
|
122
|
-
# or
|
123
|
-
t.column :uuid_column, :uuid
|
124
|
-
end
|
125
|
-
```
|
126
|
-
|
127
|
-
### Arrays
|
128
|
-
Arrays are created from any ActiveRecord supported datatype (including
|
129
|
-
ones added by postgre\_ext), and respect length constraints
|
130
|
-
|
131
|
-
```ruby
|
132
|
-
create_table :testing do |t|
|
133
|
-
t.integer :int_array, :array => true
|
134
|
-
# integer[]
|
135
|
-
t.integer :int_array, :array => true, :limit => 2
|
136
|
-
# smallint[]
|
137
|
-
t.string :macaddr_column_1, :array => true, :limit => 30
|
138
|
-
# char varying(30)[]
|
139
|
-
end
|
140
|
-
```
|
141
|
-
|
142
|
-
## Type Casting support
|
143
|
-
|
144
|
-
### INET and CIDR
|
145
|
-
INET and CIDR values are converted to
|
146
|
-
[IPAddr](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/ipaddr/rdoc/IPAddr.html)
|
147
|
-
objects when retrieved from the database, or set as a string.
|
148
|
-
|
149
|
-
```ruby
|
150
|
-
create_table :inet_examples do |t|
|
151
|
-
t.inet :ip_address
|
152
|
-
end
|
153
|
-
|
154
|
-
class InetExample < ActiveRecord::Base
|
155
|
-
end
|
156
|
-
|
157
|
-
inetExample = InetExample.new
|
158
|
-
inetExample.ip_address = '127.0.0.0/24'
|
159
|
-
inetExample.ip_address
|
160
|
-
# => #<IPAddr: IPv4:127.0.0.0/255.255.255.0>
|
161
|
-
inetExample.save
|
162
|
-
|
163
|
-
inet_2 = InetExample.first
|
164
|
-
inet_2.ip_address
|
165
|
-
# => #<IPAddr: IPv4:127.0.0.0/255.255.255.0>
|
166
|
-
```
|
167
|
-
|
168
|
-
### Arrays
|
169
|
-
Array values can be set with Array objects. Any array stored in the
|
170
|
-
database will be converted to a properly casted array of values on the
|
171
|
-
way out.
|
172
|
-
|
173
|
-
```ruby
|
174
|
-
create_table :people do |t|
|
175
|
-
t.integer :favorite_numbers, :array => true
|
176
|
-
end
|
177
|
-
|
178
|
-
class Person < ActiveRecord::Base
|
179
|
-
end
|
180
|
-
|
181
|
-
person = Person.new
|
182
|
-
person.favorite_numbers = [1,2,3]
|
183
|
-
person.favorite_numbers
|
184
|
-
# => [1,2,3]
|
185
|
-
person.save
|
186
|
-
|
187
|
-
person_2 = Person.first
|
188
|
-
person_2.favorite_numbers
|
189
|
-
# => [1,2,3]
|
190
|
-
person_2.favorite_numbers.first.class
|
191
|
-
# => Fixnum
|
192
|
-
```
|
193
|
-
|
194
|
-
## Querying PostgreSQL datatypes
|
195
|
-
|
196
|
-
* [Arrays](#arrays-2)
|
197
|
-
* [INET/CIDR](#inetcidr)
|
198
|
-
|
199
|
-
### Arrays
|
200
|
-
|
201
|
-
* [&& - Array Overlap operator](#---array-overlap-operator)
|
202
|
-
* [ANY or ALL functions](#any-or-all-functions)
|
203
|
-
|
204
|
-
#### && - Array Overlap operator
|
205
|
-
|
206
|
-
PostgreSQL implements the `&&` operator, known as the overlap operator,
|
207
|
-
for arrays. The overlap operator returns `t` (true) when two arrays have
|
208
|
-
one or more elements in common.
|
209
|
-
|
210
|
-
```sql
|
211
|
-
ARRAY[1,2,3] && ARRAY[4,5,6]
|
212
|
-
-- f
|
213
|
-
|
214
|
-
ARRAY[1,2,3] && ARRAY[3,5,6]
|
215
|
-
-- t
|
216
|
-
```
|
217
|
-
|
218
|
-
Postgres\_ext defines `array_overlap`, an [Arel](https://github.com/rails/arel)
|
219
|
-
predicate for the `&&` operator.
|
220
|
-
|
221
|
-
```ruby
|
222
|
-
user_arel = User.arel_table
|
223
|
-
|
224
|
-
# Execute the query
|
225
|
-
User.where(user_arel[:tags].array_overlap(['one','two']))
|
226
|
-
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"tags\" && '{one,two}'
|
227
|
-
```
|
228
|
-
|
229
|
-
#### ANY or ALL functions
|
230
|
-
|
231
|
-
When querying array columns, you have the ability to see if a predicate
|
232
|
-
apply's to either *any* element in the array, or *all* elements of the
|
233
|
-
array. The syntax for these predicates are slightly different then the
|
234
|
-
normal `where` syntax in PostgreSQL. To see if an array contains the
|
235
|
-
string `'test'` in any location, you would write the following in SQL
|
236
|
-
|
237
|
-
```sql
|
238
|
-
SELECT *
|
239
|
-
FROM users
|
240
|
-
WHERE 'test' = ANY(users.tags)
|
241
|
-
```
|
242
|
-
|
243
|
-
Notice that the column is on the right hand side of the predicate,
|
244
|
-
instead of the left, because we have to call the `ANY` function on that
|
245
|
-
column.
|
246
|
-
|
247
|
-
We can generate the above query using [Arel](https://github.com/rails/arel)
|
248
|
-
and generating the Node manually. We would use the following to
|
249
|
-
accompish this:
|
250
|
-
|
251
|
-
```ruby
|
252
|
-
user_arel = User.arel_table
|
253
|
-
|
254
|
-
any_tags_function = Arel::Nodes::NamedFunction.new('ANY', [user_arel[:tags]])
|
255
|
-
predicate = Arel::Nodes::Equality.new('test', any_tags_function)
|
256
|
-
|
257
|
-
# Execute the query
|
258
|
-
User.where(predicate)
|
259
|
-
#=> SELECT \"users\".* FROM \"users\" WHERE 'test' = ANY(\"users\".\"tags\")
|
260
|
-
```
|
261
|
-
|
262
|
-
The ALL version of this same predicate can be generated by swap `'ANY'`
|
263
|
-
for `'ALL'` in the named function.
|
264
|
-
|
265
|
-
### INET/CIDR
|
266
|
-
|
267
|
-
#### `<<` -- Contained within operator
|
268
|
-
|
269
|
-
PostgreSQL defines the `<<`, or contained within operator for INET and
|
270
|
-
CIDR datatypes. The `<<` operator returns `t` (true) if a INET or CIDR
|
271
|
-
address is contained within the given subnet.
|
272
|
-
|
273
|
-
```sql
|
274
|
-
inet '192.168.1.6' << inet '10.0.0.0/24'
|
275
|
-
-- f
|
276
|
-
|
277
|
-
inet '192.168.1.6' << inet '192.168.1.0/24'
|
278
|
-
-- t
|
279
|
-
```
|
280
|
-
|
281
|
-
Postgres\_ext defines `contained_within`, an [Arel](https://github.com/rails/arel)
|
282
|
-
predicate for the `<<` operator.
|
283
|
-
|
284
|
-
```ruby
|
285
|
-
user_arel = User.arel_table
|
286
|
-
|
287
|
-
# Execute the query
|
288
|
-
User.where(user_arel[:ip_address].contained_witin('127.0.0.1/24'))
|
289
|
-
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" << '127.0.0.1/24'
|
290
|
-
```
|
291
|
-
|
292
|
-
## Indexes
|
293
|
-
|
294
|
-
### Index types
|
295
|
-
|
296
|
-
Postgres\_ext allows you to specify index type and index operator
|
297
|
-
class at index creation.
|
298
|
-
|
299
|
-
```ruby
|
300
|
-
add_index :table_name, :column, :index_type => :gin
|
301
|
-
add_index :table_name, :column, :index_type => :gin, :index_opclass => :gin_trgm_ops
|
302
|
-
```
|
303
|
-
|
304
|
-
### Where clauses
|
305
|
-
|
306
|
-
Postgres\_ext allows you to specify a where clause at index creation.
|
307
|
-
|
308
|
-
```ruby
|
309
|
-
add_index :table_name, :column, :where => 'column < 50'
|
310
|
-
```
|
311
83
|
|
312
84
|
## Authors
|
313
85
|
|
data/docs/indexes.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# Indexes
|
2
|
+
|
3
|
+
## Index types
|
4
|
+
|
5
|
+
Postgres\_ext allows you to specify index type and index operator
|
6
|
+
class at index creation.
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
add_index :table_name, :column, :index_type => :gin
|
10
|
+
add_index :table_name, :column, :index_type => :gin, :index_opclass => :gin_trgm_ops
|
11
|
+
```
|
12
|
+
|
13
|
+
## Where clauses
|
14
|
+
|
15
|
+
Postgres\_ext allows you to specify a where clause at index creation.
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
add_index :table_name, :column, :where => 'column < 50'
|
19
|
+
```
|
data/docs/migrations.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Migration/Schema.rb support
|
2
|
+
|
3
|
+
## INET
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
create_table :testing do |t|
|
7
|
+
t.inet :inet_column
|
8
|
+
# or
|
9
|
+
t.inet :inet_column_1, :inet_column_2
|
10
|
+
# or
|
11
|
+
t.column :inet_column, :inet
|
12
|
+
end
|
13
|
+
```
|
14
|
+
|
15
|
+
## CIDR
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
create_table :testing do |t|
|
19
|
+
t.cidr :cidr_column
|
20
|
+
# or
|
21
|
+
t.cidr :cidr_column_1, :cidr_column_2
|
22
|
+
# or
|
23
|
+
t.column :cidr_column, :cidr
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
## MACADDR
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
create_table :testing do |t|
|
31
|
+
t.macaddr :macaddr_column
|
32
|
+
# or
|
33
|
+
t.macaddr :macaddr_column_1, :macaddr_column_2
|
34
|
+
# or
|
35
|
+
t.column :macaddr_column, :macaddr
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
## UUID
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
create_table :testing do |t|
|
43
|
+
t.uuid :uuid_column
|
44
|
+
# or
|
45
|
+
t.uuid :uuid_column_1, :uuid_column_2
|
46
|
+
# or
|
47
|
+
t.column :uuid_column, :uuid
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
## CITEXT
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
create_table :testing do |t|
|
55
|
+
t.citext :citext_column
|
56
|
+
# or
|
57
|
+
t.citext :citext_column_1, :citext_column_2
|
58
|
+
# or
|
59
|
+
t.column :citext_column, :citext
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
## Arrays
|
64
|
+
Arrays are created from any ActiveRecord supported datatype (including
|
65
|
+
ones added by postgres\_ext), and respect length constraints
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
create_table :testing do |t|
|
69
|
+
t.integer :int_array, :array => true
|
70
|
+
# integer[]
|
71
|
+
t.integer :int_array, :array => true, :limit => 2
|
72
|
+
# smallint[]
|
73
|
+
t.string :macaddr_column_1, :array => true, :limit => 30
|
74
|
+
# char varying(30)[]
|
75
|
+
end
|
76
|
+
```
|
data/docs/querying.md
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
# Querying PostgreSQL datatypes
|
2
|
+
|
3
|
+
* [Arrays](#arrays)
|
4
|
+
* [INET/CIDR](#inetcidr-queries)
|
5
|
+
|
6
|
+
## Arrays
|
7
|
+
|
8
|
+
* [&& - Array Overlap operator](#---array-overlap-operator)
|
9
|
+
* [ANY or ALL functions](#any-or-all-functions)
|
10
|
+
|
11
|
+
### && - Array Overlap operator
|
12
|
+
|
13
|
+
PostgreSQL implements the `&&` operator, known as the overlap operator,
|
14
|
+
for arrays. The overlap operator returns `t` (true) when two arrays have
|
15
|
+
one or more elements in common.
|
16
|
+
|
17
|
+
```sql
|
18
|
+
ARRAY[1,2,3] && ARRAY[4,5,6]
|
19
|
+
-- f
|
20
|
+
|
21
|
+
ARRAY[1,2,3] && ARRAY[3,5,6]
|
22
|
+
-- t
|
23
|
+
```
|
24
|
+
|
25
|
+
Postgres\_ext extends the `ActiveRecord::Relation.where` method similar
|
26
|
+
to the Rails 4.0 not clause. The easiest way to make a overlap query
|
27
|
+
would be:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
User.where.overlap(:nick_names => ['Bob', 'Fred'])
|
31
|
+
```
|
32
|
+
|
33
|
+
Postgres\_ext defines `array_overlap`, an [Arel](https://github.com/rails/arel)
|
34
|
+
predicate for the `&&` operator. This is utilized by the `where.overlap`
|
35
|
+
call above.
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
user_arel = User.arel_table
|
39
|
+
|
40
|
+
# Execute the query
|
41
|
+
User.where(user_arel[:tags].array_overlap(['one','two']))
|
42
|
+
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"tags\" && '{one,two}'
|
43
|
+
```
|
44
|
+
|
45
|
+
### ANY or ALL functions
|
46
|
+
|
47
|
+
When querying array columns, you have the ability to see if a predicate
|
48
|
+
apply's to either *any* element in the array, or *all* elements of the
|
49
|
+
array. The syntax for these predicates are slightly different then the
|
50
|
+
normal `where` syntax in PostgreSQL. To see if an array contains the
|
51
|
+
string `'test'` in any location, you would write the following in SQL
|
52
|
+
|
53
|
+
```sql
|
54
|
+
SELECT *
|
55
|
+
FROM users
|
56
|
+
WHERE 'test' = ANY(users.tags)
|
57
|
+
```
|
58
|
+
|
59
|
+
Notice that the column is on the right hand side of the predicate,
|
60
|
+
instead of the left, because we have to call the `ANY` function on that
|
61
|
+
column.
|
62
|
+
|
63
|
+
Postgres\_ext provides a `ActiveRecord::Relation.where.any()` method. The
|
64
|
+
easiest way to make a ANY query would be:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
User.where.any(:nick_names => 'Bob')
|
68
|
+
```
|
69
|
+
|
70
|
+
There is also an `ActiveRecord::Relation.where.all()` call as well. This
|
71
|
+
method utilizes the following code to create the query:
|
72
|
+
|
73
|
+
We can generate the above query using [Arel](https://github.com/rails/arel)
|
74
|
+
and generating the Node manually. We would use the following to
|
75
|
+
accompish this:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
user_arel = User.arel_table
|
79
|
+
|
80
|
+
any_tags_function = Arel::Nodes::NamedFunction.new('ANY', [user_arel[:tags]])
|
81
|
+
predicate = Arel::Nodes::Equality.new('test', any_tags_function)
|
82
|
+
|
83
|
+
# Execute the query
|
84
|
+
User.where(predicate)
|
85
|
+
#=> SELECT \"users\".* FROM \"users\" WHERE 'test' = ANY(\"users\".\"tags\")
|
86
|
+
```
|
87
|
+
|
88
|
+
The ALL version of this same predicate can be generated by swap `'ANY'`
|
89
|
+
for `'ALL'` in the named function.
|
90
|
+
|
91
|
+
## INET/CIDR Queries
|
92
|
+
|
93
|
+
PostgreSQL defines the `<<`, or contained within operator for INET and
|
94
|
+
CIDR datatypes. The `<<` operator returns `t` (true) if a INET or CIDR
|
95
|
+
address is contained within the given subnet.
|
96
|
+
|
97
|
+
```sql
|
98
|
+
inet '192.168.1.6' << inet '10.0.0.0/24'
|
99
|
+
-- f
|
100
|
+
|
101
|
+
inet '192.168.1.6' << inet '192.168.1.0/24'
|
102
|
+
-- t
|
103
|
+
```
|
104
|
+
|
105
|
+
In addition to contained within, there is also:
|
106
|
+
|
107
|
+
* `<<=` - Contained within or equals
|
108
|
+
* `>>` - Contains
|
109
|
+
* `>>=` - Contains or equals
|
110
|
+
|
111
|
+
Postgres\_ext extends the `ActiveRecord::Relation.where` method similar
|
112
|
+
to the Rails 4.0 not clause. The easiest way to make a overlap query
|
113
|
+
would be:
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
User.where.contained_within(:ip => '192.168.1.1/24')
|
117
|
+
User.where.contained_within_or_equals(:ip => '192.168.1.1/24')
|
118
|
+
User.where.contains(:ip => '192.168.1.14')
|
119
|
+
User.where.contains_or_equals(:ip => '192.168.1.14')
|
120
|
+
```
|
121
|
+
|
122
|
+
Postgres\_ext defines `contained_within`, an [Arel](https://github.com/rails/arel)
|
123
|
+
predicate for the `<<` operator. This is utilized by the
|
124
|
+
methods above.
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
user_arel = User.arel_table
|
128
|
+
|
129
|
+
# Execute the query
|
130
|
+
User.where(user_arel[:ip_address].contained_within('127.0.0.1/24'))
|
131
|
+
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" << '127.0.0.1/24'
|
132
|
+
User.where(user_arel[:ip_address].contained_within_or_equals('127.0.0.1/24'))
|
133
|
+
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" <<= '127.0.0.1/24'
|
134
|
+
User.where(user_arel[:ip_address].contains('127.0.0.1'))
|
135
|
+
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" >> '127.0.0.1'
|
136
|
+
User.where(user_arel[:ip_address].contains_or_equals('127.0.0.1'))
|
137
|
+
# => SELECT \"users\".* FROM \"users\" WHERE \"users\".\"ip_address\" >>= '127.0.0.1'
|
138
|
+
```
|