postgres_ext 0.1.0 → 0.2.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/.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
- ## Roadmap
8
+ ## Looking for help? ##
9
9
 
10
- * Arel support for INET, CIDR and Array related where clauses
11
- * Backport HStore code from Rails 4.0
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](#migrationschemarb-support)
33
- * [Type Casting support](#type-casting-support)
34
- * [Querying PostgreSQL datatypes](#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
- ### Usage Notes
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
+ ```
@@ -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
+ ```