From 374c2978d99aa0c87dbf4e7f94e0ff7976234adb Mon Sep 17 00:00:00 2001 From: emin100 Date: Mon, 6 May 2019 09:04:18 +0300 Subject: [PATCH] Deparse ILIKE, COLLATE and DISCARD (#133) --- lib/pg_query/deparse.rb | 29 +++++++++++++++++++ lib/pg_query/node_types.rb | 2 ++ spec/lib/pg_query/deparse_spec.rb | 47 +++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/lib/pg_query/deparse.rb b/lib/pg_query/deparse.rb index b7d03766..dcfe3241 100644 --- a/lib/pg_query/deparse.rb +++ b/lib/pg_query/deparse.rb @@ -36,6 +36,8 @@ def deparse_item(item, context = nil) # rubocop:disable Metrics/CyclomaticComple deparse_aexpr_any(node) when AEXPR_IN deparse_aexpr_in(node) + when AEXPR_ILIKE + deparse_aexpr_ilike(node) when CONSTR_TYPE_FOREIGN deparse_aexpr_like(node) when AEXPR_BETWEEN, AEXPR_NOT_BETWEEN, AEXPR_BETWEEN_SYM, AEXPR_NOT_BETWEEN_SYM @@ -78,6 +80,8 @@ def deparse_item(item, context = nil) # rubocop:disable Metrics/CyclomaticComple deparse_case(node) when COALESCE_EXPR deparse_coalesce(node) + when COLLATE_CLAUSE + deparse_collate(node) when COLUMN_DEF deparse_columndef(node) when COLUMN_REF @@ -100,6 +104,8 @@ def deparse_item(item, context = nil) # rubocop:disable Metrics/CyclomaticComple deparse_defelem(node) when DELETE_STMT deparse_delete_from(node) + when DISCARD_STMT + deparse_discard(node) when DROP_STMT deparse_drop(node) when EXPLAIN_STMT @@ -356,6 +362,12 @@ def deparse_aexpr_like(node) format('%s %s %s', deparse_item(node['lexpr']), operator, value) end + def deparse_aexpr_ilike(node) + value = deparse_item(node['rexpr']) + operator = node['name'][0]['String']['str'] == '~~*' ? 'ILIKE' : 'NOT ILIKE' + format('%s %s %s', deparse_item(node['lexpr']), operator, value) + end + def deparse_bool_expr_not(node) format('NOT %s', deparse_item(node['args'][0])) end @@ -510,6 +522,14 @@ def deparse_sortby(node) output.join(' ') end + def deparse_collate(node) + output = [] + output << deparse_item(node['arg']) + output << 'COLLATE' + output << deparse_item_list(node['collname']) + output.join(' ') + end + def deparse_with_clause(node) output = ['WITH'] output << 'RECURSIVE' if node['recursive'] @@ -1085,6 +1105,15 @@ def deparse_delete_from(node) output.join(' ') end + def deparse_discard(node) + output = ['DISCARD'] + output << 'ALL' if (node['target']).zero? + output << 'PLANS' if node['target'] == 1 + output << 'SEQUENCES' if node['target'] == 2 + output << 'TEMP' if node['target'] == 3 + output.join(' ') + end + def deparse_drop(node) output = ['DROP'] output << 'TABLE' if node['removeType'] == OBJECT_TYPE_TABLE diff --git a/lib/pg_query/node_types.rb b/lib/pg_query/node_types.rb index 8508b56a..890eacf3 100644 --- a/lib/pg_query/node_types.rb +++ b/lib/pg_query/node_types.rb @@ -20,6 +20,7 @@ class PgQuery CHECK_POINT_STMT = 'CheckPointStmt'.freeze CLOSE_PORTAL_STMT = 'ClosePortalStmt'.freeze COALESCE_EXPR = 'CoalesceExpr'.freeze + COLLATE_CLAUSE = 'CollateClause'.freeze COLUMN_DEF = 'ColumnDef'.freeze COLUMN_REF = 'ColumnRef'.freeze COMMON_TABLE_EXPR = 'CommonTableExpr'.freeze @@ -34,6 +35,7 @@ class PgQuery DECLARE_CURSOR_STMT = 'DeclareCursorStmt'.freeze DEF_ELEM = 'DefElem'.freeze DELETE_STMT = 'DeleteStmt'.freeze + DISCARD_STMT = 'DiscardStmt'.freeze DO_STMT = 'DoStmt'.freeze DROP_STMT = 'DropStmt'.freeze EXECUTE_STMT = 'ExecuteStmt'.freeze diff --git a/spec/lib/pg_query/deparse_spec.rb b/spec/lib/pg_query/deparse_spec.rb index bf4dcb2f..fb8f8fb8 100644 --- a/spec/lib/pg_query/deparse_spec.rb +++ b/spec/lib/pg_query/deparse_spec.rb @@ -62,6 +62,18 @@ it { is_expected.to eq query } end + context 'ORDER BY with COLLATE' do + let(:query) { 'SELECT * FROM "a" ORDER BY "x" COLLATE "tr_TR" DESC NULLS LAST' } + + it { is_expected.to eq query } + end + + context 'text with COLLATE' do + let(:query) { "SELECT 'foo' COLLATE \"tr_TR\"" } + + it { is_expected.to eq query } + end + context 'with specific column alias' do let(:query) { "SELECT * FROM (VALUES ('anne', 'smith'), ('bob', 'jones'), ('joe', 'blow')) names(\"first\", \"last\")" } @@ -80,6 +92,18 @@ it { is_expected.to eq oneline_query } end + context 'with ILIKE filter' do + let(:query) { "SELECT * FROM \"users\" WHERE \"name\" ILIKE 'postgresql:%';" } + + it { is_expected.to eq oneline_query } + end + + context 'with NOT ILIKE filter' do + let(:query) { "SELECT * FROM \"users\" WHERE \"name\" NOT ILIKE 'postgresql:%';" } + + it { is_expected.to eq oneline_query } + end + context 'simple WITH statement' do let(:query) { 'WITH t AS (SELECT random() AS x FROM generate_series(1, 3)) SELECT * FROM "t"' } @@ -1131,6 +1155,29 @@ it { is_expected.to eq oneline_query } end end + + context 'DISCARD' do + context 'all' do + let(:query) { 'DISCARD ALL' } + + it { is_expected.to eq oneline_query } + end + context 'plans' do + let(:query) { 'DISCARD PLANS' } + + it { is_expected.to eq oneline_query } + end + context 'sequences' do + let(:query) { 'DISCARD SEQUENCES' } + + it { is_expected.to eq oneline_query } + end + context 'temp' do + let(:query) { 'DISCARD TEMP' } + + it { is_expected.to eq oneline_query } + end + end end describe '#deparse' do