1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-13 07:41:39 +03:00

IS JSON predicate

This patch intrdocuces the SQL standard IS JSON predicate. It operates
on text and bytea values representing JSON as well as on the json and
jsonb types. Each test has an IS and IS NOT variant. The tests are:

IS JSON [VALUE]
IS JSON ARRAY
IS JSON OBJECT
IS JSON SCALAR
IS JSON  WITH | WITHOUT UNIQUE KEYS

These are mostly self-explanatory, but note that IS JSON WITHOUT UNIQUE
KEYS is true whenever IS JSON is true, and IS JSON WITH UNIQUE KEYS is
true whenever IS JSON is true except it IS JSON OBJECT is true and there
are duplicate keys (which is never the case when applied to jsonb values).

Nikita Glukhov

Reviewers have included (in no particular order) Andres Freund, Alexander
Korotkov, Pavel Stehule, Andrew Alsup, Erik Rijkers, Zihong Yu,
Himanshu Upadhyaya, Daniel Gustafsson, Justin Pryzby.

Discussion: https://postgr.es/m/cd0bb935-0158-78a7-08b5-904886deac4b@postgrespro.ru
This commit is contained in:
Andrew Dunstan
2022-03-03 13:02:53 -05:00
parent 6198420ad8
commit 33a377608f
25 changed files with 856 additions and 17 deletions

View File

@ -260,6 +260,9 @@ exprType(const Node *expr)
case T_JsonConstructorExpr:
type = ((const JsonConstructorExpr *) expr)->returning->typid;
break;
case T_JsonIsPredicate:
type = BOOLOID;
break;
default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
type = InvalidOid; /* keep compiler quiet */
@ -985,6 +988,9 @@ exprCollation(const Node *expr)
coll = InvalidOid;
}
break;
case T_JsonIsPredicate:
coll = InvalidOid; /* result is always an boolean type */
break;
default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
coll = InvalidOid; /* keep compiler quiet */
@ -1211,6 +1217,9 @@ exprSetCollation(Node *expr, Oid collation)
Assert(!OidIsValid(collation)); /* result is always a json[b] type */
}
break;
case T_JsonIsPredicate:
Assert(!OidIsValid(collation)); /* result is always boolean */
break;
default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
break;
@ -1663,6 +1672,9 @@ exprLocation(const Node *expr)
case T_JsonConstructorExpr:
loc = ((const JsonConstructorExpr *) expr)->location;
break;
case T_JsonIsPredicate:
loc = ((const JsonIsPredicate *) expr)->location;
break;
default:
/* for any other node type it's just unknown... */
loc = -1;
@ -2429,6 +2441,8 @@ expression_tree_walker(Node *node,
return true;
}
break;
case T_JsonIsPredicate:
return walker(((JsonIsPredicate *) node)->expr, context);
default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(node));
@ -3438,6 +3452,16 @@ expression_tree_mutator(Node *node,
MUTATE(newnode->coercion, jve->coercion, Expr *);
MUTATE(newnode->returning, jve->returning, JsonReturning *);
return (Node *) newnode;
}
case T_JsonIsPredicate:
{
JsonIsPredicate *pred = (JsonIsPredicate *) node;
JsonIsPredicate *newnode;
FLATCOPY(newnode, pred, JsonIsPredicate);
MUTATE(newnode->expr, pred->expr, Node *);
return (Node *) newnode;
}
default:
@ -4290,6 +4314,8 @@ raw_expression_tree_walker(Node *node,
return true;
}
break;
case T_JsonIsPredicate:
return walker(((JsonIsPredicate *) node)->expr, context);
default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(node));