aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/json.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/json.c')
-rw-r--r--src/backend/utils/adt/json.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 97a0e9f211e..c34a1bb50be 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -210,22 +210,17 @@ Datum
json_recv(PG_FUNCTION_ARGS)
{
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
- text *result;
char *str;
int nbytes;
JsonLexContext *lex;
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
- result = palloc(nbytes + VARHDRSZ);
- SET_VARSIZE(result, nbytes + VARHDRSZ);
- memcpy(VARDATA(result), str, nbytes);
-
/* Validate it. */
- lex = makeJsonLexContext(result, false);
+ lex = makeJsonLexContextCstringLen(str, nbytes, false);
pg_parse_json(lex, &nullSemAction);
- PG_RETURN_TEXT_P(result);
+ PG_RETURN_TEXT_P(cstring_to_text_with_len(str, nbytes));
}
/*
@@ -236,15 +231,26 @@ json_recv(PG_FUNCTION_ARGS)
*
* Without is better as it makes the processing faster, so only make one
* if really required.
+ *
+ * If you already have the json as a text* value, use the first of these
+ * functions, otherwise use makeJsonLexContextCstringLen().
*/
JsonLexContext *
makeJsonLexContext(text *json, bool need_escapes)
{
+ return makeJsonLexContextCstringLen(VARDATA(json),
+ VARSIZE(json) - VARHDRSZ,
+ need_escapes);
+}
+
+JsonLexContext *
+makeJsonLexContextCstringLen(char *json, int len, bool need_escapes)
+{
JsonLexContext *lex = palloc0(sizeof(JsonLexContext));
- lex->input = lex->token_terminator = lex->line_start = VARDATA(json);
+ lex->input = lex->token_terminator = lex->line_start = json;
lex->line_number = 1;
- lex->input_length = VARSIZE(json) - VARHDRSZ;
+ lex->input_length = len;
if (need_escapes)
lex->strval = makeStringInfo();
return lex;
@@ -1274,7 +1280,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
pfree(outputstr);
break;
case TYPCATEGORY_JSON:
- /* JSON will already be escaped */
+ /* JSON and JSONB will already be escaped */
outputstr = OidOutputFunctionCall(typoutputfunc, val);
appendStringInfoString(result, outputstr);
pfree(outputstr);
@@ -1406,7 +1412,7 @@ array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
tcategory = TYPCATEGORY_JSON_CAST;
else if (element_type == RECORDOID)
tcategory = TYPCATEGORY_COMPOSITE;
- else if (element_type == JSONOID)
+ else if (element_type == JSONOID || element_type == JSONBOID)
tcategory = TYPCATEGORY_JSON;
else
tcategory = TypeCategory(element_type);
@@ -1501,7 +1507,8 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
tcategory = TYPCATEGORY_ARRAY;
else if (tupdesc->attrs[i]->atttypid == RECORDOID)
tcategory = TYPCATEGORY_COMPOSITE;
- else if (tupdesc->attrs[i]->atttypid == JSONOID)
+ else if (tupdesc->attrs[i]->atttypid == JSONOID ||
+ tupdesc->attrs[i]->atttypid == JSONBOID)
tcategory = TYPCATEGORY_JSON;
else
tcategory = TypeCategory(tupdesc->attrs[i]->atttypid);
@@ -1689,7 +1696,7 @@ to_json(PG_FUNCTION_ARGS)
tcategory = TYPCATEGORY_ARRAY;
else if (val_type == RECORDOID)
tcategory = TYPCATEGORY_COMPOSITE;
- else if (val_type == JSONOID)
+ else if (val_type == JSONOID || val_type == JSONBOID)
tcategory = TYPCATEGORY_JSON;
else
tcategory = TypeCategory(val_type);
@@ -1783,7 +1790,7 @@ json_agg_transfn(PG_FUNCTION_ARGS)
tcategory = TYPCATEGORY_ARRAY;
else if (val_type == RECORDOID)
tcategory = TYPCATEGORY_COMPOSITE;
- else if (val_type == JSONOID)
+ else if (val_type == JSONOID || val_type == JSONBOID)
tcategory = TYPCATEGORY_JSON;
else
tcategory = TypeCategory(val_type);
@@ -2346,12 +2353,15 @@ escape_json(StringInfo buf, const char *str)
Datum
json_typeof(PG_FUNCTION_ARGS)
{
- text *json = PG_GETARG_TEXT_P(0);
+ text *json;
- JsonLexContext *lex = makeJsonLexContext(json, false);
+ JsonLexContext *lex;
JsonTokenType tok;
char *type;
+ json = PG_GETARG_TEXT_P(0);
+ lex = makeJsonLexContext(json, false);
+
/* Lex exactly one token from the input and check its type. */
json_lex(lex);
tok = lex_peek(lex);