pg_query 0.6.3 → 0.6.4

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 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: