Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Merge conflict - 2f2b18bd3f554e96a8cc885b177211be12288e4a Revert SQL/JSON features #76

Merged
merged 1 commit into from
Dec 4, 2023

Conversation

ahmed-shameem
Copy link

@ahmed-shameem ahmed-shameem commented Dec 4, 2023

Extension PR for validation: amazon-aurora/babelfish_extensions#54

Merge conflicts:

--> gram.y (Accepted incoming change)
<<<<<<< HEAD
%nonassoc	json_table_column
%nonassoc	NESTED
%left		PATH

%nonassoc	empty_json_unique
%left		WITHOUT WITH_LA_UNIQUE

/* Please note that the following line will be replaced with the contents of given file name even if with starting with a comment */
/*$$include "gram-tsql-decl.y"*/

=======
>>>>>>> 2f2b18bd3f (Revert SQL/JSON features)

--> parse_expr.c (Accepted incoming change except checksum)
<<<<<<< HEAD
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
#include "catalog/namespace.h"
=======
>>>>>>> 2f2b18bd3f (Revert SQL/JSON features)

<<<<<<< HEAD

/*
 * 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);
}

// Expands checksum(*) to checksum(c1, c2, ...)
List *
ExpandChecksumStar(ParseState *pstate, FuncCall *fn, int location)
{
        List      *target = NIL;
        ListCell   *lc;
        foreach(lc, pstate->p_namespace)
        {
                ParseNamespaceItem *nsitem = (ParseNamespaceItem *) lfirst(lc);
                target = list_concat(target, expandNSItemVars(nsitem, 0, location, NULL));
        }
        fn->agg_star = false;
        return target;
}
=======
>>>>>>> 2f2b18bd3f (Revert SQL/JSON features)


--> jsonb_util.c (Accepted incomgin change and updated the if condition to current change)
<<<<<<< HEAD
	if (hasNonUniq && unique_keys)
		ereport(ERROR,
				(errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
				 errmsg("duplicate JSON object key value")));

	if ((hasNonUniq || skip_nulls) && sql_dialect != SQL_DIALECT_TSQL)
=======
	if (hasNonUniq)
>>>>>>> 2f2b18bd3f (Revert SQL/JSON features)

--> jsonpath_exec.c (Accepted incomgin change but kept #include "parser/parser.h")
<<<<<<< HEAD
#include "nodes/nodeFuncs.h"
#include "parser/parser.h"
=======
>>>>>>> 2f2b18bd3f (Revert SQL/JSON features)

--> parse_clause.h (Removed extern ParseNamespaceItem *transformJsonTable(ParseState *pstate, JsonTable *jt); only)
<<<<<<< HEAD
/* functions in parse_jsontable.c */
extern ParseNamespaceItem *transformJsonTable(ParseState *pstate, JsonTable *jt);

typedef bool (*tle_name_comparison_hook_type)(const char *tlename, const char *identifier);
extern PGDLLEXPORT tle_name_comparison_hook_type tle_name_comparison_hook;

typedef void (*sortby_nulls_hook_type)(SortGroupClause *sortcl, bool reverse);
extern PGDLLEXPORT sortby_nulls_hook_type sortby_nulls_hook;

typedef Node* (*optimize_explicit_cast_hook_type)(ParseState *pstate, Node *node);
extern PGDLLEXPORT optimize_explicit_cast_hook_type optimize_explicit_cast_hook;

=======
>>>>>>> 2f2b18bd3f (Revert SQL/JSON features)

--> json.h (kept extern void tsql_json_build_object(StringInfo result,Datum colname, Datum colval, Oid collation, bool is_null);)
<<<<<<< HEAD
extern bool to_json_is_immutable(Oid typoid);
extern void json_categorize_type(Oid typoid, JsonTypeCategory *tcategory,
								 Oid *outfuncoid);
extern Datum to_json_worker(Datum val, JsonTypeCategory tcategory,
							Oid outfuncoid);
extern Datum json_build_object_worker(int nargs, Datum *args, bool *nulls,
									  Oid *types, bool absent_on_null,
									  bool unique_keys);
extern Datum json_build_array_worker(int nargs, Datum *args, bool *nulls,
									 Oid *types, bool absent_on_null);
extern bool json_validate(text *json, bool check_unique_keys, bool throw_error);
extern void tsql_json_build_object(StringInfo result,Datum colname, Datum colval, Oid collation, bool is_null);
=======
>>>>>>> 2f2b18bd3f (Revert SQL/JSON features)

--> jsonb.h (kept extern void jsonb_get_value(Datum val, bool is_null, JsonbValue *json, Oid val_type);)
<<<<<<< HEAD
extern bool to_jsonb_is_immutable(Oid typoid);
extern void jsonb_categorize_type(Oid typoid, JsonbTypeCategory *tcategory,
								  Oid *outfuncoid);
extern Datum to_jsonb_worker(Datum val, JsonbTypeCategory tcategory,
							 Oid outfuncoid);
extern Datum jsonb_build_object_worker(int nargs, Datum *args, bool *nulls,
									   Oid *types, bool absent_on_null,
									   bool unique_keys);
extern Datum jsonb_build_array_worker(int nargs, Datum *args, bool *nulls,
									  Oid *types, bool absent_on_null);

extern void jsonb_get_value(Datum val, bool is_null, JsonbValue *json, Oid val_type);
=======
>>>>>>> 2f2b18bd3f (Revert SQL/JSON features)

--> jsonpath.h (kept extern Jsonb *tsql_openjson_with_get_subjsonb(PG_FUNCTION_ARGS);
extern List *tsql_openjson_with_columnize(Jsonb *jb, char *col_info);)
<<<<<<< HEAD
/*
 * Evaluation of jsonpath
 */

/* External variable passed into jsonpath. */
typedef struct JsonPathVariableEvalContext
{
	char	   *name;
	Oid			typid;
	int32		typmod;
	struct ExprContext *econtext;
	struct ExprState *estate;
	MemoryContext mcxt;			/* memory context for cached value */
	Datum		value;
	bool		isnull;
	bool		evaluated;
} JsonPathVariableEvalContext;

/* SQL/JSON item */
extern void JsonItemFromDatum(Datum val, Oid typid, int32 typmod,
							  JsonbValue *res);

extern bool JsonPathExists(Datum jb, JsonPath *path, List *vars, bool *error);
extern Datum JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper,
						   bool *empty, bool *error, List *vars);
extern JsonbValue *JsonPathValue(Datum jb, JsonPath *jp, bool *empty,
								 bool *error, List *vars);

extern int	EvalJsonPathVar(void *vars, char *varName, int varNameLen,
							JsonbValue *val, JsonbValue *baseObject);

extern PGDLLIMPORT const TableFuncRoutine JsonbTableRoutine;

extern Jsonb *tsql_openjson_with_get_subjsonb(PG_FUNCTION_ARGS);
extern List *tsql_openjson_with_columnize(Jsonb *jb, char *col_info);

=======
>>>>>>> 2f2b18bd3f (Revert SQL/JSON features)

2f2b18bd3f554e96a8cc885b177211be12288e4a-conflict.txt

BABELFISH-CONFLICT: see Postgres community repo for original commit

The reverts the following and makes some associated cleanups:

    commit f79b803: Common SQL/JSON clauses
    commit f4fb45d: SQL/JSON constructors
    commit 5f0adec: Make STRING an unreserved_keyword.
    commit 33a3776: IS JSON predicate
    commit 1a36bc9: SQL/JSON query functions
    commit 606948b: SQL JSON functions
    commit 49082c2: RETURNING clause for JSON() and JSON_SCALAR()
    commit 4e34747: JSON_TABLE
    commit fadb48b: PLAN clauses for JSON_TABLE
    commit 2ef6f11: Reduce running time of jsonb_sqljson test
    commit 14d3f24: Further improve jsonb_sqljson parallel test
    commit a6baa4b: Documentation for SQL/JSON features
    commit b46bcf7: Improve readability of SQL/JSON documentation.
    commit 112fdb3: Fix finalization for json_objectagg and friends
    commit fcdb35c: Fix transformJsonBehavior
    commit 4cd8717: Improve a couple of sql/json error messages
    commit f7a605f: Small cleanups in SQL/JSON code
    commit 9c3d25e: Fix JSON_OBJECTAGG uniquefying bug
    commit a79153b: Claim SQL standard compliance for SQL/JSON features
    commit a1e7616: Rework SQL/JSON documentation
    commit 8d9f9634e: Fix errors in copyfuncs/equalfuncs support for JSON node types.
    commit 3c633f32b: Only allow returning string types or bytea from json_serialize
    commit 67b26703b: expression eval: Fix EEOP_JSON_CONSTRUCTOR and EEOP_JSONEXPR size.

The release notes are also adjusted.

Backpatch to release 15.

Discussion: https://postgr.es/m/[email protected]
(cherry picked from commit 2f2b18bd3f554e96a8cc885b177211be12288e4a)
@Sairakan Sairakan force-pushed the pg16-cherry-pick-bff-1 branch from 349f9a9 to 329b9f4 Compare December 4, 2023 15:49
Sairakan pushed a commit to amazon-aurora/babelfish_extensions that referenced this pull request Dec 4, 2023
@2jungkook 2jungkook merged commit 77a1502 into BABEL_main Dec 4, 2023
4 checks passed
@2jungkook 2jungkook deleted the pg16-cherry-pick-bff-1 branch December 4, 2023 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants