Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit d7d23f6

Browse files
author
Nikita Glukhov
committed
Add json support for JSON_EXISTS, JSON_VALUE, JSON_QUERY
1 parent cf3d961 commit d7d23f6

File tree

6 files changed

+1321
-51
lines changed

6 files changed

+1321
-51
lines changed

src/backend/executor/execExprInterp.c

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3664,15 +3664,18 @@ ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior,
36643664

36653665
static Datum
36663666
ExecEvalJsonExprCoercion(ExprEvalStep *op, ExprContext *econtext,
3667-
Datum res, bool *isNull)
3667+
Datum res, bool *isNull, bool isJsonb)
36683668
{
36693669
JsonExpr *jexpr = op->d.jsonexpr.jsexpr;
3670-
Jsonb *jb = *isNull ? NULL : DatumGetJsonb(res);
3670+
Jsonb *jb = *isNull || !isJsonb ? NULL : DatumGetJsonb(res);
3671+
Json *js = *isNull || isJsonb ? NULL : DatumGetJson(res);
36713672

36723673
if (jexpr->coerce_via_io ||
3673-
(jexpr->omit_quotes && !*isNull && JB_ROOT_IS_SCALAR(jb)))
3674+
(jexpr->omit_quotes && !*isNull &&
3675+
(isJsonb ? JB_ROOT_IS_SCALAR(jb) : JsonContainerIsScalar(&js->root))))
36743676
{
3675-
char *str = *isNull ? NULL : JsonbUnquote(jb);
3677+
char *str = *isNull ? NULL :
3678+
(isJsonb ? JsonbUnquote(jb) : JsonUnquote(js));
36763679

36773680
res = InputFunctionCall(&op->d.jsonexpr.input.func, str,
36783681
op->d.jsonexpr.input.typioparam,
@@ -3682,7 +3685,7 @@ ExecEvalJsonExprCoercion(ExprEvalStep *op, ExprContext *econtext,
36823685
res = ExecEvalExprPassingCaseValue(op->d.jsonexpr.result_expr, econtext,
36833686
isNull, res, *isNull);
36843687
else if (jexpr->coerce_via_populate)
3685-
res = json_populate_type(res, JSONBOID,
3688+
res = json_populate_type(res, isJsonb ? JSONBOID : JSONOID,
36863689
jexpr->returning.typid,
36873690
jexpr->returning.typmod,
36883691
&op->d.jsonexpr.cache,
@@ -3708,7 +3711,8 @@ EvalJsonPathVar(void *cxt, bool *isnull)
37083711
}
37093712

37103713
Datum
3711-
ExecPrepareJsonItemCoercion(JsonbValue *jbv, JsonReturning *returning,
3714+
ExecPrepareJsonItemCoercion(JsonbValue *jbv, bool is_jsonb,
3715+
JsonReturning *returning,
37123716
struct JsonScalarCoercions *coercions,
37133717
MemoryContext mcxt,
37143718
struct JsonScalarCoercionExprState **pcestate)
@@ -3718,8 +3722,14 @@ ExecPrepareJsonItemCoercion(JsonbValue *jbv, JsonReturning *returning,
37183722
Oid typid;
37193723
JsonbValue jbvbuf;
37203724

3721-
if (jbv->type == jbvBinary && JsonContainerIsScalar(jbv->val.binary.data))
3722-
jbv = JsonbExtractScalar(jbv->val.binary.data, &jbvbuf);
3725+
if (jbv->type == jbvBinary)
3726+
{
3727+
if (JsonContainerIsScalar(jbv->val.binary.data))
3728+
jbv = is_jsonb
3729+
? JsonbExtractScalar(jbv->val.binary.data, &jbvbuf)
3730+
: JsonExtractScalar((JsonContainer *) jbv->val.binary.data,
3731+
&jbvbuf);
3732+
}
37233733

37243734
switch (jbv->type)
37253735
{
@@ -3780,8 +3790,20 @@ ExecPrepareJsonItemCoercion(JsonbValue *jbv, JsonReturning *returning,
37803790
case jbvObject:
37813791
case jbvBinary:
37823792
cestate = &coercions->composite;
3783-
res = JsonbGetDatum(JsonbValueToJsonb(jbv));
3784-
typid = JSONBOID;
3793+
if (is_jsonb)
3794+
{
3795+
Jsonb *jb = JsonbValueToJsonb(jbv);
3796+
3797+
res = JsonbGetDatum(jb);
3798+
typid = JSONBOID;
3799+
}
3800+
else
3801+
{
3802+
Json *js = JsonbValueToJson(jbv);
3803+
3804+
res = JsonGetDatum(js);
3805+
typid = JSONOID;
3806+
}
37853807
break;
37863808

37873809
default:
@@ -3851,7 +3873,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
38513873
if (op->d.jsonexpr.raw_expr->isnull)
38523874
{
38533875
/* execute domain checks for NULLs */
3854-
(void) ExecEvalJsonExprCoercion(op, econtext, res, op->resnull);
3876+
(void) ExecEvalJsonExprCoercion(op, econtext, res, op->resnull, isjsonb);
38553877
return;
38563878
}
38573879

@@ -3879,31 +3901,32 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
38793901
econtext, &isnull, item, false);
38803902
if (isnull)
38813903
{
3882-
(void) ExecEvalJsonExprCoercion(op, econtext, res, op->resnull);
3904+
(void) ExecEvalJsonExprCoercion(op, econtext, res, op->resnull,
3905+
isjsonb);
38833906
return;
38843907
}
38853908
}
38863909

38873910
switch (jexpr->op)
38883911
{
38893912
case IS_JSON_QUERY:
3890-
res = JsonbPathQuery(item, path, jexpr->wrapper, &empty,
3891-
op->d.jsonexpr.args);
3913+
res = (isjsonb ? JsonbPathQuery : JsonPathQuery)
3914+
(item, path, jexpr->wrapper, &empty, op->d.jsonexpr.args);
38923915
*op->resnull = !DatumGetPointer(res);
38933916
break;
38943917

38953918
case IS_JSON_VALUE:
38963919
{
3897-
JsonbValue *jbv = JsonbPathValue(item, path, &empty,
3898-
op->d.jsonexpr.args);
3920+
JsonbValue *jbv = (isjsonb ? JsonbPathValue : JsonPathValue)
3921+
(item, path, &empty, op->d.jsonexpr.args);
38993922
struct JsonScalarCoercionExprState *cestate;
39003923

39013924
if (!jbv)
39023925
break;
39033926

39043927
*op->resnull = false;
39053928

3906-
res = ExecPrepareJsonItemCoercion(jbv,
3929+
res = ExecPrepareJsonItemCoercion(jbv, isjsonb,
39073930
&op->d.jsonexpr.jsexpr->returning,
39083931
&op->d.jsonexpr.scalar,
39093932
econtext->ecxt_per_query_memory,
@@ -3914,9 +3937,11 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
39143937
(cestate->result_expr &&
39153938
IsA(cestate->result_expr, CoerceViaIO)))
39163939
{
3917-
res = JsonbGetDatum(JsonbValueToJsonb(jbv));
3918-
res = ExecEvalJsonExprCoercion(op, econtext,
3919-
res, op->resnull);
3940+
res = isjsonb
3941+
? JsonbGetDatum(JsonbValueToJsonb(jbv))
3942+
: JsonGetDatum(JsonbValueToJson(jbv));
3943+
res = ExecEvalJsonExprCoercion(op, econtext, res,
3944+
op->resnull, isjsonb);
39203945
}
39213946
else if (cestate->result_expr_state)
39223947
{
@@ -3930,8 +3955,8 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
39303955
break;
39313956

39323957
case IS_JSON_EXISTS:
3933-
res = BoolGetDatum(JsonbPathExists(item, path,
3934-
op->d.jsonexpr.args));
3958+
res = BoolGetDatum((isjsonb ? JsonbPathExists : JsonPathExists)
3959+
(item, path, op->d.jsonexpr.args));
39353960
*op->resnull = false;
39363961
break;
39373962

@@ -3957,7 +3982,8 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
39573982
(!empty ? jexpr->op != IS_JSON_VALUE :
39583983
/* already coerced in DEFAULT case */
39593984
jexpr->on_empty.btype != JSON_BEHAVIOR_DEFAULT))
3960-
res = ExecEvalJsonExprCoercion(op, econtext, res, op->resnull);
3985+
res = ExecEvalJsonExprCoercion(op, econtext, res, op->resnull,
3986+
isjsonb);
39613987
}
39623988
PG_CATCH();
39633989
{
@@ -3974,7 +4000,8 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
39744000

39754001
if (jexpr->op != IS_JSON_EXISTS &&
39764002
jexpr->on_error.btype != JSON_BEHAVIOR_DEFAULT)
3977-
res = ExecEvalJsonExprCoercion(op, econtext, res, op->resnull);
4003+
res = ExecEvalJsonExprCoercion(op, econtext, res, op->resnull,
4004+
isjsonb);
39784005
}
39794006
PG_END_TRY();
39804007

src/backend/parser/parse_expr.c

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4424,15 +4424,10 @@ static Node *
44244424
transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
44254425
{
44264426
JsonExpr *jsexpr = transformJsonExprCommon(pstate, func);
4427-
Node *expr = jsexpr->formatted_expr ?
4428-
jsexpr->formatted_expr : jsexpr->raw_expr;
4429-
const char *func_name = NULL;
44304427

44314428
switch (func->op)
44324429
{
44334430
case IS_JSON_VALUE:
4434-
func_name = "JSON_VALUE";
4435-
44364431
transformJsonFuncExprOutput(pstate, func, jsexpr);
44374432

44384433
jsexpr->returning.format.type = JS_FORMAT_DEFAULT;
@@ -4448,8 +4443,6 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
44484443
break;
44494444

44504445
case IS_JSON_QUERY:
4451-
func_name = "JSON_QUERY";
4452-
44534446
transformJsonFuncExprOutput(pstate, func, jsexpr);
44544447

44554448
jsexpr->wrapper = func->wrapper;
@@ -4458,8 +4451,6 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
44584451
break;
44594452

44604453
case IS_JSON_EXISTS:
4461-
func_name = "JSON_EXISTS";
4462-
44634454
jsexpr->returning.format.type = JS_FORMAT_DEFAULT;
44644455
jsexpr->returning.format.encoding = JS_ENC_DEFAULT;
44654456
jsexpr->returning.format.location = -1;
@@ -4469,11 +4460,5 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
44694460
break;
44704461
}
44714462

4472-
if (exprType(expr) != JSONBOID)
4473-
ereport(ERROR,
4474-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4475-
errmsg("%s() is not yet implemented for json type", func_name),
4476-
parser_errposition(pstate, func->location)));
4477-
44784463
return (Node *) jsexpr;
44794464
}

src/include/executor/execExpr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ extern void ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op,
698698
ExprContext *econtext);
699699
extern void ExecEvalJson(ExprState *state, ExprEvalStep *op,
700700
ExprContext *econtext);
701-
extern Datum ExecPrepareJsonItemCoercion(struct JsonbValue *jbv,
701+
extern Datum ExecPrepareJsonItemCoercion(struct JsonbValue *jbv, bool is_jsonb,
702702
JsonReturning *returning,
703703
struct JsonScalarCoercions *coercions,
704704
MemoryContext mcxt,

src/include/utils/jsonpath.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,12 @@ extern Datum JsonbPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper,
299299
extern JsonbValue *JsonbPathValue(Datum jb, JsonPath *jp, bool *empty,
300300
List *vars);
301301

302+
extern bool JsonPathExists(Datum json, JsonPath *path, List *vars);
303+
extern JsonbValue *JsonPathValue(Datum json, JsonPath *jp, bool *empty,
304+
List *vars);
305+
extern Datum JsonPathQuery(Datum json, JsonPath *jp, JsonWrapper wrapper,
306+
bool *empty, List *vars);
307+
302308
extern Datum EvalJsonPathVar(void *cxt, bool *isnull);
303309

304310
#endif

0 commit comments

Comments
 (0)