Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ALL operator, UNION, EXCEPT, Renamed Columns and Empty Array problem, CREATE SCHEMA, CREATE CAST for deparsing #136

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 79 additions & 7 deletions lib/pg_query/deparse.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ def deparse_item(item, context = nil) # rubocop:disable Metrics/CyclomaticComple
case node['kind']
when AEXPR_OP
deparse_aexpr(node, context)
when AEXPR_OP_ALL
deparse_aexpr_all(node)
when AEXPR_OP_ANY
deparse_aexpr_any(node)
when AEXPR_IN
Expand Down Expand Up @@ -92,8 +94,12 @@ def deparse_item(item, context = nil) # rubocop:disable Metrics/CyclomaticComple
deparse_constraint(node)
when COPY_STMT
deparse_copy(node)
when CREATE_CAST_STMT
deparse_create_cast(node)
when CREATE_FUNCTION_STMT
deparse_create_function(node)
when CREATE_SCHEMA_STMT
deparse_create_schema(node)
when CREATE_STMT
deparse_create_table(node)
when CREATE_TABLE_AS_STMT
Expand Down Expand Up @@ -138,6 +144,8 @@ def deparse_item(item, context = nil) # rubocop:disable Metrics/CyclomaticComple
deparse_renamestmt(node)
when RES_TARGET
deparse_restarget(node, context)
when ROLE_SPEC
deparse_role_spec(node)
when ROW_EXPR
deparse_row(node)
when SELECT_STMT
Expand Down Expand Up @@ -229,9 +237,13 @@ def deparse_columnref(node)
end

def deparse_a_arrayexp(node)
'ARRAY[' + node['elements'].map do |element|
deparse_item(element)
end.join(', ') + ']'
output = 'ARRAY['
unless node['elements'].nil?
output << node['elements'].map do |element|
deparse_item(element)
end.join(', ')
end
output << ']'
end

def deparse_a_const(node)
Expand Down Expand Up @@ -259,7 +271,7 @@ def deparse_alias(node)
if node['colnames']
name + '(' + deparse_item_list(node['colnames']).join(', ') + ')'
else
name
format('"%s"', name) unless name.nil?
end
end

Expand Down Expand Up @@ -300,7 +312,7 @@ def deparse_paramref(node)

def deparse_restarget(node, context)
if context == :select
[deparse_item(node['val']), node['name']].compact.join(' AS ')
[deparse_item(node['val']), (format('"%s"', node['name']) unless node['name'].nil?)].compact.join(' AS ')
elsif context == :update
[node['name'], deparse_item(node['val'])].compact.join(' = ')
elsif node['val'].nil?
Expand Down Expand Up @@ -350,6 +362,13 @@ def deparse_functionparameter(node)
deparse_item(node['argType'])
end

def deparse_role_spec(node)
return 'CURRENT_USER' if node['roletype'] == 1
return 'SESSION_USER' if node['roletype'] == 2
return 'PUBLIC' if node['roletype'] == 3
format('"%s"', node['rolename'].gsub('"', '""'))
end

def deparse_aexpr_in(node)
rexpr = Array(node['rexpr']).map { |arg| deparse_item(arg) }
operator = node['name'].map { |n| deparse_item(n, :operator) } == ['='] ? 'IN' : 'NOT IN'
Expand Down Expand Up @@ -434,6 +453,13 @@ def deparse_aexpr_any(node)
output.join(' ' + deparse_item(node['name'][0], :operator) + ' ')
end

def deparse_aexpr_all(node)
output = []
output << deparse_item(node['lexpr'])
output << format('ALL(%s)', deparse_item(node['rexpr']))
output.join(' ' + deparse_item(node['name'][0], :operator) + ' ')
end

def deparse_aexpr_between(node)
between = case node['kind']
when AEXPR_BETWEEN
Expand Down Expand Up @@ -691,6 +717,26 @@ def deparse_copy(node)
output.join(' ')
end

def deparse_create_cast(node)
output = []
output << 'CREATE'
output << 'CAST'
output << format('(%s AS %s)', deparse_item(node['sourcetype']), deparse_item(node['targettype']))
output << if node['func']
function = node['func']['ObjectWithArgs']
name = deparse_item_list(function['objname']).join('.')
arguments = deparse_item_list(function['objargs']).join(', ')
format('WITH FUNCTION %s(%s)', name, arguments)
elsif node['inout']
'WITH INOUT'
else
'WITHOUT FUNCTION'
end
output << 'AS IMPLICIT' if (node['context']).zero?
output << 'AS ASSIGNMENT' if node['context'] == 1
output.join(' ')
end

def deparse_create_function(node)
output = []
output << 'CREATE'
Expand All @@ -708,6 +754,23 @@ def deparse_create_function(node)
output.join(' ')
end

def deparse_create_schema(node)
output = []
output << 'CREATE'

output << 'SCHEMA'

output << 'IF NOT EXISTS' if node['if_not_exists']

output << format('"%s"', node['schemaname']) if node.key?('schemaname')

output << format('AUTHORIZATION %s', deparse_item(node['authrole'])) if node.key?('authrole')

output << deparse_item_list(node['schemaElts']) if node.key?('schemaElts')

output.join(' ')
end

def deparse_create_table(node)
output = []
output << 'CREATE'
Expand Down Expand Up @@ -759,6 +822,8 @@ def deparse_when(node)
def deparse_sublink(node)
if node['subLinkType'] == SUBLINK_TYPE_ANY
format('%s IN (%s)', deparse_item(node['testexpr']), deparse_item(node['subselect']))
elsif node['subLinkType'] == SUBLINK_TYPE_ALL
format('%s %s ALL (%s)', deparse_item(node['testexpr']), deparse_item(node['operName'][0], :operator), deparse_item(node['subselect']))
elsif node['subLinkType'] == SUBLINK_TYPE_EXISTS
format('EXISTS(%s)', deparse_item(node['subselect']))
else
Expand All @@ -782,15 +847,22 @@ def deparse_row(node)
def deparse_select(node) # rubocop:disable Metrics/CyclomaticComplexity
output = []

output << deparse_item(node['withClause']) if node['withClause']

if node['op'] == 1
output << deparse_item(node['larg'])
output << 'UNION'
output << 'ALL' if node['all']
output << deparse_item(node['rarg'])
return output.join(' ')
output.join(' ')
end

output << deparse_item(node['withClause']) if node['withClause']
if node['op'] == 3
output << deparse_item(node['larg'])
output << 'EXCEPT'
output << deparse_item(node['rarg'])
output.join(' ')
end

if node[TARGET_LIST_FIELD]
output << 'SELECT'
Expand Down
1 change: 1 addition & 0 deletions lib/pg_query/node_types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class PgQuery
COMMON_TABLE_EXPR = 'CommonTableExpr'.freeze
CONSTRAINT = 'Constraint'.freeze
COPY_STMT = 'CopyStmt'.freeze
CREATE_CAST_STMT = 'CreateCastStmt'.freeze
CREATE_FUNCTION_STMT = 'CreateFunctionStmt'.freeze
CREATE_SCHEMA_STMT = 'CreateSchemaStmt'.freeze
CREATE_STMT = 'CreateStmt'.freeze
Expand Down
Loading