Skip to content

Commit abb014a

Browse files
committed
Refactor code into new JsonbValueAsText, and use it more
jsonb_object_field_text and jsonb_array_element_text both contained identical copies of this code, so extract that into new routine JsonbValueAsText. This can also be used in other places, to measurable performance benefit: the jsonb_each() and jsonb_array_elements() functions can use it for outputting text forms instead of their less efficient current implementation (because we no longer need to build intermediate a jsonb representation of each value). Author: Nikita Glukhov Discussion: https://postgr.es/m/7c417f90-f95f-247e-ba63-d95e39c0ad14@postgrespro.ru
1 parent e56cad8 commit abb014a

File tree

1 file changed

+61
-112
lines changed

1 file changed

+61
-112
lines changed

src/backend/utils/adt/jsonfuncs.c

Lines changed: 61 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text);
349349
static text *get_worker(text *json, char **tpath, int *ipath, int npath,
350350
bool normalize_results);
351351
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
352+
static text *JsonbValueAsText(JsonbValue *v);
352353

353354
/* semantic action functions for json_array_length */
354355
static void alen_object_start(void *state);
@@ -761,39 +762,9 @@ jsonb_object_field_text(PG_FUNCTION_ARGS)
761762
VARDATA_ANY(key),
762763
VARSIZE_ANY_EXHDR(key));
763764

764-
if (v != NULL)
765-
{
766-
text *result = NULL;
767765

768-
switch (v->type)
769-
{
770-
case jbvNull:
771-
break;
772-
case jbvBool:
773-
result = cstring_to_text(v->val.boolean ? "true" : "false");
774-
break;
775-
case jbvString:
776-
result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
777-
break;
778-
case jbvNumeric:
779-
result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
780-
PointerGetDatum(v->val.numeric))));
781-
break;
782-
case jbvBinary:
783-
{
784-
StringInfo jtext = makeStringInfo();
785-
786-
(void) JsonbToCString(jtext, v->val.binary.data, -1);
787-
result = cstring_to_text_with_len(jtext->data, jtext->len);
788-
}
789-
break;
790-
default:
791-
elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
792-
}
793-
794-
if (result)
795-
PG_RETURN_TEXT_P(result);
796-
}
766+
if (v != NULL && v->type != jbvNull)
767+
PG_RETURN_TEXT_P(JsonbValueAsText(v));
797768

798769
PG_RETURN_NULL();
799770
}
@@ -878,39 +849,9 @@ jsonb_array_element_text(PG_FUNCTION_ARGS)
878849
}
879850

880851
v = getIthJsonbValueFromContainer(&jb->root, element);
881-
if (v != NULL)
882-
{
883-
text *result = NULL;
884-
885-
switch (v->type)
886-
{
887-
case jbvNull:
888-
break;
889-
case jbvBool:
890-
result = cstring_to_text(v->val.boolean ? "true" : "false");
891-
break;
892-
case jbvString:
893-
result = cstring_to_text_with_len(v->val.string.val, v->val.string.len);
894-
break;
895-
case jbvNumeric:
896-
result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
897-
PointerGetDatum(v->val.numeric))));
898-
break;
899-
case jbvBinary:
900-
{
901-
StringInfo jtext = makeStringInfo();
902852

903-
(void) JsonbToCString(jtext, v->val.binary.data, -1);
904-
result = cstring_to_text_with_len(jtext->data, jtext->len);
905-
}
906-
break;
907-
default:
908-
elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
909-
}
910-
911-
if (result)
912-
PG_RETURN_TEXT_P(result);
913-
}
853+
if (v != NULL && v->type != jbvNull)
854+
PG_RETURN_TEXT_P(JsonbValueAsText(v));
914855

915856
PG_RETURN_NULL();
916857
}
@@ -1548,6 +1489,53 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
15481489
}
15491490
}
15501491

1492+
/*
1493+
* Return the text representation of the given JsonbValue.
1494+
*/
1495+
static text *
1496+
JsonbValueAsText(JsonbValue *v)
1497+
{
1498+
switch (v->type)
1499+
{
1500+
case jbvNull:
1501+
return NULL;
1502+
1503+
case jbvBool:
1504+
return v->val.boolean ?
1505+
cstring_to_text_with_len("true", 4) :
1506+
cstring_to_text_with_len("false", 5);
1507+
1508+
case jbvString:
1509+
return cstring_to_text_with_len(v->val.string.val,
1510+
v->val.string.len);
1511+
1512+
case jbvNumeric:
1513+
{
1514+
Datum cstr;
1515+
1516+
cstr = DirectFunctionCall1(numeric_out,
1517+
PointerGetDatum(v->val.numeric));
1518+
1519+
return cstring_to_text(DatumGetCString(cstr));
1520+
}
1521+
1522+
case jbvBinary:
1523+
{
1524+
StringInfoData jtext;
1525+
1526+
initStringInfo(&jtext);
1527+
(void) JsonbToCString(&jtext, v->val.binary.data,
1528+
v->val.binary.len);
1529+
1530+
return cstring_to_text_with_len(jtext.data, jtext.len);
1531+
}
1532+
1533+
default:
1534+
elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
1535+
return NULL;
1536+
}
1537+
}
1538+
15511539
/*
15521540
* SQL function json_array_length(json) -> int
15531541
*/
@@ -1758,26 +1746,7 @@ each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
17581746
values[1] = (Datum) NULL;
17591747
}
17601748
else
1761-
{
1762-
text *sv;
1763-
1764-
if (v.type == jbvString)
1765-
{
1766-
/* In text mode, scalar strings should be dequoted */
1767-
sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
1768-
}
1769-
else
1770-
{
1771-
/* Turn anything else into a json string */
1772-
StringInfo jtext = makeStringInfo();
1773-
Jsonb *jb = JsonbValueToJsonb(&v);
1774-
1775-
(void) JsonbToCString(jtext, &jb->root, 0);
1776-
sv = cstring_to_text_with_len(jtext->data, jtext->len);
1777-
}
1778-
1779-
values[1] = PointerGetDatum(sv);
1780-
}
1749+
values[1] = PointerGetDatum(JsonbValueAsText(&v));
17811750
}
17821751
else
17831752
{
@@ -2053,13 +2022,7 @@ elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
20532022
/* use the tmp context so we can clean up after each tuple is done */
20542023
old_cxt = MemoryContextSwitchTo(tmp_cxt);
20552024

2056-
if (!as_text)
2057-
{
2058-
Jsonb *val = JsonbValueToJsonb(&v);
2059-
2060-
values[0] = PointerGetDatum(val);
2061-
}
2062-
else
2025+
if (as_text)
20632026
{
20642027
if (v.type == jbvNull)
20652028
{
@@ -2068,26 +2031,14 @@ elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
20682031
values[0] = (Datum) NULL;
20692032
}
20702033
else
2071-
{
2072-
text *sv;
2073-
2074-
if (v.type == jbvString)
2075-
{
2076-
/* in text mode scalar strings should be dequoted */
2077-
sv = cstring_to_text_with_len(v.val.string.val, v.val.string.len);
2078-
}
2079-
else
2080-
{
2081-
/* turn anything else into a json string */
2082-
StringInfo jtext = makeStringInfo();
2083-
Jsonb *jb = JsonbValueToJsonb(&v);
2084-
2085-
(void) JsonbToCString(jtext, &jb->root, 0);
2086-
sv = cstring_to_text_with_len(jtext->data, jtext->len);
2087-
}
2034+
values[0] = PointerGetDatum(JsonbValueAsText(&v));
2035+
}
2036+
else
2037+
{
2038+
/* Not in text mode, just return the Jsonb */
2039+
Jsonb *val = JsonbValueToJsonb(&v);
20882040

2089-
values[0] = PointerGetDatum(sv);
2090-
}
2041+
values[0] = PointerGetDatum(val);
20912042
}
20922043

20932044
tuple = heap_form_tuple(ret_tdesc, values, nulls);
@@ -4430,7 +4381,6 @@ jsonb_delete_idx(PG_FUNCTION_ARGS)
44304381

44314382
/*
44324383
* SQL function jsonb_set(jsonb, text[], jsonb, boolean)
4433-
*
44344384
*/
44354385
Datum
44364386
jsonb_set(PG_FUNCTION_ARGS)
@@ -4522,7 +4472,6 @@ jsonb_delete_path(PG_FUNCTION_ARGS)
45224472

45234473
/*
45244474
* SQL function jsonb_insert(jsonb, text[], jsonb, boolean)
4525-
*
45264475
*/
45274476
Datum
45284477
jsonb_insert(PG_FUNCTION_ARGS)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy