From c8a026e4f15e2063cd7fe6cb9ffe44f2a81398bd Mon Sep 17 00:00:00 2001
From: Stephen Frost <sfrost@snowman.net>
Date: Mon, 29 Sep 2014 13:32:22 -0400
Subject: [PATCH] Revert 95d737ff to add 'ignore_nulls'

Per discussion, revert the commit which added 'ignore_nulls' to
row_to_json.  This capability would be better added as an independent
function rather than being bolted on to row_to_json.  Additionally,
the implementation didn't address complex JSON objects, and so was
incomplete anyway.

Pointed out by Tom and discussed with Andrew and Robert.
---
 doc/src/sgml/func.sgml               |  6 +--
 src/backend/catalog/system_views.sql | 14 -------
 src/backend/utils/adt/json.c         | 55 +++++++++++++++++++-------
 src/include/catalog/catversion.h     |  2 +-
 src/include/catalog/pg_proc.h        |  8 +++-
 src/include/utils/json.h             |  2 +
 src/test/regress/expected/json.out   | 58 ----------------------------
 src/test/regress/sql/json.sql        | 24 ------------
 8 files changed, 51 insertions(+), 118 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 7195df85ff5..3a7cfa93c27 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -10309,13 +10309,11 @@ table2-mapping
       </row>
       <row>
        <entry>
-         <literal>row_to_json(rowval record [, pretty bool [, ignore_nulls bool] ])</literal>
+         <literal>row_to_json(record [, pretty_bool])</literal>
        </entry>
        <entry>
          Returns the row as a JSON object. Line feeds will be added between
-         level-1 elements if <parameter>pretty_bool</parameter> is true. Elements
-         with NULL values will be skipped when <parameter>ignore_nulls</parameter>
-         is true.
+         level-1 elements if <parameter>pretty_bool</parameter> is true.
        </entry>
        <entry><literal>row_to_json(row(1,'foo'))</literal></entry>
        <entry><literal>{"f1":1,"f2":"foo"}</literal></entry>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 9d9d2394848..da99fd63e82 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -897,17 +897,3 @@ RETURNS interval
 LANGUAGE INTERNAL
 STRICT IMMUTABLE
 AS 'make_interval';
-
-CREATE OR REPLACE FUNCTION
-  row_to_json(rowval record, pretty boolean DEFAULT false, ignore_nulls boolean DEFAULT false)
-RETURNS json
-LANGUAGE INTERNAL
-STRICT STABLE
-AS 'row_to_json';
-
-CREATE OR REPLACE FUNCTION
-  array_to_json(arrayval anyarray, pretty boolean DEFAULT false)
-RETURNS json
-LANGUAGE INTERNAL
-STRICT STABLE
-AS 'array_to_json';
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 6f678eb8b22..d2bf640e54e 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -79,8 +79,7 @@ static void report_invalid_token(JsonLexContext *lex);
 static int	report_json_context(JsonLexContext *lex);
 static char *extract_mb_char(char *s);
 static void composite_to_json(Datum composite, StringInfo result,
-				  bool use_line_feeds,
-				  bool ignore_nulls);
+				  bool use_line_feeds);
 static void array_dim_to_json(StringInfo result, int dim, int ndims, int *dims,
 				  Datum *vals, bool *nulls, int *valcount,
 				  JsonTypeCategory tcategory, Oid outfuncoid,
@@ -1366,7 +1365,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
 			array_to_json_internal(val, result, false);
 			break;
 		case JSONTYPE_COMPOSITE:
-			composite_to_json(val, result, false, false);
+			composite_to_json(val, result, false);
 			break;
 		case JSONTYPE_BOOL:
 			outputstr = DatumGetBool(val) ? "true" : "false";
@@ -1591,8 +1590,7 @@ array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
  * Turn a composite / record into JSON.
  */
 static void
-composite_to_json(Datum composite, StringInfo result, bool use_line_feeds,
-				  bool ignore_nulls)
+composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
 {
 	HeapTupleHeader td;
 	Oid			tupType;
@@ -1631,12 +1629,6 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds,
 		if (tupdesc->attrs[i]->attisdropped)
 			continue;
 
-		val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
-
-		/* Don't serialize NULL field when we don't want it */
-		if (isnull && ignore_nulls)
-			continue;
-
 		if (needsep)
 			appendStringInfoString(result, sep);
 		needsep = true;
@@ -1645,6 +1637,8 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds,
 		escape_json(result, attname);
 		appendStringInfoChar(result, ':');
 
+		val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
+
 		if (isnull)
 		{
 			tcategory = JSONTYPE_NULL;
@@ -1693,10 +1687,26 @@ add_json(Datum val, bool is_null, StringInfo result,
 }
 
 /*
- * SQL function array_to_json(row, prettybool)
+ * SQL function array_to_json(row)
  */
 extern Datum
 array_to_json(PG_FUNCTION_ARGS)
+{
+	Datum		array = PG_GETARG_DATUM(0);
+	StringInfo	result;
+
+	result = makeStringInfo();
+
+	array_to_json_internal(array, result, false);
+
+	PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
+}
+
+/*
+ * SQL function array_to_json(row, prettybool)
+ */
+extern Datum
+array_to_json_pretty(PG_FUNCTION_ARGS)
 {
 	Datum		array = PG_GETARG_DATUM(0);
 	bool		use_line_feeds = PG_GETARG_BOOL(1);
@@ -1710,19 +1720,34 @@ array_to_json(PG_FUNCTION_ARGS)
 }
 
 /*
- * SQL function row_to_json(rowval record, pretty bool, ignore_nulls bool)
+ * SQL function row_to_json(row)
  */
 extern Datum
 row_to_json(PG_FUNCTION_ARGS)
+{
+	Datum		array = PG_GETARG_DATUM(0);
+	StringInfo	result;
+
+	result = makeStringInfo();
+
+	composite_to_json(array, result, false);
+
+	PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
+}
+
+/*
+ * SQL function row_to_json(row, prettybool)
+ */
+extern Datum
+row_to_json_pretty(PG_FUNCTION_ARGS)
 {
 	Datum		array = PG_GETARG_DATUM(0);
 	bool		use_line_feeds = PG_GETARG_BOOL(1);
-	bool		ignore_nulls = PG_GETARG_BOOL(2);
 	StringInfo	result;
 
 	result = makeStringInfo();
 
-	composite_to_json(array, result, use_line_feeds, ignore_nulls);
+	composite_to_json(array, result, use_line_feeds);
 
 	PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
 }
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index e5800f94251..a3464a5df90 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	201409292
+#define CATALOG_VERSION_NO	201409293
 
 #endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 3ce9849abff..47365328510 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -4203,10 +4203,14 @@ DATA(insert OID = 323 (  json_recv		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0
 DESCR("I/O");
 DATA(insert OID = 324 (  json_send		   PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 17 "114" _null_ _null_ _null_ _null_ json_send _null_ _null_ _null_ ));
 DESCR("I/O");
-DATA(insert OID = 3153 (  array_to_json    PGNSP PGUID 12 1 0 0 0 f f f f t f s 2 0 114 "2277 16" _null_ _null_ "{arrayval,pretty}" _null_ array_to_json _null_ _null_ _null_ ));
+DATA(insert OID = 3153 (  array_to_json    PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 114 "2277" _null_ _null_ _null_ _null_ array_to_json _null_ _null_ _null_ ));
 DESCR("map array to json");
-DATA(insert OID = 3155 (  row_to_json	   PGNSP PGUID 12 1 0 0 0 f f f f t f s 3 0 114 "2249 16 16" _null_ _null_ "{rowval,pretty,ignore_nulls}" _null_ row_to_json _null_ _null_ _null_ ));
+DATA(insert OID = 3154 (  array_to_json    PGNSP PGUID 12 1 0 0 0 f f f f t f s 2 0 114 "2277 16" _null_ _null_ _null_ _null_ array_to_json_pretty _null_ _null_ _null_ ));
+DESCR("map array to json with optional pretty printing");
+DATA(insert OID = 3155 (  row_to_json	   PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 114 "2249" _null_ _null_ _null_ _null_ row_to_json _null_ _null_ _null_ ));
 DESCR("map row to json");
+DATA(insert OID = 3156 (  row_to_json	   PGNSP PGUID 12 1 0 0 0 f f f f t f s 2 0 114 "2249 16" _null_ _null_ _null_ _null_ row_to_json_pretty _null_ _null_ _null_ ));
+DESCR("map row to json with optional pretty printing");
 DATA(insert OID = 3173 (  json_agg_transfn	 PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2281 "2281 2283" _null_ _null_ _null_ _null_ json_agg_transfn _null_ _null_ _null_ ));
 DESCR("json aggregate transition function");
 DATA(insert OID = 3174 (  json_agg_finalfn	 PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 114 "2281" _null_ _null_ _null_ _null_ json_agg_finalfn _null_ _null_ _null_ ));
diff --git a/src/include/utils/json.h b/src/include/utils/json.h
index 9d8a0a55a88..82cc48b7113 100644
--- a/src/include/utils/json.h
+++ b/src/include/utils/json.h
@@ -23,7 +23,9 @@ extern Datum json_out(PG_FUNCTION_ARGS);
 extern Datum json_recv(PG_FUNCTION_ARGS);
 extern Datum json_send(PG_FUNCTION_ARGS);
 extern Datum array_to_json(PG_FUNCTION_ARGS);
+extern Datum array_to_json_pretty(PG_FUNCTION_ARGS);
 extern Datum row_to_json(PG_FUNCTION_ARGS);
+extern Datum row_to_json_pretty(PG_FUNCTION_ARGS);
 extern Datum to_json(PG_FUNCTION_ARGS);
 
 extern Datum json_agg_transfn(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/json.out b/src/test/regress/expected/json.out
index 968e02a1e1e..bb4d9ed4beb 100644
--- a/src/test/regress/expected/json.out
+++ b/src/test/regress/expected/json.out
@@ -397,70 +397,12 @@ FROM rows q;
   "y":"txt3"}
 (3 rows)
 
-SELECT row_to_json(q,pretty := true)
-FROM rows q;
- row_to_json  
---------------
- {"x":1,     +
-  "y":"txt1"}
- {"x":2,     +
-  "y":"txt2"}
- {"x":3,     +
-  "y":"txt3"}
-(3 rows)
-
 SELECT row_to_json(row((select array_agg(x) as d from generate_series(5,10) x)),false);
       row_to_json      
 -----------------------
  {"f1":[5,6,7,8,9,10]}
 (1 row)
 
-WITH x AS (SELECT a,b,c FROM (VALUES(10,20,30),
-                             (10,NULL, NULL),
-                             (NULL, NULL, NULL)) g(a,b,c))
- SELECT row_to_json(x, false, false) FROM x;
-         row_to_json          
-------------------------------
- {"a":10,"b":20,"c":30}
- {"a":10,"b":null,"c":null}
- {"a":null,"b":null,"c":null}
-(3 rows)
-
-WITH x AS (SELECT a,b,c FROM (VALUES(10,20,30),
-                             (10,NULL, NULL),
-                             (NULL, NULL, NULL)) g(a,b,c))
- SELECT row_to_json(x, false, true) FROM x;
-      row_to_json       
-------------------------
- {"a":10,"b":20,"c":30}
- {"a":10}
- {}
-(3 rows)
-
-WITH x AS (SELECT a,b,c FROM (VALUES(10,20,30),
-                             (10,NULL, NULL),
-                             (NULL, NULL, NULL)) g(a,b,c))
- SELECT row_to_json(x, ignore_nulls := true) FROM x;
-      row_to_json       
-------------------------
- {"a":10,"b":20,"c":30}
- {"a":10}
- {}
-(3 rows)
-
-WITH x AS (SELECT a,b,c FROM (VALUES(10,20,30),
-                             (10,NULL, NULL),
-                             (NULL, NULL, NULL)) g(a,b,c))
- SELECT row_to_json(x, ignore_nulls := true, pretty := true) FROM x;
- row_to_json 
--------------
- {"a":10,   +
-  "b":20,   +
-  "c":30}
- {"a":10}
- {}
-(3 rows)
-
 -- to_json, timestamps
 select to_json(timestamp '2014-05-28 12:22:35.614298');
            to_json            
diff --git a/src/test/regress/sql/json.sql b/src/test/regress/sql/json.sql
index 3ddf6564e0c..c9801321e09 100644
--- a/src/test/regress/sql/json.sql
+++ b/src/test/regress/sql/json.sql
@@ -98,32 +98,8 @@ FROM generate_series(1,3) AS x;
 SELECT row_to_json(q,true)
 FROM rows q;
 
-SELECT row_to_json(q,pretty := true)
-FROM rows q;
-
 SELECT row_to_json(row((select array_agg(x) as d from generate_series(5,10) x)),false);
 
-WITH x AS (SELECT a,b,c FROM (VALUES(10,20,30),
-                             (10,NULL, NULL),
-                             (NULL, NULL, NULL)) g(a,b,c))
- SELECT row_to_json(x, false, false) FROM x;
-
-WITH x AS (SELECT a,b,c FROM (VALUES(10,20,30),
-                             (10,NULL, NULL),
-                             (NULL, NULL, NULL)) g(a,b,c))
- SELECT row_to_json(x, false, true) FROM x;
-
-WITH x AS (SELECT a,b,c FROM (VALUES(10,20,30),
-                             (10,NULL, NULL),
-                             (NULL, NULL, NULL)) g(a,b,c))
- SELECT row_to_json(x, ignore_nulls := true) FROM x;
-
-WITH x AS (SELECT a,b,c FROM (VALUES(10,20,30),
-                             (10,NULL, NULL),
-                             (NULL, NULL, NULL)) g(a,b,c))
- SELECT row_to_json(x, ignore_nulls := true, pretty := true) FROM x;
-
-
 -- to_json, timestamps
 
 select to_json(timestamp '2014-05-28 12:22:35.614298');
-- 
GitLab