aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/Makefile1
-rw-r--r--src/backend/parser/gram.y1115
-rw-r--r--src/backend/parser/parse_clause.c12
-rw-r--r--src/backend/parser/parse_collate.c7
-rw-r--r--src/backend/parser/parse_expr.c1503
-rw-r--r--src/backend/parser/parse_jsontable.c732
-rw-r--r--src/backend/parser/parse_relation.c7
-rw-r--r--src/backend/parser/parse_target.c40
-rw-r--r--src/backend/parser/parser.c16
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;