summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorAndrew Dunstan <andrew@dunslane.net>2022-03-03 13:02:53 -0500
committerAndrew Dunstan <andrew@dunslane.net>2022-03-28 15:37:08 -0400
commit33a377608fc29cdd1f6b63be561eab0aee5c81f0 (patch)
tree47abccafdaeae1c4466c917bbd85912f39558360 /src/include
parent6198420ad8a72e37f4fe4964616b17e0fd33b808 (diff)
downloadpostgresql-33a377608fc29cdd1f6b63be561eab0aee5c81f0.tar.gz
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
Diffstat (limited to 'src/include')
-rw-r--r--src/include/executor/execExpr.h8
-rw-r--r--src/include/nodes/makefuncs.h3
-rw-r--r--src/include/nodes/nodes.h1
-rw-r--r--src/include/nodes/primnodes.h26
-rw-r--r--src/include/parser/kwlist.h1
-rw-r--r--src/include/utils/json.h1
-rw-r--r--src/include/utils/jsonfuncs.h3
7 files changed, 43 insertions, 0 deletions
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index c830fcf726..a41722ae1e 100644
--- a/src/include/executor/execExpr.h
+++ b/src/include/executor/execExpr.h
@@ -240,6 +240,7 @@ typedef enum ExprEvalOp
EEOP_WINDOW_FUNC,
EEOP_SUBPLAN,
EEOP_JSON_CONSTRUCTOR,
+ EEOP_IS_JSON,
/* aggregation related nodes */
EEOP_AGG_STRICT_DESERIALIZE,
@@ -680,6 +681,12 @@ typedef struct ExprEvalStep
int nargs;
} json_constructor;
+ /* for EEOP_IS_JSON */
+ struct
+ {
+ JsonIsPredicate *pred; /* original expression node */
+ } is_json;
+
} d;
} ExprEvalStep;
@@ -774,6 +781,7 @@ extern void ExecEvalHashedScalarArrayOp(ExprState *state, ExprEvalStep *op,
extern void ExecEvalConstraintNotNull(ExprState *state, ExprEvalStep *op);
extern void ExecEvalConstraintCheck(ExprState *state, ExprEvalStep *op);
extern void ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op);
+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 e50b933288..380940968b 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -110,6 +110,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 vtype, bool unique_keys,
+ int location);
extern JsonEncoding makeJsonEncoding(char *name);
#endif /* MAKEFUNC_H */
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index ca440eb75f..e8f30367a4 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -505,6 +505,7 @@ typedef enum NodeTag
T_JsonAggConstructor,
T_JsonObjectAgg,
T_JsonArrayAgg,
+ T_JsonIsPredicate,
T_JsonKeyValue,
T_JsonOutput,
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index c48527e998..f4a39653ac 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -1317,6 +1317,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 -
+ * untransformed representation of IS JSON predicate
+ */
+typedef struct JsonIsPredicate
+{
+ NodeTag type;
+ Node *expr; /* untransformed expression */
+ JsonFormat *format; /* FORMAT clause, if specified */
+ JsonValueType value_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 10829941e0..c0ffa516d0 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -374,6 +374,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 63d83b815f..bfe5b21591 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);
#endif /* JSON_H */
diff --git a/src/include/utils/jsonfuncs.h b/src/include/utils/jsonfuncs.h
index 865b2ff7c1..cd16b6c0c8 100644
--- a/src/include/utils/jsonfuncs.h
+++ b/src/include/utils/jsonfuncs.h
@@ -45,6 +45,9 @@ extern void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem);
/* report an error during json lexing or parsing */
extern void json_ereport_error(JsonParseErrorType error, JsonLexContext *lex);
+/* 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);