1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-21 00:42:43 +03:00

Revert SQL/JSON features

The reverts the following and makes some associated cleanups:

    commit f79b803dc: Common SQL/JSON clauses
    commit f4fb45d15: SQL/JSON constructors
    commit 5f0adec25: Make STRING an unreserved_keyword.
    commit 33a377608: IS JSON predicate
    commit 1a36bc9db: SQL/JSON query functions
    commit 606948b05: SQL JSON functions
    commit 49082c2cc: RETURNING clause for JSON() and JSON_SCALAR()
    commit 4e34747c8: JSON_TABLE
    commit fadb48b00: PLAN clauses for JSON_TABLE
    commit 2ef6f11b0: Reduce running time of jsonb_sqljson test
    commit 14d3f24fa: Further improve jsonb_sqljson parallel test
    commit a6baa4bad: Documentation for SQL/JSON features
    commit b46bcf7a4: Improve readability of SQL/JSON documentation.
    commit 112fdb352: Fix finalization for json_objectagg and friends
    commit fcdb35c32: Fix transformJsonBehavior
    commit 4cd8717af: Improve a couple of sql/json error messages
    commit f7a605f63: Small cleanups in SQL/JSON code
    commit 9c3d25e17: Fix JSON_OBJECTAGG uniquefying bug
    commit a79153b7a: Claim SQL standard compliance for SQL/JSON features
    commit a1e7616d6: 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/40d2c882-bcac-19a9-754d-4299e1d87ac7@postgresql.org
This commit is contained in:
Andrew Dunstan
2022-09-01 17:07:14 -04:00
parent 90247e742f
commit 2f2b18bd3f
60 changed files with 348 additions and 14893 deletions

View File

@@ -67,9 +67,7 @@
#include "lib/stringinfo.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "utils/builtins.h"
#include "utils/formatting.h"
#include "utils/json.h"
#include "utils/jsonpath.h"
@@ -1079,258 +1077,3 @@ jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from, JsonPathItem *to,
return true;
}
/* SQL/JSON datatype status: */
typedef enum JsonPathDatatypeStatus
{
jpdsNonDateTime, /* null, bool, numeric, string, array, object */
jpdsUnknownDateTime, /* unknown datetime type */
jpdsDateTimeZoned, /* timetz, timestamptz */
jpdsDateTimeNonZoned /* time, timestamp, date */
} JsonPathDatatypeStatus;
/* Context for jspIsMutableWalker() */
typedef struct JsonPathMutableContext
{
List *varnames; /* list of variable names */
List *varexprs; /* list of variable expressions */
JsonPathDatatypeStatus current; /* status of @ item */
bool lax; /* jsonpath is lax or strict */
bool mutable; /* resulting mutability status */
} JsonPathMutableContext;
/*
* Recursive walker for jspIsMutable()
*/
static JsonPathDatatypeStatus
jspIsMutableWalker(JsonPathItem *jpi, JsonPathMutableContext *cxt)
{
JsonPathItem next;
JsonPathDatatypeStatus status = jpdsNonDateTime;
while (!cxt->mutable)
{
JsonPathItem arg;
JsonPathDatatypeStatus leftStatus;
JsonPathDatatypeStatus rightStatus;
switch (jpi->type)
{
case jpiRoot:
Assert(status == jpdsNonDateTime);
break;
case jpiCurrent:
Assert(status == jpdsNonDateTime);
status = cxt->current;
break;
case jpiFilter:
{
JsonPathDatatypeStatus prevStatus = cxt->current;
cxt->current = status;
jspGetArg(jpi, &arg);
jspIsMutableWalker(&arg, cxt);
cxt->current = prevStatus;
break;
}
case jpiVariable:
{
int32 len;
const char *name = jspGetString(jpi, &len);
ListCell *lc1;
ListCell *lc2;
Assert(status == jpdsNonDateTime);
forboth(lc1, cxt->varnames, lc2, cxt->varexprs)
{
String *varname = lfirst_node(String, lc1);
Node *varexpr = lfirst(lc2);
if (strncmp(varname->sval, name, len))
continue;
switch (exprType(varexpr))
{
case DATEOID:
case TIMEOID:
case TIMESTAMPOID:
status = jpdsDateTimeNonZoned;
break;
case TIMETZOID:
case TIMESTAMPTZOID:
status = jpdsDateTimeZoned;
break;
default:
status = jpdsNonDateTime;
break;
}
break;
}
break;
}
case jpiEqual:
case jpiNotEqual:
case jpiLess:
case jpiGreater:
case jpiLessOrEqual:
case jpiGreaterOrEqual:
Assert(status == jpdsNonDateTime);
jspGetLeftArg(jpi, &arg);
leftStatus = jspIsMutableWalker(&arg, cxt);
jspGetRightArg(jpi, &arg);
rightStatus = jspIsMutableWalker(&arg, cxt);
/*
* Comparison of datetime type with different timezone status
* is mutable.
*/
if (leftStatus != jpdsNonDateTime &&
rightStatus != jpdsNonDateTime &&
(leftStatus == jpdsUnknownDateTime ||
rightStatus == jpdsUnknownDateTime ||
leftStatus != rightStatus))
cxt->mutable = true;
break;
case jpiNot:
case jpiIsUnknown:
case jpiExists:
case jpiPlus:
case jpiMinus:
Assert(status == jpdsNonDateTime);
jspGetArg(jpi, &arg);
jspIsMutableWalker(&arg, cxt);
break;
case jpiAnd:
case jpiOr:
case jpiAdd:
case jpiSub:
case jpiMul:
case jpiDiv:
case jpiMod:
case jpiStartsWith:
Assert(status == jpdsNonDateTime);
jspGetLeftArg(jpi, &arg);
jspIsMutableWalker(&arg, cxt);
jspGetRightArg(jpi, &arg);
jspIsMutableWalker(&arg, cxt);
break;
case jpiIndexArray:
for (int i = 0; i < jpi->content.array.nelems; i++)
{
JsonPathItem from;
JsonPathItem to;
if (jspGetArraySubscript(jpi, &from, &to, i))
jspIsMutableWalker(&to, cxt);
jspIsMutableWalker(&from, cxt);
}
/* FALLTHROUGH */
case jpiAnyArray:
if (!cxt->lax)
status = jpdsNonDateTime;
break;
case jpiAny:
if (jpi->content.anybounds.first > 0)
status = jpdsNonDateTime;
break;
case jpiDatetime:
if (jpi->content.arg)
{
char *template;
int flags;
jspGetArg(jpi, &arg);
if (arg.type != jpiString)
{
status = jpdsNonDateTime;
break; /* there will be runtime error */
}
template = jspGetString(&arg, NULL);
flags = datetime_format_flags(template, NULL);
if (flags & DCH_ZONED)
status = jpdsDateTimeZoned;
else
status = jpdsDateTimeNonZoned;
}
else
{
status = jpdsUnknownDateTime;
}
break;
case jpiLikeRegex:
Assert(status == jpdsNonDateTime);
jspInitByBuffer(&arg, jpi->base, jpi->content.like_regex.expr);
jspIsMutableWalker(&arg, cxt);
break;
/* literals */
case jpiNull:
case jpiString:
case jpiNumeric:
case jpiBool:
/* accessors */
case jpiKey:
case jpiAnyKey:
/* special items */
case jpiSubscript:
case jpiLast:
/* item methods */
case jpiType:
case jpiSize:
case jpiAbs:
case jpiFloor:
case jpiCeiling:
case jpiDouble:
case jpiKeyValue:
status = jpdsNonDateTime;
break;
}
if (!jspGetNext(jpi, &next))
break;
jpi = &next;
}
return status;
}
/*
* Check whether jsonpath expression is immutable or not.
*/
bool
jspIsMutable(JsonPath *path, List *varnames, List *varexprs)
{
JsonPathMutableContext cxt;
JsonPathItem jpi;
cxt.varnames = varnames;
cxt.varexprs = varexprs;
cxt.current = jpdsNonDateTime;
cxt.lax = (path->header & JSONPATH_LAX) != 0;
cxt.mutable = false;
jspInit(&jpi, path);
jspIsMutableWalker(&jpi, &cxt);
return cxt.mutable;
}