From d3c72e23df6ef1fde8122db589d12d49c8495535 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Fri, 9 May 2014 11:32:28 +0300
Subject: [PATCH] Avoid some pnstrdup()s when constructing jsonb

This speeds up text to jsonb parsing and hstore to jsonb conversions
somewhat.
---
 contrib/hstore/hstore_io.c    | 8 ++++----
 src/backend/utils/adt/json.c  | 3 ---
 src/backend/utils/adt/jsonb.c | 4 ++--
 src/include/utils/jsonapi.h   | 4 ++++
 4 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c
index 441dbf4a7c2..6ce3047215d 100644
--- a/contrib/hstore/hstore_io.c
+++ b/contrib/hstore/hstore_io.c
@@ -1386,7 +1386,7 @@ hstore_to_jsonb(PG_FUNCTION_ARGS)
 
 		key.type = jbvString;
 		key.val.string.len = HS_KEYLEN(entries, i);
-		key.val.string.val = pnstrdup(HS_KEY(entries, base, i), key.val.string.len);
+		key.val.string.val = HS_KEY(entries, base, i);
 
 		res = pushJsonbValue(&state, WJB_KEY, &key);
 
@@ -1398,7 +1398,7 @@ hstore_to_jsonb(PG_FUNCTION_ARGS)
 		{
 			val.type = jbvString;
 			val.val.string.len = HS_VALLEN(entries, i);
-			val.val.string.val = pnstrdup(HS_VAL(entries, base, i), val.val.string.len);
+			val.val.string.val = HS_VAL(entries, base, i);
 		}
 		res = pushJsonbValue(&state, WJB_VALUE, &val);
 	}
@@ -1433,7 +1433,7 @@ hstore_to_jsonb_loose(PG_FUNCTION_ARGS)
 
 		key.type = jbvString;
 		key.val.string.len = HS_KEYLEN(entries, i);
-		key.val.string.val = pnstrdup(HS_KEY(entries, base, i), key.val.string.len);
+		key.val.string.val = HS_KEY(entries, base, i);
 
 		res = pushJsonbValue(&state, WJB_KEY, &key);
 
@@ -1507,7 +1507,7 @@ hstore_to_jsonb_loose(PG_FUNCTION_ARGS)
 			{
 				val.type = jbvString;
 				val.val.string.len = HS_VALLEN(entries, i);
-				val.val.string.val = pnstrdup(HS_VAL(entries, base, i), val.val.string.len);
+				val.val.string.val = HS_VAL(entries, base, i);
 			}
 		}
 		res = pushJsonbValue(&state, WJB_VALUE, &val);
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 16f4eccc06e..e2db24520eb 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -381,9 +381,6 @@ parse_object_field(JsonLexContext *lex, JsonSemAction *sem)
 
 	if (oend != NULL)
 		(*oend) (sem->semstate, fname, isnull);
-
-	if (fname != NULL)
-		pfree(fname);
 }
 
 static void
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c
index e1fe45f7128..2fd87fc9e1a 100644
--- a/src/backend/utils/adt/jsonb.c
+++ b/src/backend/utils/adt/jsonb.c
@@ -247,7 +247,7 @@ jsonb_in_object_field_start(void *pstate, char *fname, bool isnull)
 	Assert(fname != NULL);
 	v.type = jbvString;
 	v.val.string.len = checkStringLen(strlen(fname));
-	v.val.string.val = pnstrdup(fname, v.val.string.len);
+	v.val.string.val = fname;
 
 	_state->res = pushJsonbValue(&_state->parseState, WJB_KEY, &v);
 }
@@ -295,7 +295,7 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
 			Assert(token != NULL);
 			v.type = jbvString;
 			v.val.string.len = checkStringLen(strlen(token));
-			v.val.string.val = pnstrdup(token, v.val.string.len);
+			v.val.string.val = token;
 			break;
 		case JSON_TOKEN_NUMBER:
 
diff --git a/src/include/utils/jsonapi.h b/src/include/utils/jsonapi.h
index 889364fb30e..df057121a11 100644
--- a/src/include/utils/jsonapi.h
+++ b/src/include/utils/jsonapi.h
@@ -73,6 +73,10 @@ typedef void (*json_scalar_action) (void *state, char *token, JsonTokenType toke
  * point, Likewise, semstate can be NULL. Using an all-NULL structure amounts
  * to doing a pure parse with no side-effects, and is therefore exactly
  * what the json input routines do.
+ *
+ * The 'fname' and 'token' strings passed to these actions are palloc'd.
+ * They are not free'd or used further by the parser, so the action function
+ * is free to do what it wishes with them.
  */
 typedef struct JsonSemAction
 {
-- 
GitLab