diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/Makefile | 1 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 1115 | ||||
-rw-r--r-- | src/backend/parser/parse_clause.c | 12 | ||||
-rw-r--r-- | src/backend/parser/parse_collate.c | 7 | ||||
-rw-r--r-- | src/backend/parser/parse_expr.c | 1503 | ||||
-rw-r--r-- | src/backend/parser/parse_jsontable.c | 732 | ||||
-rw-r--r-- | src/backend/parser/parse_relation.c | 7 | ||||
-rw-r--r-- | src/backend/parser/parse_target.c | 40 | ||||
-rw-r--r-- | src/backend/parser/parser.c | 16 |
9 files changed, 27 insertions, 3406 deletions
diff --git a/src/backend/parser/Makefile b/src/backend/parser/Makefile index f4c0cc7f101..9f1c4022bbe 100644 --- a/src/backend/parser/Makefile +++ b/src/backend/parser/Makefile @@ -23,7 +23,6 @@ OBJS = \ parse_enr.o \ parse_expr.o \ parse_func.o \ - parse_jsontable.o \ parse_merge.o \ parse_node.o \ parse_oper.o \ diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index b5ab9d9c9a3..0492ff9a666 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -281,13 +281,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); MergeWhenClause *mergewhen; struct KeyActions *keyactions; struct KeyAction *keyaction; - JsonBehavior *jsbehavior; - struct - { - JsonBehavior *on_empty; - JsonBehavior *on_error; - } on_behavior; - JsonQuotes js_quotes; } %type <node> stmt toplevel_stmt schema_stmt routine_body_stmt @@ -576,7 +569,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <list> copy_options %type <typnam> Typename SimpleTypename ConstTypename - GenericType Numeric opt_float JsonType + GenericType Numeric opt_float Character ConstCharacter CharacterWithLength CharacterWithoutLength ConstDatetime ConstInterval @@ -656,101 +649,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <defelt> hash_partbound_elem -%type <node> json_format_clause_opt - json_representation - json_value_expr - json_func_expr - json_value_func_expr - json_query_expr - json_exists_predicate - json_parse_expr - json_scalar_expr - json_serialize_expr - json_api_common_syntax - json_context_item - json_argument - json_output_clause_opt - json_returning_clause_opt - json_value_constructor - json_object_constructor - json_object_constructor_args - json_object_constructor_args_opt - json_object_args - json_object_func_args - json_array_constructor - json_name_and_value - json_aggregate_func - json_object_aggregate_constructor - json_array_aggregate_constructor - json_path_specification - json_table - json_table_column_definition - json_table_ordinality_column_definition - json_table_regular_column_definition - json_table_formatted_column_definition - json_table_exists_column_definition - json_table_nested_columns - json_table_plan_clause_opt - json_table_specific_plan - json_table_plan - json_table_plan_simple - json_table_plan_parent_child - json_table_plan_outer - json_table_plan_inner - json_table_plan_sibling - json_table_plan_union - json_table_plan_cross - json_table_plan_primary - json_table_default_plan - -%type <list> json_name_and_value_list - json_value_expr_list - json_array_aggregate_order_by_clause_opt - json_arguments - json_passing_clause_opt - json_table_columns_clause - json_table_column_definition_list - -%type <str> json_table_path_name - json_as_path_name_clause_opt - json_table_column_path_specification_clause_opt - -%type <ival> json_encoding - json_encoding_clause_opt - json_table_default_plan_choices - json_table_default_plan_inner_outer - json_table_default_plan_union_cross - json_wrapper_clause_opt - json_wrapper_behavior - json_conditional_or_unconditional_opt - json_predicate_type_constraint_opt - -%type <jsbehavior> json_behavior_error - json_behavior_null - json_behavior_true - json_behavior_false - json_behavior_unknown - json_behavior_empty - json_behavior_empty_array - json_behavior_empty_object - json_behavior_default - json_value_behavior - json_query_behavior - json_exists_error_behavior - json_exists_error_clause_opt - json_table_error_behavior - json_table_error_clause_opt - -%type <on_behavior> json_value_on_behavior_clause_opt - json_query_on_behavior_clause_opt - -%type <js_quotes> json_quotes_behavior - json_quotes_clause_opt - -%type <boolean> json_key_uniqueness_constraint_opt - json_object_constructor_null_clause_opt - json_array_constructor_null_clause_opt - /* * Non-keyword token types. These are hard-wired into the "flex" lexer. * They must be listed first so that their numeric codes do not depend on @@ -776,7 +674,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); */ /* ordinary key words in alphabetical order */ -%token <keyword> ABORT_P ABSENT ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER +%token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC ASENSITIVE ASSERTION ASSIGNMENT ASYMMETRIC ATOMIC AT ATTACH ATTRIBUTE AUTHORIZATION @@ -786,7 +684,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); CACHE CALL CALLED CASCADE CASCADED CASE CAST CATALOG_P CHAIN CHAR_P CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE CLUSTER COALESCE COLLATE COLLATION COLUMN COLUMNS COMMENT COMMENTS COMMIT - COMMITTED COMPRESSION CONCURRENTLY CONDITIONAL CONFIGURATION CONFLICT + COMMITTED COMPRESSION CONCURRENTLY CONFIGURATION CONFLICT CONNECTION CONSTRAINT CONSTRAINTS CONTENT_P CONTINUE_P CONVERSION_P COPY COST CREATE CROSS CSV CUBE CURRENT_P CURRENT_CATALOG CURRENT_DATE CURRENT_ROLE CURRENT_SCHEMA @@ -797,12 +695,12 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); DETACH DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP - EACH ELSE EMPTY_P ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ERROR_P ESCAPE - EVENT EXCEPT EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXPRESSION + EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ESCAPE EVENT EXCEPT + EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXPRESSION EXTENSION EXTERNAL EXTRACT FALSE_P FAMILY FETCH FILTER FINALIZE FIRST_P FLOAT_P FOLLOWING FOR - FORCE FOREIGN FORMAT FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS + FORCE FOREIGN FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS GENERATED GLOBAL GRANT GRANTED GREATEST GROUP_P GROUPING GROUPS @@ -813,10 +711,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION - JOIN JSON JSON_ARRAY JSON_ARRAYAGG JSON_EXISTS JSON_OBJECT JSON_OBJECTAGG - JSON_QUERY JSON_SCALAR JSON_SERIALIZE JSON_TABLE JSON_VALUE + JOIN - KEY KEYS KEEP + KEY LABEL LANGUAGE LARGE_P LAST_P LATERAL_P LEADING LEAKPROOF LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL @@ -825,31 +722,31 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); MAPPING MATCH MATCHED MATERIALIZED MAXVALUE MERGE METHOD MINUTE_P MINVALUE MODE MONTH_P MOVE - NAME_P NAMES NATIONAL NATURAL NCHAR NESTED NEW NEXT NFC NFD NFKC NFKD NO - NONE NORMALIZE NORMALIZED + NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NFC NFD NFKC NFKD NO NONE + NORMALIZE NORMALIZED NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC - OBJECT_P OF OFF OFFSET OIDS OLD OMIT ON ONLY OPERATOR OPTION OPTIONS OR + OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OPTIONS OR ORDER ORDINALITY OTHERS OUT_P OUTER_P OVER OVERLAPS OVERLAY OVERRIDING OWNED OWNER - PARALLEL PARAMETER PARSER PARTIAL PARTITION PASSING PASSWORD PATH - PLACING PLAN PLANS POLICY + PARALLEL PARAMETER PARSER PARTIAL PARTITION PASSING PASSWORD + PLACING PLANS POLICY POSITION PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY PRIOR PRIVILEGES PROCEDURAL PROCEDURE PROCEDURES PROGRAM PUBLICATION - QUOTE QUOTES + QUOTE RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REFERENCING REFRESH REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA RESET RESTART RESTRICT RETURN RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP ROUTINE ROUTINES ROW ROWS RULE - SAVEPOINT SCALAR SCHEMA SCHEMAS SCROLL SEARCH SECOND_P SECURITY SELECT - SEQUENCE SEQUENCES SERIALIZABLE SERVER SESSION SESSION_USER SET SETS SETOF - SHARE SHOW SIMILAR SIMPLE SKIP SMALLINT SNAPSHOT SOME SQL_P STABLE STANDALONE_P - START STATEMENT STATISTICS STDIN STDOUT STORAGE STORED STRICT_P STRING STRIP_P + SAVEPOINT SCHEMA SCHEMAS SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES + SERIALIZABLE SERVER SESSION SESSION_USER SET SETS SETOF SHARE SHOW + SIMILAR SIMPLE SKIP SMALLINT SNAPSHOT SOME SQL_P STABLE STANDALONE_P + START STATEMENT STATISTICS STDIN STDOUT STORAGE STORED STRICT_P STRIP_P SUBSCRIPTION SUBSTRING SUPPORT SYMMETRIC SYSID SYSTEM_P TABLE TABLES TABLESAMPLE TABLESPACE TEMP TEMPLATE TEMPORARY TEXT_P THEN @@ -857,7 +754,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); TREAT TRIGGER TRIM TRUE_P TRUNCATE TRUSTED TYPE_P TYPES_P - UESCAPE UNBOUNDED UNCONDITIONAL UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN + UESCAPE UNBOUNDED UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNLOGGED UNTIL UPDATE USER USING VACUUM VALID VALIDATE VALIDATOR VALUE_P VALUES VARCHAR VARIADIC VARYING @@ -882,7 +779,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); * as NOT, at least with respect to their left-hand subexpression. * NULLS_LA and WITH_LA are needed to make the grammar LALR(1). */ -%token NOT_LA NULLS_LA WITH_LA WITH_LA_UNIQUE WITHOUT_LA +%token NOT_LA NULLS_LA WITH_LA /* * The grammar likewise thinks these tokens are keywords, but they are never @@ -900,7 +797,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); /* Precedence: lowest to highest */ %nonassoc SET /* see relation_expr_opt_alias */ -%right FORMAT %left UNION EXCEPT %left INTERSECT %left OR @@ -936,15 +832,11 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); * Using the same precedence as IDENT seems right for the reasons given above. */ %nonassoc UNBOUNDED /* ideally would have same precedence as IDENT */ -%nonassoc ERROR_P EMPTY_P DEFAULT ABSENT /* JSON error/empty behavior */ -%nonassoc FALSE_P KEEP OMIT PASSING TRUE_P UNKNOWN UNIQUE JSON COLUMNS %nonassoc IDENT PARTITION RANGE ROWS GROUPS PRECEDING FOLLOWING CUBE ROLLUP %left Op OPERATOR /* multi-character ops and user-defined operators */ %left '+' '-' %left '*' '/' '%' %left '^' -%left KEYS /* UNIQUE [ KEYS ] */ -%left OBJECT_P SCALAR VALUE_P /* JSON [ OBJECT | SCALAR | VALUE ] */ /* Unary Operators */ %left AT /* sets precedence for AT TIME ZONE */ %left COLLATE @@ -962,13 +854,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); */ %left JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL -%nonassoc json_table_column -%nonassoc NESTED -%left PATH - -%nonassoc empty_json_unique -%left WITHOUT WITH_LA_UNIQUE - %% /* @@ -13407,21 +13292,6 @@ table_ref: relation_expr opt_alias_clause $2->alias = $4; $$ = (Node *) $2; } - | json_table opt_alias_clause - { - JsonTable *jt = castNode(JsonTable, $1); - - jt->alias = $2; - $$ = (Node *) jt; - } - | LATERAL_P json_table opt_alias_clause - { - JsonTable *jt = castNode(JsonTable, $2); - - jt->alias = $3; - jt->lateral = true; - $$ = (Node *) jt; - } ; @@ -13989,8 +13859,6 @@ xmltable_column_option_el: { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(true), @1); } | NULL_P { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(false), @1); } - | PATH b_expr - { $$ = makeDefElem("path", $2, @1); } ; xml_namespace_list: @@ -14091,7 +13959,6 @@ SimpleTypename: $$->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1), makeIntConst($3, @3)); } - | JsonType { $$ = $1; } ; /* We have a separate ConstTypename to allow defaulting fixed-length @@ -14110,7 +13977,6 @@ ConstTypename: | ConstBit { $$ = $1; } | ConstCharacter { $$ = $1; } | ConstDatetime { $$ = $1; } - | JsonType { $$ = $1; } ; /* @@ -14404,7 +14270,7 @@ ConstInterval: opt_timezone: WITH_LA TIME ZONE { $$ = true; } - | WITHOUT_LA TIME ZONE { $$ = false; } + | WITHOUT TIME ZONE { $$ = false; } | /*EMPTY*/ { $$ = false; } ; @@ -14479,13 +14345,6 @@ interval_second: } ; -JsonType: - JSON - { - $$ = SystemTypeName("json"); - $$->location = @1; - } - ; /***************************************************************************** * @@ -14956,47 +14815,6 @@ a_expr: c_expr { $$ = $1; } @2), @2); } - | a_expr - IS json_predicate_type_constraint_opt - json_key_uniqueness_constraint_opt %prec IS - { - JsonFormat *format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1); - $$ = makeJsonIsPredicate($1, format, $3, $4, @1); - } - /* - * Required by standard, but it would conflict with expressions - * like: 'str' || format(...) - | a_expr - FORMAT json_representation - IS json_predicate_type_constraint_opt - json_key_uniqueness_constraint_opt %prec FORMAT - { - $3.location = @2; - $$ = makeJsonIsPredicate($1, $3, $5, $6, @1); - } - */ - | a_expr - IS NOT - json_predicate_type_constraint_opt - json_key_uniqueness_constraint_opt %prec IS - { - JsonFormat *format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1); - - $$ = makeNotExpr(makeJsonIsPredicate($1, format, $4, $5, @1), @1); - } - /* - * Required by standard, but it would conflict with expressions - * like: 'str' || format(...) - | a_expr - FORMAT json_representation - IS NOT - json_predicate_type_constraint_opt - json_key_uniqueness_constraint_opt %prec FORMAT - { - $3.location = @2; - $$ = makeNotExpr(makeJsonIsPredicate($1, $3, $6, $7, @1), @1); - } - */ | DEFAULT { /* @@ -15080,25 +14898,6 @@ b_expr: c_expr } ; -json_predicate_type_constraint_opt: - JSON { $$ = JS_TYPE_ANY; } - | JSON VALUE_P { $$ = JS_TYPE_ANY; } - | JSON ARRAY { $$ = JS_TYPE_ARRAY; } - | JSON OBJECT_P { $$ = JS_TYPE_OBJECT; } - | JSON SCALAR { $$ = JS_TYPE_SCALAR; } - ; - -json_key_uniqueness_constraint_opt: - WITH_LA_UNIQUE unique_keys { $$ = true; } - | WITHOUT unique_keys { $$ = false; } - | /* EMPTY */ %prec empty_json_unique { $$ = false; } - ; - -unique_keys: - UNIQUE - | UNIQUE KEYS - ; - /* * Productions that can be used in both a_expr and b_expr. * @@ -15369,16 +15168,6 @@ func_expr: func_application within_group_clause filter_clause over_clause n->over = $4; $$ = (Node *) n; } - | json_aggregate_func filter_clause over_clause - { - JsonAggConstructor *n = IsA($1, JsonObjectAgg) ? - ((JsonObjectAgg *) $1)->constructor : - ((JsonArrayAgg *) $1)->constructor; - - n->agg_filter = $2; - n->over = $3; - $$ = (Node *) $1; - } | func_expr_common_subexpr { $$ = $1; } ; @@ -15392,7 +15181,6 @@ func_expr: func_application within_group_clause filter_clause over_clause func_expr_windowless: func_application { $$ = $1; } | func_expr_common_subexpr { $$ = $1; } - | json_aggregate_func { $$ = $1; } ; /* @@ -15685,8 +15473,6 @@ func_expr_common_subexpr: n->location = @1; $$ = (Node *) n; } - | json_func_expr - { $$ = $1; } ; /* @@ -16406,813 +16192,6 @@ opt_asymmetric: ASYMMETRIC | /*EMPTY*/ ; -/* SQL/JSON support */ -json_func_expr: - json_value_constructor - | json_value_func_expr - | json_query_expr - | json_exists_predicate - | json_parse_expr - | json_scalar_expr - | json_serialize_expr - ; - -json_parse_expr: - JSON '(' json_value_expr json_key_uniqueness_constraint_opt - json_returning_clause_opt ')' - { - JsonParseExpr *n = makeNode(JsonParseExpr); - - n->expr = (JsonValueExpr *) $3; - n->unique_keys = $4; - n->output = (JsonOutput *) $5; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_scalar_expr: - JSON_SCALAR '(' a_expr json_returning_clause_opt ')' - { - JsonScalarExpr *n = makeNode(JsonScalarExpr); - - n->expr = (Expr *) $3; - n->output = (JsonOutput *) $4; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_serialize_expr: - JSON_SERIALIZE '(' json_value_expr json_output_clause_opt ')' - { - JsonSerializeExpr *n = makeNode(JsonSerializeExpr); - - n->expr = (JsonValueExpr *) $3; - n->output = (JsonOutput *) $4; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_value_func_expr: - JSON_VALUE '(' - json_api_common_syntax - json_returning_clause_opt - json_value_on_behavior_clause_opt - ')' - { - JsonFuncExpr *n = makeNode(JsonFuncExpr); - - n->op = JSON_VALUE_OP; - n->common = (JsonCommon *) $3; - n->output = (JsonOutput *) $4; - n->on_empty = $5.on_empty; - n->on_error = $5.on_error; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_api_common_syntax: - json_context_item ',' json_path_specification - json_as_path_name_clause_opt - json_passing_clause_opt - { - JsonCommon *n = makeNode(JsonCommon); - - n->expr = (JsonValueExpr *) $1; - n->pathspec = $3; - n->pathname = $4; - n->passing = $5; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_context_item: - json_value_expr { $$ = $1; } - ; - -json_path_specification: - a_expr { $$ = $1; } - ; - -json_as_path_name_clause_opt: - AS json_table_path_name { $$ = $2; } - | /* EMPTY */ { $$ = NULL; } - ; - -json_table_path_name: - name { $$ = $1; } - ; - -json_passing_clause_opt: - PASSING json_arguments { $$ = $2; } - | /* EMPTY */ { $$ = NIL; } - ; - -json_arguments: - json_argument { $$ = list_make1($1); } - | json_arguments ',' json_argument { $$ = lappend($1, $3); } - ; - -json_argument: - json_value_expr AS ColLabel - { - JsonArgument *n = makeNode(JsonArgument); - - n->val = (JsonValueExpr *) $1; - n->name = $3; - $$ = (Node *) n; - } - ; - -json_value_expr: - a_expr json_format_clause_opt - { - $$ = (Node *) makeJsonValueExpr((Expr *) $1, castNode(JsonFormat, $2)); - } - ; - -json_format_clause_opt: - FORMAT json_representation - { - $$ = $2; - castNode(JsonFormat, $$)->location = @1; - } - | /* EMPTY */ - { - $$ = (Node *) makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1); - } - ; - -json_representation: - JSON json_encoding_clause_opt - { - $$ = (Node *) makeJsonFormat(JS_FORMAT_JSON, $2, @1); - } - /* | other implementation defined JSON representation options (BSON, AVRO etc) */ - ; - -json_encoding_clause_opt: - ENCODING json_encoding { $$ = $2; } - | /* EMPTY */ { $$ = JS_ENC_DEFAULT; } - ; - -json_encoding: - name { $$ = makeJsonEncoding($1); } - ; - -json_behavior_error: - ERROR_P { $$ = makeJsonBehavior(JSON_BEHAVIOR_ERROR, NULL); } - ; - -json_behavior_null: - NULL_P { $$ = makeJsonBehavior(JSON_BEHAVIOR_NULL, NULL); } - ; - -json_behavior_true: - TRUE_P { $$ = makeJsonBehavior(JSON_BEHAVIOR_TRUE, NULL); } - ; - -json_behavior_false: - FALSE_P { $$ = makeJsonBehavior(JSON_BEHAVIOR_FALSE, NULL); } - ; - -json_behavior_unknown: - UNKNOWN { $$ = makeJsonBehavior(JSON_BEHAVIOR_UNKNOWN, NULL); } - ; - -json_behavior_empty: - EMPTY_P { $$ = makeJsonBehavior(JSON_BEHAVIOR_EMPTY_OBJECT, NULL); } - ; - -json_behavior_empty_array: - EMPTY_P ARRAY { $$ = makeJsonBehavior(JSON_BEHAVIOR_EMPTY_ARRAY, NULL); } - /* non-standard, for Oracle compatibility only */ - | EMPTY_P { $$ = makeJsonBehavior(JSON_BEHAVIOR_EMPTY_ARRAY, NULL); } - ; - -json_behavior_empty_object: - EMPTY_P OBJECT_P { $$ = makeJsonBehavior(JSON_BEHAVIOR_EMPTY_OBJECT, NULL); } - ; - -json_behavior_default: - DEFAULT a_expr { $$ = makeJsonBehavior(JSON_BEHAVIOR_DEFAULT, $2); } - ; - - -json_value_behavior: - json_behavior_null - | json_behavior_error - | json_behavior_default - ; - -json_value_on_behavior_clause_opt: - json_value_behavior ON EMPTY_P - { $$.on_empty = $1; $$.on_error = NULL; } - | json_value_behavior ON EMPTY_P json_value_behavior ON ERROR_P - { $$.on_empty = $1; $$.on_error = $4; } - | json_value_behavior ON ERROR_P - { $$.on_empty = NULL; $$.on_error = $1; } - | /* EMPTY */ - { $$.on_empty = NULL; $$.on_error = NULL; } - ; - -json_query_expr: - JSON_QUERY '(' - json_api_common_syntax - json_output_clause_opt - json_wrapper_clause_opt - json_quotes_clause_opt - json_query_on_behavior_clause_opt - ')' - { - JsonFuncExpr *n = makeNode(JsonFuncExpr); - - n->op = JSON_QUERY_OP; - n->common = (JsonCommon *) $3; - n->output = (JsonOutput *) $4; - n->wrapper = $5; - if (n->wrapper != JSW_NONE && $6 != JS_QUOTES_UNSPEC) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used"), - parser_errposition(@6))); - n->omit_quotes = $6 == JS_QUOTES_OMIT; - n->on_empty = $7.on_empty; - n->on_error = $7.on_error; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_wrapper_clause_opt: - json_wrapper_behavior WRAPPER { $$ = $1; } - | /* EMPTY */ { $$ = 0; } - ; - -json_wrapper_behavior: - WITHOUT array_opt { $$ = JSW_NONE; } - | WITH json_conditional_or_unconditional_opt array_opt { $$ = $2; } - ; - -array_opt: - ARRAY { } - | /* EMPTY */ { } - ; - -json_conditional_or_unconditional_opt: - CONDITIONAL { $$ = JSW_CONDITIONAL; } - | UNCONDITIONAL { $$ = JSW_UNCONDITIONAL; } - | /* EMPTY */ { $$ = JSW_UNCONDITIONAL; } - ; - -json_quotes_clause_opt: - json_quotes_behavior QUOTES json_on_scalar_string_opt { $$ = $1; } - | /* EMPTY */ { $$ = JS_QUOTES_UNSPEC; } - ; - -json_quotes_behavior: - KEEP { $$ = JS_QUOTES_KEEP; } - | OMIT { $$ = JS_QUOTES_OMIT; } - ; - -json_on_scalar_string_opt: - ON SCALAR STRING { } - | /* EMPTY */ { } - ; - -json_query_behavior: - json_behavior_error - | json_behavior_null - | json_behavior_empty_array - | json_behavior_empty_object - | json_behavior_default - ; - -json_query_on_behavior_clause_opt: - json_query_behavior ON EMPTY_P - { $$.on_empty = $1; $$.on_error = NULL; } - | json_query_behavior ON EMPTY_P json_query_behavior ON ERROR_P - { $$.on_empty = $1; $$.on_error = $4; } - | json_query_behavior ON ERROR_P - { $$.on_empty = NULL; $$.on_error = $1; } - | /* EMPTY */ - { $$.on_empty = NULL; $$.on_error = NULL; } - ; - -json_table: - JSON_TABLE '(' - json_api_common_syntax - json_table_columns_clause - json_table_plan_clause_opt - json_table_error_clause_opt - ')' - { - JsonTable *n = makeNode(JsonTable); - - n->common = (JsonCommon *) $3; - n->columns = $4; - n->plan = (JsonTablePlan *) $5; - n->on_error = $6; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_table_columns_clause: - COLUMNS '(' json_table_column_definition_list ')' { $$ = $3; } - ; - -json_table_column_definition_list: - json_table_column_definition - { $$ = list_make1($1); } - | json_table_column_definition_list ',' json_table_column_definition - { $$ = lappend($1, $3); } - ; - -json_table_column_definition: - json_table_ordinality_column_definition %prec json_table_column - | json_table_regular_column_definition %prec json_table_column - | json_table_formatted_column_definition %prec json_table_column - | json_table_exists_column_definition %prec json_table_column - | json_table_nested_columns - ; - -json_table_ordinality_column_definition: - ColId FOR ORDINALITY - { - JsonTableColumn *n = makeNode(JsonTableColumn); - - n->coltype = JTC_FOR_ORDINALITY; - n->name = $1; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_table_regular_column_definition: - ColId Typename - json_table_column_path_specification_clause_opt - json_wrapper_clause_opt - json_quotes_clause_opt - json_value_on_behavior_clause_opt - { - JsonTableColumn *n = makeNode(JsonTableColumn); - - n->coltype = JTC_REGULAR; - n->name = $1; - n->typeName = $2; - n->format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1); - n->wrapper = $4; /* JSW_NONE */ - n->omit_quotes = $5; /* false */ - n->pathspec = $3; - n->on_empty = $6.on_empty; - n->on_error = $6.on_error; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_table_exists_column_definition: - ColId Typename - EXISTS json_table_column_path_specification_clause_opt - json_exists_error_clause_opt - { - JsonTableColumn *n = makeNode(JsonTableColumn); - - n->coltype = JTC_EXISTS; - n->name = $1; - n->typeName = $2; - n->format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1); - n->wrapper = JSW_NONE; - n->omit_quotes = false; - n->pathspec = $4; - n->on_empty = NULL; - n->on_error = $5; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_table_error_behavior: - json_behavior_error - | json_behavior_empty - ; - -json_table_error_clause_opt: - json_table_error_behavior ON ERROR_P { $$ = $1; } - | /* EMPTY */ { $$ = NULL; } - ; - -json_table_column_path_specification_clause_opt: - PATH Sconst { $$ = $2; } - | /* EMPTY */ %prec json_table_column { $$ = NULL; } - ; - -json_table_formatted_column_definition: - ColId Typename FORMAT json_representation - json_table_column_path_specification_clause_opt - json_wrapper_clause_opt - json_quotes_clause_opt - json_query_on_behavior_clause_opt - { - JsonTableColumn *n = makeNode(JsonTableColumn); - - n->coltype = JTC_FORMATTED; - n->name = $1; - n->typeName = $2; - n->format = castNode(JsonFormat, $4); - n->pathspec = $5; - n->wrapper = $6; - if (n->wrapper != JSW_NONE && $7 != JS_QUOTES_UNSPEC) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used"), - parser_errposition(@7))); - n->omit_quotes = $7 == JS_QUOTES_OMIT; - n->on_empty = $8.on_empty; - n->on_error = $8.on_error; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_table_nested_columns: - NESTED path_opt Sconst - json_as_path_name_clause_opt - json_table_columns_clause - { - JsonTableColumn *n = makeNode(JsonTableColumn); - - n->coltype = JTC_NESTED; - n->pathspec = $3; - n->pathname = $4; - n->columns = $5; - n->location = @1; - $$ = (Node *) n; - } - ; - -path_opt: - PATH { } - | /* EMPTY */ { } - ; - -json_table_plan_clause_opt: - json_table_specific_plan { $$ = $1; } - | json_table_default_plan { $$ = $1; } - | /* EMPTY */ { $$ = NULL; } - ; - -json_table_specific_plan: - PLAN '(' json_table_plan ')' { $$ = $3; } - ; - -json_table_plan: - json_table_plan_simple - | json_table_plan_parent_child - | json_table_plan_sibling - ; - -json_table_plan_simple: - json_table_path_name - { - JsonTablePlan *n = makeNode(JsonTablePlan); - - n->plan_type = JSTP_SIMPLE; - n->pathname = $1; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_table_plan_parent_child: - json_table_plan_outer - | json_table_plan_inner - ; - -json_table_plan_outer: - json_table_plan_simple OUTER_P json_table_plan_primary - { $$ = makeJsonTableJoinedPlan(JSTPJ_OUTER, $1, $3, @1); } - ; - -json_table_plan_inner: - json_table_plan_simple INNER_P json_table_plan_primary - { $$ = makeJsonTableJoinedPlan(JSTPJ_INNER, $1, $3, @1); } - ; - -json_table_plan_sibling: - json_table_plan_union - | json_table_plan_cross - ; - -json_table_plan_union: - json_table_plan_primary UNION json_table_plan_primary - { $$ = makeJsonTableJoinedPlan(JSTPJ_UNION, $1, $3, @1); } - | json_table_plan_union UNION json_table_plan_primary - { $$ = makeJsonTableJoinedPlan(JSTPJ_UNION, $1, $3, @1); } - ; - -json_table_plan_cross: - json_table_plan_primary CROSS json_table_plan_primary - { $$ = makeJsonTableJoinedPlan(JSTPJ_CROSS, $1, $3, @1); } - | json_table_plan_cross CROSS json_table_plan_primary - { $$ = makeJsonTableJoinedPlan(JSTPJ_CROSS, $1, $3, @1); } - ; - -json_table_plan_primary: - json_table_plan_simple { $$ = $1; } - | '(' json_table_plan ')' - { - castNode(JsonTablePlan, $2)->location = @1; - $$ = $2; - } - ; - -json_table_default_plan: - PLAN DEFAULT '(' json_table_default_plan_choices ')' - { - JsonTablePlan *n = makeNode(JsonTablePlan); - - n->plan_type = JSTP_DEFAULT; - n->join_type = $4; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_table_default_plan_choices: - json_table_default_plan_inner_outer { $$ = $1 | JSTPJ_UNION; } - | json_table_default_plan_inner_outer ',' - json_table_default_plan_union_cross { $$ = $1 | $3; } - | json_table_default_plan_union_cross { $$ = $1 | JSTPJ_OUTER; } - | json_table_default_plan_union_cross ',' - json_table_default_plan_inner_outer { $$ = $1 | $3; } - ; - -json_table_default_plan_inner_outer: - INNER_P { $$ = JSTPJ_INNER; } - | OUTER_P { $$ = JSTPJ_OUTER; } - ; - -json_table_default_plan_union_cross: - UNION { $$ = JSTPJ_UNION; } - | CROSS { $$ = JSTPJ_CROSS; } - ; - -json_returning_clause_opt: - RETURNING Typename - { - JsonOutput *n = makeNode(JsonOutput); - - n->typeName = $2; - n->returning = makeNode(JsonReturning); - n->returning->format = - makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, @2); - $$ = (Node *) n; - } - | /* EMPTY */ { $$ = NULL; } - ; - -json_output_clause_opt: - RETURNING Typename json_format_clause_opt - { - JsonOutput *n = makeNode(JsonOutput); - - n->typeName = $2; - n->returning = makeNode(JsonReturning); - n->returning->format = (JsonFormat *) $3; - $$ = (Node *) n; - } - | /* EMPTY */ { $$ = NULL; } - ; - -json_exists_predicate: - JSON_EXISTS '(' - json_api_common_syntax - json_returning_clause_opt - json_exists_error_clause_opt - ')' - { - JsonFuncExpr *p = makeNode(JsonFuncExpr); - - p->op = JSON_EXISTS_OP; - p->common = (JsonCommon *) $3; - p->output = (JsonOutput *) $4; - p->on_error = $5; - p->location = @1; - $$ = (Node *) p; - } - ; - -json_exists_error_clause_opt: - json_exists_error_behavior ON ERROR_P { $$ = $1; } - | /* EMPTY */ { $$ = NULL; } - ; - -json_exists_error_behavior: - json_behavior_error - | json_behavior_true - | json_behavior_false - | json_behavior_unknown - ; - -json_value_constructor: - json_object_constructor - | json_array_constructor - ; - -json_object_constructor: - JSON_OBJECT '(' json_object_args ')' - { - $$ = $3; - } - ; - -json_object_args: - json_object_constructor_args - | json_object_func_args - ; - -json_object_func_args: - func_arg_list - { - List *func = list_make1(makeString("json_object")); - - $$ = (Node *) makeFuncCall(func, $1, COERCE_EXPLICIT_CALL, @1); - } - ; - -json_object_constructor_args: - json_object_constructor_args_opt json_output_clause_opt - { - JsonObjectConstructor *n = (JsonObjectConstructor *) $1; - - n->output = (JsonOutput *) $2; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_object_constructor_args_opt: - json_name_and_value_list - json_object_constructor_null_clause_opt - json_key_uniqueness_constraint_opt - { - JsonObjectConstructor *n = makeNode(JsonObjectConstructor); - - n->exprs = $1; - n->absent_on_null = $2; - n->unique = $3; - $$ = (Node *) n; - } - | /* EMPTY */ - { - JsonObjectConstructor *n = makeNode(JsonObjectConstructor); - - n->exprs = NULL; - n->absent_on_null = false; - n->unique = false; - $$ = (Node *) n; - } - ; - -json_name_and_value_list: - json_name_and_value - { $$ = list_make1($1); } - | json_name_and_value_list ',' json_name_and_value - { $$ = lappend($1, $3); } - ; - -json_name_and_value: -/* TODO This is not supported due to conflicts - KEY c_expr VALUE_P json_value_expr %prec POSTFIXOP - { $$ = makeJsonKeyValue($2, $4); } - | -*/ - c_expr VALUE_P json_value_expr - { $$ = makeJsonKeyValue($1, $3); } - | - a_expr ':' json_value_expr - { $$ = makeJsonKeyValue($1, $3); } - ; - -json_object_constructor_null_clause_opt: - NULL_P ON NULL_P { $$ = false; } - | ABSENT ON NULL_P { $$ = true; } - | /* EMPTY */ { $$ = false; } - ; - -json_array_constructor: - JSON_ARRAY '(' - json_value_expr_list - json_array_constructor_null_clause_opt - json_output_clause_opt - ')' - { - JsonArrayConstructor *n = makeNode(JsonArrayConstructor); - - n->exprs = $3; - n->absent_on_null = $4; - n->output = (JsonOutput *) $5; - n->location = @1; - $$ = (Node *) n; - } - | JSON_ARRAY '(' - select_no_parens - /* json_format_clause_opt */ - /* json_array_constructor_null_clause_opt */ - json_output_clause_opt - ')' - { - JsonArrayQueryConstructor *n = makeNode(JsonArrayQueryConstructor); - - n->query = $3; - n->format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1); - /* n->format = $4; */ - n->absent_on_null = true /* $5 */; - n->output = (JsonOutput *) $4; - n->location = @1; - $$ = (Node *) n; - } - | JSON_ARRAY '(' - json_output_clause_opt - ')' - { - JsonArrayConstructor *n = makeNode(JsonArrayConstructor); - - n->exprs = NIL; - n->absent_on_null = true; - n->output = (JsonOutput *) $3; - n->location = @1; - $$ = (Node *) n; - } - ; - -json_value_expr_list: - json_value_expr { $$ = list_make1($1); } - | json_value_expr_list ',' json_value_expr { $$ = lappend($1, $3);} - ; - -json_array_constructor_null_clause_opt: - NULL_P ON NULL_P { $$ = false; } - | ABSENT ON NULL_P { $$ = true; } - | /* EMPTY */ { $$ = true; } - ; - -json_aggregate_func: - json_object_aggregate_constructor - | json_array_aggregate_constructor - ; - -json_object_aggregate_constructor: - JSON_OBJECTAGG '(' - json_name_and_value - json_object_constructor_null_clause_opt - json_key_uniqueness_constraint_opt - json_output_clause_opt - ')' - { - JsonObjectAgg *n = makeNode(JsonObjectAgg); - - n->arg = (JsonKeyValue *) $3; - n->absent_on_null = $4; - n->unique = $5; - n->constructor = makeNode(JsonAggConstructor); - n->constructor->output = (JsonOutput *) $6; - n->constructor->agg_order = NULL; - n->constructor->location = @1; - $$ = (Node *) n; - } - ; - -json_array_aggregate_constructor: - JSON_ARRAYAGG '(' - json_value_expr - json_array_aggregate_order_by_clause_opt - json_array_constructor_null_clause_opt - json_output_clause_opt - ')' - { - JsonArrayAgg *n = makeNode(JsonArrayAgg); - - n->arg = (JsonValueExpr *) $3; - n->absent_on_null = $5; - n->constructor = makeNode(JsonAggConstructor); - n->constructor->agg_order = $4; - n->constructor->output = (JsonOutput *) $6; - n->constructor->location = @1; - $$ = (Node *) n; - } - ; - -json_array_aggregate_order_by_clause_opt: - ORDER BY sortby_list { $$ = $3; } - | /* EMPTY */ { $$ = NIL; } - ; /***************************************************************************** * @@ -17664,7 +16643,6 @@ BareColLabel: IDENT { $$ = $1; } */ unreserved_keyword: ABORT_P - | ABSENT | ABSOLUTE_P | ACCESS | ACTION @@ -17705,7 +16683,6 @@ unreserved_keyword: | COMMIT | COMMITTED | COMPRESSION - | CONDITIONAL | CONFIGURATION | CONFLICT | CONNECTION @@ -17742,12 +16719,10 @@ unreserved_keyword: | DOUBLE_P | DROP | EACH - | EMPTY_P | ENABLE_P | ENCODING | ENCRYPTED | ENUM_P - | ERROR_P | ESCAPE | EVENT | EXCLUDE @@ -17764,7 +16739,6 @@ unreserved_keyword: | FIRST_P | FOLLOWING | FORCE - | FORMAT | FORWARD | FUNCTION | FUNCTIONS @@ -17796,9 +16770,7 @@ unreserved_keyword: | INSTEAD | INVOKER | ISOLATION - | KEEP | KEY - | KEYS | LABEL | LANGUAGE | LARGE_P @@ -17826,7 +16798,6 @@ unreserved_keyword: | MOVE | NAME_P | NAMES - | NESTED | NEW | NEXT | NFC @@ -17844,7 +16815,6 @@ unreserved_keyword: | OFF | OIDS | OLD - | OMIT | OPERATOR | OPTION | OPTIONS @@ -17861,8 +16831,6 @@ unreserved_keyword: | PARTITION | PASSING | PASSWORD - | PATH - | PLAN | PLANS | POLICY | PRECEDING @@ -17877,7 +16845,6 @@ unreserved_keyword: | PROGRAM | PUBLICATION | QUOTE - | QUOTES | RANGE | READ | REASSIGN @@ -17907,7 +16874,6 @@ unreserved_keyword: | ROWS | RULE | SAVEPOINT - | SCALAR | SCHEMA | SCHEMAS | SCROLL @@ -17937,7 +16903,6 @@ unreserved_keyword: | STORAGE | STORED | STRICT_P - | STRING | STRIP_P | SUBSCRIPTION | SUPPORT @@ -17960,7 +16925,6 @@ unreserved_keyword: | UESCAPE | UNBOUNDED | UNCOMMITTED - | UNCONDITIONAL | UNENCRYPTED | UNKNOWN | UNLISTEN @@ -18018,17 +16982,6 @@ col_name_keyword: | INT_P | INTEGER | INTERVAL - | JSON - | JSON_ARRAY - | JSON_ARRAYAGG - | JSON_EXISTS - | JSON_OBJECT - | JSON_OBJECTAGG - | JSON_QUERY - | JSON_SCALAR - | JSON_SERIALIZE - | JSON_TABLE - | JSON_VALUE | LEAST | NATIONAL | NCHAR @@ -18197,7 +17150,6 @@ reserved_keyword: */ bare_label_keyword: ABORT_P - | ABSENT | ABSOLUTE_P | ACCESS | ACTION @@ -18260,7 +17212,6 @@ bare_label_keyword: | COMMITTED | COMPRESSION | CONCURRENTLY - | CONDITIONAL | CONFIGURATION | CONFLICT | CONNECTION @@ -18313,13 +17264,11 @@ bare_label_keyword: | DROP | EACH | ELSE - | EMPTY_P | ENABLE_P | ENCODING | ENCRYPTED | END_P | ENUM_P - | ERROR_P | ESCAPE | EVENT | EXCLUDE @@ -18340,7 +17289,6 @@ bare_label_keyword: | FOLLOWING | FORCE | FOREIGN - | FORMAT | FORWARD | FREEZE | FULL @@ -18385,20 +17333,7 @@ bare_label_keyword: | IS | ISOLATION | JOIN - | JSON - | JSON_ARRAY - | JSON_ARRAYAGG - | JSON_EXISTS - | JSON_OBJECT - | JSON_OBJECTAGG - | JSON_QUERY - | JSON_SCALAR - | JSON_SERIALIZE - | JSON_TABLE - | JSON_VALUE - | KEEP | KEY - | KEYS | LABEL | LANGUAGE | LARGE_P @@ -18434,7 +17369,6 @@ bare_label_keyword: | NATIONAL | NATURAL | NCHAR - | NESTED | NEW | NEXT | NFC @@ -18458,7 +17392,6 @@ bare_label_keyword: | OFF | OIDS | OLD - | OMIT | ONLY | OPERATOR | OPTION @@ -18479,9 +17412,7 @@ bare_label_keyword: | PARTITION | PASSING | PASSWORD - | PATH | PLACING - | PLAN | PLANS | POLICY | POSITION @@ -18498,7 +17429,6 @@ bare_label_keyword: | PROGRAM | PUBLICATION | QUOTE - | QUOTES | RANGE | READ | REAL @@ -18532,7 +17462,6 @@ bare_label_keyword: | ROWS | RULE | SAVEPOINT - | SCALAR | SCHEMA | SCHEMAS | SCROLL @@ -18567,7 +17496,6 @@ bare_label_keyword: | STORAGE | STORED | STRICT_P - | STRING | STRIP_P | SUBSCRIPTION | SUBSTRING @@ -18601,7 +17529,6 @@ bare_label_keyword: | UESCAPE | UNBOUNDED | UNCOMMITTED - | UNCONDITIONAL | UNENCRYPTED | UNIQUE | UNKNOWN diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index b85fbebd00e..061d0bcc505 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -690,9 +690,7 @@ transformRangeTableFunc(ParseState *pstate, RangeTableFunc *rtf) char **names; int colno; - /* Currently only XMLTABLE and JSON_TABLE are supported */ - - tf->functype = TFT_XMLTABLE; + /* Currently only XMLTABLE is supported */ constructName = "XMLTABLE"; docType = XMLOID; @@ -1099,17 +1097,13 @@ transformFromClauseItem(ParseState *pstate, Node *n, rtr->rtindex = nsitem->p_rtindex; return (Node *) rtr; } - else if (IsA(n, RangeTableFunc) || IsA(n, JsonTable)) + else if (IsA(n, RangeTableFunc)) { /* table function is like a plain relation */ RangeTblRef *rtr; ParseNamespaceItem *nsitem; - if (IsA(n, RangeTableFunc)) - nsitem = transformRangeTableFunc(pstate, (RangeTableFunc *) n); - else - nsitem = transformJsonTable(pstate, (JsonTable *) n); - + nsitem = transformRangeTableFunc(pstate, (RangeTableFunc *) n); *top_nsitem = nsitem; *namespace = list_make1(nsitem); rtr = makeNode(RangeTblRef); diff --git a/src/backend/parser/parse_collate.c b/src/backend/parser/parse_collate.c index e90af4c4771..7582faabb37 100644 --- a/src/backend/parser/parse_collate.c +++ b/src/backend/parser/parse_collate.c @@ -691,13 +691,6 @@ assign_collations_walker(Node *node, assign_collations_context *context) &loccontext); } break; - case T_JsonExpr: - - /* - * Context item and PASSING arguments are already - * marked with collations in parse_expr.c. - */ - break; default: /* diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index fabb5f72076..7aaf1c673f8 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -15,8 +15,6 @@ #include "postgres.h" -#include "catalog/pg_aggregate.h" -#include "catalog/pg_proc.h" #include "catalog/pg_type.h" #include "commands/dbcommands.h" #include "miscadmin.h" @@ -36,7 +34,6 @@ #include "parser/parse_type.h" #include "utils/builtins.h" #include "utils/date.h" -#include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/timestamp.h" #include "utils/xml.h" @@ -77,21 +74,6 @@ static Node *transformWholeRowRef(ParseState *pstate, static Node *transformIndirection(ParseState *pstate, A_Indirection *ind); static Node *transformTypeCast(ParseState *pstate, TypeCast *tc); static Node *transformCollateClause(ParseState *pstate, CollateClause *c); -static Node *transformJsonObjectConstructor(ParseState *pstate, - JsonObjectConstructor *ctor); -static Node *transformJsonArrayConstructor(ParseState *pstate, - JsonArrayConstructor *ctor); -static Node *transformJsonArrayQueryConstructor(ParseState *pstate, - JsonArrayQueryConstructor *ctor); -static Node *transformJsonObjectAgg(ParseState *pstate, JsonObjectAgg *agg); -static Node *transformJsonArrayAgg(ParseState *pstate, JsonArrayAgg *agg); -static Node *transformJsonIsPredicate(ParseState *pstate, JsonIsPredicate *p); -static Node *transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *p); -static Node *transformJsonValueExpr(ParseState *pstate, JsonValueExpr *jve); -static Node *transformJsonParseExpr(ParseState *pstate, JsonParseExpr *expr); -static Node *transformJsonScalarExpr(ParseState *pstate, JsonScalarExpr *expr); -static Node *transformJsonSerializeExpr(ParseState *pstate, - JsonSerializeExpr *expr); static Node *make_row_comparison_op(ParseState *pstate, List *opname, List *largs, List *rargs, int location); static Node *make_row_distinct_op(ParseState *pstate, List *opname, @@ -319,50 +301,6 @@ transformExprRecurse(ParseState *pstate, Node *expr) break; } - case T_JsonObjectConstructor: - result = transformJsonObjectConstructor(pstate, (JsonObjectConstructor *) expr); - break; - - case T_JsonArrayConstructor: - result = transformJsonArrayConstructor(pstate, (JsonArrayConstructor *) expr); - break; - - case T_JsonArrayQueryConstructor: - result = transformJsonArrayQueryConstructor(pstate, (JsonArrayQueryConstructor *) expr); - break; - - case T_JsonObjectAgg: - result = transformJsonObjectAgg(pstate, (JsonObjectAgg *) expr); - break; - - case T_JsonArrayAgg: - result = transformJsonArrayAgg(pstate, (JsonArrayAgg *) expr); - break; - - case T_JsonIsPredicate: - result = transformJsonIsPredicate(pstate, (JsonIsPredicate *) expr); - break; - - case T_JsonFuncExpr: - result = transformJsonFuncExpr(pstate, (JsonFuncExpr *) expr); - break; - - case T_JsonValueExpr: - result = transformJsonValueExpr(pstate, (JsonValueExpr *) expr); - break; - - case T_JsonParseExpr: - result = transformJsonParseExpr(pstate, (JsonParseExpr *) expr); - break; - - case T_JsonScalarExpr: - result = transformJsonScalarExpr(pstate, (JsonScalarExpr *) expr); - break; - - case T_JsonSerializeExpr: - result = transformJsonSerializeExpr(pstate, (JsonSerializeExpr *) expr); - break; - default: /* should not reach here */ elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr)); @@ -3163,1444 +3101,3 @@ ParseExprKindName(ParseExprKind exprKind) } return "unrecognized expression kind"; } - -/* - * Make string Const node from JSON encoding name. - * - * UTF8 is default encoding. - */ -static Const * -getJsonEncodingConst(JsonFormat *format) -{ - JsonEncoding encoding; - const char *enc; - Name encname = palloc(sizeof(NameData)); - - if (!format || - format->format_type == JS_FORMAT_DEFAULT || - format->encoding == JS_ENC_DEFAULT) - encoding = JS_ENC_UTF8; - else - encoding = format->encoding; - - switch (encoding) - { - case JS_ENC_UTF16: - enc = "UTF16"; - break; - case JS_ENC_UTF32: - enc = "UTF32"; - break; - case JS_ENC_UTF8: - enc = "UTF8"; - break; - default: - elog(ERROR, "invalid JSON encoding: %d", encoding); - break; - } - - namestrcpy(encname, enc); - - return makeConst(NAMEOID, -1, InvalidOid, NAMEDATALEN, - NameGetDatum(encname), false, false); -} - -/* - * Make bytea => text conversion using specified JSON format encoding. - */ -static Node * -makeJsonByteaToTextConversion(Node *expr, JsonFormat *format, int location) -{ - Const *encoding = getJsonEncodingConst(format); - FuncExpr *fexpr = makeFuncExpr(F_CONVERT_FROM, TEXTOID, - list_make2(expr, encoding), - InvalidOid, InvalidOid, - COERCE_EXPLICIT_CALL); - - fexpr->location = location; - - return (Node *) fexpr; -} - -/* - * Make CaseTestExpr node. - */ -static Node * -makeCaseTestExpr(Node *expr) -{ - CaseTestExpr *placeholder = makeNode(CaseTestExpr); - - placeholder->typeId = exprType(expr); - placeholder->typeMod = exprTypmod(expr); - placeholder->collation = exprCollation(expr); - - return (Node *) placeholder; -} - -/* - * Transform JSON value expression using specified input JSON format or - * default format otherwise. - */ -static Node * -transformJsonValueExprExt(ParseState *pstate, JsonValueExpr *ve, - JsonFormatType default_format, bool isarg, - Oid targettype) -{ - Node *expr = transformExprRecurse(pstate, (Node *) ve->raw_expr); - Node *rawexpr; - JsonFormatType format; - Oid exprtype; - int location; - char typcategory; - bool typispreferred; - - if (exprType(expr) == UNKNOWNOID) - expr = coerce_to_specific_type(pstate, expr, TEXTOID, "JSON_VALUE_EXPR"); - - rawexpr = expr; - exprtype = exprType(expr); - location = exprLocation(expr); - - get_type_category_preferred(exprtype, &typcategory, &typispreferred); - - rawexpr = expr; - - if (ve->format->format_type != JS_FORMAT_DEFAULT) - { - if (ve->format->encoding != JS_ENC_DEFAULT && exprtype != BYTEAOID) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("JSON ENCODING clause is only allowed for bytea input type"), - parser_errposition(pstate, ve->format->location))); - - if (exprtype == JSONOID || exprtype == JSONBOID) - { - format = JS_FORMAT_DEFAULT; /* do not format json[b] types */ - ereport(WARNING, - (errmsg("FORMAT JSON has no effect for json and jsonb types"), - parser_errposition(pstate, ve->format->location))); - } - else - format = ve->format->format_type; - } - else if (isarg) - { - /* Pass SQL/JSON item types directly without conversion to json[b]. */ - switch (exprtype) - { - case TEXTOID: - case NUMERICOID: - case BOOLOID: - case INT2OID: - case INT4OID: - case INT8OID: - case FLOAT4OID: - case FLOAT8OID: - case DATEOID: - case TIMEOID: - case TIMETZOID: - case TIMESTAMPOID: - case TIMESTAMPTZOID: - return expr; - - default: - if (typcategory == TYPCATEGORY_STRING) - return coerce_to_specific_type(pstate, expr, TEXTOID, - "JSON_VALUE_EXPR"); - /* else convert argument to json[b] type */ - break; - } - - format = default_format; - } - else if (exprtype == JSONOID || exprtype == JSONBOID) - format = JS_FORMAT_DEFAULT; /* do not format json[b] types */ - else - format = default_format; - - if (format == JS_FORMAT_DEFAULT && - (!OidIsValid(targettype) || exprtype == targettype)) - expr = rawexpr; - else - { - Node *orig = makeCaseTestExpr(expr); - Node *coerced; - bool cast_is_needed = OidIsValid(targettype); - - if (!isarg && !cast_is_needed && - exprtype != BYTEAOID && typcategory != TYPCATEGORY_STRING) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg(ve->format->format_type == JS_FORMAT_DEFAULT ? - "cannot use non-string types with implicit FORMAT JSON clause" : - "cannot use non-string types with explicit FORMAT JSON clause"), - parser_errposition(pstate, ve->format->location >= 0 ? - ve->format->location : location))); - - expr = orig; - - /* Convert encoded JSON text from bytea. */ - if (format == JS_FORMAT_JSON && exprtype == BYTEAOID) - { - expr = makeJsonByteaToTextConversion(expr, ve->format, location); - exprtype = TEXTOID; - } - - if (!OidIsValid(targettype)) - targettype = format == JS_FORMAT_JSONB ? JSONBOID : JSONOID; - - /* Try to coerce to the target type. */ - coerced = coerce_to_target_type(pstate, expr, exprtype, - targettype, -1, - COERCION_EXPLICIT, - COERCE_EXPLICIT_CAST, - location); - - if (!coerced) - { - /* If coercion failed, use to_json()/to_jsonb() functions. */ - FuncExpr *fexpr; - Oid fnoid; - - if (cast_is_needed) /* only CAST is allowed */ - ereport(ERROR, - (errcode(ERRCODE_CANNOT_COERCE), - errmsg("cannot cast type %s to %s", - format_type_be(exprtype), - format_type_be(targettype)), - parser_errposition(pstate, location))); - - fnoid = targettype == JSONOID ? F_TO_JSON : F_TO_JSONB; - fexpr = makeFuncExpr(fnoid, targettype, list_make1(expr), - InvalidOid, InvalidOid, COERCE_EXPLICIT_CALL); - - fexpr->location = location; - - coerced = (Node *) fexpr; - } - - if (coerced == orig) - expr = rawexpr; - else - { - ve = copyObject(ve); - ve->raw_expr = (Expr *) rawexpr; - ve->formatted_expr = (Expr *) coerced; - - expr = (Node *) ve; - } - } - - return expr; -} - -/* - * Transform JSON value expression using FORMAT JSON by default. - */ -static Node * -transformJsonValueExpr(ParseState *pstate, JsonValueExpr *jve) -{ - return transformJsonValueExprExt(pstate, jve, JS_FORMAT_JSON, false, - InvalidOid); -} - -/* - * Transform JSON value expression using unspecified format by default. - */ -static Node * -transformJsonValueExprDefault(ParseState *pstate, JsonValueExpr *jve) -{ - return transformJsonValueExprExt(pstate, jve, JS_FORMAT_DEFAULT, false, - InvalidOid); -} - -/* - * Checks specified output format for its applicability to the target type. - */ -static void -checkJsonOutputFormat(ParseState *pstate, const JsonFormat *format, - Oid targettype, bool allow_format_for_non_strings) -{ - if (!allow_format_for_non_strings && - format->format_type != JS_FORMAT_DEFAULT && - (targettype != BYTEAOID && - targettype != JSONOID && - targettype != JSONBOID)) - { - char typcategory; - bool typispreferred; - - get_type_category_preferred(targettype, &typcategory, &typispreferred); - - if (typcategory != TYPCATEGORY_STRING) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - parser_errposition(pstate, format->location), - errmsg("cannot use JSON format with non-string output types"))); - } - - if (format->format_type == JS_FORMAT_JSON) - { - JsonEncoding enc = format->encoding != JS_ENC_DEFAULT ? - format->encoding : JS_ENC_UTF8; - - if (targettype != BYTEAOID && - format->encoding != JS_ENC_DEFAULT) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - parser_errposition(pstate, format->location), - errmsg("cannot set JSON encoding for non-bytea output types"))); - - if (enc != JS_ENC_UTF8) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("unsupported JSON encoding"), - errhint("Only UTF8 JSON encoding is supported."), - parser_errposition(pstate, format->location))); - } -} - -/* - * Transform JSON output clause. - * - * Assigns target type oid and modifier. - * Assigns default format or checks specified format for its applicability to - * the target type. - */ -static JsonReturning * -transformJsonOutput(ParseState *pstate, const JsonOutput *output, - bool allow_format) -{ - JsonReturning *ret; - - /* if output clause is not specified, make default clause value */ - if (!output) - { - ret = makeNode(JsonReturning); - - ret->format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1); - ret->typid = InvalidOid; - ret->typmod = -1; - - return ret; - } - - ret = copyObject(output->returning); - - typenameTypeIdAndMod(pstate, output->typeName, &ret->typid, &ret->typmod); - - if (output->typeName->setof) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("returning SETOF types is not supported in SQL/JSON functions"))); - - if (ret->format->format_type == JS_FORMAT_DEFAULT) - /* assign JSONB format when returning jsonb, or JSON format otherwise */ - ret->format->format_type = - ret->typid == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON; - else - checkJsonOutputFormat(pstate, ret->format, ret->typid, allow_format); - - return ret; -} - -/* - * Transform JSON output clause of JSON constructor functions. - * - * Derive RETURNING type, if not specified, from argument types. - */ -static JsonReturning * -transformJsonConstructorOutput(ParseState *pstate, JsonOutput *output, - List *args) -{ - JsonReturning *returning = transformJsonOutput(pstate, output, true); - - if (!OidIsValid(returning->typid)) - { - ListCell *lc; - bool have_jsonb = false; - - foreach(lc, args) - { - Node *expr = lfirst(lc); - Oid typid = exprType(expr); - - have_jsonb |= typid == JSONBOID; - - if (have_jsonb) - break; - } - - if (have_jsonb) - { - returning->typid = JSONBOID; - returning->format->format_type = JS_FORMAT_JSONB; - } - else - { - /* XXX TEXT is default by the standard, but we return JSON */ - returning->typid = JSONOID; - returning->format->format_type = JS_FORMAT_JSON; - } - - returning->typmod = -1; - } - - return returning; -} - -/* - * Coerce json[b]-valued function expression to the output type. - */ -static Node * -coerceJsonFuncExpr(ParseState *pstate, Node *expr, - const JsonReturning *returning, bool report_error) -{ - Node *res; - int location; - Oid exprtype = exprType(expr); - - /* if output type is not specified or equals to function type, return */ - if (!OidIsValid(returning->typid) || returning->typid == exprtype) - return expr; - - location = exprLocation(expr); - - if (location < 0) - location = returning->format->location; - - /* special case for RETURNING bytea FORMAT json */ - if (returning->format->format_type == JS_FORMAT_JSON && - returning->typid == BYTEAOID) - { - /* encode json text into bytea using pg_convert_to() */ - Node *texpr = coerce_to_specific_type(pstate, expr, TEXTOID, - "JSON_FUNCTION"); - Const *enc = getJsonEncodingConst(returning->format); - FuncExpr *fexpr = makeFuncExpr(F_CONVERT_TO, BYTEAOID, - list_make2(texpr, enc), - InvalidOid, InvalidOid, - COERCE_EXPLICIT_CALL); - - fexpr->location = location; - - return (Node *) fexpr; - } - - /* try to coerce expression to the output type */ - res = coerce_to_target_type(pstate, expr, exprtype, - returning->typid, returning->typmod, - /* XXX throwing errors when casting to char(N) */ - COERCION_EXPLICIT, - COERCE_EXPLICIT_CAST, - location); - - if (!res && report_error) - ereport(ERROR, - (errcode(ERRCODE_CANNOT_COERCE), - errmsg("cannot cast type %s to %s", - format_type_be(exprtype), - format_type_be(returning->typid)), - parser_coercion_errposition(pstate, location, expr))); - - return res; -} - -static Node * -makeJsonConstructorExpr(ParseState *pstate, JsonConstructorType type, - List *args, Expr *fexpr, JsonReturning *returning, - bool unique, bool absent_on_null, int location) -{ - JsonConstructorExpr *jsctor = makeNode(JsonConstructorExpr); - Node *placeholder; - Node *coercion; - Oid intermediate_typid = - returning->format->format_type == JS_FORMAT_JSONB ? JSONBOID : JSONOID; - - jsctor->args = args; - jsctor->func = fexpr; - jsctor->type = type; - jsctor->returning = returning; - jsctor->unique = unique; - jsctor->absent_on_null = absent_on_null; - jsctor->location = location; - - if (fexpr) - placeholder = makeCaseTestExpr((Node *) fexpr); - else - { - CaseTestExpr *cte = makeNode(CaseTestExpr); - - cte->typeId = intermediate_typid; - cte->typeMod = -1; - cte->collation = InvalidOid; - - placeholder = (Node *) cte; - } - - coercion = coerceJsonFuncExpr(pstate, placeholder, returning, true); - - if (coercion != placeholder) - jsctor->coercion = (Expr *) coercion; - - return (Node *) jsctor; -} - -/* - * Transform JSON_OBJECT() constructor. - * - * JSON_OBJECT() is transformed into json[b]_build_object[_ext]() call - * depending on the output JSON format. The first two arguments of - * json[b]_build_object_ext() are absent_on_null and check_key_uniqueness. - * - * Then function call result is coerced to the target type. - */ -static Node * -transformJsonObjectConstructor(ParseState *pstate, JsonObjectConstructor *ctor) -{ - JsonReturning *returning; - List *args = NIL; - - /* transform key-value pairs, if any */ - if (ctor->exprs) - { - ListCell *lc; - - /* transform and append key-value arguments */ - foreach(lc, ctor->exprs) - { - JsonKeyValue *kv = castNode(JsonKeyValue, lfirst(lc)); - Node *key = transformExprRecurse(pstate, (Node *) kv->key); - Node *val = transformJsonValueExprDefault(pstate, kv->value); - - args = lappend(args, key); - args = lappend(args, val); - } - } - - returning = transformJsonConstructorOutput(pstate, ctor->output, args); - - return makeJsonConstructorExpr(pstate, JSCTOR_JSON_OBJECT, args, NULL, - returning, ctor->unique, - ctor->absent_on_null, ctor->location); -} - -/* - * Transform JSON_ARRAY(query [FORMAT] [RETURNING] [ON NULL]) into - * (SELECT JSON_ARRAYAGG(a [FORMAT] [RETURNING] [ON NULL]) FROM (query) q(a)) - */ -static Node * -transformJsonArrayQueryConstructor(ParseState *pstate, - JsonArrayQueryConstructor *ctor) -{ - SubLink *sublink = makeNode(SubLink); - SelectStmt *select = makeNode(SelectStmt); - RangeSubselect *range = makeNode(RangeSubselect); - Alias *alias = makeNode(Alias); - ResTarget *target = makeNode(ResTarget); - JsonArrayAgg *agg = makeNode(JsonArrayAgg); - ColumnRef *colref = makeNode(ColumnRef); - Query *query; - ParseState *qpstate; - - /* Transform query only for counting target list entries. */ - qpstate = make_parsestate(pstate); - - query = transformStmt(qpstate, ctor->query); - - if (count_nonjunk_tlist_entries(query->targetList) != 1) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("subquery must return only one column"), - parser_errposition(pstate, ctor->location))); - - free_parsestate(qpstate); - - colref->fields = list_make2(makeString(pstrdup("q")), - makeString(pstrdup("a"))); - colref->location = ctor->location; - - agg->arg = makeJsonValueExpr((Expr *) colref, ctor->format); - agg->absent_on_null = ctor->absent_on_null; - agg->constructor = makeNode(JsonAggConstructor); - agg->constructor->agg_order = NIL; - agg->constructor->output = ctor->output; - agg->constructor->location = ctor->location; - - target->name = NULL; - target->indirection = NIL; - target->val = (Node *) agg; - target->location = ctor->location; - - alias->aliasname = pstrdup("q"); - alias->colnames = list_make1(makeString(pstrdup("a"))); - - range->lateral = false; - range->subquery = ctor->query; - range->alias = alias; - - select->targetList = list_make1(target); - select->fromClause = list_make1(range); - - sublink->subLinkType = EXPR_SUBLINK; - sublink->subLinkId = 0; - sublink->testexpr = NULL; - sublink->operName = NIL; - sublink->subselect = (Node *) select; - sublink->location = ctor->location; - - return transformExprRecurse(pstate, (Node *) sublink); -} - -/* - * Common code for JSON_OBJECTAGG and JSON_ARRAYAGG transformation. - */ -static Node * -transformJsonAggConstructor(ParseState *pstate, JsonAggConstructor *agg_ctor, - JsonReturning *returning, List *args, - const char *aggfn, Oid aggtype, - JsonConstructorType ctor_type, - bool unique, bool absent_on_null) -{ - Oid aggfnoid; - Node *node; - Expr *aggfilter = agg_ctor->agg_filter ? (Expr *) - transformWhereClause(pstate, agg_ctor->agg_filter, - EXPR_KIND_FILTER, "FILTER") : NULL; - - aggfnoid = DatumGetInt32(DirectFunctionCall1(regprocin, - CStringGetDatum(aggfn))); - - if (agg_ctor->over) - { - /* window function */ - WindowFunc *wfunc = makeNode(WindowFunc); - - wfunc->winfnoid = aggfnoid; - wfunc->wintype = aggtype; - /* wincollid and inputcollid will be set by parse_collate.c */ - wfunc->args = args; - /* winref will be set by transformWindowFuncCall */ - wfunc->winstar = false; - wfunc->winagg = true; - wfunc->aggfilter = aggfilter; - wfunc->location = agg_ctor->location; - - /* - * ordered aggs not allowed in windows yet - */ - if (agg_ctor->agg_order != NIL) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("aggregate ORDER BY is not implemented for window functions"), - parser_errposition(pstate, agg_ctor->location))); - - /* parse_agg.c does additional window-func-specific processing */ - transformWindowFuncCall(pstate, wfunc, agg_ctor->over); - - node = (Node *) wfunc; - } - else - { - Aggref *aggref = makeNode(Aggref); - - aggref->aggfnoid = aggfnoid; - aggref->aggtype = aggtype; - - /* aggcollid and inputcollid will be set by parse_collate.c */ - aggref->aggtranstype = InvalidOid; /* will be set by planner */ - /* aggargtypes will be set by transformAggregateCall */ - /* aggdirectargs and args will be set by transformAggregateCall */ - /* aggorder and aggdistinct will be set by transformAggregateCall */ - aggref->aggfilter = aggfilter; - aggref->aggstar = false; - aggref->aggvariadic = false; - aggref->aggkind = AGGKIND_NORMAL; - aggref->aggpresorted = false; - /* agglevelsup will be set by transformAggregateCall */ - aggref->aggsplit = AGGSPLIT_SIMPLE; /* planner might change this */ - aggref->location = agg_ctor->location; - - transformAggregateCall(pstate, aggref, args, agg_ctor->agg_order, false); - - node = (Node *) aggref; - } - - return makeJsonConstructorExpr(pstate, ctor_type, NIL, (Expr *) node, - returning, unique, absent_on_null, - agg_ctor->location); -} - -/* - * Transform JSON_OBJECTAGG() aggregate function. - * - * JSON_OBJECTAGG() is transformed into - * json[b]_objectagg(key, value, absent_on_null, check_unique) call depending on - * the output JSON format. Then the function call result is coerced to the - * target output type. - */ -static Node * -transformJsonObjectAgg(ParseState *pstate, JsonObjectAgg *agg) -{ - JsonReturning *returning; - Node *key; - Node *val; - List *args; - const char *aggfnname; - Oid aggtype; - - key = transformExprRecurse(pstate, (Node *) agg->arg->key); - val = transformJsonValueExprDefault(pstate, agg->arg->value); - args = list_make2(key, val); - - returning = transformJsonConstructorOutput(pstate, agg->constructor->output, - args); - - if (returning->format->format_type == JS_FORMAT_JSONB) - { - if (agg->absent_on_null) - if (agg->unique) - aggfnname = "pg_catalog.jsonb_object_agg_unique_strict"; /* F_JSONB_OBJECT_AGG_UNIQUE_STRICT */ - else - aggfnname = "pg_catalog.jsonb_object_agg_strict"; /* F_JSONB_OBJECT_AGG_STRICT */ - else if (agg->unique) - aggfnname = "pg_catalog.jsonb_object_agg_unique"; /* F_JSONB_OBJECT_AGG_UNIQUE */ - else - aggfnname = "pg_catalog.jsonb_object_agg"; /* F_JSONB_OBJECT_AGG */ - - aggtype = JSONBOID; - } - else - { - if (agg->absent_on_null) - if (agg->unique) - aggfnname = "pg_catalog.json_object_agg_unique_strict"; /* F_JSON_OBJECT_AGG_UNIQUE_STRICT */ - else - aggfnname = "pg_catalog.json_object_agg_strict"; /* F_JSON_OBJECT_AGG_STRICT */ - else if (agg->unique) - aggfnname = "pg_catalog.json_object_agg_unique"; /* F_JSON_OBJECT_AGG_UNIQUE */ - else - aggfnname = "pg_catalog.json_object_agg"; /* F_JSON_OBJECT_AGG */ - - aggtype = JSONOID; - } - - return transformJsonAggConstructor(pstate, agg->constructor, returning, - args, aggfnname, aggtype, - JSCTOR_JSON_OBJECTAGG, - agg->unique, agg->absent_on_null); -} - -/* - * Transform JSON_ARRAYAGG() aggregate function. - * - * JSON_ARRAYAGG() is transformed into json[b]_agg[_strict]() call depending - * on the output JSON format and absent_on_null. Then the function call result - * is coerced to the target output type. - */ -static Node * -transformJsonArrayAgg(ParseState *pstate, JsonArrayAgg *agg) -{ - JsonReturning *returning; - Node *arg; - const char *aggfnname; - Oid aggtype; - - arg = transformJsonValueExprDefault(pstate, agg->arg); - - returning = transformJsonConstructorOutput(pstate, agg->constructor->output, - list_make1(arg)); - - if (returning->format->format_type == JS_FORMAT_JSONB) - { - aggfnname = agg->absent_on_null ? - "pg_catalog.jsonb_agg_strict" : "pg_catalog.jsonb_agg"; - aggtype = JSONBOID; - } - else - { - aggfnname = agg->absent_on_null ? - "pg_catalog.json_agg_strict" : "pg_catalog.json_agg"; - aggtype = JSONOID; - } - - return transformJsonAggConstructor(pstate, agg->constructor, returning, - list_make1(arg), aggfnname, aggtype, - JSCTOR_JSON_ARRAYAGG, - false, agg->absent_on_null); -} - -/* - * Transform JSON_ARRAY() constructor. - * - * JSON_ARRAY() is transformed into json[b]_build_array[_ext]() call - * depending on the output JSON format. The first argument of - * json[b]_build_array_ext() is absent_on_null. - * - * Then function call result is coerced to the target type. - */ -static Node * -transformJsonArrayConstructor(ParseState *pstate, JsonArrayConstructor *ctor) -{ - JsonReturning *returning; - List *args = NIL; - - /* transform element expressions, if any */ - if (ctor->exprs) - { - ListCell *lc; - - /* transform and append element arguments */ - foreach(lc, ctor->exprs) - { - JsonValueExpr *jsval = castNode(JsonValueExpr, lfirst(lc)); - Node *val = transformJsonValueExprDefault(pstate, jsval); - - args = lappend(args, val); - } - } - - returning = transformJsonConstructorOutput(pstate, ctor->output, args); - - return makeJsonConstructorExpr(pstate, JSCTOR_JSON_ARRAY, args, NULL, - returning, false, ctor->absent_on_null, - ctor->location); -} - -static Node * -transformJsonParseArg(ParseState *pstate, Node *jsexpr, JsonFormat *format, - Oid *exprtype) -{ - Node *raw_expr = transformExprRecurse(pstate, jsexpr); - Node *expr = raw_expr; - - *exprtype = exprType(expr); - - /* prepare input document */ - if (*exprtype == BYTEAOID) - { - JsonValueExpr *jve; - - expr = makeCaseTestExpr(raw_expr); - expr = makeJsonByteaToTextConversion(expr, format, exprLocation(expr)); - *exprtype = TEXTOID; - - jve = makeJsonValueExpr((Expr *) raw_expr, format); - - jve->formatted_expr = (Expr *) expr; - expr = (Node *) jve; - } - else - { - char typcategory; - bool typispreferred; - - get_type_category_preferred(*exprtype, &typcategory, &typispreferred); - - if (*exprtype == UNKNOWNOID || typcategory == TYPCATEGORY_STRING) - { - expr = coerce_to_target_type(pstate, (Node *) expr, *exprtype, - TEXTOID, -1, - COERCION_IMPLICIT, - COERCE_IMPLICIT_CAST, -1); - *exprtype = TEXTOID; - } - - if (format->encoding != JS_ENC_DEFAULT) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - parser_errposition(pstate, format->location), - errmsg("cannot use JSON FORMAT ENCODING clause for non-bytea input types"))); - } - - return expr; -} - -/* - * Transform IS JSON predicate. - */ -static Node * -transformJsonIsPredicate(ParseState *pstate, JsonIsPredicate *pred) -{ - Oid exprtype; - Node *expr = transformJsonParseArg(pstate, pred->expr, pred->format, - &exprtype); - - /* make resulting expression */ - if (exprtype != TEXTOID && exprtype != JSONOID && exprtype != JSONBOID) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("cannot use type %s in IS JSON predicate", - format_type_be(exprtype)))); - - /* This intentionally(?) drops the format clause. */ - return makeJsonIsPredicate(expr, NULL, pred->item_type, - pred->unique_keys, pred->location); -} - -/* - * Transform a JSON PASSING clause. - */ -static void -transformJsonPassingArgs(ParseState *pstate, JsonFormatType format, List *args, - List **passing_values, List **passing_names) -{ - ListCell *lc; - - *passing_values = NIL; - *passing_names = NIL; - - foreach(lc, args) - { - JsonArgument *arg = castNode(JsonArgument, lfirst(lc)); - Node *expr = transformJsonValueExprExt(pstate, arg->val, - format, true, InvalidOid); - - assign_expr_collations(pstate, expr); - - *passing_values = lappend(*passing_values, expr); - *passing_names = lappend(*passing_names, makeString(arg->name)); - } -} - -/* - * Transform a JSON BEHAVIOR clause. - */ -static JsonBehavior * -transformJsonBehavior(ParseState *pstate, JsonBehavior *behavior, - JsonBehaviorType default_behavior) -{ - JsonBehaviorType behavior_type = default_behavior; - Node *default_expr = NULL; - - if (behavior) - { - behavior_type = behavior->btype; - if (behavior_type == JSON_BEHAVIOR_DEFAULT) - default_expr = transformExprRecurse(pstate, behavior->default_expr); - } - return makeJsonBehavior(behavior_type, default_expr); -} - -/* - * Common code for JSON_VALUE, JSON_QUERY, JSON_EXISTS transformation - * into a JsonExpr node. - */ -static JsonExpr * -transformJsonExprCommon(ParseState *pstate, JsonFuncExpr *func) -{ - JsonExpr *jsexpr = makeNode(JsonExpr); - Node *pathspec; - JsonFormatType format; - - if (func->common->pathname && func->op != JSON_TABLE_OP) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("JSON_TABLE path name is not allowed here"), - parser_errposition(pstate, func->location))); - - jsexpr->location = func->location; - jsexpr->op = func->op; - jsexpr->formatted_expr = transformJsonValueExpr(pstate, func->common->expr); - - assign_expr_collations(pstate, jsexpr->formatted_expr); - - /* format is determined by context item type */ - format = exprType(jsexpr->formatted_expr) == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON; - - jsexpr->result_coercion = NULL; - jsexpr->omit_quotes = false; - - jsexpr->format = func->common->expr->format; - - pathspec = transformExprRecurse(pstate, func->common->pathspec); - - jsexpr->path_spec = - coerce_to_target_type(pstate, pathspec, exprType(pathspec), - JSONPATHOID, -1, - COERCION_EXPLICIT, COERCE_IMPLICIT_CAST, - exprLocation(pathspec)); - if (!jsexpr->path_spec) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("JSON path expression must be type %s, not type %s", - "jsonpath", format_type_be(exprType(pathspec))), - parser_errposition(pstate, exprLocation(pathspec)))); - - /* transform and coerce to json[b] passing arguments */ - transformJsonPassingArgs(pstate, format, func->common->passing, - &jsexpr->passing_values, &jsexpr->passing_names); - - if (func->op != JSON_EXISTS_OP && func->op != JSON_TABLE_OP) - jsexpr->on_empty = transformJsonBehavior(pstate, func->on_empty, - JSON_BEHAVIOR_NULL); - - if (func->op == JSON_EXISTS_OP) - jsexpr->on_error = transformJsonBehavior(pstate, func->on_error, - JSON_BEHAVIOR_FALSE); - else if (func->op == JSON_TABLE_OP) - jsexpr->on_error = transformJsonBehavior(pstate, func->on_error, - JSON_BEHAVIOR_EMPTY); - else - jsexpr->on_error = transformJsonBehavior(pstate, func->on_error, - JSON_BEHAVIOR_NULL); - - return jsexpr; -} - -/* - * Assign default JSON returning type from the specified format or from - * the context item type. - */ -static void -assignDefaultJsonReturningType(Node *context_item, JsonFormat *context_format, - JsonReturning *ret) -{ - bool is_jsonb; - - ret->format = copyObject(context_format); - - if (ret->format->format_type == JS_FORMAT_DEFAULT) - is_jsonb = exprType(context_item) == JSONBOID; - else - is_jsonb = ret->format->format_type == JS_FORMAT_JSONB; - - ret->typid = is_jsonb ? JSONBOID : JSONOID; - ret->typmod = -1; -} - -/* - * Try to coerce expression to the output type or - * use json_populate_type() for composite, array and domain types or - * use coercion via I/O. - */ -static JsonCoercion * -coerceJsonExpr(ParseState *pstate, Node *expr, const JsonReturning *returning) -{ - char typtype; - JsonCoercion *coercion = makeNode(JsonCoercion); - - coercion->expr = coerceJsonFuncExpr(pstate, expr, returning, false); - - if (coercion->expr) - { - if (coercion->expr == expr) - coercion->expr = NULL; - - return coercion; - } - - typtype = get_typtype(returning->typid); - - if (returning->typid == RECORDOID || - typtype == TYPTYPE_COMPOSITE || - typtype == TYPTYPE_DOMAIN || - type_is_array(returning->typid)) - coercion->via_populate = true; - else - coercion->via_io = true; - - return coercion; -} - -/* - * Transform a JSON output clause of JSON_VALUE and JSON_QUERY. - */ -static void -transformJsonFuncExprOutput(ParseState *pstate, JsonFuncExpr *func, - JsonExpr *jsexpr) -{ - Node *expr = jsexpr->formatted_expr; - - jsexpr->returning = transformJsonOutput(pstate, func->output, false); - - /* JSON_VALUE returns text by default */ - if (func->op == JSON_VALUE_OP && !OidIsValid(jsexpr->returning->typid)) - { - jsexpr->returning->typid = TEXTOID; - jsexpr->returning->typmod = -1; - } - - if (OidIsValid(jsexpr->returning->typid)) - { - JsonReturning ret; - - if (func->op == JSON_VALUE_OP && - jsexpr->returning->typid != JSONOID && - jsexpr->returning->typid != JSONBOID) - { - /* Forced coercion via I/O for JSON_VALUE for non-JSON types */ - jsexpr->result_coercion = makeNode(JsonCoercion); - jsexpr->result_coercion->expr = NULL; - jsexpr->result_coercion->via_io = true; - return; - } - - assignDefaultJsonReturningType(jsexpr->formatted_expr, jsexpr->format, &ret); - - if (ret.typid != jsexpr->returning->typid || - ret.typmod != jsexpr->returning->typmod) - { - Node *placeholder = makeCaseTestExpr(expr); - - Assert(((CaseTestExpr *) placeholder)->typeId == ret.typid); - Assert(((CaseTestExpr *) placeholder)->typeMod == ret.typmod); - - jsexpr->result_coercion = coerceJsonExpr(pstate, placeholder, - jsexpr->returning); - } - } - else - assignDefaultJsonReturningType(jsexpr->formatted_expr, jsexpr->format, - jsexpr->returning); -} - -/* - * Coerce an expression in JSON DEFAULT behavior to the target output type. - */ -static Node * -coerceDefaultJsonExpr(ParseState *pstate, JsonExpr *jsexpr, Node *defexpr) -{ - int location; - Oid exprtype; - - if (!defexpr) - return NULL; - - exprtype = exprType(defexpr); - location = exprLocation(defexpr); - - if (location < 0) - location = jsexpr->location; - - defexpr = coerce_to_target_type(pstate, - defexpr, - exprtype, - jsexpr->returning->typid, - jsexpr->returning->typmod, - COERCION_EXPLICIT, - COERCE_IMPLICIT_CAST, - location); - - if (!defexpr) - ereport(ERROR, - (errcode(ERRCODE_CANNOT_COERCE), - errmsg("cannot cast DEFAULT expression type %s to %s", - format_type_be(exprtype), - format_type_be(jsexpr->returning->typid)), - parser_errposition(pstate, location))); - - return defexpr; -} - -/* - * Initialize SQL/JSON item coercion from the SQL type "typid" to the target - * "returning" type. - */ -static JsonCoercion * -initJsonItemCoercion(ParseState *pstate, Oid typid, - const JsonReturning *returning) -{ - Node *expr; - - if (typid == UNKNOWNOID) - { - expr = (Node *) makeNullConst(UNKNOWNOID, -1, InvalidOid); - } - else - { - CaseTestExpr *placeholder = makeNode(CaseTestExpr); - - placeholder->typeId = typid; - placeholder->typeMod = -1; - placeholder->collation = InvalidOid; - - expr = (Node *) placeholder; - } - - return coerceJsonExpr(pstate, expr, returning); -} - -static void -initJsonItemCoercions(ParseState *pstate, JsonItemCoercions *coercions, - const JsonReturning *returning, Oid contextItemTypeId) -{ - struct - { - JsonCoercion **coercion; - Oid typid; - } *p, - coercionTypids[] = - { - {&coercions->null, UNKNOWNOID}, - {&coercions->string, TEXTOID}, - {&coercions->numeric, NUMERICOID}, - {&coercions->boolean, BOOLOID}, - {&coercions->date, DATEOID}, - {&coercions->time, TIMEOID}, - {&coercions->timetz, TIMETZOID}, - {&coercions->timestamp, TIMESTAMPOID}, - {&coercions->timestamptz, TIMESTAMPTZOID}, - {&coercions->composite, contextItemTypeId}, - {NULL, InvalidOid} - }; - - for (p = coercionTypids; p->coercion; p++) - *p->coercion = initJsonItemCoercion(pstate, p->typid, returning); -} - -/* - * Transform JSON_VALUE, JSON_QUERY, JSON_EXISTS functions into a JsonExpr node. - */ -static Node * -transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func) -{ - JsonExpr *jsexpr = transformJsonExprCommon(pstate, func); - const char *func_name = NULL; - Node *contextItemExpr = jsexpr->formatted_expr; - - switch (func->op) - { - case JSON_VALUE_OP: - func_name = "JSON_VALUE"; - - transformJsonFuncExprOutput(pstate, func, jsexpr); - - jsexpr->returning->format->format_type = JS_FORMAT_DEFAULT; - jsexpr->returning->format->encoding = JS_ENC_DEFAULT; - - jsexpr->on_empty->default_expr = - coerceDefaultJsonExpr(pstate, jsexpr, - jsexpr->on_empty->default_expr); - - jsexpr->on_error->default_expr = - coerceDefaultJsonExpr(pstate, jsexpr, - jsexpr->on_error->default_expr); - - jsexpr->coercions = makeNode(JsonItemCoercions); - initJsonItemCoercions(pstate, jsexpr->coercions, jsexpr->returning, - exprType(contextItemExpr)); - - break; - - case JSON_QUERY_OP: - func_name = "JSON_QUERY"; - - transformJsonFuncExprOutput(pstate, func, jsexpr); - - jsexpr->on_empty->default_expr = - coerceDefaultJsonExpr(pstate, jsexpr, - jsexpr->on_empty->default_expr); - - jsexpr->on_error->default_expr = - coerceDefaultJsonExpr(pstate, jsexpr, - jsexpr->on_error->default_expr); - - jsexpr->wrapper = func->wrapper; - jsexpr->omit_quotes = func->omit_quotes; - - break; - - case JSON_EXISTS_OP: - func_name = "JSON_EXISTS"; - - jsexpr->returning = transformJsonOutput(pstate, func->output, false); - - jsexpr->returning->format->format_type = JS_FORMAT_DEFAULT; - jsexpr->returning->format->encoding = JS_ENC_DEFAULT; - - if (!OidIsValid(jsexpr->returning->typid)) - { - jsexpr->returning->typid = BOOLOID; - jsexpr->returning->typmod = -1; - } - else if (jsexpr->returning->typid != BOOLOID) - { - CaseTestExpr *placeholder = makeNode(CaseTestExpr); - int location = exprLocation((Node *) jsexpr); - - placeholder->typeId = BOOLOID; - placeholder->typeMod = -1; - placeholder->collation = InvalidOid; - - jsexpr->result_coercion = makeNode(JsonCoercion); - jsexpr->result_coercion->expr = - coerce_to_target_type(pstate, (Node *) placeholder, BOOLOID, - jsexpr->returning->typid, - jsexpr->returning->typmod, - COERCION_EXPLICIT, - COERCE_IMPLICIT_CAST, - location); - - if (!jsexpr->result_coercion->expr) - ereport(ERROR, - (errcode(ERRCODE_CANNOT_COERCE), - errmsg("cannot cast type %s to %s", - format_type_be(BOOLOID), - format_type_be(jsexpr->returning->typid)), - parser_coercion_errposition(pstate, location, (Node *) jsexpr))); - - if (jsexpr->result_coercion->expr == (Node *) placeholder) - jsexpr->result_coercion->expr = NULL; - } - break; - - case JSON_TABLE_OP: - jsexpr->returning = makeNode(JsonReturning); - jsexpr->returning->format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1); - jsexpr->returning->typid = exprType(contextItemExpr); - jsexpr->returning->typmod = -1; - - if (jsexpr->returning->typid != JSONBOID) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("JSON_TABLE() is not yet implemented for the json type"), - errhint("Try casting the argument to jsonb"), - parser_errposition(pstate, func->location))); - - break; - } - - if (exprType(contextItemExpr) != JSONBOID) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("%s() is not yet implemented for the json type", func_name), - errhint("Try casting the argument to jsonb"), - parser_errposition(pstate, func->location))); - - return (Node *) jsexpr; -} - -static JsonReturning * -transformJsonConstructorRet(ParseState *pstate, JsonOutput *output, const char *fname) -{ - JsonReturning *returning; - - if (output) - { - returning = transformJsonOutput(pstate, output, false); - - Assert(OidIsValid(returning->typid)); - - if (returning->typid != JSONOID && returning->typid != JSONBOID) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("cannot use RETURNING type %s in %s", - format_type_be(returning->typid), fname), - parser_errposition(pstate, output->typeName->location))); - } - else - { - Oid targettype = JSONOID; - JsonFormatType format = JS_FORMAT_JSON; - - returning = makeNode(JsonReturning); - returning->format = makeJsonFormat(format, JS_ENC_DEFAULT, -1); - returning->typid = targettype; - returning->typmod = -1; - } - - return returning; -} - -/* - * Transform a JSON() expression. - */ -static Node * -transformJsonParseExpr(ParseState *pstate, JsonParseExpr *jsexpr) -{ - JsonReturning *returning = transformJsonConstructorRet(pstate, jsexpr->output, - "JSON()"); - Node *arg; - - if (jsexpr->unique_keys) - { - /* - * Coerce string argument to text and then to json[b] in the executor - * node with key uniqueness check. - */ - JsonValueExpr *jve = jsexpr->expr; - Oid arg_type; - - arg = transformJsonParseArg(pstate, (Node *) jve->raw_expr, jve->format, - &arg_type); - - if (arg_type != TEXTOID) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("cannot use non-string types with WITH UNIQUE KEYS clause"), - parser_errposition(pstate, jsexpr->location))); - } - else - { - /* - * Coerce argument to target type using CAST for compatibility with PG - * function-like CASTs. - */ - arg = transformJsonValueExprExt(pstate, jsexpr->expr, JS_FORMAT_JSON, - false, returning->typid); - } - - return makeJsonConstructorExpr(pstate, JSCTOR_JSON_PARSE, list_make1(arg), NULL, - returning, jsexpr->unique_keys, false, - jsexpr->location); -} - -/* - * Transform a JSON_SCALAR() expression. - */ -static Node * -transformJsonScalarExpr(ParseState *pstate, JsonScalarExpr *jsexpr) -{ - Node *arg = transformExprRecurse(pstate, (Node *) jsexpr->expr); - JsonReturning *returning = transformJsonConstructorRet(pstate, jsexpr->output, - "JSON_SCALAR()"); - - if (exprType(arg) == UNKNOWNOID) - arg = coerce_to_specific_type(pstate, arg, TEXTOID, "JSON_SCALAR"); - - return makeJsonConstructorExpr(pstate, JSCTOR_JSON_SCALAR, list_make1(arg), NULL, - returning, false, false, jsexpr->location); -} - -/* - * Transform a JSON_SERIALIZE() expression. - */ -static Node * -transformJsonSerializeExpr(ParseState *pstate, JsonSerializeExpr *expr) -{ - Node *arg = transformJsonValueExpr(pstate, expr->expr); - JsonReturning *returning; - - if (expr->output) - { - returning = transformJsonOutput(pstate, expr->output, true); - - if (returning->typid != BYTEAOID) - { - char typcategory; - bool typispreferred; - - get_type_category_preferred(returning->typid, &typcategory, - &typispreferred); - if (typcategory != TYPCATEGORY_STRING) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("cannot use RETURNING type %s in %s", - format_type_be(returning->typid), - "JSON_SERIALIZE()"), - errhint("Try returning a string type or bytea."))); - } - } - else - { - /* RETURNING TEXT FORMAT JSON is by default */ - returning = makeNode(JsonReturning); - returning->format = makeJsonFormat(JS_FORMAT_JSON, JS_ENC_DEFAULT, -1); - returning->typid = TEXTOID; - returning->typmod = -1; - } - - return makeJsonConstructorExpr(pstate, JSCTOR_JSON_SERIALIZE, list_make1(arg), - NULL, returning, false, false, expr->location); -} diff --git a/src/backend/parser/parse_jsontable.c b/src/backend/parser/parse_jsontable.c deleted file mode 100644 index 3e94071248e..00000000000 --- a/src/backend/parser/parse_jsontable.c +++ /dev/null @@ -1,732 +0,0 @@ -/*------------------------------------------------------------------------- - * - * parse_jsontable.c - * parsing of JSON_TABLE - * - * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * src/backend/parser/parse_jsontable.c - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" - -#include "catalog/pg_collation.h" -#include "catalog/pg_type.h" -#include "miscadmin.h" -#include "nodes/makefuncs.h" -#include "nodes/nodeFuncs.h" -#include "optimizer/optimizer.h" -#include "parser/parse_clause.h" -#include "parser/parse_collate.h" -#include "parser/parse_expr.h" -#include "parser/parse_relation.h" -#include "parser/parse_type.h" -#include "utils/builtins.h" -#include "utils/json.h" -#include "utils/lsyscache.h" - -/* Context for JSON_TABLE transformation */ -typedef struct JsonTableContext -{ - ParseState *pstate; /* parsing state */ - JsonTable *table; /* untransformed node */ - TableFunc *tablefunc; /* transformed node */ - List *pathNames; /* list of all path and columns names */ - int pathNameId; /* path name id counter */ - Oid contextItemTypid; /* type oid of context item (json/jsonb) */ -} JsonTableContext; - -static JsonTableParent *transformJsonTableColumns(JsonTableContext *cxt, - JsonTablePlan *plan, - List *columns, - char *pathSpec, - char **pathName, - int location); - -static Node * -makeStringConst(char *str, int location) -{ - A_Const *n = makeNode(A_Const); - - n->val.node.type = T_String; - n->val.sval.sval = str; - n->location = location; - - return (Node *) n; -} - -/* - * Transform JSON_TABLE column - * - regular column into JSON_VALUE() - * - FORMAT JSON column into JSON_QUERY() - * - EXISTS column into JSON_EXISTS() - */ -static Node * -transformJsonTableColumn(JsonTableColumn *jtc, Node *contextItemExpr, - List *passingArgs, bool errorOnError) -{ - JsonFuncExpr *jfexpr = makeNode(JsonFuncExpr); - JsonCommon *common = makeNode(JsonCommon); - JsonOutput *output = makeNode(JsonOutput); - char *pathspec; - JsonFormat *default_format; - - jfexpr->op = - jtc->coltype == JTC_REGULAR ? JSON_VALUE_OP : - jtc->coltype == JTC_EXISTS ? JSON_EXISTS_OP : JSON_QUERY_OP; - jfexpr->common = common; - jfexpr->output = output; - jfexpr->on_empty = jtc->on_empty; - jfexpr->on_error = jtc->on_error; - if (!jfexpr->on_error && errorOnError) - jfexpr->on_error = makeJsonBehavior(JSON_BEHAVIOR_ERROR, NULL); - jfexpr->omit_quotes = jtc->omit_quotes; - jfexpr->wrapper = jtc->wrapper; - jfexpr->location = jtc->location; - - output->typeName = jtc->typeName; - output->returning = makeNode(JsonReturning); - output->returning->format = jtc->format; - - default_format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1); - - common->pathname = NULL; - common->expr = makeJsonValueExpr((Expr *) contextItemExpr, default_format); - common->passing = passingArgs; - - if (jtc->pathspec) - pathspec = jtc->pathspec; - else - { - /* Construct default path as '$."column_name"' */ - StringInfoData path; - - initStringInfo(&path); - - appendStringInfoString(&path, "$."); - escape_json(&path, jtc->name); - - pathspec = path.data; - } - - common->pathspec = makeStringConst(pathspec, -1); - - return (Node *) jfexpr; -} - -static bool -isJsonTablePathNameDuplicate(JsonTableContext *cxt, const char *pathname) -{ - ListCell *lc; - - foreach(lc, cxt->pathNames) - { - if (!strcmp(pathname, (const char *) lfirst(lc))) - return true; - } - - return false; -} - -/* Register the column name in the path name list. */ -static void -registerJsonTableColumn(JsonTableContext *cxt, char *colname) -{ - if (isJsonTablePathNameDuplicate(cxt, colname)) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_ALIAS), - errmsg("duplicate JSON_TABLE column name: %s", colname), - errhint("JSON_TABLE column names must be distinct from one another."))); - - cxt->pathNames = lappend(cxt->pathNames, colname); -} - -/* Recursively register all nested column names in the path name list. */ -static void -registerAllJsonTableColumns(JsonTableContext *cxt, List *columns) -{ - ListCell *lc; - - foreach(lc, columns) - { - JsonTableColumn *jtc = castNode(JsonTableColumn, lfirst(lc)); - - if (jtc->coltype == JTC_NESTED) - { - if (jtc->pathname) - registerJsonTableColumn(cxt, jtc->pathname); - - registerAllJsonTableColumns(cxt, jtc->columns); - } - else - { - registerJsonTableColumn(cxt, jtc->name); - } - } -} - -/* Generate a new unique JSON_TABLE path name. */ -static char * -generateJsonTablePathName(JsonTableContext *cxt) -{ - char namebuf[32]; - char *name = namebuf; - - do - { - snprintf(namebuf, sizeof(namebuf), "json_table_path_%d", - ++cxt->pathNameId); - } while (isJsonTablePathNameDuplicate(cxt, name)); - - name = pstrdup(name); - cxt->pathNames = lappend(cxt->pathNames, name); - - return name; -} - -/* Collect sibling path names from plan to the specified list. */ -static void -collectSiblingPathsInJsonTablePlan(JsonTablePlan *plan, List **paths) -{ - if (plan->plan_type == JSTP_SIMPLE) - *paths = lappend(*paths, plan->pathname); - else if (plan->plan_type == JSTP_JOINED) - { - if (plan->join_type == JSTPJ_INNER || - plan->join_type == JSTPJ_OUTER) - { - Assert(plan->plan1->plan_type == JSTP_SIMPLE); - *paths = lappend(*paths, plan->plan1->pathname); - } - else if (plan->join_type == JSTPJ_CROSS || - plan->join_type == JSTPJ_UNION) - { - collectSiblingPathsInJsonTablePlan(plan->plan1, paths); - collectSiblingPathsInJsonTablePlan(plan->plan2, paths); - } - else - elog(ERROR, "invalid JSON_TABLE join type %d", - plan->join_type); - } -} - -/* - * Validate child JSON_TABLE plan by checking that: - * - all nested columns have path names specified - * - all nested columns have corresponding node in the sibling plan - * - plan does not contain duplicate or extra nodes - */ -static void -validateJsonTableChildPlan(ParseState *pstate, JsonTablePlan *plan, - List *columns) -{ - ListCell *lc1; - List *siblings = NIL; - int nchildren = 0; - - if (plan) - collectSiblingPathsInJsonTablePlan(plan, &siblings); - - foreach(lc1, columns) - { - JsonTableColumn *jtc = castNode(JsonTableColumn, lfirst(lc1)); - - if (jtc->coltype == JTC_NESTED) - { - ListCell *lc2; - bool found = false; - - if (!jtc->pathname) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("nested JSON_TABLE columns must contain an explicit AS pathname specification if an explicit PLAN clause is used"), - parser_errposition(pstate, jtc->location))); - - /* find nested path name in the list of sibling path names */ - foreach(lc2, siblings) - { - if ((found = !strcmp(jtc->pathname, lfirst(lc2)))) - break; - } - - if (!found) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid JSON_TABLE plan"), - errdetail("Plan node for nested path %s was not found in plan.", jtc->pathname), - parser_errposition(pstate, jtc->location))); - - nchildren++; - } - } - - if (list_length(siblings) > nchildren) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid JSON_TABLE plan"), - errdetail("Plan node contains some extra or duplicate sibling nodes."), - parser_errposition(pstate, plan ? plan->location : -1))); -} - -static JsonTableColumn * -findNestedJsonTableColumn(List *columns, const char *pathname) -{ - ListCell *lc; - - foreach(lc, columns) - { - JsonTableColumn *jtc = castNode(JsonTableColumn, lfirst(lc)); - - if (jtc->coltype == JTC_NESTED && - jtc->pathname && - !strcmp(jtc->pathname, pathname)) - return jtc; - } - - return NULL; -} - -static Node * -transformNestedJsonTableColumn(JsonTableContext *cxt, JsonTableColumn *jtc, - JsonTablePlan *plan) -{ - JsonTableParent *node; - char *pathname = jtc->pathname; - - node = transformJsonTableColumns(cxt, plan, jtc->columns, jtc->pathspec, - &pathname, jtc->location); - node->name = pstrdup(pathname); - - return (Node *) node; -} - -static Node * -makeJsonTableSiblingJoin(bool cross, Node *lnode, Node *rnode) -{ - JsonTableSibling *join = makeNode(JsonTableSibling); - - join->larg = lnode; - join->rarg = rnode; - join->cross = cross; - - return (Node *) join; -} - -/* - * Recursively transform child JSON_TABLE plan. - * - * Default plan is transformed into a cross/union join of its nested columns. - * Simple and outer/inner plans are transformed into a JsonTableParent by - * finding and transforming corresponding nested column. - * Sibling plans are recursively transformed into a JsonTableSibling. - */ -static Node * -transformJsonTableChildPlan(JsonTableContext *cxt, JsonTablePlan *plan, - List *columns) -{ - JsonTableColumn *jtc = NULL; - - if (!plan || plan->plan_type == JSTP_DEFAULT) - { - /* unspecified or default plan */ - Node *res = NULL; - ListCell *lc; - bool cross = plan && (plan->join_type & JSTPJ_CROSS); - - /* transform all nested columns into cross/union join */ - foreach(lc, columns) - { - JsonTableColumn *col = castNode(JsonTableColumn, lfirst(lc)); - Node *node; - - if (col->coltype != JTC_NESTED) - continue; - - node = transformNestedJsonTableColumn(cxt, col, plan); - - /* join transformed node with previous sibling nodes */ - res = res ? makeJsonTableSiblingJoin(cross, res, node) : node; - } - - return res; - } - else if (plan->plan_type == JSTP_SIMPLE) - { - jtc = findNestedJsonTableColumn(columns, plan->pathname); - } - else if (plan->plan_type == JSTP_JOINED) - { - if (plan->join_type == JSTPJ_INNER || - plan->join_type == JSTPJ_OUTER) - { - Assert(plan->plan1->plan_type == JSTP_SIMPLE); - jtc = findNestedJsonTableColumn(columns, plan->plan1->pathname); - } - else - { - Node *node1 = transformJsonTableChildPlan(cxt, plan->plan1, - columns); - Node *node2 = transformJsonTableChildPlan(cxt, plan->plan2, - columns); - - return makeJsonTableSiblingJoin(plan->join_type == JSTPJ_CROSS, - node1, node2); - } - } - else - elog(ERROR, "invalid JSON_TABLE plan type %d", plan->plan_type); - - if (!jtc) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid JSON_TABLE plan"), - errdetail("Path name was %s not found in nested columns list.", - plan->pathname), - parser_errposition(cxt->pstate, plan->location))); - - return transformNestedJsonTableColumn(cxt, jtc, plan); -} - -/* Check whether type is json/jsonb, array, or record. */ -static bool -typeIsComposite(Oid typid) -{ - char typtype; - - if (typid == JSONOID || - typid == JSONBOID || - typid == RECORDOID || - type_is_array(typid)) - return true; - - typtype = get_typtype(typid); - - if (typtype == TYPTYPE_COMPOSITE) - return true; - - if (typtype == TYPTYPE_DOMAIN) - return typeIsComposite(getBaseType(typid)); - - return false; -} - -/* Append transformed non-nested JSON_TABLE columns to the TableFunc node */ -static void -appendJsonTableColumns(JsonTableContext *cxt, List *columns) -{ - ListCell *col; - ParseState *pstate = cxt->pstate; - JsonTable *jt = cxt->table; - TableFunc *tf = cxt->tablefunc; - bool errorOnError = jt->on_error && - jt->on_error->btype == JSON_BEHAVIOR_ERROR; - - foreach(col, columns) - { - JsonTableColumn *rawc = castNode(JsonTableColumn, lfirst(col)); - Oid typid; - int32 typmod; - Node *colexpr; - - if (rawc->name) - { - /* make sure column names are unique */ - ListCell *colname; - - foreach(colname, tf->colnames) - if (!strcmp((const char *) colname, rawc->name)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("column name \"%s\" is not unique", - rawc->name), - parser_errposition(pstate, rawc->location))); - - tf->colnames = lappend(tf->colnames, - makeString(pstrdup(rawc->name))); - } - - /* - * Determine the type and typmod for the new column. FOR ORDINALITY - * columns are INTEGER by standard; the others are user-specified. - */ - switch (rawc->coltype) - { - case JTC_FOR_ORDINALITY: - colexpr = NULL; - typid = INT4OID; - typmod = -1; - break; - - case JTC_REGULAR: - typenameTypeIdAndMod(pstate, rawc->typeName, &typid, &typmod); - - /* - * Use implicit FORMAT JSON for composite types (arrays and - * records) - */ - if (typeIsComposite(typid)) - rawc->coltype = JTC_FORMATTED; - else if (rawc->wrapper != JSW_NONE) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("cannot use WITH WRAPPER clause with scalar columns"), - parser_errposition(pstate, rawc->location))); - else if (rawc->omit_quotes) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("cannot use OMIT QUOTES clause with scalar columns"), - parser_errposition(pstate, rawc->location))); - - /* FALLTHROUGH */ - case JTC_EXISTS: - case JTC_FORMATTED: - { - Node *je; - CaseTestExpr *param = makeNode(CaseTestExpr); - - param->collation = InvalidOid; - param->typeId = cxt->contextItemTypid; - param->typeMod = -1; - - je = transformJsonTableColumn(rawc, (Node *) param, - NIL, errorOnError); - - colexpr = transformExpr(pstate, je, EXPR_KIND_FROM_FUNCTION); - assign_expr_collations(pstate, colexpr); - - typid = exprType(colexpr); - typmod = exprTypmod(colexpr); - break; - } - - case JTC_NESTED: - continue; - - default: - elog(ERROR, "unknown JSON_TABLE column type: %d", rawc->coltype); - break; - } - - tf->coltypes = lappend_oid(tf->coltypes, typid); - tf->coltypmods = lappend_int(tf->coltypmods, typmod); - tf->colcollations = lappend_oid(tf->colcollations, get_typcollation(typid)); - tf->colvalexprs = lappend(tf->colvalexprs, colexpr); - } -} - -/* - * Create transformed JSON_TABLE parent plan node by appending all non-nested - * columns to the TableFunc node and remembering their indices in the - * colvalexprs list. - */ -static JsonTableParent * -makeParentJsonTableNode(JsonTableContext *cxt, char *pathSpec, List *columns) -{ - JsonTableParent *node = makeNode(JsonTableParent); - - node->path = makeConst(JSONPATHOID, -1, InvalidOid, -1, - DirectFunctionCall1(jsonpath_in, - CStringGetDatum(pathSpec)), - false, false); - - /* save start of column range */ - node->colMin = list_length(cxt->tablefunc->colvalexprs); - - appendJsonTableColumns(cxt, columns); - - /* save end of column range */ - node->colMax = list_length(cxt->tablefunc->colvalexprs) - 1; - - node->errorOnError = - cxt->table->on_error && - cxt->table->on_error->btype == JSON_BEHAVIOR_ERROR; - - return node; -} - -static JsonTableParent * -transformJsonTableColumns(JsonTableContext *cxt, JsonTablePlan *plan, - List *columns, char *pathSpec, char **pathName, - int location) -{ - JsonTableParent *node; - JsonTablePlan *childPlan; - bool defaultPlan = !plan || plan->plan_type == JSTP_DEFAULT; - - if (!*pathName) - { - if (cxt->table->plan) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid JSON_TABLE expression"), - errdetail("JSON_TABLE columns must contain " - "explicit AS pathname specification if " - "explicit PLAN clause is used"), - parser_errposition(cxt->pstate, location))); - - *pathName = generateJsonTablePathName(cxt); - } - - if (defaultPlan) - childPlan = plan; - else - { - /* validate parent and child plans */ - JsonTablePlan *parentPlan; - - if (plan->plan_type == JSTP_JOINED) - { - if (plan->join_type != JSTPJ_INNER && - plan->join_type != JSTPJ_OUTER) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid JSON_TABLE plan"), - errdetail("Expected INNER or OUTER JSON_TABLE plan node."), - parser_errposition(cxt->pstate, plan->location))); - - parentPlan = plan->plan1; - childPlan = plan->plan2; - - Assert(parentPlan->plan_type != JSTP_JOINED); - Assert(parentPlan->pathname); - } - else - { - parentPlan = plan; - childPlan = NULL; - } - - if (strcmp(parentPlan->pathname, *pathName)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("invalid JSON_TABLE plan"), - errdetail("Path name mismatch: expected %s but %s is given.", - *pathName, parentPlan->pathname), - parser_errposition(cxt->pstate, plan->location))); - - validateJsonTableChildPlan(cxt->pstate, childPlan, columns); - } - - /* transform only non-nested columns */ - node = makeParentJsonTableNode(cxt, pathSpec, columns); - node->name = pstrdup(*pathName); - - if (childPlan || defaultPlan) - { - /* transform recursively nested columns */ - node->child = transformJsonTableChildPlan(cxt, childPlan, columns); - if (node->child) - node->outerJoin = !plan || (plan->join_type & JSTPJ_OUTER); - /* else: default plan case, no children found */ - } - - return node; -} - -/* - * transformJsonTable - - * Transform a raw JsonTable into TableFunc. - * - * Transform the document-generating expression, the row-generating expression, - * the column-generating expressions, and the default value expressions. - */ -ParseNamespaceItem * -transformJsonTable(ParseState *pstate, JsonTable *jt) -{ - JsonTableContext cxt; - TableFunc *tf = makeNode(TableFunc); - JsonFuncExpr *jfe = makeNode(JsonFuncExpr); - JsonTablePlan *plan = jt->plan; - JsonCommon *jscommon; - char *rootPathName = jt->common->pathname; - char *rootPath; - bool is_lateral; - - cxt.pstate = pstate; - cxt.table = jt; - cxt.tablefunc = tf; - cxt.pathNames = NIL; - cxt.pathNameId = 0; - - if (rootPathName) - registerJsonTableColumn(&cxt, rootPathName); - - registerAllJsonTableColumns(&cxt, jt->columns); - -#if 0 /* XXX it' unclear from the standard whether - * root path name is mandatory or not */ - if (plan && plan->plan_type != JSTP_DEFAULT && !rootPathName) - { - /* Assign root path name and create corresponding plan node */ - JsonTablePlan *rootNode = makeNode(JsonTablePlan); - JsonTablePlan *rootPlan = (JsonTablePlan *) - makeJsonTableJoinedPlan(JSTPJ_OUTER, (Node *) rootNode, - (Node *) plan, jt->location); - - rootPathName = generateJsonTablePathName(&cxt); - - rootNode->plan_type = JSTP_SIMPLE; - rootNode->pathname = rootPathName; - - plan = rootPlan; - } -#endif - - jscommon = copyObject(jt->common); - jscommon->pathspec = makeStringConst(pstrdup("$"), -1); - - jfe->op = JSON_TABLE_OP; - jfe->common = jscommon; - jfe->on_error = jt->on_error; - jfe->location = jt->common->location; - - /* - * We make lateral_only names of this level visible, whether or not the - * RangeTableFunc is explicitly marked LATERAL. This is needed for SQL - * spec compliance and seems useful on convenience grounds for all - * functions in FROM. - * - * (LATERAL can't nest within a single pstate level, so we don't need - * save/restore logic here.) - */ - Assert(!pstate->p_lateral_active); - pstate->p_lateral_active = true; - - tf->functype = TFT_JSON_TABLE; - tf->docexpr = transformExpr(pstate, (Node *) jfe, EXPR_KIND_FROM_FUNCTION); - - cxt.contextItemTypid = exprType(tf->docexpr); - - if (!IsA(jt->common->pathspec, A_Const) || - castNode(A_Const, jt->common->pathspec)->val.node.type != T_String) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("only string constants supported in JSON_TABLE path specification"), - parser_errposition(pstate, - exprLocation(jt->common->pathspec)))); - - rootPath = castNode(A_Const, jt->common->pathspec)->val.sval.sval; - - tf->plan = (Node *) transformJsonTableColumns(&cxt, plan, jt->columns, - rootPath, &rootPathName, - jt->common->location); - - tf->ordinalitycol = -1; /* undefine ordinality column number */ - tf->location = jt->location; - - pstate->p_lateral_active = false; - - /* - * Mark the RTE as LATERAL if the user said LATERAL explicitly, or if - * there are any lateral cross-references in it. - */ - is_lateral = jt->lateral || contain_vars_of_level((Node *) tf, 0); - - return addRangeTableEntryForTableFunc(pstate, - tf, jt->alias, is_lateral, true); -} diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index f6b740df0ac..f44937a8bba 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -2017,7 +2017,7 @@ addRangeTableEntryForTableFunc(ParseState *pstate, bool inFromCl) { RangeTblEntry *rte = makeNode(RangeTblEntry); - char *refname; + char *refname = alias ? alias->aliasname : pstrdup("xmltable"); Alias *eref; int numaliases; @@ -2035,8 +2035,7 @@ addRangeTableEntryForTableFunc(ParseState *pstate, Assert(list_length(tf->coltypmods) == list_length(tf->colnames)); Assert(list_length(tf->colcollations) == list_length(tf->colnames)); - refname = alias ? alias->aliasname : - pstrdup(tf->functype == TFT_XMLTABLE ? "xmltable" : "json_table"); + refname = alias ? alias->aliasname : pstrdup("xmltable"); rte->rtekind = RTE_TABLEFUNC; rte->relid = InvalidOid; @@ -2059,7 +2058,7 @@ addRangeTableEntryForTableFunc(ParseState *pstate, ereport(ERROR, (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), errmsg("%s function has %d columns available but %d columns specified", - tf->functype == TFT_XMLTABLE ? "XMLTABLE" : "JSON_TABLE", + "XMLTABLE", list_length(tf->colnames), numaliases))); rte->eref = eref; diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 16a0fe59e21..4e1593d9008 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -1957,46 +1957,6 @@ FigureColnameInternal(Node *node, char **name) case T_XmlSerialize: *name = "xmlserialize"; return 2; - case T_JsonParseExpr: - *name = "json"; - return 2; - case T_JsonScalarExpr: - *name = "json_scalar"; - return 2; - case T_JsonSerializeExpr: - *name = "json_serialize"; - return 2; - case T_JsonObjectConstructor: - *name = "json_object"; - return 2; - case T_JsonArrayConstructor: - case T_JsonArrayQueryConstructor: - *name = "json_array"; - return 2; - case T_JsonObjectAgg: - *name = "json_objectagg"; - return 2; - case T_JsonArrayAgg: - *name = "json_arrayagg"; - return 2; - case T_JsonFuncExpr: - /* make SQL/JSON functions act like a regular function */ - switch (((JsonFuncExpr *) node)->op) - { - case JSON_QUERY_OP: - *name = "json_query"; - return 2; - case JSON_VALUE_OP: - *name = "json_value"; - return 2; - case JSON_EXISTS_OP: - *name = "json_exists"; - return 2; - case JSON_TABLE_OP: - *name = "json_table"; - return 2; - } - break; default: break; } diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c index eee0a29c08f..50227cc0989 100644 --- a/src/backend/parser/parser.c +++ b/src/backend/parser/parser.c @@ -150,9 +150,6 @@ base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner) case USCONST: cur_token_length = strlen(yyextra->core_yy_extra.scanbuf + *llocp); break; - case WITHOUT: - cur_token_length = 7; - break; default: return cur_token; } @@ -224,19 +221,6 @@ base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner) case ORDINALITY: cur_token = WITH_LA; break; - case UNIQUE: - cur_token = WITH_LA_UNIQUE; - break; - } - break; - - case WITHOUT: - /* Replace WITHOUT by WITHOUT_LA if it's followed by TIME */ - switch (next_token) - { - case TIME: - cur_token = WITHOUT_LA; - break; } break; |