diff options
author | Alvaro Herrera | 2023-03-31 20:34:04 +0000 |
---|---|---|
committer | Alvaro Herrera | 2023-03-31 20:34:04 +0000 |
commit | 6ee30209a6f161d0a267a33f090c70c579c87c00 (patch) | |
tree | eda2b3a9f0a61f3fc484819b39abf1eb130e0d88 /src/include | |
parent | a2a0c7c29e47f39da905577659e66b0086b769cc (diff) |
SQL/JSON: support the IS JSON predicate
This patch introduces 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 IS and IS NOT variants and supports a WITH
UNIQUE KEYS flag. The tests are:
IS JSON [VALUE]
IS JSON ARRAY
IS JSON OBJECT
IS JSON SCALAR
These should be self-explanatory.
The WITH UNIQUE KEYS flag makes these return false when duplicate keys
exist in any object within the value, not necessarily directly contained
in the outermost object.
Author: Nikita Glukhov <n.gluhov@postgrespro.ru>
Author: Teodor Sigaev <teodor@sigaev.ru>
Author: Oleg Bartunov <obartunov@gmail.com>
Author: Alexander Korotkov <aekorotkov@gmail.com>
Author: Amit Langote <amitlangote09@gmail.com>
Author: Andrew Dunstan <andrew@dunslane.net>
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/CAF4Au4w2x-5LTnN_bxky-mq4=WOqsGsxSpENCzHRAzSnEd8+WQ@mail.gmail.com
Discussion: https://postgr.es/m/cd0bb935-0158-78a7-08b5-904886deac4b@postgrespro.ru
Discussion: https://postgr.es/m/20220616233130.rparivafipt6doj3@alap3.anarazel.de
Discussion: https://postgr.es/m/abd9b83b-aa66-f230-3d6d-734817f0995d%40postgresql.org
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/catalog/catversion.h | 2 | ||||
-rw-r--r-- | src/include/executor/execExpr.h | 8 | ||||
-rw-r--r-- | src/include/nodes/makefuncs.h | 3 | ||||
-rw-r--r-- | src/include/nodes/primnodes.h | 26 | ||||
-rw-r--r-- | src/include/parser/kwlist.h | 1 | ||||
-rw-r--r-- | src/include/utils/json.h | 1 | ||||
-rw-r--r-- | src/include/utils/jsonfuncs.h | 3 |
7 files changed, 43 insertions, 1 deletions
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 2419f2b11de..81e78230e4e 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -57,6 +57,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202303301 +#define CATALOG_VERSION_NO 202303311 #endif diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h index 53e2c9a467a..ea3ac10876f 100644 --- a/src/include/executor/execExpr.h +++ b/src/include/executor/execExpr.h @@ -236,6 +236,7 @@ typedef enum ExprEvalOp EEOP_HASHED_SCALARARRAYOP, EEOP_XMLEXPR, EEOP_JSON_CONSTRUCTOR, + EEOP_IS_JSON, EEOP_AGGREF, EEOP_GROUPING_FUNC, EEOP_WINDOW_FUNC, @@ -675,6 +676,12 @@ typedef struct ExprEvalStep int setoff; } agg_trans; + /* for EEOP_IS_JSON */ + struct + { + JsonIsPredicate *pred; /* original expression node */ + } is_json; + } d; } ExprEvalStep; @@ -789,6 +796,7 @@ extern void ExecEvalConstraintCheck(ExprState *state, ExprEvalStep *op); extern void ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op); extern void ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op, ExprContext *econtext); +extern void ExecEvalJsonIsPredicate(ExprState *state, ExprEvalStep *op); extern void ExecEvalGroupingFunc(ExprState *state, ExprEvalStep *op); extern void ExecEvalSubPlan(ExprState *state, ExprEvalStep *op, ExprContext *econtext); diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h index 50aa00e0c1b..06d991b7257 100644 --- a/src/include/nodes/makefuncs.h +++ b/src/include/nodes/makefuncs.h @@ -112,6 +112,9 @@ extern JsonFormat *makeJsonFormat(JsonFormatType type, JsonEncoding encoding, int location); extern JsonValueExpr *makeJsonValueExpr(Expr *expr, JsonFormat *format); extern Node *makeJsonKeyValue(Node *key, Node *value); +extern Node *makeJsonIsPredicate(Node *expr, JsonFormat *format, + JsonValueType item_type, bool unique_keys, + int location); extern JsonEncoding makeJsonEncoding(char *name); #endif /* MAKEFUNC_H */ diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index 1764b61cdbd..be9c29f0bfb 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -1583,6 +1583,32 @@ typedef struct JsonConstructorExpr int location; } JsonConstructorExpr; +/* + * JsonValueType - + * representation of JSON item type in IS JSON predicate + */ +typedef enum JsonValueType +{ + JS_TYPE_ANY, /* IS JSON [VALUE] */ + JS_TYPE_OBJECT, /* IS JSON OBJECT */ + JS_TYPE_ARRAY, /* IS JSON ARRAY */ + JS_TYPE_SCALAR /* IS JSON SCALAR */ +} JsonValueType; + +/* + * JsonIsPredicate - + * representation of IS JSON predicate + */ +typedef struct JsonIsPredicate +{ + NodeTag type; + Node *expr; /* subject expression */ + JsonFormat *format; /* FORMAT clause, if specified */ + JsonValueType item_type; /* JSON item type */ + bool unique_keys; /* check key uniqueness? */ + int location; /* token location, or -1 if unknown */ +} JsonIsPredicate; + /* ---------------- * NullTest * diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index 868f389a04d..f5b2e61ca52 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -376,6 +376,7 @@ PG_KEYWORD("row", ROW, COL_NAME_KEYWORD, BARE_LABEL) PG_KEYWORD("rows", ROWS, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("rule", RULE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("savepoint", SAVEPOINT, UNRESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("scalar", SCALAR, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("schema", SCHEMA, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("schemas", SCHEMAS, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("scroll", SCROLL, UNRESERVED_KEYWORD, BARE_LABEL) diff --git a/src/include/utils/json.h b/src/include/utils/json.h index b75f7d929dd..35a9a5545d8 100644 --- a/src/include/utils/json.h +++ b/src/include/utils/json.h @@ -26,5 +26,6 @@ extern Datum json_build_object_worker(int nargs, Datum *args, bool *nulls, 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); #endif /* JSON_H */ diff --git a/src/include/utils/jsonfuncs.h b/src/include/utils/jsonfuncs.h index fc610f65031..a85203d4a4b 100644 --- a/src/include/utils/jsonfuncs.h +++ b/src/include/utils/jsonfuncs.h @@ -50,6 +50,9 @@ extern bool pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem, extern void json_errsave_error(JsonParseErrorType error, JsonLexContext *lex, struct Node *escontext); +/* get first JSON token */ +extern JsonTokenType json_get_first_token(text *json, bool throw_error); + extern uint32 parse_jsonb_index_flags(Jsonb *jb); extern void iterate_jsonb_values(Jsonb *jb, uint32 flags, void *state, JsonIterateStringValuesAction action); |