From: Nikita Glukhov Date: Thu, 21 Feb 2019 03:04:13 +0300 Subject: [PATCH v3 2/5] Optimize jsonb operator #>> using extracted JsonbValueAsText() --- src/backend/utils/adt/jsonfuncs.c | 164 +++++++++--------------------- 1 file changed, 50 insertions(+), 114 deletions(-) diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 667f9d9563..c7f71408d5 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -747,6 +747,47 @@ json_object_field_text(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } +static text * +JsonbValueAsText(JsonbValue *v) +{ + switch (v->type) + { + case jbvNull: + return NULL; + + case jbvBool: + return v->val.boolean ? + cstring_to_text_with_len("true", 4) : + cstring_to_text_with_len("false", 5); + + case jbvString: + return cstring_to_text_with_len(v->val.string.val, + v->val.string.len); + + case jbvNumeric: + { + Datum cstr = DirectFunctionCall1(numeric_out, + PointerGetDatum(v->val.numeric)); + + return cstring_to_text(DatumGetCString(cstr)); + } + + case jbvBinary: + { + StringInfoData jtext; + + initStringInfo(&jtext); + (void) JsonbToCString(&jtext, v->val.binary.data, -1); + + return cstring_to_text_with_len(jtext.data, jtext.len); + } + + default: + elog(ERROR, "unrecognized jsonb type: %d", (int) v->type); + return NULL; + } +} + Datum jsonb_object_field_text(PG_FUNCTION_ARGS) { @@ -761,39 +802,9 @@ jsonb_object_field_text(PG_FUNCTION_ARGS) VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key)); - if (v != NULL) - { - text *result = NULL; - switch (v->type) - { - case jbvNull: - break; - case jbvBool: - result = cstring_to_text(v->val.boolean ? "true" : "false"); - break; - case jbvString: - result = cstring_to_text_with_len(v->val.string.val, v->val.string.len); - break; - case jbvNumeric: - result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out, - PointerGetDatum(v->val.numeric)))); - break; - case jbvBinary: - { - StringInfo jtext = makeStringInfo(); - - (void) JsonbToCString(jtext, v->val.binary.data, -1); - result = cstring_to_text_with_len(jtext->data, jtext->len); - } - break; - default: - elog(ERROR, "unrecognized jsonb type: %d", (int) v->type); - } - - if (result) - PG_RETURN_TEXT_P(result); - } + if (v != NULL && v->type != jbvNull) + PG_RETURN_TEXT_P(JsonbValueAsText(v)); PG_RETURN_NULL(); } @@ -878,39 +889,9 @@ jsonb_array_element_text(PG_FUNCTION_ARGS) } v = getIthJsonbValueFromContainer(&jb->root, element); - if (v != NULL) - { - text *result = NULL; - switch (v->type) - { - case jbvNull: - break; - case jbvBool: - result = cstring_to_text(v->val.boolean ? "true" : "false"); - break; - case jbvString: - result = cstring_to_text_with_len(v->val.string.val, v->val.string.len); - break; - case jbvNumeric: - result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out, - PointerGetDatum(v->val.numeric)))); - break; - case jbvBinary: - { - StringInfo jtext = makeStringInfo(); - - (void) JsonbToCString(jtext, v->val.binary.data, -1); - result = cstring_to_text_with_len(jtext->data, jtext->len); - } - break; - default: - elog(ERROR, "unrecognized jsonb type: %d", (int) v->type); - } - - if (result) - PG_RETURN_TEXT_P(result); - } + if (v != NULL && v->type != jbvNull) + PG_RETURN_TEXT_P(JsonbValueAsText(v)); PG_RETURN_NULL(); } @@ -1388,7 +1369,6 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text) { Jsonb *jb = PG_GETARG_JSONB_P(0); ArrayType *path = PG_GETARG_ARRAYTYPE_P(1); - Jsonb *res; Datum *pathtext; bool *pathnulls; int npath; @@ -1396,7 +1376,6 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text) bool have_object = false, have_array = false; JsonbValue *jbvp = NULL; - JsonbValue tv; JsonbContainer *container; /* @@ -1525,24 +1504,15 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text) if (as_text) { - /* special-case outputs for string and null values */ - if (jbvp->type == jbvString) - PG_RETURN_TEXT_P(cstring_to_text_with_len(jbvp->val.string.val, - jbvp->val.string.len)); if (jbvp->type == jbvNull) PG_RETURN_NULL(); - } - res = JsonbValueToJsonb(jbvp); - - if (as_text) - { - PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL, - &res->root, - VARSIZE(res)))); + PG_RETURN_TEXT_P(JsonbValueAsText(jbvp)); } else { + Jsonb *res = JsonbValueToJsonb(jbvp); + /* not text mode - just hand back the jsonb */ PG_RETURN_JSONB_P(res); } @@ -1759,24 +1729,7 @@ each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text) } else { - text *sv; - - if (v.type == jbvString) - { - /* In text mode, scalar strings should be dequoted */ - sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len); - } - else - { - /* Turn anything else into a json string */ - StringInfo jtext = makeStringInfo(); - Jsonb *jb = JsonbValueToJsonb(&v); - - (void) JsonbToCString(jtext, &jb->root, 0); - sv = cstring_to_text_with_len(jtext->data, jtext->len); - } - - values[1] = PointerGetDatum(sv); + values[1] = PointerGetDatum(JsonbValueAsText(&v)); } } else @@ -2069,24 +2022,7 @@ elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, } else { - text *sv; - - if (v.type == jbvString) - { - /* in text mode scalar strings should be dequoted */ - sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len); - } - else - { - /* turn anything else into a json string */ - StringInfo jtext = makeStringInfo(); - Jsonb *jb = JsonbValueToJsonb(&v); - - (void) JsonbToCString(jtext, &jb->root, 0); - sv = cstring_to_text_with_len(jtext->data, jtext->len); - } - - values[0] = PointerGetDatum(sv); + values[0] = PointerGetDatum(JsonbValueAsText(&v)); } } -- 2.17.1 --IJpNTDwzlM2Ie8A6 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v3-0003-Optimize-JsonbContainer-type-recognition-in-get_j.patch"