diff options
author | Andrew Dunstan <andrew@dunslane.net> | 2020-01-17 11:41:35 +1030 |
---|---|---|
committer | Andrew Dunstan <andrew@dunslane.net> | 2020-01-17 11:52:39 +1030 |
commit | a83586b5543b948f9e621462537a7303b113c482 (patch) | |
tree | 98c49e29a4b1a4014fd8ae040d6939812696a841 /src/backend/utils/adt/jsonfuncs.c | |
parent | f7cd5896a69621818189fbdd209fb2e1fc008102 (diff) | |
download | postgresql-a83586b5543b948f9e621462537a7303b113c482.tar.gz postgresql-a83586b5543b948f9e621462537a7303b113c482.zip |
Add a non-strict version of jsonb_set
jsonb_set_lax() is the same as jsonb_set, except that it takes and extra
argument that specifies what to do if the value argument is NULL. The
default is 'use_json_null'. Other possibilities are 'raise_exception',
'return_target' and 'delete_key', all these behaviours having been
suggested as reasonable by various users.
Discussion: https://postgr.es/m/375873e2-c957-3a8d-64f9-26c43c2b16e7@2ndQuadrant.com
Reviewed by: Pavel Stehule
Diffstat (limited to 'src/backend/utils/adt/jsonfuncs.c')
-rw-r--r-- | src/backend/utils/adt/jsonfuncs.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index ab5a24a8584..4b5a0214dca 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -4396,6 +4396,70 @@ jsonb_set(PG_FUNCTION_ARGS) /* + * SQL function jsonb_set_lax(jsonb, text[], jsonb, boolean, text) + */ +Datum +jsonb_set_lax(PG_FUNCTION_ARGS) +{ + /* Jsonb *in = PG_GETARG_JSONB_P(0); */ + /* ArrayType *path = PG_GETARG_ARRAYTYPE_P(1); */ + /* Jsonb *newval = PG_GETARG_JSONB_P(2); */ + /* bool create = PG_GETARG_BOOL(3); */ + text *handle_null; + char *handle_val; + + if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(3)) + PG_RETURN_NULL(); + + /* could happen if they pass in an explicit NULL */ + if (PG_ARGISNULL(4)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("need delete_key, return_target, use_json_null, or raise_exception"))); + + /* if the new value isn't an SQL NULL just call jsonb_set */ + if (! PG_ARGISNULL(2)) + return jsonb_set(fcinfo); + + handle_null = PG_GETARG_TEXT_P(4); + handle_val = text_to_cstring(handle_null); + + if (strcmp(handle_val,"raise_exception") == 0) + { + ereport(ERROR, + (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), + errmsg("NULL is not allowed"), + errdetail("exception raised due to \"null_value_treatment => 'raise_exception'\""), + errhint("to avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not used"))); + } + else if (strcmp(handle_val, "use_json_null") == 0) + { + Datum newval; + + newval = DirectFunctionCall1(jsonb_in, CStringGetDatum("null")); + + fcinfo->args[2].value = newval; + fcinfo->args[2].isnull = false; + return jsonb_set(fcinfo); + } + else if (strcmp(handle_val, "delete_key") == 0) + { + return jsonb_delete_path(fcinfo); + } + else if (strcmp(handle_val, "return_target") == 0) + { + Jsonb *in = PG_GETARG_JSONB_P(0); + PG_RETURN_JSONB_P(in); + } + else + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("need delete_key, return_target, use_json_null, or raise_exception"))); + } +} + +/* * SQL function jsonb_delete_path(jsonb, text[]) */ Datum |