diff --git a/lib/pg_query.rb b/lib/pg_query.rb index ee2a683a..ac1346bf 100644 --- a/lib/pg_query.rb +++ b/lib/pg_query.rb @@ -1,16 +1,15 @@ require 'pg_query/version' require 'pg_query/parse_error' -require 'pg_query/parse_tree_pb' +require 'pg_query/pg_query_pb' require 'pg_query/pg_query' +require 'pg_query/constants' require 'pg_query/parse' require 'pg_query/treewalker' require 'pg_query/node_types' require 'pg_query/deep_dup' -require 'pg_query/legacy_parsetree' - require 'pg_query/filter_columns' require 'pg_query/fingerprint' require 'pg_query/param_refs' diff --git a/lib/pg_query/parse.rb b/lib/pg_query/parse.rb index 76377888..5177a9a5 100644 --- a/lib/pg_query/parse.rb +++ b/lib/pg_query/parse.rb @@ -1,13 +1,19 @@ -require 'json' +module PgQuery + class Node + def inspect + node ? format('', node, public_send(node).inspect) : '' + end + end +end module PgQuery def self.parse(query) - tree, stderr = _raw_parse(query) + result, stderr = parse_protobuf(query) begin - tree = JSON.parse(tree, max_nesting: 1000) - rescue JSON::ParserError - raise ParseError.new('Failed to parse JSON', __FILE__, __LINE__, -1) + result = PgQuery::ParseResult.decode(result) + rescue Google::Protobuf::ParseError + raise PgQuery::ParseError.new('Failed to parse tree', __FILE__, __LINE__, -1) end warnings = [] @@ -16,10 +22,10 @@ def self.parse(query) warnings << line.strip end - PgQuery::ParseResult.new(query, tree, warnings) + PgQuery::ParserResult.new(query, result, warnings) end - class ParseResult + class ParserResult attr_reader :query attr_reader :tree attr_reader :warnings @@ -71,134 +77,139 @@ def load_tables_and_aliases! # rubocop:disable Metrics/CyclomaticComplexity @cte_names = [] @aliases = {} - statements = @tree.dup + statements = @tree.stmts.dup.to_a.map { |s| s.stmt } from_clause_items = [] # types: select, dml, ddl subselect_items = [] loop do statement = statements.shift if statement - case statement.keys[0] - when RAW_STMT - statements << statement[RAW_STMT][STMT_FIELD] + case statement.node + when :list + statements += statement.list.items # The following statement types do not modify tables and are added to from_clause_items # (and subsequently @tables) - when SELECT_STMT - case statement[SELECT_STMT]['op'] - when 0 - (statement[SELECT_STMT][FROM_CLAUSE_FIELD] || []).each do |item| - if item[RANGE_SUBSELECT] - statements << item[RANGE_SUBSELECT]['subquery'] + when :select_stmt + subselect_items.concat(statement.select_stmt.target_list) + subselect_items << statement.select_stmt.where_clause if statement.select_stmt.where_clause + subselect_items.concat(statement.select_stmt.sort_clause.collect { |h| h.sort_by.node }) + subselect_items.concat(statement.select_stmt.group_clause) + subselect_items << statement.select_stmt.having_clause if statement.select_stmt.having_clause + + case statement.select_stmt.op + when :SETOP_NONE + (statement.select_stmt.from_clause || []).each do |item| + if item.node == :range_subselect + statements << item.range_subselect.subquery else from_clause_items << { item: item, type: :select } end end - when 1 - statements << statement[SELECT_STMT]['larg'] if statement[SELECT_STMT]['larg'] - statements << statement[SELECT_STMT]['rarg'] if statement[SELECT_STMT]['rarg'] + when :SETOP_UNION + statements << PgQuery::Node.new(select_stmt: statement.select_stmt.larg) if statement.select_stmt.larg + statements << PgQuery::Node.new(select_stmt: statement.select_stmt.rarg) if statement.select_stmt.rarg end - if (with_clause = statement[SELECT_STMT]['withClause']) - cte_statements, cte_names = statements_and_cte_names_for_with_clause(with_clause) + if statement.select_stmt.with_clause + cte_statements, cte_names = statements_and_cte_names_for_with_clause(statement.select_stmt.with_clause) @cte_names.concat(cte_names) statements.concat(cte_statements) end # The following statements modify the contents of a table - when INSERT_STMT, UPDATE_STMT, DELETE_STMT - value = statement.values[0] - from_clause_items << { item: value['relation'], type: :dml } - statements << value['selectStmt'] if value.key?('selectStmt') - statements << value['withClause'] if value.key?('withClause') + when :insert_stmt, :update_stmt, :delete_stmt + value = statement.public_send(statement.node) + from_clause_items << { item: PgQuery::Node.new(range_var: value.relation), type: :dml } + statements << value.select_stmt if statement.node == :insert_stmt && value.select_stmt + + subselect_items.concat(statement.update_stmt.target_list) if statement.node == :update_stmt + subselect_items << statement.update_stmt.where_clause if statement.node == :update_stmt && statement.update_stmt.where_clause + subselect_items << statement.delete_stmt.where_clause if statement.node == :delete_stmt && statement.delete_stmt.where_clause - if (with_clause = value['withClause']) - cte_statements, cte_names = statements_and_cte_names_for_with_clause(with_clause) + if value.with_clause + cte_statements, cte_names = statements_and_cte_names_for_with_clause(value.with_clause) @cte_names.concat(cte_names) statements.concat(cte_statements) end - when COPY_STMT - from_clause_items << { item: statement.values[0]['relation'], type: :dml } if statement.values[0]['relation'] - statements << statement.values[0]['query'] + when :copy_stmt + from_clause_items << { item: PgQuery::Node.new(range_var: statement.copy_stmt.relation), type: :dml } if statement.copy_stmt.relation + statements << statement.copy_stmt.query # The following statement types are DDL (changing table structure) - when ALTER_TABLE_STMT, CREATE_STMT - from_clause_items << { item: statement.values[0]['relation'], type: :ddl } - when CREATE_TABLE_AS_STMT - if statement[CREATE_TABLE_AS_STMT]['into'] && statement[CREATE_TABLE_AS_STMT]['into'][INTO_CLAUSE]['rel'] - from_clause_items << { item: statement[CREATE_TABLE_AS_STMT]['into'][INTO_CLAUSE]['rel'], type: :ddl } + when :alter_table_stmt + from_clause_items << { item: PgQuery::Node.new(range_var: statement.alter_table_stmt.relation), type: :ddl } + when :create_stmt + from_clause_items << { item: PgQuery::Node.new(range_var: statement.create_stmt.relation), type: :ddl } + when :create_table_as_stmt + if statement.create_table_as_stmt.into && statement.create_table_as_stmt.into.rel + from_clause_items << { item: PgQuery::Node.new(range_var: statement.create_table_as_stmt.into.rel), type: :ddl } end - if statement[CREATE_TABLE_AS_STMT]['query'] - statements << statement[CREATE_TABLE_AS_STMT]['query'] - end - when TRUNCATE_STMT - from_clause_items += statement.values[0]['relations'].map { |r| { item: r, type: :ddl } } - when VIEW_STMT - from_clause_items << { item: statement[VIEW_STMT]['view'], type: :ddl } - statements << statement[VIEW_STMT]['query'] - when INDEX_STMT, CREATE_TRIG_STMT, RULE_STMT - from_clause_items << { item: statement.values[0]['relation'], type: :ddl } - when VACUUM_STMT - from_clause_items += statement.values[0]['rels'].map { |r| { item: r[VACUUM_RELATION]['relation'], type: :ddl } } - when REFRESH_MAT_VIEW_STMT - from_clause_items << { item: statement[REFRESH_MAT_VIEW_STMT]['relation'], type: :ddl } - when DROP_STMT - objects = statement[DROP_STMT]['objects'].map do |obj| - if obj.is_a?(Array) - obj.map { |obj2| obj2['String'] && obj2['String']['str'] } - else - obj['String'] && obj['String']['str'] + statements << statement.create_table_as_stmt.query if statement.create_table_as_stmt.query + when :truncate_stmt + from_clause_items += statement.truncate_stmt.relations.map { |r| { item: r, type: :ddl } } + when :view_stmt + from_clause_items << { item: PgQuery::Node.new(range_var: statement.view_stmt.view), type: :ddl } + statements << statement.view_stmt.query + when :index_stmt + from_clause_items << { item: PgQuery::Node.new(range_var: statement.index_stmt.relation), type: :ddl } + when :create_trig_stmt + from_clause_items << { item: PgQuery::Node.new(range_var: statement.create_trig_stmt.relation), type: :ddl } + when :rule_stmt + from_clause_items << { item: PgQuery::Node.new(range_var: statement.rule_stmt.relation), type: :ddl } + when :vacuum_stmt + from_clause_items += statement.vacuum_stmt.rels.map { |r| { item: PgQuery::Node.new(range_var: r.vacuum_relation.relation), type: :ddl } if r.node == :vacuum_relation } + when :refresh_mat_view_stmt + from_clause_items << { item: PgQuery::Node.new(range_var: statement.refresh_mat_view_stmt.relation), type: :ddl } + when :drop_stmt + objects = statement.drop_stmt.objects.map do |obj| + case obj.node + when :list + obj.list.items.map { |obj2| obj2.string.str if obj2.node == :string } + when :string + obj.string.str end end - case statement[DROP_STMT]['removeType'] - when OBJECT_TYPE_TABLE + case statement.drop_stmt.remove_type + when :OBJECT_TABLE @tables += objects.map { |r| { name: r.join('.'), type: :ddl } } - when OBJECT_TYPE_RULE, OBJECT_TYPE_TRIGGER + when :OBJECT_RULE, :OBJECT_TRIGGER @tables += objects.map { |r| { name: r[0..-2].join('.'), type: :ddl } } end - when GRANT_STMT - objects = statement[GRANT_STMT]['objects'] - case statement[GRANT_STMT]['objtype'] - when OBJECT_TYPE_COLUMN # Column # rubocop:disable Lint/EmptyWhen + when :grant_stmt + objects = statement.grant_stmt.objects + case statement.grant_stmt.objtype + when :OBJECT_COLUMN # Column # rubocop:disable Lint/EmptyWhen # FIXME - when OBJECT_TYPE_TABLE # Table + when :OBJECT_TABLE # Table from_clause_items += objects.map { |o| { item: o, type: :ddl } } - when OBJECT_TYPE_SEQUENCE # Sequence # rubocop:disable Lint/EmptyWhen + when :OBJECT_SEQUENCE # Sequence # rubocop:disable Lint/EmptyWhen # FIXME end - when LOCK_STMT - from_clause_items += statement.values[0]['relations'].map { |r| { item: r, type: :ddl } } + when :lock_stmt + from_clause_items += statement.lock_stmt.relations.map { |r| { item: r, type: :ddl } } # The following are other statements that don't fit into query/DML/DDL - when EXPLAIN_STMT - statements << statement[EXPLAIN_STMT]['query'] - end - - statement_value = statement.values[0] - unless statement.empty? - subselect_items.concat(statement_value['targetList']) if statement_value['targetList'] - subselect_items << statement_value['whereClause'] if statement_value['whereClause'] - subselect_items.concat(statement_value['sortClause'].collect { |h| h[SORT_BY]['node'] }) if statement_value['sortClause'] - subselect_items.concat(statement_value['groupClause']) if statement_value['groupClause'] - subselect_items << statement_value['havingClause'] if statement_value['havingClause'] + when :explain_stmt + statements << statement.explain_stmt.query end end next_item = subselect_items.shift if next_item - case next_item.keys[0] - when A_EXPR + case next_item.node + when :a_expr %w[lexpr rexpr].each do |side| - elem = next_item.values[0][side] + elem = next_item.a_expr.public_send(side) next unless elem - if elem.is_a?(Array) + if elem.is_a?(Array) # FIXME - this needs to traverse a list subselect_items += elem else subselect_items << elem end end - when BOOL_EXPR - subselect_items.concat(next_item.values[0]['args']) - when RES_TARGET - subselect_items << next_item[RES_TARGET]['val'] - when SUB_LINK - statements << next_item[SUB_LINK]['subselect'] + when :bool_expr + subselect_items.concat(next_item.bool_expr.args) + when :res_target + subselect_items << next_item.res_target.val + when :sub_link + statements << next_item.sub_link.subselect end end @@ -209,31 +220,30 @@ def load_tables_and_aliases! # rubocop:disable Metrics/CyclomaticComplexity next_item = from_clause_items.shift break unless next_item && next_item[:item] - case next_item[:item].keys[0] - when JOIN_EXPR - %w[larg rarg].each do |side| - from_clause_items << { item: next_item[:item][JOIN_EXPR][side], type: next_item[:type] } - end - when ROW_EXPR - from_clause_items += next_item[:item][ROW_EXPR]['args'].map { |a| { item: a, type: next_item[:type] } } - when RANGE_VAR - rangevar = next_item[:item][RANGE_VAR] - next if !rangevar['schemaname'] && @cte_names.include?(rangevar['relname']) + case next_item[:item].node + when :join_expr + from_clause_items << { item: next_item[:item].join_expr.larg, type: next_item[:type] } + from_clause_items << { item: next_item[:item].join_expr.rarg, type: next_item[:type] } + when :row_expr + from_clause_items += next_item[:item].row_expr.args.map { |a| { item: a, type: next_item[:type] } } + when :range_var + rangevar = next_item[:item].range_var + next if rangevar.schemaname.empty? && @cte_names.include?(rangevar.relname) - table = [rangevar['schemaname'], rangevar['relname']].compact.join('.') + table = [rangevar.schemaname, rangevar.relname].reject { |s| s.nil? || s.empty? }.join('.') @tables << { name: table, type: next_item[:type], - location: rangevar['location'], - schemaname: rangevar['schemaname'], - relname: rangevar['relname'], - inh: rangevar['inh'] + location: rangevar.location, + schemaname: (rangevar.schemaname if !rangevar.schemaname.empty?), + relname: rangevar.relname, + inh: rangevar.inh } - @aliases[rangevar['alias'][ALIAS]['aliasname']] = table if rangevar['alias'] - when RANGE_SUBSELECT - from_clause_items << { item: next_item[:item][RANGE_SUBSELECT]['subquery'], type: next_item[:type] } - when SELECT_STMT - from_clause = next_item[:item][SELECT_STMT][FROM_CLAUSE_FIELD] + @aliases[rangevar.alias.aliasname] = table if rangevar.alias + when :range_subselect + from_clause_items << { item: next_item[:item].range_subselect.subquery, type: next_item[:type] } + when :select_stmt + from_clause = next_item[:item].select_stmt.from_clause from_clause_items += from_clause.map { |r| { item: r, type: next_item[:type] } } if from_clause end end @@ -242,17 +252,17 @@ def load_tables_and_aliases! # rubocop:disable Metrics/CyclomaticComplexity @cte_names.uniq! end - def statements_and_cte_names_for_with_clause(with_clause) + def statements_and_cte_names_for_with_clause(with_clause) # FIXME statements = [] cte_names = [] - with_clause[WITH_CLAUSE]['ctes'].each do |item| - next unless item[COMMON_TABLE_EXPR] - cte_names << item[COMMON_TABLE_EXPR]['ctename'] - statements << item[COMMON_TABLE_EXPR]['ctequery'] + with_clause.ctes.each do |item| + next unless item.node == :common_table_expr + cte_names << item.common_table_expr.ctename + statements << item.common_table_expr.ctequery end [statements, cte_names] end end -end \ No newline at end of file +end diff --git a/lib/pg_query/parse_tree_pb.rb b/lib/pg_query/pg_query_pb.rb similarity index 80% rename from lib/pg_query/parse_tree_pb.rb rename to lib/pg_query/pg_query_pb.rb index ebd253fd..7375b03a 100644 --- a/lib/pg_query/parse_tree_pb.rb +++ b/lib/pg_query/pg_query_pb.rb @@ -1,10 +1,18 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! -# source: parse_tree.proto +# source: pg_query.proto require 'google/protobuf' Google::Protobuf::DescriptorPool.generated_pool.build do - add_file("parse_tree.proto", :syntax => :proto3) do + add_file("pg_query.proto", :syntax => :proto3) do + add_message "pg_query.ParseResult" do + optional :version, :int32, 1 + repeated :stmts, :message, 2, "pg_query.RawStmt" + end + add_message "pg_query.ScanResult" do + optional :version, :int32, 1 + repeated :tokens, :message, 2, "pg_query.ScanToken" + end add_message "pg_query.Node" do oneof :node do optional :alias, :message, 1, "pg_query.Alias" @@ -284,8 +292,9 @@ repeated :colcollations, :message, 8, "pg_query.Node" repeated :colexprs, :message, 9, "pg_query.Node" repeated :coldefexprs, :message, 10, "pg_query.Node" - optional :ordinalitycol, :int32, 11 - optional :location, :int32, 12 + repeated :notnulls, :uint64, 11 + optional :ordinalitycol, :int32, 12 + optional :location, :int32, 13 end add_message "pg_query.Expr" do end @@ -1669,7 +1678,11 @@ optional :in_from_cl, :bool, 29 optional :required_perms, :uint32, 30 optional :check_as_user, :uint32, 31 - repeated :security_quals, :message, 32, "pg_query.Node" + repeated :selected_cols, :uint64, 32 + repeated :inserted_cols, :uint64, 33 + repeated :updated_cols, :uint64, 34 + repeated :extra_updated_cols, :uint64, 35 + repeated :security_quals, :message, 36, "pg_query.Node" end add_message "pg_query.RangeTblFunction" do optional :funcexpr, :message, 1, "pg_query.Node" @@ -1678,6 +1691,7 @@ repeated :funccoltypes, :message, 4, "pg_query.Node" repeated :funccoltypmods, :message, 5, "pg_query.Node" repeated :funccolcollations, :message, 6, "pg_query.Node" + repeated :funcparams, :uint64, 7 end add_message "pg_query.TableSampleClause" do optional :tsmhandler, :uint32, 1 @@ -1849,494 +1863,1064 @@ add_message "pg_query.CallContext" do optional :atomic, :bool, 1 end + add_message "pg_query.ScanToken" do + optional :start, :int32, 1 + optional :end, :int32, 2 + optional :token, :enum, 4, "pg_query.Token" + optional :keyword_kind, :enum, 5, "pg_query.KeywordKind" + end add_enum "pg_query.OverridingKind" do - value :OVERRIDING_NOT_SET, 0 - value :OVERRIDING_USER_VALUE, 1 - value :OVERRIDING_SYSTEM_VALUE, 2 + value :OVERRIDING_KIND_UNDEFINED, 0 + value :OVERRIDING_NOT_SET, 1 + value :OVERRIDING_USER_VALUE, 2 + value :OVERRIDING_SYSTEM_VALUE, 3 end add_enum "pg_query.QuerySource" do - value :QSRC_ORIGINAL, 0 - value :QSRC_PARSER, 1 - value :QSRC_INSTEAD_RULE, 2 - value :QSRC_QUAL_INSTEAD_RULE, 3 - value :QSRC_NON_INSTEAD_RULE, 4 + value :QUERY_SOURCE_UNDEFINED, 0 + value :QSRC_ORIGINAL, 1 + value :QSRC_PARSER, 2 + value :QSRC_INSTEAD_RULE, 3 + value :QSRC_QUAL_INSTEAD_RULE, 4 + value :QSRC_NON_INSTEAD_RULE, 5 end add_enum "pg_query.SortByDir" do - value :SORTBY_DEFAULT, 0 - value :SORTBY_ASC, 1 - value :SORTBY_DESC, 2 - value :SORTBY_USING, 3 + value :SORT_BY_DIR_UNDEFINED, 0 + value :SORTBY_DEFAULT, 1 + value :SORTBY_ASC, 2 + value :SORTBY_DESC, 3 + value :SORTBY_USING, 4 end add_enum "pg_query.SortByNulls" do - value :SORTBY_NULLS_DEFAULT, 0 - value :SORTBY_NULLS_FIRST, 1 - value :SORTBY_NULLS_LAST, 2 + value :SORT_BY_NULLS_UNDEFINED, 0 + value :SORTBY_NULLS_DEFAULT, 1 + value :SORTBY_NULLS_FIRST, 2 + value :SORTBY_NULLS_LAST, 3 end add_enum "pg_query.A_Expr_Kind" do - value :AEXPR_OP, 0 - value :AEXPR_OP_ANY, 1 - value :AEXPR_OP_ALL, 2 - value :AEXPR_DISTINCT, 3 - value :AEXPR_NOT_DISTINCT, 4 - value :AEXPR_NULLIF, 5 - value :AEXPR_OF, 6 - value :AEXPR_IN, 7 - value :AEXPR_LIKE, 8 - value :AEXPR_ILIKE, 9 - value :AEXPR_SIMILAR, 10 - value :AEXPR_BETWEEN, 11 - value :AEXPR_NOT_BETWEEN, 12 - value :AEXPR_BETWEEN_SYM, 13 - value :AEXPR_NOT_BETWEEN_SYM, 14 - value :AEXPR_PAREN, 15 + value :A_EXPR_KIND_UNDEFINED, 0 + value :AEXPR_OP, 1 + value :AEXPR_OP_ANY, 2 + value :AEXPR_OP_ALL, 3 + value :AEXPR_DISTINCT, 4 + value :AEXPR_NOT_DISTINCT, 5 + value :AEXPR_NULLIF, 6 + value :AEXPR_OF, 7 + value :AEXPR_IN, 8 + value :AEXPR_LIKE, 9 + value :AEXPR_ILIKE, 10 + value :AEXPR_SIMILAR, 11 + value :AEXPR_BETWEEN, 12 + value :AEXPR_NOT_BETWEEN, 13 + value :AEXPR_BETWEEN_SYM, 14 + value :AEXPR_NOT_BETWEEN_SYM, 15 + value :AEXPR_PAREN, 16 end add_enum "pg_query.RoleSpecType" do - value :ROLESPEC_CSTRING, 0 - value :ROLESPEC_CURRENT_USER, 1 - value :ROLESPEC_SESSION_USER, 2 - value :ROLESPEC_PUBLIC, 3 + value :ROLE_SPEC_TYPE_UNDEFINED, 0 + value :ROLESPEC_CSTRING, 1 + value :ROLESPEC_CURRENT_USER, 2 + value :ROLESPEC_SESSION_USER, 3 + value :ROLESPEC_PUBLIC, 4 end add_enum "pg_query.TableLikeOption" do - value :CREATE_TABLE_LIKE_COMMENTS, 0 - value :CREATE_TABLE_LIKE_CONSTRAINTS, 1 - value :CREATE_TABLE_LIKE_DEFAULTS, 2 - value :CREATE_TABLE_LIKE_GENERATED, 3 - value :CREATE_TABLE_LIKE_IDENTITY, 4 - value :CREATE_TABLE_LIKE_INDEXES, 5 - value :CREATE_TABLE_LIKE_STATISTICS, 6 - value :CREATE_TABLE_LIKE_STORAGE, 7 - value :CREATE_TABLE_LIKE_ALL, 8 + value :TABLE_LIKE_OPTION_UNDEFINED, 0 + value :CREATE_TABLE_LIKE_COMMENTS, 1 + value :CREATE_TABLE_LIKE_CONSTRAINTS, 2 + value :CREATE_TABLE_LIKE_DEFAULTS, 3 + value :CREATE_TABLE_LIKE_GENERATED, 4 + value :CREATE_TABLE_LIKE_IDENTITY, 5 + value :CREATE_TABLE_LIKE_INDEXES, 6 + value :CREATE_TABLE_LIKE_STATISTICS, 7 + value :CREATE_TABLE_LIKE_STORAGE, 8 + value :CREATE_TABLE_LIKE_ALL, 9 end add_enum "pg_query.DefElemAction" do - value :DEFELEM_UNSPEC, 0 - value :DEFELEM_SET, 1 - value :DEFELEM_ADD, 2 - value :DEFELEM_DROP, 3 + value :DEF_ELEM_ACTION_UNDEFINED, 0 + value :DEFELEM_UNSPEC, 1 + value :DEFELEM_SET, 2 + value :DEFELEM_ADD, 3 + value :DEFELEM_DROP, 4 end add_enum "pg_query.PartitionRangeDatumKind" do - value :PARTITION_RANGE_DATUM_MINVALUE, 0 - value :PARTITION_RANGE_DATUM_VALUE, 1 - value :PARTITION_RANGE_DATUM_MAXVALUE, 2 + value :PARTITION_RANGE_DATUM_KIND_UNDEFINED, 0 + value :PARTITION_RANGE_DATUM_MINVALUE, 1 + value :PARTITION_RANGE_DATUM_VALUE, 2 + value :PARTITION_RANGE_DATUM_MAXVALUE, 3 end add_enum "pg_query.RTEKind" do - value :RTE_RELATION, 0 - value :RTE_SUBQUERY, 1 - value :RTE_JOIN, 2 - value :RTE_FUNCTION, 3 - value :RTE_TABLEFUNC, 4 - value :RTE_VALUES, 5 - value :RTE_CTE, 6 - value :RTE_NAMEDTUPLESTORE, 7 - value :RTE_RESULT, 8 + value :RTEKIND_UNDEFINED, 0 + value :RTE_RELATION, 1 + value :RTE_SUBQUERY, 2 + value :RTE_JOIN, 3 + value :RTE_FUNCTION, 4 + value :RTE_TABLEFUNC, 5 + value :RTE_VALUES, 6 + value :RTE_CTE, 7 + value :RTE_NAMEDTUPLESTORE, 8 + value :RTE_RESULT, 9 end add_enum "pg_query.WCOKind" do - value :WCO_VIEW_CHECK, 0 - value :WCO_RLS_INSERT_CHECK, 1 - value :WCO_RLS_UPDATE_CHECK, 2 - value :WCO_RLS_CONFLICT_CHECK, 3 + value :WCOKIND_UNDEFINED, 0 + value :WCO_VIEW_CHECK, 1 + value :WCO_RLS_INSERT_CHECK, 2 + value :WCO_RLS_UPDATE_CHECK, 3 + value :WCO_RLS_CONFLICT_CHECK, 4 end add_enum "pg_query.GroupingSetKind" do - value :GROUPING_SET_EMPTY, 0 - value :GROUPING_SET_SIMPLE, 1 - value :GROUPING_SET_ROLLUP, 2 - value :GROUPING_SET_CUBE, 3 - value :GROUPING_SET_SETS, 4 + value :GROUPING_SET_KIND_UNDEFINED, 0 + value :GROUPING_SET_EMPTY, 1 + value :GROUPING_SET_SIMPLE, 2 + value :GROUPING_SET_ROLLUP, 3 + value :GROUPING_SET_CUBE, 4 + value :GROUPING_SET_SETS, 5 end add_enum "pg_query.CTEMaterialize" do - value :CTEMaterializeDefault, 0 - value :CTEMaterializeAlways, 1 - value :CTEMaterializeNever, 2 + value :CTEMATERIALIZE_UNDEFINED, 0 + value :CTEMaterializeDefault, 1 + value :CTEMaterializeAlways, 2 + value :CTEMaterializeNever, 3 end add_enum "pg_query.SetOperation" do - value :SETOP_NONE, 0 - value :SETOP_UNION, 1 - value :SETOP_INTERSECT, 2 - value :SETOP_EXCEPT, 3 + value :SET_OPERATION_UNDEFINED, 0 + value :SETOP_NONE, 1 + value :SETOP_UNION, 2 + value :SETOP_INTERSECT, 3 + value :SETOP_EXCEPT, 4 end add_enum "pg_query.ObjectType" do - value :OBJECT_ACCESS_METHOD, 0 - value :OBJECT_AGGREGATE, 1 - value :OBJECT_AMOP, 2 - value :OBJECT_AMPROC, 3 - value :OBJECT_ATTRIBUTE, 4 - value :OBJECT_CAST, 5 - value :OBJECT_COLUMN, 6 - value :OBJECT_COLLATION, 7 - value :OBJECT_CONVERSION, 8 - value :OBJECT_DATABASE, 9 - value :OBJECT_DEFAULT, 10 - value :OBJECT_DEFACL, 11 - value :OBJECT_DOMAIN, 12 - value :OBJECT_DOMCONSTRAINT, 13 - value :OBJECT_EVENT_TRIGGER, 14 - value :OBJECT_EXTENSION, 15 - value :OBJECT_FDW, 16 - value :OBJECT_FOREIGN_SERVER, 17 - value :OBJECT_FOREIGN_TABLE, 18 - value :OBJECT_FUNCTION, 19 - value :OBJECT_INDEX, 20 - value :OBJECT_LANGUAGE, 21 - value :OBJECT_LARGEOBJECT, 22 - value :OBJECT_MATVIEW, 23 - value :OBJECT_OPCLASS, 24 - value :OBJECT_OPERATOR, 25 - value :OBJECT_OPFAMILY, 26 - value :OBJECT_POLICY, 27 - value :OBJECT_PROCEDURE, 28 - value :OBJECT_PUBLICATION, 29 - value :OBJECT_PUBLICATION_REL, 30 - value :OBJECT_ROLE, 31 - value :OBJECT_ROUTINE, 32 - value :OBJECT_RULE, 33 - value :OBJECT_SCHEMA, 34 - value :OBJECT_SEQUENCE, 35 - value :OBJECT_SUBSCRIPTION, 36 - value :OBJECT_STATISTIC_EXT, 37 - value :OBJECT_TABCONSTRAINT, 38 - value :OBJECT_TABLE, 39 - value :OBJECT_TABLESPACE, 40 - value :OBJECT_TRANSFORM, 41 - value :OBJECT_TRIGGER, 42 - value :OBJECT_TSCONFIGURATION, 43 - value :OBJECT_TSDICTIONARY, 44 - value :OBJECT_TSPARSER, 45 - value :OBJECT_TSTEMPLATE, 46 - value :OBJECT_TYPE, 47 - value :OBJECT_USER_MAPPING, 48 - value :OBJECT_VIEW, 49 + value :OBJECT_TYPE_UNDEFINED, 0 + value :OBJECT_ACCESS_METHOD, 1 + value :OBJECT_AGGREGATE, 2 + value :OBJECT_AMOP, 3 + value :OBJECT_AMPROC, 4 + value :OBJECT_ATTRIBUTE, 5 + value :OBJECT_CAST, 6 + value :OBJECT_COLUMN, 7 + value :OBJECT_COLLATION, 8 + value :OBJECT_CONVERSION, 9 + value :OBJECT_DATABASE, 10 + value :OBJECT_DEFAULT, 11 + value :OBJECT_DEFACL, 12 + value :OBJECT_DOMAIN, 13 + value :OBJECT_DOMCONSTRAINT, 14 + value :OBJECT_EVENT_TRIGGER, 15 + value :OBJECT_EXTENSION, 16 + value :OBJECT_FDW, 17 + value :OBJECT_FOREIGN_SERVER, 18 + value :OBJECT_FOREIGN_TABLE, 19 + value :OBJECT_FUNCTION, 20 + value :OBJECT_INDEX, 21 + value :OBJECT_LANGUAGE, 22 + value :OBJECT_LARGEOBJECT, 23 + value :OBJECT_MATVIEW, 24 + value :OBJECT_OPCLASS, 25 + value :OBJECT_OPERATOR, 26 + value :OBJECT_OPFAMILY, 27 + value :OBJECT_POLICY, 28 + value :OBJECT_PROCEDURE, 29 + value :OBJECT_PUBLICATION, 30 + value :OBJECT_PUBLICATION_REL, 31 + value :OBJECT_ROLE, 32 + value :OBJECT_ROUTINE, 33 + value :OBJECT_RULE, 34 + value :OBJECT_SCHEMA, 35 + value :OBJECT_SEQUENCE, 36 + value :OBJECT_SUBSCRIPTION, 37 + value :OBJECT_STATISTIC_EXT, 38 + value :OBJECT_TABCONSTRAINT, 39 + value :OBJECT_TABLE, 40 + value :OBJECT_TABLESPACE, 41 + value :OBJECT_TRANSFORM, 42 + value :OBJECT_TRIGGER, 43 + value :OBJECT_TSCONFIGURATION, 44 + value :OBJECT_TSDICTIONARY, 45 + value :OBJECT_TSPARSER, 46 + value :OBJECT_TSTEMPLATE, 47 + value :OBJECT_TYPE, 48 + value :OBJECT_USER_MAPPING, 49 + value :OBJECT_VIEW, 50 end add_enum "pg_query.DropBehavior" do - value :DROP_RESTRICT, 0 - value :DROP_CASCADE, 1 + value :DROP_BEHAVIOR_UNDEFINED, 0 + value :DROP_RESTRICT, 1 + value :DROP_CASCADE, 2 end add_enum "pg_query.AlterTableType" do - value :AT_AddColumn, 0 - value :AT_AddColumnRecurse, 1 - value :AT_AddColumnToView, 2 - value :AT_ColumnDefault, 3 - value :AT_CookedColumnDefault, 4 - value :AT_DropNotNull, 5 - value :AT_SetNotNull, 6 - value :AT_DropExpression, 7 - value :AT_CheckNotNull, 8 - value :AT_SetStatistics, 9 - value :AT_SetOptions, 10 - value :AT_ResetOptions, 11 - value :AT_SetStorage, 12 - value :AT_DropColumn, 13 - value :AT_DropColumnRecurse, 14 - value :AT_AddIndex, 15 - value :AT_ReAddIndex, 16 - value :AT_AddConstraint, 17 - value :AT_AddConstraintRecurse, 18 - value :AT_ReAddConstraint, 19 - value :AT_ReAddDomainConstraint, 20 - value :AT_AlterConstraint, 21 - value :AT_ValidateConstraint, 22 - value :AT_ValidateConstraintRecurse, 23 - value :AT_AddIndexConstraint, 24 - value :AT_DropConstraint, 25 - value :AT_DropConstraintRecurse, 26 - value :AT_ReAddComment, 27 - value :AT_AlterColumnType, 28 - value :AT_AlterColumnGenericOptions, 29 - value :AT_ChangeOwner, 30 - value :AT_ClusterOn, 31 - value :AT_DropCluster, 32 - value :AT_SetLogged, 33 - value :AT_SetUnLogged, 34 - value :AT_DropOids, 35 - value :AT_SetTableSpace, 36 - value :AT_SetRelOptions, 37 - value :AT_ResetRelOptions, 38 - value :AT_ReplaceRelOptions, 39 - value :AT_EnableTrig, 40 - value :AT_EnableAlwaysTrig, 41 - value :AT_EnableReplicaTrig, 42 - value :AT_DisableTrig, 43 - value :AT_EnableTrigAll, 44 - value :AT_DisableTrigAll, 45 - value :AT_EnableTrigUser, 46 - value :AT_DisableTrigUser, 47 - value :AT_EnableRule, 48 - value :AT_EnableAlwaysRule, 49 - value :AT_EnableReplicaRule, 50 - value :AT_DisableRule, 51 - value :AT_AddInherit, 52 - value :AT_DropInherit, 53 - value :AT_AddOf, 54 - value :AT_DropOf, 55 - value :AT_ReplicaIdentity, 56 - value :AT_EnableRowSecurity, 57 - value :AT_DisableRowSecurity, 58 - value :AT_ForceRowSecurity, 59 - value :AT_NoForceRowSecurity, 60 - value :AT_GenericOptions, 61 - value :AT_AttachPartition, 62 - value :AT_DetachPartition, 63 - value :AT_AddIdentity, 64 - value :AT_SetIdentity, 65 - value :AT_DropIdentity, 66 + value :ALTER_TABLE_TYPE_UNDEFINED, 0 + value :AT_AddColumn, 1 + value :AT_AddColumnRecurse, 2 + value :AT_AddColumnToView, 3 + value :AT_ColumnDefault, 4 + value :AT_CookedColumnDefault, 5 + value :AT_DropNotNull, 6 + value :AT_SetNotNull, 7 + value :AT_DropExpression, 8 + value :AT_CheckNotNull, 9 + value :AT_SetStatistics, 10 + value :AT_SetOptions, 11 + value :AT_ResetOptions, 12 + value :AT_SetStorage, 13 + value :AT_DropColumn, 14 + value :AT_DropColumnRecurse, 15 + value :AT_AddIndex, 16 + value :AT_ReAddIndex, 17 + value :AT_AddConstraint, 18 + value :AT_AddConstraintRecurse, 19 + value :AT_ReAddConstraint, 20 + value :AT_ReAddDomainConstraint, 21 + value :AT_AlterConstraint, 22 + value :AT_ValidateConstraint, 23 + value :AT_ValidateConstraintRecurse, 24 + value :AT_AddIndexConstraint, 25 + value :AT_DropConstraint, 26 + value :AT_DropConstraintRecurse, 27 + value :AT_ReAddComment, 28 + value :AT_AlterColumnType, 29 + value :AT_AlterColumnGenericOptions, 30 + value :AT_ChangeOwner, 31 + value :AT_ClusterOn, 32 + value :AT_DropCluster, 33 + value :AT_SetLogged, 34 + value :AT_SetUnLogged, 35 + value :AT_DropOids, 36 + value :AT_SetTableSpace, 37 + value :AT_SetRelOptions, 38 + value :AT_ResetRelOptions, 39 + value :AT_ReplaceRelOptions, 40 + value :AT_EnableTrig, 41 + value :AT_EnableAlwaysTrig, 42 + value :AT_EnableReplicaTrig, 43 + value :AT_DisableTrig, 44 + value :AT_EnableTrigAll, 45 + value :AT_DisableTrigAll, 46 + value :AT_EnableTrigUser, 47 + value :AT_DisableTrigUser, 48 + value :AT_EnableRule, 49 + value :AT_EnableAlwaysRule, 50 + value :AT_EnableReplicaRule, 51 + value :AT_DisableRule, 52 + value :AT_AddInherit, 53 + value :AT_DropInherit, 54 + value :AT_AddOf, 55 + value :AT_DropOf, 56 + value :AT_ReplicaIdentity, 57 + value :AT_EnableRowSecurity, 58 + value :AT_DisableRowSecurity, 59 + value :AT_ForceRowSecurity, 60 + value :AT_NoForceRowSecurity, 61 + value :AT_GenericOptions, 62 + value :AT_AttachPartition, 63 + value :AT_DetachPartition, 64 + value :AT_AddIdentity, 65 + value :AT_SetIdentity, 66 + value :AT_DropIdentity, 67 end add_enum "pg_query.GrantTargetType" do - value :ACL_TARGET_OBJECT, 0 - value :ACL_TARGET_ALL_IN_SCHEMA, 1 - value :ACL_TARGET_DEFAULTS, 2 + value :GRANT_TARGET_TYPE_UNDEFINED, 0 + value :ACL_TARGET_OBJECT, 1 + value :ACL_TARGET_ALL_IN_SCHEMA, 2 + value :ACL_TARGET_DEFAULTS, 3 end add_enum "pg_query.VariableSetKind" do - value :VAR_SET_VALUE, 0 - value :VAR_SET_DEFAULT, 1 - value :VAR_SET_CURRENT, 2 - value :VAR_SET_MULTI, 3 - value :VAR_RESET, 4 - value :VAR_RESET_ALL, 5 + value :VARIABLE_SET_KIND_UNDEFINED, 0 + value :VAR_SET_VALUE, 1 + value :VAR_SET_DEFAULT, 2 + value :VAR_SET_CURRENT, 3 + value :VAR_SET_MULTI, 4 + value :VAR_RESET, 5 + value :VAR_RESET_ALL, 6 end add_enum "pg_query.ConstrType" do - value :CONSTR_NULL, 0 - value :CONSTR_NOTNULL, 1 - value :CONSTR_DEFAULT, 2 - value :CONSTR_IDENTITY, 3 - value :CONSTR_GENERATED, 4 - value :CONSTR_CHECK, 5 - value :CONSTR_PRIMARY, 6 - value :CONSTR_UNIQUE, 7 - value :CONSTR_EXCLUSION, 8 - value :CONSTR_FOREIGN, 9 - value :CONSTR_ATTR_DEFERRABLE, 10 - value :CONSTR_ATTR_NOT_DEFERRABLE, 11 - value :CONSTR_ATTR_DEFERRED, 12 - value :CONSTR_ATTR_IMMEDIATE, 13 + value :CONSTR_TYPE_UNDEFINED, 0 + value :CONSTR_NULL, 1 + value :CONSTR_NOTNULL, 2 + value :CONSTR_DEFAULT, 3 + value :CONSTR_IDENTITY, 4 + value :CONSTR_GENERATED, 5 + value :CONSTR_CHECK, 6 + value :CONSTR_PRIMARY, 7 + value :CONSTR_UNIQUE, 8 + value :CONSTR_EXCLUSION, 9 + value :CONSTR_FOREIGN, 10 + value :CONSTR_ATTR_DEFERRABLE, 11 + value :CONSTR_ATTR_NOT_DEFERRABLE, 12 + value :CONSTR_ATTR_DEFERRED, 13 + value :CONSTR_ATTR_IMMEDIATE, 14 end add_enum "pg_query.ImportForeignSchemaType" do - value :FDW_IMPORT_SCHEMA_ALL, 0 - value :FDW_IMPORT_SCHEMA_LIMIT_TO, 1 - value :FDW_IMPORT_SCHEMA_EXCEPT, 2 + value :IMPORT_FOREIGN_SCHEMA_TYPE_UNDEFINED, 0 + value :FDW_IMPORT_SCHEMA_ALL, 1 + value :FDW_IMPORT_SCHEMA_LIMIT_TO, 2 + value :FDW_IMPORT_SCHEMA_EXCEPT, 3 end add_enum "pg_query.RoleStmtType" do - value :ROLESTMT_ROLE, 0 - value :ROLESTMT_USER, 1 - value :ROLESTMT_GROUP, 2 + value :ROLE_STMT_TYPE_UNDEFINED, 0 + value :ROLESTMT_ROLE, 1 + value :ROLESTMT_USER, 2 + value :ROLESTMT_GROUP, 3 end add_enum "pg_query.FetchDirection" do - value :FETCH_FORWARD, 0 - value :FETCH_BACKWARD, 1 - value :FETCH_ABSOLUTE, 2 - value :FETCH_RELATIVE, 3 + value :FETCH_DIRECTION_UNDEFINED, 0 + value :FETCH_FORWARD, 1 + value :FETCH_BACKWARD, 2 + value :FETCH_ABSOLUTE, 3 + value :FETCH_RELATIVE, 4 end add_enum "pg_query.FunctionParameterMode" do - value :FUNC_PARAM_IN, 0 - value :FUNC_PARAM_OUT, 1 - value :FUNC_PARAM_INOUT, 2 - value :FUNC_PARAM_VARIADIC, 3 - value :FUNC_PARAM_TABLE, 4 + value :FUNCTION_PARAMETER_MODE_UNDEFINED, 0 + value :FUNC_PARAM_IN, 1 + value :FUNC_PARAM_OUT, 2 + value :FUNC_PARAM_INOUT, 3 + value :FUNC_PARAM_VARIADIC, 4 + value :FUNC_PARAM_TABLE, 5 end add_enum "pg_query.TransactionStmtKind" do - value :TRANS_STMT_BEGIN, 0 - value :TRANS_STMT_START, 1 - value :TRANS_STMT_COMMIT, 2 - value :TRANS_STMT_ROLLBACK, 3 - value :TRANS_STMT_SAVEPOINT, 4 - value :TRANS_STMT_RELEASE, 5 - value :TRANS_STMT_ROLLBACK_TO, 6 - value :TRANS_STMT_PREPARE, 7 - value :TRANS_STMT_COMMIT_PREPARED, 8 - value :TRANS_STMT_ROLLBACK_PREPARED, 9 + value :TRANSACTION_STMT_KIND_UNDEFINED, 0 + value :TRANS_STMT_BEGIN, 1 + value :TRANS_STMT_START, 2 + value :TRANS_STMT_COMMIT, 3 + value :TRANS_STMT_ROLLBACK, 4 + value :TRANS_STMT_SAVEPOINT, 5 + value :TRANS_STMT_RELEASE, 6 + value :TRANS_STMT_ROLLBACK_TO, 7 + value :TRANS_STMT_PREPARE, 8 + value :TRANS_STMT_COMMIT_PREPARED, 9 + value :TRANS_STMT_ROLLBACK_PREPARED, 10 end add_enum "pg_query.ViewCheckOption" do - value :NO_CHECK_OPTION, 0 - value :LOCAL_CHECK_OPTION, 1 - value :CASCADED_CHECK_OPTION, 2 + value :VIEW_CHECK_OPTION_UNDEFINED, 0 + value :NO_CHECK_OPTION, 1 + value :LOCAL_CHECK_OPTION, 2 + value :CASCADED_CHECK_OPTION, 3 end add_enum "pg_query.ClusterOption" do - value :CLUOPT_RECHECK, 0 - value :CLUOPT_VERBOSE, 1 + value :CLUSTER_OPTION_UNDEFINED, 0 + value :CLUOPT_RECHECK, 1 + value :CLUOPT_VERBOSE, 2 end add_enum "pg_query.DiscardMode" do - value :DISCARD_ALL, 0 - value :DISCARD_PLANS, 1 - value :DISCARD_SEQUENCES, 2 - value :DISCARD_TEMP, 3 + value :DISCARD_MODE_UNDEFINED, 0 + value :DISCARD_ALL, 1 + value :DISCARD_PLANS, 2 + value :DISCARD_SEQUENCES, 3 + value :DISCARD_TEMP, 4 end add_enum "pg_query.ReindexObjectType" do - value :REINDEX_OBJECT_INDEX, 0 - value :REINDEX_OBJECT_TABLE, 1 - value :REINDEX_OBJECT_SCHEMA, 2 - value :REINDEX_OBJECT_SYSTEM, 3 - value :REINDEX_OBJECT_DATABASE, 4 + value :REINDEX_OBJECT_TYPE_UNDEFINED, 0 + value :REINDEX_OBJECT_INDEX, 1 + value :REINDEX_OBJECT_TABLE, 2 + value :REINDEX_OBJECT_SCHEMA, 3 + value :REINDEX_OBJECT_SYSTEM, 4 + value :REINDEX_OBJECT_DATABASE, 5 end add_enum "pg_query.AlterTSConfigType" do - value :ALTER_TSCONFIG_ADD_MAPPING, 0 - value :ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN, 1 - value :ALTER_TSCONFIG_REPLACE_DICT, 2 - value :ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN, 3 - value :ALTER_TSCONFIG_DROP_MAPPING, 4 + value :ALTER_TSCONFIG_TYPE_UNDEFINED, 0 + value :ALTER_TSCONFIG_ADD_MAPPING, 1 + value :ALTER_TSCONFIG_ALTER_MAPPING_FOR_TOKEN, 2 + value :ALTER_TSCONFIG_REPLACE_DICT, 3 + value :ALTER_TSCONFIG_REPLACE_DICT_FOR_TOKEN, 4 + value :ALTER_TSCONFIG_DROP_MAPPING, 5 end add_enum "pg_query.AlterSubscriptionType" do - value :ALTER_SUBSCRIPTION_OPTIONS, 0 - value :ALTER_SUBSCRIPTION_CONNECTION, 1 - value :ALTER_SUBSCRIPTION_PUBLICATION, 2 - value :ALTER_SUBSCRIPTION_REFRESH, 3 - value :ALTER_SUBSCRIPTION_ENABLED, 4 + value :ALTER_SUBSCRIPTION_TYPE_UNDEFINED, 0 + value :ALTER_SUBSCRIPTION_OPTIONS, 1 + value :ALTER_SUBSCRIPTION_CONNECTION, 2 + value :ALTER_SUBSCRIPTION_PUBLICATION, 3 + value :ALTER_SUBSCRIPTION_REFRESH, 4 + value :ALTER_SUBSCRIPTION_ENABLED, 5 end add_enum "pg_query.OnCommitAction" do - value :ONCOMMIT_NOOP, 0 - value :ONCOMMIT_PRESERVE_ROWS, 1 - value :ONCOMMIT_DELETE_ROWS, 2 - value :ONCOMMIT_DROP, 3 + value :ON_COMMIT_ACTION_UNDEFINED, 0 + value :ONCOMMIT_NOOP, 1 + value :ONCOMMIT_PRESERVE_ROWS, 2 + value :ONCOMMIT_DELETE_ROWS, 3 + value :ONCOMMIT_DROP, 4 end add_enum "pg_query.ParamKind" do - value :PARAM_EXTERN, 0 - value :PARAM_EXEC, 1 - value :PARAM_SUBLINK, 2 - value :PARAM_MULTIEXPR, 3 + value :PARAM_KIND_UNDEFINED, 0 + value :PARAM_EXTERN, 1 + value :PARAM_EXEC, 2 + value :PARAM_SUBLINK, 3 + value :PARAM_MULTIEXPR, 4 end add_enum "pg_query.CoercionContext" do - value :COERCION_IMPLICIT, 0 - value :COERCION_ASSIGNMENT, 1 - value :COERCION_EXPLICIT, 2 + value :COERCION_CONTEXT_UNDEFINED, 0 + value :COERCION_IMPLICIT, 1 + value :COERCION_ASSIGNMENT, 2 + value :COERCION_EXPLICIT, 3 end add_enum "pg_query.CoercionForm" do - value :COERCE_EXPLICIT_CALL, 0 - value :COERCE_EXPLICIT_CAST, 1 - value :COERCE_IMPLICIT_CAST, 2 + value :COERCION_FORM_UNDEFINED, 0 + value :COERCE_EXPLICIT_CALL, 1 + value :COERCE_EXPLICIT_CAST, 2 + value :COERCE_IMPLICIT_CAST, 3 end add_enum "pg_query.BoolExprType" do - value :AND_EXPR, 0 - value :OR_EXPR, 1 + value :BOOL_EXPR_TYPE_UNDEFINED, 0 + value :AND_EXPR, 1 + value :OR_EXPR, 2 + value :NOT_EXPR, 3 end add_enum "pg_query.SubLinkType" do - value :EXISTS_SUBLINK, 0 - value :ALL_SUBLINK, 1 - value :ANY_SUBLINK, 2 - value :ROWCOMPARE_SUBLINK, 3 - value :EXPR_SUBLINK, 4 - value :MULTIEXPR_SUBLINK, 5 - value :ARRAY_SUBLINK, 6 - value :CTE_SUBLINK, 7 + value :SUB_LINK_TYPE_UNDEFINED, 0 + value :EXISTS_SUBLINK, 1 + value :ALL_SUBLINK, 2 + value :ANY_SUBLINK, 3 + value :ROWCOMPARE_SUBLINK, 4 + value :EXPR_SUBLINK, 5 + value :MULTIEXPR_SUBLINK, 6 + value :ARRAY_SUBLINK, 7 + value :CTE_SUBLINK, 8 end add_enum "pg_query.RowCompareType" do - value :ROWCOMPARE_LT, 0 - value :ROWCOMPARE_LE, 1 - value :ROWCOMPARE_EQ, 2 - value :ROWCOMPARE_GE, 3 - value :ROWCOMPARE_GT, 4 - value :ROWCOMPARE_NE, 5 + value :ROW_COMPARE_TYPE_UNDEFINED, 0 + value :ROWCOMPARE_LT, 1 + value :ROWCOMPARE_LE, 2 + value :ROWCOMPARE_EQ, 3 + value :ROWCOMPARE_GE, 4 + value :ROWCOMPARE_GT, 5 + value :ROWCOMPARE_NE, 6 end add_enum "pg_query.MinMaxOp" do - value :IS_GREATEST, 0 - value :IS_LEAST, 1 + value :MIN_MAX_OP_UNDEFINED, 0 + value :IS_GREATEST, 1 + value :IS_LEAST, 2 end add_enum "pg_query.SQLValueFunctionOp" do - value :SVFOP_CURRENT_DATE, 0 - value :SVFOP_CURRENT_TIME, 1 - value :SVFOP_CURRENT_TIME_N, 2 - value :SVFOP_CURRENT_TIMESTAMP, 3 - value :SVFOP_CURRENT_TIMESTAMP_N, 4 - value :SVFOP_LOCALTIME, 5 - value :SVFOP_LOCALTIME_N, 6 - value :SVFOP_LOCALTIMESTAMP, 7 - value :SVFOP_LOCALTIMESTAMP_N, 8 - value :SVFOP_CURRENT_ROLE, 9 - value :SVFOP_CURRENT_USER, 10 - value :SVFOP_USER, 11 - value :SVFOP_SESSION_USER, 12 - value :SVFOP_CURRENT_CATALOG, 13 - value :SVFOP_CURRENT_SCHEMA, 14 + value :SQLVALUE_FUNCTION_OP_UNDEFINED, 0 + value :SVFOP_CURRENT_DATE, 1 + value :SVFOP_CURRENT_TIME, 2 + value :SVFOP_CURRENT_TIME_N, 3 + value :SVFOP_CURRENT_TIMESTAMP, 4 + value :SVFOP_CURRENT_TIMESTAMP_N, 5 + value :SVFOP_LOCALTIME, 6 + value :SVFOP_LOCALTIME_N, 7 + value :SVFOP_LOCALTIMESTAMP, 8 + value :SVFOP_LOCALTIMESTAMP_N, 9 + value :SVFOP_CURRENT_ROLE, 10 + value :SVFOP_CURRENT_USER, 11 + value :SVFOP_USER, 12 + value :SVFOP_SESSION_USER, 13 + value :SVFOP_CURRENT_CATALOG, 14 + value :SVFOP_CURRENT_SCHEMA, 15 end add_enum "pg_query.XmlExprOp" do - value :IS_XMLCONCAT, 0 - value :IS_XMLELEMENT, 1 - value :IS_XMLFOREST, 2 - value :IS_XMLPARSE, 3 - value :IS_XMLPI, 4 - value :IS_XMLROOT, 5 - value :IS_XMLSERIALIZE, 6 - value :IS_DOCUMENT, 7 + value :XML_EXPR_OP_UNDEFINED, 0 + value :IS_XMLCONCAT, 1 + value :IS_XMLELEMENT, 2 + value :IS_XMLFOREST, 3 + value :IS_XMLPARSE, 4 + value :IS_XMLPI, 5 + value :IS_XMLROOT, 6 + value :IS_XMLSERIALIZE, 7 + value :IS_DOCUMENT, 8 end add_enum "pg_query.XmlOptionType" do - value :XMLOPTION_DOCUMENT, 0 - value :XMLOPTION_CONTENT, 1 + value :XML_OPTION_TYPE_UNDEFINED, 0 + value :XMLOPTION_DOCUMENT, 1 + value :XMLOPTION_CONTENT, 2 end add_enum "pg_query.NullTestType" do - value :IS_NULL, 0 - value :IS_NOT_NULL, 1 + value :NULL_TEST_TYPE_UNDEFINED, 0 + value :IS_NULL, 1 + value :IS_NOT_NULL, 2 end add_enum "pg_query.BoolTestType" do - value :IS_TRUE, 0 - value :IS_NOT_TRUE, 1 + value :BOOL_TEST_TYPE_UNDEFINED, 0 + value :IS_TRUE, 1 + value :IS_NOT_TRUE, 2 + value :IS_FALSE, 3 + value :IS_NOT_FALSE, 4 + value :IS_UNKNOWN, 5 + value :IS_NOT_UNKNOWN, 6 end add_enum "pg_query.CmdType" do - value :CMD_UNKNOWN, 0 - value :CMD_SELECT, 1 - value :CMD_UPDATE, 2 - value :CMD_INSERT, 3 - value :CMD_DELETE, 4 - value :CMD_UTILITY, 5 - value :CMD_NOTHING, 6 + value :CMD_TYPE_UNDEFINED, 0 + value :CMD_UNKNOWN, 1 + value :CMD_SELECT, 2 + value :CMD_UPDATE, 3 + value :CMD_INSERT, 4 + value :CMD_DELETE, 5 + value :CMD_UTILITY, 6 + value :CMD_NOTHING, 7 end add_enum "pg_query.JoinType" do - value :JOIN_INNER, 0 - value :JOIN_LEFT, 1 - value :JOIN_FULL, 2 - value :JOIN_RIGHT, 3 - value :JOIN_SEMI, 4 - value :JOIN_ANTI, 5 - value :JOIN_UNIQUE_OUTER, 6 - value :JOIN_UNIQUE_INNER, 7 + value :JOIN_TYPE_UNDEFINED, 0 + value :JOIN_INNER, 1 + value :JOIN_LEFT, 2 + value :JOIN_FULL, 3 + value :JOIN_RIGHT, 4 + value :JOIN_SEMI, 5 + value :JOIN_ANTI, 6 + value :JOIN_UNIQUE_OUTER, 7 + value :JOIN_UNIQUE_INNER, 8 end add_enum "pg_query.AggStrategy" do - value :AGG_PLAIN, 0 - value :AGG_SORTED, 1 - value :AGG_HASHED, 2 - value :AGG_MIXED, 3 + value :AGG_STRATEGY_UNDEFINED, 0 + value :AGG_PLAIN, 1 + value :AGG_SORTED, 2 + value :AGG_HASHED, 3 + value :AGG_MIXED, 4 end add_enum "pg_query.AggSplit" do - value :AGGSPLIT_SIMPLE, 0 - value :AGGSPLIT_INITIAL_SERIAL, 1 - value :AGGSPLIT_FINAL_DESERIAL, 2 + value :AGG_SPLIT_UNDEFINED, 0 + value :AGGSPLIT_SIMPLE, 1 + value :AGGSPLIT_INITIAL_SERIAL, 2 + value :AGGSPLIT_FINAL_DESERIAL, 3 end add_enum "pg_query.SetOpCmd" do - value :SETOPCMD_INTERSECT, 0 - value :SETOPCMD_INTERSECT_ALL, 1 - value :SETOPCMD_EXCEPT, 2 - value :SETOPCMD_EXCEPT_ALL, 3 + value :SET_OP_CMD_UNDEFINED, 0 + value :SETOPCMD_INTERSECT, 1 + value :SETOPCMD_INTERSECT_ALL, 2 + value :SETOPCMD_EXCEPT, 3 + value :SETOPCMD_EXCEPT_ALL, 4 end add_enum "pg_query.SetOpStrategy" do - value :SETOP_SORTED, 0 - value :SETOP_HASHED, 1 + value :SET_OP_STRATEGY_UNDEFINED, 0 + value :SETOP_SORTED, 1 + value :SETOP_HASHED, 2 end add_enum "pg_query.OnConflictAction" do - value :ONCONFLICT_NONE, 0 - value :ONCONFLICT_NOTHING, 1 - value :ONCONFLICT_UPDATE, 2 + value :ON_CONFLICT_ACTION_UNDEFINED, 0 + value :ONCONFLICT_NONE, 1 + value :ONCONFLICT_NOTHING, 2 + value :ONCONFLICT_UPDATE, 3 end add_enum "pg_query.LimitOption" do - value :LIMIT_OPTION_COUNT, 0 - value :LIMIT_OPTION_WITH_TIES, 1 - value :LIMIT_OPTION_DEFAULT, 2 + value :LIMIT_OPTION_UNDEFINED, 0 + value :LIMIT_OPTION_DEFAULT, 1 + value :LIMIT_OPTION_COUNT, 2 + value :LIMIT_OPTION_WITH_TIES, 3 end add_enum "pg_query.LockClauseStrength" do - value :LCS_NONE, 0 - value :LCS_FORKEYSHARE, 1 - value :LCS_FORSHARE, 2 - value :LCS_FORNOKEYUPDATE, 3 - value :LCS_FORUPDATE, 4 + value :LOCK_CLAUSE_STRENGTH_UNDEFINED, 0 + value :LCS_NONE, 1 + value :LCS_FORKEYSHARE, 2 + value :LCS_FORSHARE, 3 + value :LCS_FORNOKEYUPDATE, 4 + value :LCS_FORUPDATE, 5 end add_enum "pg_query.LockWaitPolicy" do - value :LockWaitBlock, 0 - value :LockWaitSkip, 1 - value :LockWaitError, 2 + value :LOCK_WAIT_POLICY_UNDEFINED, 0 + value :LockWaitBlock, 1 + value :LockWaitSkip, 2 + value :LockWaitError, 3 end add_enum "pg_query.LockTupleMode" do - value :LockTupleKeyShare, 0 - value :LockTupleShare, 1 - value :LockTupleNoKeyExclusive, 2 - value :LockTupleExclusive, 3 + value :LOCK_TUPLE_MODE_UNDEFINED, 0 + value :LockTupleKeyShare, 1 + value :LockTupleShare, 2 + value :LockTupleNoKeyExclusive, 3 + value :LockTupleExclusive, 4 + end + add_enum "pg_query.KeywordKind" do + value :NO_KEYWORD, 0 + value :UNRESERVED_KEYWORD, 1 + value :COL_NAME_KEYWORD, 2 + value :TYPE_FUNC_NAME_KEYWORD, 3 + value :RESERVED_KEYWORD, 4 + end + add_enum "pg_query.Token" do + value :NUL, 0 + value :ASCII_37, 37 + value :ASCII_40, 40 + value :ASCII_41, 41 + value :ASCII_42, 42 + value :ASCII_43, 43 + value :ASCII_44, 44 + value :ASCII_45, 45 + value :ASCII_46, 46 + value :ASCII_47, 47 + value :ASCII_58, 58 + value :ASCII_59, 59 + value :ASCII_60, 60 + value :ASCII_61, 61 + value :ASCII_62, 62 + value :ASCII_63, 63 + value :ASCII_91, 91 + value :ASCII_93, 93 + value :ASCII_94, 94 + value :IDENT, 258 + value :UIDENT, 259 + value :FCONST, 260 + value :SCONST, 261 + value :USCONST, 262 + value :BCONST, 263 + value :XCONST, 264 + value :Op, 265 + value :ICONST, 266 + value :PARAM, 267 + value :TYPECAST, 268 + value :DOT_DOT, 269 + value :COLON_EQUALS, 270 + value :EQUALS_GREATER, 271 + value :LESS_EQUALS, 272 + value :GREATER_EQUALS, 273 + value :NOT_EQUALS, 274 + value :SQL_COMMENT, 275 + value :C_COMMENT, 276 + value :ABORT_P, 277 + value :ABSOLUTE_P, 278 + value :ACCESS, 279 + value :ACTION, 280 + value :ADD_P, 281 + value :ADMIN, 282 + value :AFTER, 283 + value :AGGREGATE, 284 + value :ALL, 285 + value :ALSO, 286 + value :ALTER, 287 + value :ALWAYS, 288 + value :ANALYSE, 289 + value :ANALYZE, 290 + value :AND, 291 + value :ANY, 292 + value :ARRAY, 293 + value :AS, 294 + value :ASC, 295 + value :ASSERTION, 296 + value :ASSIGNMENT, 297 + value :ASYMMETRIC, 298 + value :AT, 299 + value :ATTACH, 300 + value :ATTRIBUTE, 301 + value :AUTHORIZATION, 302 + value :BACKWARD, 303 + value :BEFORE, 304 + value :BEGIN_P, 305 + value :BETWEEN, 306 + value :BIGINT, 307 + value :BINARY, 308 + value :BIT, 309 + value :BOOLEAN_P, 310 + value :BOTH, 311 + value :BY, 312 + value :CACHE, 313 + value :CALL, 314 + value :CALLED, 315 + value :CASCADE, 316 + value :CASCADED, 317 + value :CASE, 318 + value :CAST, 319 + value :CATALOG_P, 320 + value :CHAIN, 321 + value :CHAR_P, 322 + value :CHARACTER, 323 + value :CHARACTERISTICS, 324 + value :CHECK, 325 + value :CHECKPOINT, 326 + value :CLASS, 327 + value :CLOSE, 328 + value :CLUSTER, 329 + value :COALESCE, 330 + value :COLLATE, 331 + value :COLLATION, 332 + value :COLUMN, 333 + value :COLUMNS, 334 + value :COMMENT, 335 + value :COMMENTS, 336 + value :COMMIT, 337 + value :COMMITTED, 338 + value :CONCURRENTLY, 339 + value :CONFIGURATION, 340 + value :CONFLICT, 341 + value :CONNECTION, 342 + value :CONSTRAINT, 343 + value :CONSTRAINTS, 344 + value :CONTENT_P, 345 + value :CONTINUE_P, 346 + value :CONVERSION_P, 347 + value :COPY, 348 + value :COST, 349 + value :CREATE, 350 + value :CROSS, 351 + value :CSV, 352 + value :CUBE, 353 + value :CURRENT_P, 354 + value :CURRENT_CATALOG, 355 + value :CURRENT_DATE, 356 + value :CURRENT_ROLE, 357 + value :CURRENT_SCHEMA, 358 + value :CURRENT_TIME, 359 + value :CURRENT_TIMESTAMP, 360 + value :CURRENT_USER, 361 + value :CURSOR, 362 + value :CYCLE, 363 + value :DATA_P, 364 + value :DATABASE, 365 + value :DAY_P, 366 + value :DEALLOCATE, 367 + value :DEC, 368 + value :DECIMAL_P, 369 + value :DECLARE, 370 + value :DEFAULT, 371 + value :DEFAULTS, 372 + value :DEFERRABLE, 373 + value :DEFERRED, 374 + value :DEFINER, 375 + value :DELETE_P, 376 + value :DELIMITER, 377 + value :DELIMITERS, 378 + value :DEPENDS, 379 + value :DESC, 380 + value :DETACH, 381 + value :DICTIONARY, 382 + value :DISABLE_P, 383 + value :DISCARD, 384 + value :DISTINCT, 385 + value :DO, 386 + value :DOCUMENT_P, 387 + value :DOMAIN_P, 388 + value :DOUBLE_P, 389 + value :DROP, 390 + value :EACH, 391 + value :ELSE, 392 + value :ENABLE_P, 393 + value :ENCODING, 394 + value :ENCRYPTED, 395 + value :END_P, 396 + value :ENUM_P, 397 + value :ESCAPE, 398 + value :EVENT, 399 + value :EXCEPT, 400 + value :EXCLUDE, 401 + value :EXCLUDING, 402 + value :EXCLUSIVE, 403 + value :EXECUTE, 404 + value :EXISTS, 405 + value :EXPLAIN, 406 + value :EXPRESSION, 407 + value :EXTENSION, 408 + value :EXTERNAL, 409 + value :EXTRACT, 410 + value :FALSE_P, 411 + value :FAMILY, 412 + value :FETCH, 413 + value :FILTER, 414 + value :FIRST_P, 415 + value :FLOAT_P, 416 + value :FOLLOWING, 417 + value :FOR, 418 + value :FORCE, 419 + value :FOREIGN, 420 + value :FORWARD, 421 + value :FREEZE, 422 + value :FROM, 423 + value :FULL, 424 + value :FUNCTION, 425 + value :FUNCTIONS, 426 + value :GENERATED, 427 + value :GLOBAL, 428 + value :GRANT, 429 + value :GRANTED, 430 + value :GREATEST, 431 + value :GROUP_P, 432 + value :GROUPING, 433 + value :GROUPS, 434 + value :HANDLER, 435 + value :HAVING, 436 + value :HEADER_P, 437 + value :HOLD, 438 + value :HOUR_P, 439 + value :IDENTITY_P, 440 + value :IF_P, 441 + value :ILIKE, 442 + value :IMMEDIATE, 443 + value :IMMUTABLE, 444 + value :IMPLICIT_P, 445 + value :IMPORT_P, 446 + value :IN_P, 447 + value :INCLUDE, 448 + value :INCLUDING, 449 + value :INCREMENT, 450 + value :INDEX, 451 + value :INDEXES, 452 + value :INHERIT, 453 + value :INHERITS, 454 + value :INITIALLY, 455 + value :INLINE_P, 456 + value :INNER_P, 457 + value :INOUT, 458 + value :INPUT_P, 459 + value :INSENSITIVE, 460 + value :INSERT, 461 + value :INSTEAD, 462 + value :INT_P, 463 + value :INTEGER, 464 + value :INTERSECT, 465 + value :INTERVAL, 466 + value :INTO, 467 + value :INVOKER, 468 + value :IS, 469 + value :ISNULL, 470 + value :ISOLATION, 471 + value :JOIN, 472 + value :KEY, 473 + value :LABEL, 474 + value :LANGUAGE, 475 + value :LARGE_P, 476 + value :LAST_P, 477 + value :LATERAL_P, 478 + value :LEADING, 479 + value :LEAKPROOF, 480 + value :LEAST, 481 + value :LEFT, 482 + value :LEVEL, 483 + value :LIKE, 484 + value :LIMIT, 485 + value :LISTEN, 486 + value :LOAD, 487 + value :LOCAL, 488 + value :LOCALTIME, 489 + value :LOCALTIMESTAMP, 490 + value :LOCATION, 491 + value :LOCK_P, 492 + value :LOCKED, 493 + value :LOGGED, 494 + value :MAPPING, 495 + value :MATCH, 496 + value :MATERIALIZED, 497 + value :MAXVALUE, 498 + value :METHOD, 499 + value :MINUTE_P, 500 + value :MINVALUE, 501 + value :MODE, 502 + value :MONTH_P, 503 + value :MOVE, 504 + value :NAME_P, 505 + value :NAMES, 506 + value :NATIONAL, 507 + value :NATURAL, 508 + value :NCHAR, 509 + value :NEW, 510 + value :NEXT, 511 + value :NFC, 512 + value :NFD, 513 + value :NFKC, 514 + value :NFKD, 515 + value :NO, 516 + value :NONE, 517 + value :NORMALIZE, 518 + value :NORMALIZED, 519 + value :NOT, 520 + value :NOTHING, 521 + value :NOTIFY, 522 + value :NOTNULL, 523 + value :NOWAIT, 524 + value :NULL_P, 525 + value :NULLIF, 526 + value :NULLS_P, 527 + value :NUMERIC, 528 + value :OBJECT_P, 529 + value :OF, 530 + value :OFF, 531 + value :OFFSET, 532 + value :OIDS, 533 + value :OLD, 534 + value :ON, 535 + value :ONLY, 536 + value :OPERATOR, 537 + value :OPTION, 538 + value :OPTIONS, 539 + value :OR, 540 + value :ORDER, 541 + value :ORDINALITY, 542 + value :OTHERS, 543 + value :OUT_P, 544 + value :OUTER_P, 545 + value :OVER, 546 + value :OVERLAPS, 547 + value :OVERLAY, 548 + value :OVERRIDING, 549 + value :OWNED, 550 + value :OWNER, 551 + value :PARALLEL, 552 + value :PARSER, 553 + value :PARTIAL, 554 + value :PARTITION, 555 + value :PASSING, 556 + value :PASSWORD, 557 + value :PLACING, 558 + value :PLANS, 559 + value :POLICY, 560 + value :POSITION, 561 + value :PRECEDING, 562 + value :PRECISION, 563 + value :PRESERVE, 564 + value :PREPARE, 565 + value :PREPARED, 566 + value :PRIMARY, 567 + value :PRIOR, 568 + value :PRIVILEGES, 569 + value :PROCEDURAL, 570 + value :PROCEDURE, 571 + value :PROCEDURES, 572 + value :PROGRAM, 573 + value :PUBLICATION, 574 + value :QUOTE, 575 + value :RANGE, 576 + value :READ, 577 + value :REAL, 578 + value :REASSIGN, 579 + value :RECHECK, 580 + value :RECURSIVE, 581 + value :REF, 582 + value :REFERENCES, 583 + value :REFERENCING, 584 + value :REFRESH, 585 + value :REINDEX, 586 + value :RELATIVE_P, 587 + value :RELEASE, 588 + value :RENAME, 589 + value :REPEATABLE, 590 + value :REPLACE, 591 + value :REPLICA, 592 + value :RESET, 593 + value :RESTART, 594 + value :RESTRICT, 595 + value :RETURNING, 596 + value :RETURNS, 597 + value :REVOKE, 598 + value :RIGHT, 599 + value :ROLE, 600 + value :ROLLBACK, 601 + value :ROLLUP, 602 + value :ROUTINE, 603 + value :ROUTINES, 604 + value :ROW, 605 + value :ROWS, 606 + value :RULE, 607 + value :SAVEPOINT, 608 + value :SCHEMA, 609 + value :SCHEMAS, 610 + value :SCROLL, 611 + value :SEARCH, 612 + value :SECOND_P, 613 + value :SECURITY, 614 + value :SELECT, 615 + value :SEQUENCE, 616 + value :SEQUENCES, 617 + value :SERIALIZABLE, 618 + value :SERVER, 619 + value :SESSION, 620 + value :SESSION_USER, 621 + value :SET, 622 + value :SETS, 623 + value :SETOF, 624 + value :SHARE, 625 + value :SHOW, 626 + value :SIMILAR, 627 + value :SIMPLE, 628 + value :SKIP, 629 + value :SMALLINT, 630 + value :SNAPSHOT, 631 + value :SOME, 632 + value :SQL_P, 633 + value :STABLE, 634 + value :STANDALONE_P, 635 + value :START, 636 + value :STATEMENT, 637 + value :STATISTICS, 638 + value :STDIN, 639 + value :STDOUT, 640 + value :STORAGE, 641 + value :STORED, 642 + value :STRICT_P, 643 + value :STRIP_P, 644 + value :SUBSCRIPTION, 645 + value :SUBSTRING, 646 + value :SUPPORT, 647 + value :SYMMETRIC, 648 + value :SYSID, 649 + value :SYSTEM_P, 650 + value :TABLE, 651 + value :TABLES, 652 + value :TABLESAMPLE, 653 + value :TABLESPACE, 654 + value :TEMP, 655 + value :TEMPLATE, 656 + value :TEMPORARY, 657 + value :TEXT_P, 658 + value :THEN, 659 + value :TIES, 660 + value :TIME, 661 + value :TIMESTAMP, 662 + value :TO, 663 + value :TRAILING, 664 + value :TRANSACTION, 665 + value :TRANSFORM, 666 + value :TREAT, 667 + value :TRIGGER, 668 + value :TRIM, 669 + value :TRUE_P, 670 + value :TRUNCATE, 671 + value :TRUSTED, 672 + value :TYPE_P, 673 + value :TYPES_P, 674 + value :UESCAPE, 675 + value :UNBOUNDED, 676 + value :UNCOMMITTED, 677 + value :UNENCRYPTED, 678 + value :UNION, 679 + value :UNIQUE, 680 + value :UNKNOWN, 681 + value :UNLISTEN, 682 + value :UNLOGGED, 683 + value :UNTIL, 684 + value :UPDATE, 685 + value :USER, 686 + value :USING, 687 + value :VACUUM, 688 + value :VALID, 689 + value :VALIDATE, 690 + value :VALIDATOR, 691 + value :VALUE_P, 692 + value :VALUES, 693 + value :VARCHAR, 694 + value :VARIADIC, 695 + value :VARYING, 696 + value :VERBOSE, 697 + value :VERSION_P, 698 + value :VIEW, 699 + value :VIEWS, 700 + value :VOLATILE, 701 + value :WHEN, 702 + value :WHERE, 703 + value :WHITESPACE_P, 704 + value :WINDOW, 705 + value :WITH, 706 + value :WITHIN, 707 + value :WITHOUT, 708 + value :WORK, 709 + value :WRAPPER, 710 + value :WRITE, 711 + value :XML_P, 712 + value :XMLATTRIBUTES, 713 + value :XMLCONCAT, 714 + value :XMLELEMENT, 715 + value :XMLEXISTS, 716 + value :XMLFOREST, 717 + value :XMLNAMESPACES, 718 + value :XMLPARSE, 719 + value :XMLPI, 720 + value :XMLROOT, 721 + value :XMLSERIALIZE, 722 + value :XMLTABLE, 723 + value :YEAR_P, 724 + value :YES_P, 725 + value :ZONE, 726 + value :NOT_LA, 727 + value :NULLS_LA, 728 + value :WITH_LA, 729 + value :POSTFIXOP, 730 + value :UMINUS, 731 end end end module PgQuery + ParseResult = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.ParseResult").msgclass + ScanResult = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.ScanResult").msgclass Node = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.Node").msgclass Integer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.Integer").msgclass Float = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.Float").msgclass @@ -2566,6 +3150,7 @@ module PgQuery VacuumRelation = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.VacuumRelation").msgclass InlineCodeBlock = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.InlineCodeBlock").msgclass CallContext = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.CallContext").msgclass + ScanToken = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.ScanToken").msgclass OverridingKind = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.OverridingKind").enummodule QuerySource = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.QuerySource").enummodule SortByDir = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.SortByDir").enummodule @@ -2621,4 +3206,6 @@ module PgQuery LockClauseStrength = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.LockClauseStrength").enummodule LockWaitPolicy = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.LockWaitPolicy").enummodule LockTupleMode = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.LockTupleMode").enummodule + KeywordKind = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.KeywordKind").enummodule + Token = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.Token").enummodule end diff --git a/lib/pg_query/scan.rb b/lib/pg_query/scan.rb index d2e8678e..976d015e 100644 --- a/lib/pg_query/scan.rb +++ b/lib/pg_query/scan.rb @@ -1,5 +1,3 @@ -require 'pg_query/scan_output_pb' - module PgQuery class ScanError < ArgumentError attr_reader :location @@ -12,7 +10,7 @@ def initialize(message, source_file, source_line, location) def self.scan(query) out, stderr = _raw_scan(query) - result = PgQuery::ScanOutput.decode(out) + result = PgQuery::ScanResult.decode(out) warnings = [] stderr.each_line do |line| diff --git a/lib/pg_query/scan_output_pb.rb b/lib/pg_query/scan_output_pb.rb deleted file mode 100644 index 5ee5e3dd..00000000 --- a/lib/pg_query/scan_output_pb.rb +++ /dev/null @@ -1,527 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: scan_output.proto - -require 'google/protobuf' - -Google::Protobuf::DescriptorPool.generated_pool.build do - add_file("scan_output.proto", :syntax => :proto3) do - add_message "pg_query.ScanOutput" do - repeated :tokens, :message, 1, "pg_query.ScanToken" - end - add_message "pg_query.ScanToken" do - optional :start, :int32, 1 - optional :end, :int32, 2 - optional :token, :enum, 4, "pg_query.Token" - optional :keyword_kind, :enum, 5, "pg_query.KeywordKind" - end - add_enum "pg_query.KeywordKind" do - value :NO_KEYWORD, 0 - value :UNRESERVED_KEYWORD, 1 - value :COL_NAME_KEYWORD, 2 - value :TYPE_FUNC_NAME_KEYWORD, 3 - value :RESERVED_KEYWORD, 4 - end - add_enum "pg_query.Token" do - value :NUL, 0 - value :ASCII_37, 37 - value :ASCII_40, 40 - value :ASCII_41, 41 - value :ASCII_42, 42 - value :ASCII_43, 43 - value :ASCII_44, 44 - value :ASCII_45, 45 - value :ASCII_46, 46 - value :ASCII_47, 47 - value :ASCII_58, 58 - value :ASCII_59, 59 - value :ASCII_60, 60 - value :ASCII_61, 61 - value :ASCII_62, 62 - value :ASCII_63, 63 - value :ASCII_91, 91 - value :ASCII_93, 93 - value :ASCII_94, 94 - value :IDENT, 258 - value :UIDENT, 259 - value :FCONST, 260 - value :SCONST, 261 - value :USCONST, 262 - value :BCONST, 263 - value :XCONST, 264 - value :Op, 265 - value :ICONST, 266 - value :PARAM, 267 - value :TYPECAST, 268 - value :DOT_DOT, 269 - value :COLON_EQUALS, 270 - value :EQUALS_GREATER, 271 - value :LESS_EQUALS, 272 - value :GREATER_EQUALS, 273 - value :NOT_EQUALS, 274 - value :SQL_COMMENT, 275 - value :C_COMMENT, 276 - value :ABORT_P, 277 - value :ABSOLUTE_P, 278 - value :ACCESS, 279 - value :ACTION, 280 - value :ADD_P, 281 - value :ADMIN, 282 - value :AFTER, 283 - value :AGGREGATE, 284 - value :ALL, 285 - value :ALSO, 286 - value :ALTER, 287 - value :ALWAYS, 288 - value :ANALYSE, 289 - value :ANALYZE, 290 - value :AND, 291 - value :ANY, 292 - value :ARRAY, 293 - value :AS, 294 - value :ASC, 295 - value :ASSERTION, 296 - value :ASSIGNMENT, 297 - value :ASYMMETRIC, 298 - value :AT, 299 - value :ATTACH, 300 - value :ATTRIBUTE, 301 - value :AUTHORIZATION, 302 - value :BACKWARD, 303 - value :BEFORE, 304 - value :BEGIN_P, 305 - value :BETWEEN, 306 - value :BIGINT, 307 - value :BINARY, 308 - value :BIT, 309 - value :BOOLEAN_P, 310 - value :BOTH, 311 - value :BY, 312 - value :CACHE, 313 - value :CALL, 314 - value :CALLED, 315 - value :CASCADE, 316 - value :CASCADED, 317 - value :CASE, 318 - value :CAST, 319 - value :CATALOG_P, 320 - value :CHAIN, 321 - value :CHAR_P, 322 - value :CHARACTER, 323 - value :CHARACTERISTICS, 324 - value :CHECK, 325 - value :CHECKPOINT, 326 - value :CLASS, 327 - value :CLOSE, 328 - value :CLUSTER, 329 - value :COALESCE, 330 - value :COLLATE, 331 - value :COLLATION, 332 - value :COLUMN, 333 - value :COLUMNS, 334 - value :COMMENT, 335 - value :COMMENTS, 336 - value :COMMIT, 337 - value :COMMITTED, 338 - value :CONCURRENTLY, 339 - value :CONFIGURATION, 340 - value :CONFLICT, 341 - value :CONNECTION, 342 - value :CONSTRAINT, 343 - value :CONSTRAINTS, 344 - value :CONTENT_P, 345 - value :CONTINUE_P, 346 - value :CONVERSION_P, 347 - value :COPY, 348 - value :COST, 349 - value :CREATE, 350 - value :CROSS, 351 - value :CSV, 352 - value :CUBE, 353 - value :CURRENT_P, 354 - value :CURRENT_CATALOG, 355 - value :CURRENT_DATE, 356 - value :CURRENT_ROLE, 357 - value :CURRENT_SCHEMA, 358 - value :CURRENT_TIME, 359 - value :CURRENT_TIMESTAMP, 360 - value :CURRENT_USER, 361 - value :CURSOR, 362 - value :CYCLE, 363 - value :DATA_P, 364 - value :DATABASE, 365 - value :DAY_P, 366 - value :DEALLOCATE, 367 - value :DEC, 368 - value :DECIMAL_P, 369 - value :DECLARE, 370 - value :DEFAULT, 371 - value :DEFAULTS, 372 - value :DEFERRABLE, 373 - value :DEFERRED, 374 - value :DEFINER, 375 - value :DELETE_P, 376 - value :DELIMITER, 377 - value :DELIMITERS, 378 - value :DEPENDS, 379 - value :DESC, 380 - value :DETACH, 381 - value :DICTIONARY, 382 - value :DISABLE_P, 383 - value :DISCARD, 384 - value :DISTINCT, 385 - value :DO, 386 - value :DOCUMENT_P, 387 - value :DOMAIN_P, 388 - value :DOUBLE_P, 389 - value :DROP, 390 - value :EACH, 391 - value :ELSE, 392 - value :ENABLE_P, 393 - value :ENCODING, 394 - value :ENCRYPTED, 395 - value :END_P, 396 - value :ENUM_P, 397 - value :ESCAPE, 398 - value :EVENT, 399 - value :EXCEPT, 400 - value :EXCLUDE, 401 - value :EXCLUDING, 402 - value :EXCLUSIVE, 403 - value :EXECUTE, 404 - value :EXISTS, 405 - value :EXPLAIN, 406 - value :EXPRESSION, 407 - value :EXTENSION, 408 - value :EXTERNAL, 409 - value :EXTRACT, 410 - value :FALSE_P, 411 - value :FAMILY, 412 - value :FETCH, 413 - value :FILTER, 414 - value :FIRST_P, 415 - value :FLOAT_P, 416 - value :FOLLOWING, 417 - value :FOR, 418 - value :FORCE, 419 - value :FOREIGN, 420 - value :FORWARD, 421 - value :FREEZE, 422 - value :FROM, 423 - value :FULL, 424 - value :FUNCTION, 425 - value :FUNCTIONS, 426 - value :GENERATED, 427 - value :GLOBAL, 428 - value :GRANT, 429 - value :GRANTED, 430 - value :GREATEST, 431 - value :GROUP_P, 432 - value :GROUPING, 433 - value :GROUPS, 434 - value :HANDLER, 435 - value :HAVING, 436 - value :HEADER_P, 437 - value :HOLD, 438 - value :HOUR_P, 439 - value :IDENTITY_P, 440 - value :IF_P, 441 - value :ILIKE, 442 - value :IMMEDIATE, 443 - value :IMMUTABLE, 444 - value :IMPLICIT_P, 445 - value :IMPORT_P, 446 - value :IN_P, 447 - value :INCLUDE, 448 - value :INCLUDING, 449 - value :INCREMENT, 450 - value :INDEX, 451 - value :INDEXES, 452 - value :INHERIT, 453 - value :INHERITS, 454 - value :INITIALLY, 455 - value :INLINE_P, 456 - value :INNER_P, 457 - value :INOUT, 458 - value :INPUT_P, 459 - value :INSENSITIVE, 460 - value :INSERT, 461 - value :INSTEAD, 462 - value :INT_P, 463 - value :INTEGER, 464 - value :INTERSECT, 465 - value :INTERVAL, 466 - value :INTO, 467 - value :INVOKER, 468 - value :IS, 469 - value :ISNULL, 470 - value :ISOLATION, 471 - value :JOIN, 472 - value :KEY, 473 - value :LABEL, 474 - value :LANGUAGE, 475 - value :LARGE_P, 476 - value :LAST_P, 477 - value :LATERAL_P, 478 - value :LEADING, 479 - value :LEAKPROOF, 480 - value :LEAST, 481 - value :LEFT, 482 - value :LEVEL, 483 - value :LIKE, 484 - value :LIMIT, 485 - value :LISTEN, 486 - value :LOAD, 487 - value :LOCAL, 488 - value :LOCALTIME, 489 - value :LOCALTIMESTAMP, 490 - value :LOCATION, 491 - value :LOCK_P, 492 - value :LOCKED, 493 - value :LOGGED, 494 - value :MAPPING, 495 - value :MATCH, 496 - value :MATERIALIZED, 497 - value :MAXVALUE, 498 - value :METHOD, 499 - value :MINUTE_P, 500 - value :MINVALUE, 501 - value :MODE, 502 - value :MONTH_P, 503 - value :MOVE, 504 - value :NAME_P, 505 - value :NAMES, 506 - value :NATIONAL, 507 - value :NATURAL, 508 - value :NCHAR, 509 - value :NEW, 510 - value :NEXT, 511 - value :NFC, 512 - value :NFD, 513 - value :NFKC, 514 - value :NFKD, 515 - value :NO, 516 - value :NONE, 517 - value :NORMALIZE, 518 - value :NORMALIZED, 519 - value :NOT, 520 - value :NOTHING, 521 - value :NOTIFY, 522 - value :NOTNULL, 523 - value :NOWAIT, 524 - value :NULL_P, 525 - value :NULLIF, 526 - value :NULLS_P, 527 - value :NUMERIC, 528 - value :OBJECT_P, 529 - value :OF, 530 - value :OFF, 531 - value :OFFSET, 532 - value :OIDS, 533 - value :OLD, 534 - value :ON, 535 - value :ONLY, 536 - value :OPERATOR, 537 - value :OPTION, 538 - value :OPTIONS, 539 - value :OR, 540 - value :ORDER, 541 - value :ORDINALITY, 542 - value :OTHERS, 543 - value :OUT_P, 544 - value :OUTER_P, 545 - value :OVER, 546 - value :OVERLAPS, 547 - value :OVERLAY, 548 - value :OVERRIDING, 549 - value :OWNED, 550 - value :OWNER, 551 - value :PARALLEL, 552 - value :PARSER, 553 - value :PARTIAL, 554 - value :PARTITION, 555 - value :PASSING, 556 - value :PASSWORD, 557 - value :PLACING, 558 - value :PLANS, 559 - value :POLICY, 560 - value :POSITION, 561 - value :PRECEDING, 562 - value :PRECISION, 563 - value :PRESERVE, 564 - value :PREPARE, 565 - value :PREPARED, 566 - value :PRIMARY, 567 - value :PRIOR, 568 - value :PRIVILEGES, 569 - value :PROCEDURAL, 570 - value :PROCEDURE, 571 - value :PROCEDURES, 572 - value :PROGRAM, 573 - value :PUBLICATION, 574 - value :QUOTE, 575 - value :RANGE, 576 - value :READ, 577 - value :REAL, 578 - value :REASSIGN, 579 - value :RECHECK, 580 - value :RECURSIVE, 581 - value :REF, 582 - value :REFERENCES, 583 - value :REFERENCING, 584 - value :REFRESH, 585 - value :REINDEX, 586 - value :RELATIVE_P, 587 - value :RELEASE, 588 - value :RENAME, 589 - value :REPEATABLE, 590 - value :REPLACE, 591 - value :REPLICA, 592 - value :RESET, 593 - value :RESTART, 594 - value :RESTRICT, 595 - value :RETURNING, 596 - value :RETURNS, 597 - value :REVOKE, 598 - value :RIGHT, 599 - value :ROLE, 600 - value :ROLLBACK, 601 - value :ROLLUP, 602 - value :ROUTINE, 603 - value :ROUTINES, 604 - value :ROW, 605 - value :ROWS, 606 - value :RULE, 607 - value :SAVEPOINT, 608 - value :SCHEMA, 609 - value :SCHEMAS, 610 - value :SCROLL, 611 - value :SEARCH, 612 - value :SECOND_P, 613 - value :SECURITY, 614 - value :SELECT, 615 - value :SEQUENCE, 616 - value :SEQUENCES, 617 - value :SERIALIZABLE, 618 - value :SERVER, 619 - value :SESSION, 620 - value :SESSION_USER, 621 - value :SET, 622 - value :SETS, 623 - value :SETOF, 624 - value :SHARE, 625 - value :SHOW, 626 - value :SIMILAR, 627 - value :SIMPLE, 628 - value :SKIP, 629 - value :SMALLINT, 630 - value :SNAPSHOT, 631 - value :SOME, 632 - value :SQL_P, 633 - value :STABLE, 634 - value :STANDALONE_P, 635 - value :START, 636 - value :STATEMENT, 637 - value :STATISTICS, 638 - value :STDIN, 639 - value :STDOUT, 640 - value :STORAGE, 641 - value :STORED, 642 - value :STRICT_P, 643 - value :STRIP_P, 644 - value :SUBSCRIPTION, 645 - value :SUBSTRING, 646 - value :SUPPORT, 647 - value :SYMMETRIC, 648 - value :SYSID, 649 - value :SYSTEM_P, 650 - value :TABLE, 651 - value :TABLES, 652 - value :TABLESAMPLE, 653 - value :TABLESPACE, 654 - value :TEMP, 655 - value :TEMPLATE, 656 - value :TEMPORARY, 657 - value :TEXT_P, 658 - value :THEN, 659 - value :TIES, 660 - value :TIME, 661 - value :TIMESTAMP, 662 - value :TO, 663 - value :TRAILING, 664 - value :TRANSACTION, 665 - value :TRANSFORM, 666 - value :TREAT, 667 - value :TRIGGER, 668 - value :TRIM, 669 - value :TRUE_P, 670 - value :TRUNCATE, 671 - value :TRUSTED, 672 - value :TYPE_P, 673 - value :TYPES_P, 674 - value :UESCAPE, 675 - value :UNBOUNDED, 676 - value :UNCOMMITTED, 677 - value :UNENCRYPTED, 678 - value :UNION, 679 - value :UNIQUE, 680 - value :UNKNOWN, 681 - value :UNLISTEN, 682 - value :UNLOGGED, 683 - value :UNTIL, 684 - value :UPDATE, 685 - value :USER, 686 - value :USING, 687 - value :VACUUM, 688 - value :VALID, 689 - value :VALIDATE, 690 - value :VALIDATOR, 691 - value :VALUE_P, 692 - value :VALUES, 693 - value :VARCHAR, 694 - value :VARIADIC, 695 - value :VARYING, 696 - value :VERBOSE, 697 - value :VERSION_P, 698 - value :VIEW, 699 - value :VIEWS, 700 - value :VOLATILE, 701 - value :WHEN, 702 - value :WHERE, 703 - value :WHITESPACE_P, 704 - value :WINDOW, 705 - value :WITH, 706 - value :WITHIN, 707 - value :WITHOUT, 708 - value :WORK, 709 - value :WRAPPER, 710 - value :WRITE, 711 - value :XML_P, 712 - value :XMLATTRIBUTES, 713 - value :XMLCONCAT, 714 - value :XMLELEMENT, 715 - value :XMLEXISTS, 716 - value :XMLFOREST, 717 - value :XMLNAMESPACES, 718 - value :XMLPARSE, 719 - value :XMLPI, 720 - value :XMLROOT, 721 - value :XMLSERIALIZE, 722 - value :XMLTABLE, 723 - value :YEAR_P, 724 - value :YES_P, 725 - value :ZONE, 726 - value :NOT_LA, 727 - value :NULLS_LA, 728 - value :WITH_LA, 729 - value :POSTFIXOP, 730 - value :UMINUS, 731 - end - end -end - -module PgQuery - ScanOutput = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.ScanOutput").msgclass - ScanToken = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.ScanToken").msgclass - KeywordKind = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.KeywordKind").enummodule - Token = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("pg_query.Token").enummodule -end diff --git a/spec/lib/parse_spec.rb b/spec/lib/parse_spec.rb index 52421ad4..a83b300b 100644 --- a/spec/lib/parse_spec.rb +++ b/spec/lib/parse_spec.rb @@ -3,39 +3,69 @@ describe PgQuery, '.parse' do it "parses a simple query" do query = described_class.parse("SELECT 1") - expect(query.tree).to eq [ - { - described_class::RAW_STMT => { - described_class::STMT_FIELD => { - described_class::SELECT_STMT => { - described_class::TARGET_LIST_FIELD => [ + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + select_stmt: PgQuery::SelectStmt.new( + target_list: [ + PgQuery::Node.new( + res_target: PgQuery::ResTarget.new( + val: PgQuery::Node.new( + a_const: PgQuery::A_Const.new( + val: PgQuery::Node.new( + integer: PgQuery::Integer.new( + ival: 1 + ) + ), + location: 7 + ) + ), + location: 7 + ) + ) + ], + limit_option: :LIMIT_OPTION_DEFAULT, # TODO: This is cumbersome, we should have LIMIT_OPTION_DEFAULT be the zero state here + op: :SETOP_NONE # TODO: This should be the default + ) + ) + ) + ) + expect(JSON.parse(PgQuery::ParseResult.encode_json(query.tree))).to eq({ + "version" => 130002, + "stmts" => [ + { + "stmt" => { + "selectStmt" => { + "limitOption" => "LIMIT_OPTION_DEFAULT", + "op" => "SETOP_NONE", + "targetList" => [ { - described_class::RES_TARGET => { + "resTarget" => { + "location"=>7, "val" => { - described_class::A_CONST => { + "aConst" => { + "location" => 7, "val" => { - described_class::INTEGER => { "ival" => 1 } - }, - "location" => 7 + "integer" => { + "ival" => 1 + } + } } - }, - "location" => 7 + } } } - ], - "limitOption" => 0, - "op" => 0 + ] } } } - } - ] + ] + }) end it "handles errors" do expect { described_class.parse("SELECT 'ERR") }.to(raise_error do |error| - expect(error).to be_a(described_class::ParseError) - expect(error.message).to eq "unterminated quoted string at or near \"'ERR\" (scan.l:1233)" + expect(error).to be_a(PgQuery::ParseError) + expect(error.message).to eq "unterminated quoted string at or near \"'ERR\" (scan.l:1234)" expect(error.location).to eq 8 # 8th character in query string end) end @@ -43,8 +73,8 @@ it 'returns JSON error due to too much nesting' do query_text = 'SELECT a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(a(b))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))' expect { described_class.parse(query_text) }.to(raise_error do |error| - expect(error).to be_a(described_class::ParseError) - expect(error.message).to start_with 'Failed to parse JSON' + expect(error).to be_a(PgQuery::ParseError) + expect(error.message).to start_with 'Failed to parse tree' end) end @@ -57,33 +87,33 @@ it "parses empty queries" do query = described_class.parse("-- nothing") - expect(query.tree).to eq [] + expect(query.tree).to eq PgQuery::ParseResult.new(version: 130002, stmts: []) expect(query.tables).to eq [] expect(query.warnings).to be_empty end it "parses floats with leading dot" do q = described_class.parse("SELECT .1") - expr = q.tree[0][described_class::RAW_STMT][described_class::STMT_FIELD][described_class::SELECT_STMT][described_class::TARGET_LIST_FIELD][0][described_class::RES_TARGET]["val"] - expect(expr).to eq(described_class::A_CONST => {"val"=>{described_class::FLOAT => {"str" => ".1"}}, "location"=>7}) + expr = q.tree.stmts[0].stmt.select_stmt.target_list[0].res_target.val + expect(expr).to eq(PgQuery::Node.new(a_const: PgQuery::A_Const.new(val: PgQuery::Node.new(float: PgQuery::Float.new(str: '.1')), location: 7))) end it "parses floats with trailing dot" do q = described_class.parse("SELECT 1.") - expr = q.tree[0][described_class::RAW_STMT][described_class::STMT_FIELD][described_class::SELECT_STMT][described_class::TARGET_LIST_FIELD][0][described_class::RES_TARGET]["val"] - expect(expr).to eq(described_class::A_CONST => {"val"=>{described_class::FLOAT => {"str" => "1."}}, "location"=>7}) + expr = q.tree.stmts[0].stmt.select_stmt.target_list[0].res_target.val + expect(expr).to eq(PgQuery::Node.new(a_const: PgQuery::A_Const.new(val: PgQuery::Node.new(float: PgQuery::Float.new(str: '1.')), location: 7))) end it 'parses bit strings (binary notation)' do q = described_class.parse("SELECT B'0101'") - expr = q.tree[0][described_class::RAW_STMT][described_class::STMT_FIELD][described_class::SELECT_STMT][described_class::TARGET_LIST_FIELD][0][described_class::RES_TARGET]["val"] - expect(expr).to eq(described_class::A_CONST => {"val"=>{described_class::BIT_STRING => {"str" => "b0101"}}, "location"=>7}) + expr = q.tree.stmts[0].stmt.select_stmt.target_list[0].res_target.val + expect(expr).to eq(PgQuery::Node.new(a_const: PgQuery::A_Const.new(val: PgQuery::Node.new(bit_string: PgQuery::BitString.new(str: 'b0101')), location: 7))) end it 'parses bit strings (hex notation)' do q = described_class.parse("SELECT X'EFFF'") - expr = q.tree[0][described_class::RAW_STMT][described_class::STMT_FIELD][described_class::SELECT_STMT][described_class::TARGET_LIST_FIELD][0][described_class::RES_TARGET]["val"] - expect(expr).to eq(described_class::A_CONST => {"val"=>{described_class::BIT_STRING => {"str" => "xEFFF"}}, "location"=>7}) + expr = q.tree.stmts[0].stmt.select_stmt.target_list[0].res_target.val + expect(expr).to eq(PgQuery::Node.new(a_const: PgQuery::A_Const.new(val: PgQuery::Node.new(bit_string: PgQuery::BitString.new(str: 'xEFFF')), location: 7))) end it "parses ALTER TABLE" do @@ -91,54 +121,95 @@ expect(query.warnings).to eq [] expect(query.tables).to eq ['test'] expect(query.ddl_tables).to eq ['test'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => {described_class::ALTER_TABLE_STMT=> - {"relation"=> - {described_class::RANGE_VAR=> - {"relname"=>"test", - "inh"=>true, - "relpersistence"=>"p", - "location"=>12}}, - "cmds"=> - [{described_class::ALTER_TABLE_CMD=> - {"subtype"=>described_class::AT_AddConstraint, - "def"=> - {described_class::CONSTRAINT=> - {"contype"=>described_class::CONSTR_TYPE_PRIMARY, - "location"=>21, - "keys"=>[{"String" => {"str" => "gid"}}]}}, - "behavior"=>0}}], - "relkind"=>described_class::OBJECT_TYPE_TABLE}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + alter_table_stmt: PgQuery::AlterTableStmt.new( + relation: PgQuery::RangeVar.new(relname: 'test', inh: true, relpersistence: 'p', location: 12), + cmds: [ + PgQuery::Node.new( + alter_table_cmd: PgQuery::AlterTableCmd.new( + subtype: :AT_AddConstraint, + def: PgQuery::Node.new( + constraint: PgQuery::Constraint.new( + contype: :CONSTR_PRIMARY, + location: 21, + keys: [PgQuery::Node.new(string: PgQuery::String.new(str: 'gid'))] + ) + ), + behavior: :DROP_RESTRICT + ) + ) + ], + relkind: :OBJECT_TABLE + ) + ) + ) + ) end it "parses SET" do query = described_class.parse("SET statement_timeout=0") expect(query.warnings).to eq [] expect(query.tables).to eq [] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::VARIABLE_SET_STMT=> - {"kind"=>0, - "name"=>"statement_timeout", - "args"=>[{described_class::A_CONST=>{"val"=>{described_class::INTEGER => {"ival" => 0}}, "location"=>22}}]}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + variable_set_stmt: PgQuery::VariableSetStmt.new( + kind: :VAR_SET_VALUE, + name: 'statement_timeout', + args: [ + PgQuery::Node.new( + a_const: PgQuery::A_Const.new( + val: PgQuery::Node.new( + integer: PgQuery::Integer.new(ival: 0) + ), + location: 22 + ) + ) + ] + ) + ) + ) + ) end it "parses SHOW" do query = described_class.parse("SHOW work_mem") expect(query.warnings).to eq [] expect(query.tables).to eq [] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::VARIABLE_SHOW_STMT=>{"name"=>"work_mem"}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + variable_show_stmt: PgQuery::VariableShowStmt.new( + name: 'work_mem' + ) + ) + ) + ) end it "parses COPY" do query = described_class.parse("COPY test (id) TO stdout") expect(query.warnings).to eq [] expect(query.tables).to eq ['test'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::COPY_STMT=> - {"relation"=> - {described_class::RANGE_VAR=> - {"relname"=>"test", - "inh"=>true, - "relpersistence"=>"p", - "location"=>5}}, - "attlist"=>[{"String"=>{"str"=>"id"}}]}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + copy_stmt: PgQuery::CopyStmt.new( + relation: PgQuery::RangeVar.new( + relname: 'test', + inh: true, + relpersistence: 'p', + location: 5, + ), + attlist: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'id')) + ] + ) + ) + ) + ) end it "parses DROP TABLE" do @@ -146,22 +217,50 @@ expect(query.warnings).to eq [] expect(query.tables).to eq ['abc.test123'] expect(query.ddl_tables).to eq ['abc.test123'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::DROP_STMT=> - {"objects"=>[[{"String"=>{"str"=>"abc"}}, {"String"=>{"str"=>"test123"}}]], - "removeType"=>described_class::OBJECT_TYPE_TABLE, - "behavior"=>1}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + drop_stmt: PgQuery::DropStmt.new( + objects: [ + PgQuery::Node.new(list: PgQuery::List.new( + items: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'abc')), + PgQuery::Node.new(string: PgQuery::String.new(str: 'test123')) + ] + )) + ], + remove_type: :OBJECT_TABLE, + behavior: :DROP_CASCADE + ) + ) + ) + ) end it "parses COMMIT" do query = described_class.parse("COMMIT") expect(query.warnings).to eq [] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::TRANSACTION_STMT=>{"kind"=>2}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + transaction_stmt: PgQuery::TransactionStmt.new( + kind: :TRANS_STMT_COMMIT + ) + ) + ) + ) end it "parses CHECKPOINT" do query = described_class.parse("CHECKPOINT") expect(query.warnings).to eq [] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::CHECK_POINT_STMT=>{}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + check_point_stmt: PgQuery::CheckPointStmt.new + ) + ) + ) end it "parses VACUUM" do @@ -169,46 +268,51 @@ expect(query.warnings).to eq [] expect(query.tables).to eq ['my_table'] expect(query.ddl_tables).to eq ['my_table'] - expect(query.tree).to eq [ - { - described_class::RAW_STMT => { - described_class::STMT_FIELD => { - described_class::VACUUM_STMT => { - "is_vacuumcmd"=>true, - "rels"=> [ - { - "VacuumRelation" => { - "relation" => { - described_class::RANGE_VAR => { - "relname" => "my_table", - "inh" => true, - "relpersistence" => "p", - "location"=>7 - } - } - } - } - ] - } - } - } - } - ] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + vacuum_stmt: PgQuery::VacuumStmt.new( + is_vacuumcmd: true, + rels: [ + PgQuery::Node.new( + vacuum_relation: PgQuery::VacuumRelation.new( + relation: PgQuery::RangeVar.new( + relname: 'my_table', + inh: true, + relpersistence: 'p', + location: 7 + ) + ) + ) + ] + ) + ) + ) + ) end it "parses EXPLAIN" do query = described_class.parse("EXPLAIN DELETE FROM test") expect(query.warnings).to eq [] expect(query.tables).to eq ['test'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::EXPLAIN_STMT=> - {"query"=> - {described_class::DELETE_STMT=> - {"relation"=> - {described_class::RANGE_VAR=> - {"relname"=>"test", - "inh"=>true, - "relpersistence"=>"p", - "location"=>20}}}}}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + explain_stmt: PgQuery::ExplainStmt.new( + query: PgQuery::Node.new( + delete_stmt: PgQuery::DeleteStmt.new( + relation: PgQuery::RangeVar.new( + relname: 'test', + inh: true, + relpersistence: 'p', + location: 20 + ) + ) + ) + ) + ) + ) + ) end it "parses SELECT INTO" do @@ -216,40 +320,71 @@ expect(query.warnings).to eq [] expect(query.tables).to eq ['test'] expect(query.ddl_tables).to eq ['test'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::CREATE_TABLE_AS_STMT=> - {"query"=> - {described_class::SELECT_STMT=> - {described_class::TARGET_LIST_FIELD=> - [{described_class::RES_TARGET=> - {"val"=>{described_class::A_CONST=>{"val"=>{described_class::INTEGER => {"ival" => 1}}, "location"=>33}}, - "location"=>33}}], - "limitOption" => 0, - "op"=>0}}, - "into"=> - {described_class::INTO_CLAUSE=> - {"rel"=> - {described_class::RANGE_VAR=> - {"relname"=>"test", - "inh"=>true, - "relpersistence"=>"t", - "location"=>18}}, - "onCommit"=>0}}, - "relkind"=>described_class::OBJECT_TYPE_TABLE}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + create_table_as_stmt: PgQuery::CreateTableAsStmt.new( + query: PgQuery::Node.new( + select_stmt: PgQuery::SelectStmt.new( + target_list: [ + PgQuery::Node.new( + res_target: PgQuery::ResTarget.new( + val: PgQuery::Node.new( + a_const: PgQuery::A_Const.new( + val: PgQuery::Node.new( + integer: PgQuery::Integer.new(ival: 1) + ), + location: 33 + ) + ), + location: 33 + ) + ) + ], + limit_option: :LIMIT_OPTION_DEFAULT, + op: :SETOP_NONE + ) + ), + into: PgQuery::IntoClause.new( + rel: PgQuery::RangeVar.new( + relname: 'test', + inh: true, + relpersistence: 't', + location: 18 + ), + on_commit: :ONCOMMIT_NOOP + ), + relkind: :OBJECT_TABLE + ) + ) + ) + ) end it "parses LOCK" do query = described_class.parse("LOCK TABLE public.schema_migrations IN ACCESS SHARE MODE") expect(query.warnings).to eq [] expect(query.tables).to eq ['public.schema_migrations'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::LOCK_STMT=> - {"relations"=> - [{described_class::RANGE_VAR=> - {"schemaname"=>"public", - "relname"=>"schema_migrations", - "inh"=>true, - "relpersistence"=>"p", - "location"=>11}}], - "mode"=>1}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + lock_stmt: PgQuery::LockStmt.new( + relations: [ + PgQuery::Node.new( + range_var: PgQuery::RangeVar.new( + schemaname: 'public', + relname: 'schema_migrations', + inh: true, + relpersistence: 'p', + location: 11 + ) + ) + ], + mode: PgQuery::LOCK_MODE_ACCESS_SHARE_LOCK + ) + ) + ) + ) end it 'parses CREATE TABLE' do @@ -257,30 +392,43 @@ expect(query.warnings).to eq [] expect(query.tables).to eq ['test'] expect(query.ddl_tables).to eq ['test'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::CREATE_STMT=> - {"relation"=> - {described_class::RANGE_VAR=> - {"relname"=>"test", - "inh"=>true, - "relpersistence"=>"p", - "location"=>13}}, - "tableElts"=> - [{described_class::COLUMN_DEF=> - {"colname"=>"a", - "typeName"=> - {described_class::TYPE_NAME=> - {"names"=>[{"String"=>{"str"=>"int4"}}], - "typemod"=>-1, - "location"=>21}}, - "is_local"=>true, - "location"=>19}}], - "oncommit"=>0}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + create_stmt: PgQuery::CreateStmt.new( + relation: PgQuery::RangeVar.new( + relname: 'test', + inh: true, + relpersistence: 'p', + location: 13 + ), + table_elts: [ + PgQuery::Node.new( + column_def: PgQuery::ColumnDef.new( + colname: 'a', + type_name: PgQuery::TypeName.new( + names: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'int4')) + ], + typemod: -1, + location: 21 + ), + is_local: true, + location: 19 + ) + ) + ], + oncommit: :ONCOMMIT_NOOP + ) + ) + ) + ) end it 'fails to parse CREATE TABLE WITH OIDS' do expect { described_class.parse("CREATE TABLE test (a int4) WITH OIDS") }.to(raise_error do |error| - expect(error).to be_a(described_class::ParseError) - expect(error.message).to eq "syntax error at or near \"OIDS\" (scan.l:1233)" + expect(error).to be_a(PgQuery::ParseError) + expect(error.message).to eq "syntax error at or near \"OIDS\" (scan.l:1234)" expect(error.location).to eq 33 # 33rd character in query string end) end @@ -290,47 +438,48 @@ expect(query.warnings).to eq [] expect(query.tables).to eq ['test'] expect(query.ddl_tables).to eq ['test'] - expect(query.tree).to eq [ - { - described_class::RAW_STMT => { - described_class::STMT_FIELD => { - described_class::INDEX_STMT => { - "idxname" => "testidx", - "relation" => { - described_class::RANGE_VAR => { - "relname" => "test", - "inh" => true, - "relpersistence" => "p", - "location" => 24 - } - }, - "accessMethod" => "gist", - "indexParams" => [ - { - described_class::INDEX_ELEM => { - "name" => "a", - "ordering" => 0, - "nulls_ordering" => 0 - } - } - ], - "oldCreateSubid"=>0, - "oldFirstRelfilenodeSubid"=>0 - } - } - } - } - ] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + index_stmt: PgQuery::IndexStmt.new( + idxname: 'testidx', + relation: PgQuery::RangeVar.new( + relname: 'test', + inh: true, + relpersistence: 'p', + location: 24 + ), + access_method: 'gist', + index_params: [ + PgQuery::Node.new( + index_elem: PgQuery::IndexElem.new( + name: 'a', + ordering: :SORTBY_DEFAULT, + nulls_ordering: :SORTBY_NULLS_DEFAULT + ) + ) + ] + ) + ) + ) + ) end it 'parses CREATE SCHEMA' do query = described_class.parse('CREATE SCHEMA IF NOT EXISTS test AUTHORIZATION joe') expect(query.warnings).to eq [] expect(query.tables).to eq [] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::CREATE_SCHEMA_STMT=> - {"schemaname"=>"test", - "authrole"=>{described_class::ROLE_SPEC=>{"roletype"=>0, "rolename"=>"joe", "location"=>47}}, - "if_not_exists"=>true}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + create_schema_stmt: PgQuery::CreateSchemaStmt.new( + schemaname: 'test', + authrole: PgQuery::RoleSpec.new(roletype: :ROLESPEC_CSTRING, rolename: 'joe', location: 47), + if_not_exists: true + ) + ) + ) + ) end it 'parses CREATE VIEW' do @@ -339,29 +488,52 @@ expect(query.tables).to eq ['myview', 'mytab'] expect(query.ddl_tables).to eq ['myview'] expect(query.select_tables).to eq ['mytab'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::VIEW_STMT=> - {"view"=> - {described_class::RANGE_VAR=> - {"relname"=>"myview", - "inh"=>true, - "relpersistence"=>"p", - "location"=>12}}, - "query"=> - {described_class::SELECT_STMT=> - {described_class::TARGET_LIST_FIELD=> - [{described_class::RES_TARGET=> - {"val"=> - {described_class::COLUMN_REF=>{"fields"=>[{described_class::A_STAR=>{}}], "location"=>29}}, - "location"=>29}}], - "fromClause"=> - [{described_class::RANGE_VAR=> - {"relname"=>"mytab", - "inh"=>true, - "relpersistence"=>"p", - "location"=>36}}], - "limitOption"=>0, - "op"=>0}}, - "withCheckOption"=>0}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + view_stmt: PgQuery::ViewStmt.new( + view: PgQuery::RangeVar.new( + relname: 'myview', + inh: true, + relpersistence: 'p', + location: 12 + ), + query: PgQuery::Node.new( + select_stmt: PgQuery::SelectStmt.new( + target_list: [ + PgQuery::Node.new( + res_target: PgQuery::ResTarget.new( + val: PgQuery::Node.new( + column_ref: PgQuery::ColumnRef.new( + fields: [ + PgQuery::Node.new(a_star: PgQuery::A_Star.new) + ], + location: 29 + ) + ), + location: 29 + ) + ) + ], + from_clause: [ + PgQuery::Node.new( + range_var: PgQuery::RangeVar.new( + relname: 'mytab', + inh: true, + relpersistence: 'p', + location: 36 + ) + ) + ], + limit_option: :LIMIT_OPTION_DEFAULT, + op: :SETOP_NONE + ) + ), + with_check_option: :NO_CHECK_OPTION + ) + ) + ) + ) end it 'parses REFRESH MATERIALIZED VIEW' do @@ -369,13 +541,20 @@ expect(query.warnings).to eq [] expect(query.tables).to eq ['myview'] expect(query.ddl_tables).to eq ['myview'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::REFRESH_MAT_VIEW_STMT=> - {"relation"=> - {described_class::RANGE_VAR=> - {"relname"=>"myview", - "inh"=>true, - "relpersistence"=>"p", - "location"=>26}}}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + refresh_mat_view_stmt: PgQuery::RefreshMatViewStmt.new( + relation: PgQuery::RangeVar.new( + relname: 'myview', + inh: true, + relpersistence: 'p', + location: 26 + ) + ) + ) + ) + ) end it 'parses CREATE RULE' do @@ -383,16 +562,23 @@ DO INSTEAD NOTHING') expect(query.warnings).to eq [] expect(query.tables).to eq ['shoe'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::RULE_STMT=> - {"relation"=> - {described_class::RANGE_VAR=> - {"relname"=>"shoe", - "inh"=>true, - "relpersistence"=>"p", - "location"=>45}}, - "rulename"=>"shoe_ins_protect", - "event"=>3, - "instead"=>true}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + rule_stmt: PgQuery::RuleStmt.new( + relation: PgQuery::RangeVar.new( + relname: 'shoe', + inh: true, + relpersistence: 'p', + location: 45 + ), + rulename: 'shoe_ins_protect', + event: :CMD_INSERT, + instead: true + ) + ) + ) + ) end it 'parses CREATE TRIGGER' do @@ -402,70 +588,157 @@ EXECUTE PROCEDURE check_account_update()') expect(query.warnings).to eq [] expect(query.tables).to eq ['accounts'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::CREATE_TRIG_STMT=> - {"trigname"=>"check_update", - "relation"=> - {described_class::RANGE_VAR=> - {"relname"=>"accounts", - "inh"=>true, - "relpersistence"=>"p", - "location"=>72}}, - "funcname"=>[{"String"=>{"str"=>"check_account_update"}}], - "row"=>true, - "timing"=>2, - "events"=>16}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + create_trig_stmt: PgQuery::CreateTrigStmt.new( + trigname: 'check_update', + relation: PgQuery::RangeVar.new( + relname: 'accounts', + inh: true, + relpersistence: 'p', + location: 72 + ), + funcname: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'check_account_update')) + ], + row: true, + timing: PgQuery::TRIGGER_TYPE_BEFORE, + events: PgQuery::TRIGGER_TYPE_UPDATE + ) + ) + ) + ) end it 'parses DROP SCHEMA' do query = described_class.parse('DROP SCHEMA myschema') expect(query.warnings).to eq [] expect(query.tables).to eq [] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::DROP_STMT=> - {"objects"=>[{"String"=>{"str"=>"myschema"}}], - "removeType"=>described_class::OBJECT_TYPE_SCHEMA, - "behavior"=>0}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + drop_stmt: PgQuery::DropStmt.new( + objects: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'myschema')) + ], + remove_type: :OBJECT_SCHEMA, + behavior: :DROP_RESTRICT + ) + ) + ) + ) end it 'parses DROP VIEW' do query = described_class.parse('DROP VIEW myview, myview2') expect(query.warnings).to eq [] expect(query.tables).to eq [] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::DROP_STMT=> - {"objects"=>[[{"String"=>{"str"=>"myview"}}], [{"String"=>{"str"=>"myview2"}}]], - "removeType"=>described_class::OBJECT_TYPE_VIEW, - "behavior"=>0}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + drop_stmt: PgQuery::DropStmt.new( + objects: [ + PgQuery::Node.new( + list: PgQuery::List.new( + items: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'myview')) + ] + ) + ), + PgQuery::Node.new( + list: PgQuery::List.new( + items: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'myview2')) + ] + ) + ) + ], + remove_type: :OBJECT_VIEW, + behavior: :DROP_RESTRICT + ) + ) + ) + ) end it 'parses DROP INDEX' do query = described_class.parse('DROP INDEX CONCURRENTLY myindex') expect(query.warnings).to eq [] expect(query.tables).to eq [] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::DROP_STMT=> - {"objects"=>[[{"String"=>{"str"=>"myindex"}}]], - "removeType"=>described_class::OBJECT_TYPE_INDEX, - "behavior"=>0, - "concurrent"=>true}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + drop_stmt: PgQuery::DropStmt.new( + objects: [ + PgQuery::Node.new( + list: PgQuery::List.new( + items: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'myindex')) + ] + ) + ) + ], + remove_type: :OBJECT_INDEX, + behavior: :DROP_RESTRICT, + concurrent: true + ) + ) + ) + ) end it 'parses DROP RULE' do query = described_class.parse('DROP RULE myrule ON mytable CASCADE') expect(query.warnings).to eq [] expect(query.tables).to eq ['mytable'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::DROP_STMT=> - {"objects"=>[[{"String"=>{"str"=>"mytable"}}, {"String"=>{"str"=>"myrule"}}]], - "removeType"=>described_class::OBJECT_TYPE_RULE, - "behavior"=>1}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + drop_stmt: PgQuery::DropStmt.new( + objects: [ + PgQuery::Node.new( + list: PgQuery::List.new( + items: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'mytable')), + PgQuery::Node.new(string: PgQuery::String.new(str: 'myrule')) + ] + ) + ) + ], + remove_type: :OBJECT_RULE, + behavior: :DROP_CASCADE + ) + ) + ) + ) end it 'parses DROP TRIGGER' do query = described_class.parse('DROP TRIGGER IF EXISTS mytrigger ON mytable RESTRICT') expect(query.warnings).to eq [] expect(query.tables).to eq ['mytable'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::DROP_STMT=> - {"objects"=>[[{"String"=>{"str"=>"mytable"}}, {"String"=>{"str"=>"mytrigger"}}]], - "removeType"=>described_class::OBJECT_TYPE_TRIGGER, - "behavior"=>0, - "missing_ok"=>true}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + drop_stmt: PgQuery::DropStmt.new( + objects: [ + PgQuery::Node.new( + list: PgQuery::List.new( + items: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'mytable')), + PgQuery::Node.new(string: PgQuery::String.new(str: 'mytrigger')) + ] + ) + ) + ], + remove_type: :OBJECT_TRIGGER, + behavior: :DROP_RESTRICT, + missing_ok: true + ) + ) + ) + ) end it 'parses GRANT' do @@ -473,31 +746,56 @@ expect(query.warnings).to eq [] expect(query.tables).to eq ['mytable'] expect(query.ddl_tables).to eq ['mytable'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::GRANT_STMT=> - {"is_grant"=>true, - "targtype"=>0, - "objtype"=>described_class::OBJECT_TYPE_TABLE, - "objects"=> - [{described_class::RANGE_VAR=> - {"relname"=>"mytable", - "inh"=>true, - "relpersistence"=>"p", - "location"=>24}}], - "privileges"=> - [{described_class::ACCESS_PRIV=>{"priv_name"=>"insert"}}, - {described_class::ACCESS_PRIV=>{"priv_name"=>"update"}}], - "grantees"=>[{described_class::ROLE_SPEC=>{"roletype"=>0, "rolename"=>"myuser", "location"=>35}}], - "behavior"=>0}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + grant_stmt: PgQuery::GrantStmt.new( + is_grant: true, + targtype: :ACL_TARGET_OBJECT, + objtype: :OBJECT_TABLE, + objects: [ + PgQuery::Node.new( + range_var: PgQuery::RangeVar.new( + relname: 'mytable', + inh: true, + relpersistence: 'p', + location: 24 + ) + ) + ], + privileges: [ + PgQuery::Node.new(access_priv: PgQuery::AccessPriv.new(priv_name: 'insert')), + PgQuery::Node.new(access_priv: PgQuery::AccessPriv.new(priv_name: 'update')) + ], + grantees: [ + PgQuery::Node.new(role_spec: PgQuery::RoleSpec.new(roletype: :ROLESPEC_CSTRING, rolename: 'myuser', location: 35)) + ], + behavior: :DROP_RESTRICT + ) + ) + ) + ) end it 'parses REVOKE' do query = described_class.parse('REVOKE admins FROM joe') expect(query.warnings).to eq [] expect(query.tables).to eq [] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::GRANT_ROLE_STMT=> - {"granted_roles"=>[{described_class::ACCESS_PRIV=>{"priv_name"=>"admins"}}], - "grantee_roles"=>[{described_class::ROLE_SPEC=>{"roletype"=>0, "rolename"=>"joe", "location"=>19}}], - "behavior"=>0}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + grant_role_stmt: PgQuery::GrantRoleStmt.new( + granted_roles: [ + PgQuery::Node.new(access_priv: PgQuery::AccessPriv.new(priv_name: 'admins')) + ], + grantee_roles: [ + PgQuery::Node.new(role_spec: PgQuery::RoleSpec.new(roletype: :ROLESPEC_CSTRING, rolename: 'joe', location: 19)) + ], + behavior: :DROP_RESTRICT + ) + ) + ) + ) end it 'parses TRUNCATE' do @@ -523,20 +821,34 @@ type: :ddl } ] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::TRUNCATE_STMT=> - {"relations"=> - [{described_class::RANGE_VAR=> - {"relname"=>"bigtable", - "inh"=>true, - "relpersistence"=>"p", - "location"=>9}}, - {described_class::RANGE_VAR=> - {"relname"=>"fattable", - "inh"=>true, - "relpersistence"=>"p", - "location"=>19}}], - "restart_seqs"=>true, - "behavior"=>0}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + truncate_stmt: PgQuery::TruncateStmt.new( + relations: [ + PgQuery::Node.new( + range_var: PgQuery::RangeVar.new( + relname: 'bigtable', + inh: true, + relpersistence: 'p', + location: 9 + ) + ), + PgQuery::Node.new( + range_var: PgQuery::RangeVar.new( + relname: 'fattable', + inh: true, + relpersistence: 'p', + location: 19 + ) + ) + ], + restart_seqs: true, + behavior: :DROP_RESTRICT + ) + ) + ) + ) end it 'parses WITH' do @@ -544,63 +856,142 @@ expect(query.warnings).to eq [] expect(query.tables).to eq ['x'] expect(query.cte_names).to eq ['a'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::SELECT_STMT=> - {described_class::TARGET_LIST_FIELD=> - [{described_class::RES_TARGET=> - {"val"=>{described_class::COLUMN_REF=>{"fields"=>[{described_class::A_STAR=>{}}], "location"=>61}}, - "location"=>61}}], - "fromClause"=> - [{described_class::RANGE_VAR=> - {"relname"=>"a", - "inh"=>true, - "relpersistence"=>"p", - "location"=>68}}], - "limitOption"=>0, - "withClause"=> - {described_class::WITH_CLAUSE=> - {"ctes"=> - [{described_class::COMMON_TABLE_EXPR=> - {"ctematerialized"=>0, - "ctename"=>"a", - "ctequery"=> - {described_class::SELECT_STMT=> - {described_class::TARGET_LIST_FIELD=> - [{described_class::RES_TARGET=> - {"val"=> - {described_class::COLUMN_REF=> - {"fields"=>[{described_class::A_STAR=>{}}], "location"=>18}}, - "location"=>18}}], - "fromClause"=> - [{described_class::RANGE_VAR=> - {"relname"=>"x", - "inh"=>true, - "relpersistence"=>"p", - "location"=>25}}], - "whereClause"=> - {described_class::BOOL_EXPR=> - {"boolop"=>0, - "args"=> - [{described_class::A_EXPR=> - {"kind" => 0, - "name"=>[{"String"=>{"str"=>"="}}], - "lexpr"=> - {described_class::COLUMN_REF=> - {"fields"=>[{"String"=>{"str"=>"x"}}, {"String"=>{"str"=>"y"}}], "location"=>33}}, - "rexpr"=>{described_class::PARAM_REF=>{"location"=>39}}, - "location"=>37}}, - {described_class::A_EXPR=> - {"kind" => 0, - "name"=>[{"String"=>{"str"=>"="}}], - "lexpr"=> - {described_class::COLUMN_REF=> - {"fields"=>[{"String"=>{"str"=>"x"}}, {"String"=>{"str"=>"z"}}], "location"=>45}}, - "rexpr"=>{described_class::A_CONST=>{"val"=>{described_class::INTEGER => {"ival" => 1}}, "location"=>51}}, - "location"=>49}}], - "location"=>41}}, - "limitOption"=>0, - "op"=>0}}, - "location"=>5}}]}}, - "op"=>0}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + select_stmt: PgQuery::SelectStmt.new( + target_list: [ + PgQuery::Node.new( + res_target: PgQuery::ResTarget.new( + val: PgQuery::Node.new( + column_ref: PgQuery::ColumnRef.new( + fields: [ + PgQuery::Node.new( + a_star: PgQuery::A_Star.new + ) + ], + location: 61 + ) + ), + location: 61 + ) + ) + ], + from_clause: [ + PgQuery::Node.new( + range_var: PgQuery::RangeVar.new( + relname: 'a', + inh: true, + relpersistence: 'p', + location: 68 + ) + ) + ], + limit_option: :LIMIT_OPTION_DEFAULT, + op: :SETOP_NONE, + with_clause: PgQuery::WithClause.new( + ctes: [ + PgQuery::Node.new( + common_table_expr: PgQuery::CommonTableExpr.new( + ctematerialized: :CTEMaterializeDefault, + ctename: 'a', + ctequery: PgQuery::Node.new( + select_stmt: PgQuery::SelectStmt.new( + target_list: [ + PgQuery::Node.new( + res_target: PgQuery::ResTarget.new( + val: PgQuery::Node.new( + column_ref: PgQuery::ColumnRef.new( + fields: [ + PgQuery::Node.new( + a_star: PgQuery::A_Star.new + ) + ], + location: 18 + ) + ), + location: 18 + ) + ) + ], + from_clause: [ + PgQuery::Node.new( + range_var: PgQuery::RangeVar.new( + relname: 'x', + inh: true, + relpersistence: 'p', + location: 25 + ) + ) + ], + limit_option: :LIMIT_OPTION_DEFAULT, + op: :SETOP_NONE, + where_clause: PgQuery::Node.new( + bool_expr: PgQuery::BoolExpr.new( + boolop: :AND_EXPR, + args: [ + PgQuery::Node.new( + a_expr: PgQuery::A_Expr.new( + kind: :AEXPR_OP, + name: [ + PgQuery::Node.new(string: PgQuery::String.new(str: '=')) + ], + lexpr: PgQuery::Node.new( + column_ref: PgQuery::ColumnRef.new( + fields: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'x')), + PgQuery::Node.new(string: PgQuery::String.new(str: 'y')) + ], + location: 33 + ) + ), + rexpr: PgQuery::Node.new( + param_ref: PgQuery::ParamRef.new( + location: 39 + ) + ), + location: 37 + ) + ), + PgQuery::Node.new( + a_expr: PgQuery::A_Expr.new( + kind: :AEXPR_OP, + name: [ + PgQuery::Node.new(string: PgQuery::String.new(str: '=')) + ], + lexpr: PgQuery::Node.new( + column_ref: PgQuery::ColumnRef.new( + fields: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'x')), + PgQuery::Node.new(string: PgQuery::String.new(str: 'z')) + ], + location: 45 + ) + ), + rexpr: PgQuery::Node.new( + a_const: PgQuery::A_Const.new( + val: PgQuery::Node.new(integer: PgQuery::Integer.new(ival: 1)), + location: 51 + ) + ), + location: 49 + ) + ) + ], + location: 41 + ) + ) + ) + ), + location: 5 + ) + ) + ] + ) + ) + ) + ) + ) end it 'parses multi-line function definitions' do @@ -624,41 +1015,77 @@ LANGUAGE plpgsql STABLE') expect(query.warnings).to eq [] expect(query.tables).to eq [] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::CREATE_FUNCTION_STMT=> - {"replace"=>true, - "funcname"=>[{"String"=>{"str"=>"thing"}}], - "parameters"=> - [{described_class::FUNCTION_PARAMETER=> - {"name"=>"parameter_thing", - "argType"=> - {described_class::TYPE_NAME=> - {"names"=>[{"String"=>{"str"=>"text"}}], - "typemod"=>-1, - "location"=>49}}, - "mode"=>105}}], - "returnType"=> - {described_class::TYPE_NAME=> - {"names"=>[{"String"=>{"str"=>"pg_catalog"}}, {"String"=>{"str"=>"int8"}}], - "typemod"=>-1, - "location"=>65}}, - "options"=> - [{described_class::DEF_ELEM=> - {"defname"=>"as", - "arg"=> - [{"String"=> - {"str"=>"\nDECLARE\n local_thing_id BIGINT := 0;\nBEGIN\n SELECT thing_id INTO local_thing_id FROM thing_map\n WHERE\n thing_map_field = parameter_thing\n ORDER BY 1 LIMIT 1;\n\n IF NOT FOUND THEN\n local_thing_id = 0;\n END IF;\n RETURN local_thing_id;\nEND;\n"}}], - "defaction"=>0, - "location"=>72}}, - {described_class::DEF_ELEM=> - {"defname"=>"language", - "arg"=>{"String"=>{"str"=>"plpgsql"}}, - "defaction"=>0, - "location"=>407}}, - {described_class::DEF_ELEM=> - {"defname"=>"volatility", - "arg"=>{"String"=>{"str"=>"stable"}}, - "defaction"=>0, - "location"=>424}}]}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + create_function_stmt: PgQuery::CreateFunctionStmt.new( + replace: true, + funcname: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'thing')) + ], + parameters: [ + PgQuery::Node.new(function_parameter: PgQuery::FunctionParameter.new( + name: 'parameter_thing', + arg_type: PgQuery::TypeName.new( + names: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'text')) + ], + typemod: -1, + location: 49 + ), + mode: :FUNC_PARAM_IN + )) + ], + return_type: PgQuery::TypeName.new( + names: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'pg_catalog')), + PgQuery::Node.new(string: PgQuery::String.new(str: 'int8')) + ], + typemod: -1, + location: 65 + ), + options: [ + PgQuery::Node.new( + def_elem: PgQuery::DefElem.new( + defname: 'as', + arg: PgQuery::Node.new( + list: PgQuery::List.new( + items: [ + PgQuery::Node.new( + string: PgQuery::String.new(str: "\nDECLARE\n local_thing_id BIGINT := 0;\nBEGIN\n SELECT thing_id INTO local_thing_id FROM thing_map\n WHERE\n thing_map_field = parameter_thing\n ORDER BY 1 LIMIT 1;\n\n IF NOT FOUND THEN\n local_thing_id = 0;\n END IF;\n RETURN local_thing_id;\nEND;\n") + ) + ] + ) + ), + defaction: :DEFELEM_UNSPEC, + location: 72 + ) + ), + PgQuery::Node.new( + def_elem: PgQuery::DefElem.new( + defname: 'language', + arg: PgQuery::Node.new( + string: PgQuery::String.new(str: 'plpgsql') + ), + defaction: :DEFELEM_UNSPEC, + location: 407 + ) + ), + PgQuery::Node.new( + def_elem: PgQuery::DefElem.new( + defname: 'volatility', + arg: PgQuery::Node.new( + string: PgQuery::String.new(str: 'stable') + ), + defaction: :DEFELEM_UNSPEC, + location: 424 + ) + ) + ] + ) + ) + ) + ) end it 'parses table functions' do @@ -667,41 +1094,83 @@ ' LANGUAGE SQL") expect(query.warnings).to eq [] expect(query.tables).to eq [] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { described_class::CREATE_FUNCTION_STMT=> - {"funcname"=>[{"String"=>{"str"=>"getfoo"}}], - "parameters"=> - [{described_class::FUNCTION_PARAMETER=> - {"argType"=> - {described_class::TYPE_NAME=> - {"names"=>[{"String"=>{"str"=>"pg_catalog"}}, {"String"=>{"str"=>"int4"}}], - "typemod"=>-1, - "location"=>23}}, - "mode"=>105}}, - {described_class::FUNCTION_PARAMETER=> - {"name"=>"f1", - "argType"=> - {described_class::TYPE_NAME=> - {"names"=>[{"String"=>{"str"=>"pg_catalog"}}, {"String"=>{"str"=>"int4"}}], - "typemod"=>-1, - "location"=>46}}, - "mode"=>116}}], - "returnType"=> - {described_class::TYPE_NAME=> - {"names"=>[{"String"=>{"str"=>"pg_catalog"}}, {"String"=>{"str"=>"int4"}}], - "setof"=>true, - "typemod"=>-1, - "location"=>36}}, - "options"=> - [{described_class::DEF_ELEM=> - {"defname"=>"as", - "arg"=>[{"String"=>{"str"=>"\n SELECT * FROM foo WHERE fooid = $1;\n"}}], - "defaction"=>0, - "location"=>51}}, - {described_class::DEF_ELEM=> - {"defname"=>"language", - "arg"=>{"String"=>{"str"=>"sql"}}, - "defaction"=>0, - "location"=>98}}]}}}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + create_function_stmt: PgQuery::CreateFunctionStmt.new( + funcname: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'getfoo')) + ], + parameters: [ + PgQuery::Node.new( + function_parameter: PgQuery::FunctionParameter.new( + arg_type: PgQuery::TypeName.new( + names: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'pg_catalog')), + PgQuery::Node.new(string: PgQuery::String.new(str: 'int4')) + ], + typemod: -1, + location: 23 + ), + mode: :FUNC_PARAM_IN + ) + ), + PgQuery::Node.new( + function_parameter: PgQuery::FunctionParameter.new( + name: 'f1', + arg_type: PgQuery::TypeName.new( + names: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'pg_catalog')), + PgQuery::Node.new(string: PgQuery::String.new(str: 'int4')) + ], + typemod: -1, + location: 46 + ), + mode: :FUNC_PARAM_TABLE + ) + ) + ], + return_type: PgQuery::TypeName.new( + names: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'pg_catalog')), + PgQuery::Node.new(string: PgQuery::String.new(str: 'int4')) + ], + setof: true, + typemod: -1, + location: 36 + ), + options: [ + PgQuery::Node.new( + def_elem: PgQuery::DefElem.new( + defname: 'as', + arg: PgQuery::Node.new( + list: PgQuery::List.new( + items: [ + PgQuery::Node.new( + string: PgQuery::String.new(str: "\n SELECT * FROM foo WHERE fooid = $1;\n") + ) + ] + ) + ), + defaction: :DEFELEM_UNSPEC, + location: 51 + ) + ), + PgQuery::Node.new( + def_elem: PgQuery::DefElem.new( + defname: 'language', + arg: PgQuery::Node.new( + string: PgQuery::String.new(str: 'sql') + ), + defaction: :DEFELEM_UNSPEC, + location: 98 + ) + ) + ] + ) + ) + ) + ) end # https://github.com/lfittl/pg_query/issues/38 @@ -940,55 +1409,80 @@ query = described_class.parse("DROP TYPE IF EXISTS repack.pk_something") expect(query.warnings).to eq [] expect(query.tables).to eq [] - expect(query.tree).to eq [{ - described_class::RAW_STMT => { - described_class::STMT_FIELD => - { - "DropStmt"=> - { - "objects"=> - [{"TypeName"=> - {"names"=> - [{"String"=>{"str"=>"repack"}}, - {"String"=>{"str"=>"pk_something"}}], - "typemod"=>-1, - "location"=>20}}], - "removeType"=>described_class::OBJECT_TYPE_TYPE, - "behavior"=>0, - "missing_ok"=>true - } - } - } - }] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + drop_stmt: PgQuery::DropStmt.new( + objects: [ + PgQuery::Node.new( + type_name: PgQuery::TypeName.new( + names: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'repack')), + PgQuery::Node.new(string: PgQuery::String.new(str: 'pk_something')) + ], + typemod: -1, + location: 20 + ) + ) + ], + remove_type: :OBJECT_TYPE, + behavior: :DROP_RESTRICT, + missing_ok: true + ) + ) + ) + ) end it 'handles COPY' do query = described_class.parse("COPY (SELECT test FROM abc) TO STDOUT WITH (FORMAT 'csv')") expect(query.warnings).to eq [] expect(query.tables).to eq ['abc'] - expect(query.tree).to eq [{ described_class::RAW_STMT => { described_class::STMT_FIELD => { 'CopyStmt' => - { 'query' => - { 'SelectStmt' => - { 'targetList' => - [{ 'ResTarget' => - { 'val' => - { 'ColumnRef' => - { 'fields' => [{ 'String' => { 'str' => 'test' } }], 'location' => 13 } }, - 'location' => 13 } }], - 'fromClause' => - [{ 'RangeVar' => - { 'relname' => 'abc', - 'inh' => true, - 'relpersistence' => 'p', - 'location' => 23 } }], - 'limitOption' => 0, - 'op' => 0 } }, - 'options' => - [{ 'DefElem' => - { 'defname' => 'format', - 'arg' => { 'String' => { 'str' => 'csv' } }, - 'defaction' => 0, - 'location' => 44 } }] } }}}] + expect(query.tree.stmts.first).to eq( + PgQuery::RawStmt.new( + stmt: PgQuery::Node.new( + copy_stmt: PgQuery::CopyStmt.new( + query: PgQuery::Node.new( + select_stmt: PgQuery::SelectStmt.new( + target_list: [ + PgQuery::Node.new( + res_target: PgQuery::ResTarget.new( + val: PgQuery::Node.new( + column_ref: PgQuery::ColumnRef.new( + fields: [ + PgQuery::Node.new(string: PgQuery::String.new(str: 'test')) + ], + location: 13 + ) + ), + location: 13 + ) + ) + ], + from_clause: [ + PgQuery::Node.new(range_var: PgQuery::RangeVar.new( + relname: 'abc', + inh: true, + relpersistence: 'p', + location: 23, + )) + ], + limit_option: :LIMIT_OPTION_DEFAULT, + op: :SETOP_NONE + ) + ), + options: [ + PgQuery::Node.new(def_elem: PgQuery::DefElem.new( + defname: 'format', + arg: PgQuery::Node.new(string: PgQuery::String.new(str: 'csv')), + defaction: :DEFELEM_UNSPEC, + location: 44 + )) + ] + ) + ) + ) + ) end describe 'parsing CREATE TABLE AS' do