pg_query 0.6.3 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f75ea93d3521a2b9f912943357d6b16e3598bbea
4
- data.tar.gz: f320d5689ceda9ba637d751bf10e4f09d8dddaae
3
+ metadata.gz: 75abf971dc2e2ed3ba84e61b7964e7c52ac62faf
4
+ data.tar.gz: e80a542497240ffc2c36892422b972ff3049f02d
5
5
  SHA512:
6
- metadata.gz: 2007ca5cea466541823b11818ba6ba9b86cdf447e3f449024a790b8ebfbf8a9762dfefc82e0e9abb6e96c42e5a3602c4c7bf7ed479aa431666f078f503911a7f
7
- data.tar.gz: 687b67153015d9e3e36053a6ffc4e7c558cec3f4ca7eac3860188c0d88a72b41a38d57dcae0e02deb11535f3b8e2f499789fc1ad9281e1da8365c7d9a421e308
6
+ metadata.gz: 85e96b1d41a656569bf83a716194d71907f7c9d8c0a9c7282b30bc4b0110bdbc6c90d5cbf6df95c6211bd011d73763e58205de8eb626e5855c944ce96b6be0ac
7
+ data.tar.gz: 7f5b864b1e61711da44c0bca0d318edf719506633297310d9be4d7daf17729e7602daa2a4e191c19039670e54ac9a4f404fd3ab115caf0a2ffac21c7c9ce977d
data/CHANGELOG.md CHANGED
@@ -1,10 +1,19 @@
1
1
  # Changelog
2
2
 
3
- ## 0.6.4 UNRELEASED
3
+ ## 0.6.5 UNRELEASED
4
4
 
5
5
  * ...
6
6
 
7
7
 
8
+ ## 0.6.4 2015-10-01
9
+
10
+ * Deparsing
11
+ * Constraints & Interval Types [#28](https://github.com/lfittl/pg_query/pull/28) [@JackDanger](https://github.com/JackDanger)
12
+ * Cross joins [#29](https://github.com/lfittl/pg_query/pull/29) [@mme](https://github.com/mme)
13
+ * ALTER TABLE [#30](https://github.com/lfittl/pg_query/pull/30) [@JackDanger](https://github.com/JackDanger)
14
+ * LIMIT and OFFSET [#33](https://github.com/lfittl/pg_query/pull/33) [@jcsjcs](https://github.com/jcsjcs)
15
+
16
+
8
17
  ## 0.6.3 2015-08-20
9
18
 
10
19
  * Deparsing
@@ -1,15 +1,20 @@
1
+ require_relative 'deparse/interval'
2
+ require_relative 'deparse/alter_table'
1
3
  class PgQuery
2
4
  # Reconstruct all of the parsed queries into their original form
3
5
  def deparse(tree = @parsetree)
4
6
  tree.map do |item|
5
- self.class.deparse(item)
7
+ Deparse.from(item)
6
8
  end.join('; ')
7
9
  end
8
10
 
9
- class << self
11
+ # rubocop:disable Metrics/ModuleLength
12
+ module Deparse
13
+ extend self
14
+
10
15
  # Given one element of the PgQuery#parsetree reconstruct it back into the
11
16
  # original query.
12
- def deparse(item)
17
+ def from(item)
13
18
  deparse_item(item)
14
19
  end
15
20
 
@@ -17,6 +22,7 @@ class PgQuery
17
22
 
18
23
  def deparse_item(item, context = nil) # rubocop:disable Metrics/CyclomaticComplexity
19
24
  return if item.nil?
25
+ return item if item.is_a?(Fixnum)
20
26
 
21
27
  type = item.keys[0]
22
28
  node = item.values[0]
@@ -33,9 +39,13 @@ class PgQuery
33
39
  when 'AEXPR OR'
34
40
  deparse_aexpr_or(node)
35
41
  when 'AEXPR'
36
- deparse_aexpr(node)
42
+ deparse_aexpr(node, context)
37
43
  when 'ALIAS'
38
44
  deparse_alias(node)
45
+ when 'ALTER TABLE'
46
+ deparse_alter_table(node)
47
+ when 'ALTER TABLE CMD'
48
+ deparse_alter_table_cmd(node)
39
49
  when 'A_ARRAYEXPR'
40
50
  deparse_a_arrayexp(node)
41
51
  when 'A_CONST'
@@ -68,6 +78,8 @@ class PgQuery
68
78
  deparse_defelem(node)
69
79
  when 'DELETE FROM'
70
80
  deparse_delete_from(node)
81
+ when 'DROP'
82
+ deparse_drop(node)
71
83
  when 'FUNCCALL'
72
84
  deparse_funccall(node)
73
85
  when 'FUNCTIONPARAMETER'
@@ -86,6 +98,8 @@ class PgQuery
86
98
  deparse_rangesubselect(node)
87
99
  when 'RANGEVAR'
88
100
  deparse_rangevar(node)
101
+ when 'RENAMESTMT'
102
+ deparse_renamestmt(node)
89
103
  when 'RESTARGET'
90
104
  deparse_restarget(node, context)
91
105
  when 'ROW'
@@ -125,6 +139,19 @@ class PgQuery
125
139
  output.join(' ')
126
140
  end
127
141
 
142
+ def deparse_renamestmt(node)
143
+ output = []
144
+
145
+ if node['renameType'] == 26 # table
146
+ output << 'ALTER TABLE'
147
+ output << deparse_item(node['relation'])
148
+ output << 'RENAME TO'
149
+ output << node['newname']
150
+ end
151
+
152
+ output.join(' ')
153
+ end
154
+
128
155
  def deparse_columnref(node)
129
156
  node['fields'].map do |field|
130
157
  field.is_a?(String) ? field : deparse_item(field)
@@ -166,6 +193,33 @@ class PgQuery
166
193
  end
167
194
  end
168
195
 
196
+ def deparse_alter_table(node)
197
+ output = []
198
+ output << 'ALTER TABLE'
199
+
200
+ output << deparse_item(node['relation'])
201
+
202
+ output << node['cmds'].map do |item|
203
+ deparse_item(item)
204
+ end.join(', ')
205
+
206
+ output.join(' ')
207
+ end
208
+
209
+ def deparse_alter_table_cmd(node)
210
+ command, options = AlterTable.commands(node)
211
+
212
+ output = []
213
+ output << command if command
214
+ output << 'IF EXISTS' if node['missing_ok']
215
+ output << node['name']
216
+ output << options if options
217
+ output << deparse_item(node['def']) if node['def']
218
+ output << 'CASCADE' if node['behavior'] == 1
219
+
220
+ output.compact.join(' ')
221
+ end
222
+
169
223
  def deparse_paramref(node)
170
224
  if node['number'] == 0
171
225
  '?'
@@ -194,7 +248,8 @@ class PgQuery
194
248
  # COUNT(*)
195
249
  args << '*' if node['agg_star']
196
250
 
197
- output << format('%s(%s)', node['funcname'].join('.'), args.join(', '))
251
+ name = (node['funcname'] - ['pg_catalog']).join('.')
252
+ output << format('%s(%s)', name, args.join(', '))
198
253
  output << format('OVER (%s)', deparse_item(node['over'])) if node['over']
199
254
 
200
255
  output.join(' ')
@@ -241,11 +296,16 @@ class PgQuery
241
296
  output.join(' ')
242
297
  end
243
298
 
244
- def deparse_aexpr(node)
299
+ def deparse_aexpr(node, context = false)
245
300
  output = []
246
- output << deparse_item(node['lexpr'])
247
- output << deparse_item(node['rexpr'])
248
- output.join(' ' + node['name'][0] + ' ')
301
+ output << deparse_item(node['lexpr'], context || true)
302
+ output << deparse_item(node['rexpr'], context || true)
303
+ output = output.join(' ' + node['name'][0] + ' ')
304
+ if context
305
+ # This is a nested expression, add parentheses.
306
+ output = '(' + output + ')'
307
+ end
308
+ output
249
309
  end
250
310
 
251
311
  def deparse_aexpr_and(node)
@@ -273,6 +333,7 @@ class PgQuery
273
333
  output = []
274
334
  output << deparse_item(node['larg'])
275
335
  output << 'LEFT' if node['jointype'] == 1
336
+ output << 'CROSS' if node['jointype'] == 0 && node['quals'].nil?
276
337
  output << 'JOIN'
277
338
  output << deparse_item(node['rarg'])
278
339
 
@@ -347,19 +408,35 @@ class PgQuery
347
408
  def deparse_columndef(node)
348
409
  output = [node['colname']]
349
410
  output << deparse_item(node['typeName'])
411
+ if node['raw_default']
412
+ output << 'USING'
413
+ output << deparse_item(node['raw_default'])
414
+ end
350
415
  if node['constraints']
351
416
  output += node['constraints'].map do |item|
352
417
  deparse_item(item)
353
418
  end
354
419
  end
355
- output.join(' ')
420
+ output.compact.join(' ')
356
421
  end
357
422
 
358
423
  def deparse_constraint(node)
359
424
  output = []
425
+ if node['conname']
426
+ output << 'CONSTRAINT'
427
+ output << node['conname']
428
+ end
360
429
  # NOT_NULL -> NOT NULL
361
430
  output << node['contype'].gsub('_', ' ')
362
- output << deparse_item(node['raw_expr']) if node['raw_expr']
431
+
432
+ if node['raw_expr']
433
+ expression = deparse_item(node['raw_expr'])
434
+ # Unless it's simple, put parentheses around it
435
+ expression = '(' + expression + ')' if node['raw_expr'].keys == ['AEXPR']
436
+ output << expression
437
+ end
438
+ output << '(' + node['keys'].join(', ') + ')' if node['keys']
439
+ output << "USING INDEX #{node['indexname']}" if node['indexname']
363
440
  output.join(' ')
364
441
  end
365
442
 
@@ -487,6 +564,16 @@ class PgQuery
487
564
  end.join(', ')
488
565
  end
489
566
 
567
+ if node['limitCount']
568
+ output << 'LIMIT'
569
+ output << deparse_item(node['limitCount'])
570
+ end
571
+
572
+ if node['limitOffset']
573
+ output << 'OFFSET'
574
+ output << deparse_item(node['limitOffset'])
575
+ end
576
+
490
577
  output.join(' ')
491
578
  end
492
579
 
@@ -547,6 +634,10 @@ class PgQuery
547
634
  end
548
635
 
549
636
  def deparse_typename(node)
637
+ # Intervals are tricky and should be handled in a separate method because
638
+ # they require performing some bitmask operations.
639
+ return deparse_interval_type(node) if node['names'] == %w(pg_catalog interval)
640
+
550
641
  output = []
551
642
  output << 'SETOF' if node['setof']
552
643
 
@@ -555,7 +646,6 @@ class PgQuery
555
646
  deparse_item(item)
556
647
  end.join(', ')
557
648
  end
558
-
559
649
  output << deparse_typename_cast(node['names'], arguments)
560
650
 
561
651
  output.join(' ')
@@ -589,11 +679,39 @@ class PgQuery
589
679
  'real'
590
680
  when 'float8'
591
681
  'double'
682
+ when 'time'
683
+ 'time'
684
+ when 'timetz'
685
+ 'time with time zone'
686
+ when 'timestamp'
687
+ 'timestamp'
688
+ when 'timestamptz'
689
+ 'timestamp with time zone'
592
690
  else
593
691
  fail format("Can't deparse type: %s", type)
594
692
  end
595
693
  end
596
694
 
695
+ # Deparses interval type expressions like `interval year to month` or
696
+ # `interval hour to second(5)`
697
+ def deparse_interval_type(node)
698
+ type = ['interval']
699
+
700
+ if node['typmods']
701
+ typmods = node['typmods'].map { |typmod| deparse_item(typmod) }
702
+ type << Interval.from_int(typmods.first.to_i).map do |part|
703
+ # only the `second` type can take an argument.
704
+ if part == 'second' && typmods.size == 2
705
+ "second(#{typmods.last})"
706
+ else
707
+ part
708
+ end.downcase
709
+ end.join(' to ')
710
+ end
711
+
712
+ type.join(' ')
713
+ end
714
+
597
715
  def deparse_nulltest(node)
598
716
  output = [deparse_item(node['arg'])]
599
717
  if node['nulltesttype'] == 0
@@ -668,6 +786,19 @@ class PgQuery
668
786
  output.join(' ')
669
787
  end
670
788
 
789
+ def deparse_drop(node)
790
+ output = ['DROP']
791
+ output << 'TABLE' if node['removeType'] == 26
792
+ output << 'CONCURRENTLY' if node['concurrent']
793
+ output << 'IF EXISTS' if node['missing_ok']
794
+
795
+ output << node['objects'].join(', ')
796
+
797
+ output << 'CASCADE' if node['behavior'] == 1
798
+
799
+ output.join(' ')
800
+ end
801
+
671
802
  # The PG parser adds several pieces of view data onto the RANGEVAR
672
803
  # that need to be printed before deparse_rangevar is called.
673
804
  def relpersistence(rangevar)
@@ -0,0 +1,143 @@
1
+ class PgQuery
2
+ module Deparse
3
+ module AlterTable
4
+ # Returns a list of strings of length one or length two. The first string
5
+ # will be placed before the column name and the second, if present, will be
6
+ # placed after.
7
+ #
8
+ # If node['subtype'] is the integer 4,
9
+ # Then the fifth ALTER_TABLE entry ('DropNotNull') will be selected
10
+ # And the return value of this method will be:
11
+ #
12
+ # ['ALTER COLUMN', 'DROP NOT NULL']
13
+ #
14
+ # Which will be composed into the SQL as:
15
+ #
16
+ # ALTER COLUMN {column_name} DROP NOT NULL
17
+ #
18
+ def self.commands(node)
19
+ action = ALTER_TABLE[ALTER_TABLE_COMMANDS[node['subtype']]]
20
+ PgQuery::Deparse.instance_exec(node, &action)
21
+ end
22
+
23
+ # From include/nodes/parsenodes.h:1455
24
+ #
25
+ # Many of these will not be implemented here as they'll never be part of
26
+ # valid SQL. We keep them all here in their original order because we look
27
+ # these values up by array index.
28
+ NOT_IMPLEMENTED = 'NotImplemented'
29
+ ALTER_TABLE = {
30
+ # add column
31
+ 'AddColumn' => -> (_node) { ['ADD COLUMN'] },
32
+ # internal to commands/tablecmds.c
33
+ 'AddColumnRecurse' => -> (_node) { NotImplemented },
34
+ # implicitly via CREATE OR REPLACE VIEW
35
+ 'AddColumnToView' => -> (_node) { NotImplemented },
36
+ # alter column default
37
+ 'ColumnDefault' => -> (node) { ['ALTER COLUMN', node['def'] ? 'SET DEFAULT' : 'DROP DEFAULT'] },
38
+ # alter column drop not null
39
+ 'DropNotNull' => -> (_node) { ['ALTER COLUMN', 'DROP NOT NULL'] },
40
+ # alter column set not null
41
+ 'SetNotNull' => -> (_node) { ['ALTER COLUMN', 'SET NOT NULL'] },
42
+ # alter column set statistics
43
+ 'SetStatistics' => -> (_node) { ['ALTER COLUMN', 'SET STATISTICS'] },
44
+ # alter column set ( options )
45
+ 'SetOptions' => -> (_node) { ['ALTER COLUMN', 'SET'] },
46
+ # alter column reset ( options )
47
+ 'ResetOptions' => -> (_node) { ['ALTER COLUMN', 'RESET'] },
48
+ # alter column set storage
49
+ 'SetStorage' => -> (_node) { ['ALTER COLUMN', 'SET STORAGE'] },
50
+ # drop column
51
+ 'DropColumn' => -> (_node) { ['DROP'] },
52
+ # internal to commands/tablecmds.c
53
+ 'DropColumnRecurse' => -> (_node) { NotImplemented },
54
+ # add index
55
+ 'AddIndex' => -> (_node) { ['ADD INDEX'] },
56
+ # internal to commands/tablecmds.c
57
+ 'ReAddIndex' => -> (_node) { NotImplemented },
58
+ # add constraint
59
+ 'AddConstraint' => -> (_node) { ['ADD'] },
60
+ # internal to commands/tablecmds.c
61
+ 'AddConstraintRecurse' => -> (_node) { NotImplemented },
62
+ # internal to commands/tablecmds.c
63
+ 'ReAddConstraint' => -> (_node) { NotImplemented },
64
+ # alter constraint
65
+ 'AlterConstraint' => -> (_node) { ['ALTER CONSTRAINT'] },
66
+ # validate constraint
67
+ 'ValidateConstraint' => -> (_node) { ['VALIDATE CONSTRAINT'] },
68
+ # internal to commands/tablecmds.c
69
+ 'ValidateConstraintRecurse' => -> (_node) { NotImplemented },
70
+ # pre-processed add constraint (local in parser/parse_utilcmd.c)
71
+ 'ProcessedConstraint' => -> (_node) { NotImplemented },
72
+ # add constraint using existing index
73
+ 'AddIndexConstraint' => -> (_node) { NotImplemented },
74
+ # drop constraint
75
+ 'DropConstraint' => -> (_node) { ['DROP CONSTRAINT'] },
76
+ # internal to commands/tablecmds.c
77
+ 'DropConstraintRecurse' => -> (_node) { NotImplemented },
78
+ # alter column type
79
+ 'AlterColumnType' => -> (_node) { ['ALTER COLUMN', 'TYPE'] },
80
+ # alter column OPTIONS (...)
81
+ 'AlterColumnGenericOptions' => -> (_node) { ['ALTER COLUMN', 'OPTIONS'] },
82
+ # change owner
83
+ 'ChangeOwner' => -> (_node) { NotImplemented },
84
+ # CLUSTER ON
85
+ 'ClusterOn' => -> (_node) { NotImplemented },
86
+ # SET WITHOUT CLUSTER
87
+ 'DropCluster' => -> (_node) { NotImplemented },
88
+ # SET WITH OIDS
89
+ 'AddOids' => -> (_node) { NotImplemented },
90
+ # internal to commands/tablecmds.c
91
+ 'AddOidsRecurse' => -> (_node) { NotImplemented },
92
+ # SET WITHOUT OIDS
93
+ 'DropOids' => -> (_node) { NotImplemented },
94
+ # SET TABLESPACE
95
+ 'SetTableSpace' => -> (_node) { NotImplemented },
96
+ # SET (...) -- AM specific parameters
97
+ 'SetRelOptions' => -> (_node) { NotImplemented },
98
+ # RESET (...) -- AM specific parameters
99
+ 'ResetRelOptions' => -> (_node) { NotImplemented },
100
+ # replace reloption list in its entirety
101
+ 'ReplaceRelOptions' => -> (_node) { NotImplemented },
102
+ # ENABLE TRIGGER name
103
+ 'EnableTrig' => -> (_node) { NotImplemented },
104
+ # ENABLE ALWAYS TRIGGER name
105
+ 'EnableAlwaysTrig' => -> (_node) { NotImplemented },
106
+ # ENABLE REPLICA TRIGGER name
107
+ 'EnableReplicaTrig' => -> (_node) { NotImplemented },
108
+ # DISABLE TRIGGER name
109
+ 'DisableTrig' => -> (_node) { NotImplemented },
110
+ # ENABLE TRIGGER ALL
111
+ 'EnableTrigAll' => -> (_node) { NotImplemented },
112
+ # DISABLE TRIGGER ALL
113
+ 'DisableTrigAll' => -> (_node) { NotImplemented },
114
+ # ENABLE TRIGGER USER
115
+ 'EnableTrigUser' => -> (_node) { NotImplemented },
116
+ # DISABLE TRIGGER USER
117
+ 'DisableTrigUser' => -> (_node) { NotImplemented },
118
+ # ENABLE RULE name
119
+ 'EnableRule' => -> (_node) { NotImplemented },
120
+ # ENABLE ALWAYS RULE name
121
+ 'EnableAlwaysRule' => -> (_node) { NotImplemented },
122
+ # ENABLE REPLICA RULE name
123
+ 'EnableReplicaRule' => -> (_node) { NotImplemented },
124
+ # DISABLE RULE name
125
+ 'DisableRule' => -> (_node) { NotImplemented },
126
+ # INHERIT parent
127
+ 'AddInherit' => -> (_node) { NotImplemented },
128
+ # NO INHERIT parent
129
+ 'DropInherit' => -> (_node) { NotImplemented },
130
+ # OF <type_name>
131
+ 'AddOf' => -> (_node) { NotImplemented },
132
+ # NOT OF
133
+ 'DropOf' => -> (_node) { NotImplemented },
134
+ # REPLICA IDENTITY
135
+ 'ReplicaIdentity' => -> (_node) { NotImplemented },
136
+ # OPTIONS (...)
137
+ 'GenericOptions' => -> (_node) { NotImplemented }
138
+ }
139
+ # Relying on Ruby's hashes maintaining key sort order
140
+ ALTER_TABLE_COMMANDS = ALTER_TABLE.keys
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,105 @@
1
+ class PgQuery
2
+ module Deparse
3
+ module Interval
4
+ # A type called 'interval hour to minute' is stored in a compressed way by
5
+ # simplifying 'hour to minute' to a simple integer. This integer is computed
6
+ # by looking up the arbitrary number (always a power of two) for 'hour' and
7
+ # the one for 'minute' and XORing them together.
8
+ #
9
+ # For example, when parsing "interval hour to minute":
10
+ #
11
+ # HOUR_MASK = 10
12
+ # MINUTE_MASK = 11
13
+ # mask = (1 << 10) | (1 << 11)
14
+ # mask = 1024 | 2048
15
+ # mask = (010000000000
16
+ # xor
17
+ # 100000000000)
18
+ # mask = 110000000000
19
+ # mask = 3072
20
+ #
21
+ # Postgres will store this type as 'interval,3072'
22
+ # We deparse it by simply reversing that process.
23
+ #
24
+ def self.from_int(int)
25
+ SQL_BY_MASK[int]
26
+ end
27
+
28
+ # From src/include/utils/datetime.h
29
+ # The number is the power of 2 used for the mask.
30
+ MASKS = {
31
+ 0 => 'RESERV',
32
+ 1 => 'MONTH',
33
+ 2 => 'YEAR',
34
+ 3 => 'DAY',
35
+ 4 => 'JULIAN',
36
+ 5 => 'TZ',
37
+ 6 => 'DTZ',
38
+ 7 => 'DYNTZ',
39
+ 8 => 'IGNORE_DTF',
40
+ 9 => 'AMPM',
41
+ 10 => 'HOUR',
42
+ 11 => 'MINUTE',
43
+ 12 => 'SECOND',
44
+ 13 => 'MILLISECOND',
45
+ 14 => 'MICROSECOND',
46
+ 15 => 'DOY',
47
+ 16 => 'DOW',
48
+ 17 => 'UNITS',
49
+ 18 => 'ADBC',
50
+ 19 => 'AGO',
51
+ 20 => 'ABS_BEFORE',
52
+ 21 => 'ABS_AFTER',
53
+ 22 => 'ISODATE',
54
+ 23 => 'ISOTIME',
55
+ 24 => 'WEEK',
56
+ 25 => 'DECADE',
57
+ 26 => 'CENTURY',
58
+ 27 => 'MILLENNIUM',
59
+ 28 => 'DTZMOD'
60
+ }
61
+ KEYS = MASKS.invert
62
+
63
+ # Postgres stores the interval 'day second' as 'day hour minute second' so
64
+ # we need to reconstruct the sql with only the largest and smallest time
65
+ # values. Since the rules for this are hardcoded in the grammar (and the
66
+ # above list is not sorted in any sensible way) it makes sense to hardcode
67
+ # the patterns here, too.
68
+ #
69
+ # This hash takes the form:
70
+ #
71
+ # { (1 << 1) | (1 << 2) => 'year to month' }
72
+ #
73
+ # Which is:
74
+ #
75
+ # { 6 => 'year to month' }
76
+ #
77
+ SQL_BY_MASK = {
78
+ (1 << KEYS['YEAR']) => %w(year),
79
+ (1 << KEYS['MONTH']) => %w(month),
80
+ (1 << KEYS['DAY']) => %w(day),
81
+ (1 << KEYS['HOUR']) => %w(hour),
82
+ (1 << KEYS['MINUTE']) => %w(minute),
83
+ (1 << KEYS['SECOND']) => %w(second),
84
+ (1 << KEYS['YEAR'] |
85
+ 1 << KEYS['MONTH']) => %w(year month),
86
+ (1 << KEYS['DAY'] |
87
+ 1 << KEYS['HOUR']) => %w(day hour),
88
+ (1 << KEYS['DAY'] |
89
+ 1 << KEYS['HOUR'] |
90
+ 1 << KEYS['MINUTE']) => %w(day minute),
91
+ (1 << KEYS['DAY'] |
92
+ 1 << KEYS['HOUR'] |
93
+ 1 << KEYS['MINUTE'] |
94
+ 1 << KEYS['SECOND']) => %w(day second),
95
+ (1 << KEYS['HOUR'] |
96
+ 1 << KEYS['MINUTE']) => %w(hour minute),
97
+ (1 << KEYS['HOUR'] |
98
+ 1 << KEYS['MINUTE'] |
99
+ 1 << KEYS['SECOND']) => %w(hour second),
100
+ (1 << KEYS['MINUTE'] |
101
+ 1 << KEYS['SECOND']) => %w(minute second)
102
+ }
103
+ end
104
+ end
105
+ end
@@ -1,3 +1,3 @@
1
1
  class PgQuery
2
- VERSION = '0.6.3'
2
+ VERSION = '0.6.4'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_query
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.6.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lukas Fittl
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-21 00:00:00.000000000 Z
11
+ date: 2015-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -102,6 +102,8 @@ files:
102
102
  - ext/pg_query/pg_query_parse.c
103
103
  - lib/pg_query.rb
104
104
  - lib/pg_query/deparse.rb
105
+ - lib/pg_query/deparse/alter_table.rb
106
+ - lib/pg_query/deparse/interval.rb
105
107
  - lib/pg_query/filter_columns.rb
106
108
  - lib/pg_query/fingerprint.rb
107
109
  - lib/pg_query/param_refs.rb
@@ -134,9 +136,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
136
  version: '0'
135
137
  requirements: []
136
138
  rubyforge_project:
137
- rubygems_version: 2.4.5
139
+ rubygems_version: 2.4.5.1
138
140
  signing_key:
139
141
  specification_version: 4
140
142
  summary: PostgreSQL query parsing and normalization library
141
143
  test_files: []
142
- has_rdoc: