From ddb5cfd79a3acd943b82cb3c9a6105404e601dcf Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Thu, 23 Jan 2020 12:03:29 -0800
Subject: [PATCH 11/11] Adding src/bin/pg_test_json

This is a command line tool for testing whether
a string is valid json.  It is not that useful
in itself, but it proves that the json parser in
src/common can be used from frontend code.
---
 src/bin/Makefile                    |  1 +
 src/bin/pg_test_json/Makefile       | 46 +++++++++++++++++
 src/bin/pg_test_json/nls.mk         |  4 ++
 src/bin/pg_test_json/pg_test_json.c | 80 +++++++++++++++++++++++++++++
 4 files changed, 131 insertions(+)
 create mode 100644 src/bin/pg_test_json/Makefile
 create mode 100644 src/bin/pg_test_json/nls.mk
 create mode 100644 src/bin/pg_test_json/pg_test_json.c

diff --git a/src/bin/Makefile b/src/bin/Makefile
index 7f4120a34f..7a9a7980b4 100644
--- a/src/bin/Makefile
+++ b/src/bin/Makefile
@@ -25,6 +25,7 @@ SUBDIRS = \
 	pg_resetwal \
 	pg_rewind \
 	pg_test_fsync \
+	pg_test_json \
 	pg_test_timing \
 	pg_upgrade \
 	pg_waldump \
diff --git a/src/bin/pg_test_json/Makefile b/src/bin/pg_test_json/Makefile
new file mode 100644
index 0000000000..3e0458db99
--- /dev/null
+++ b/src/bin/pg_test_json/Makefile
@@ -0,0 +1,46 @@
+#-------------------------------------------------------------------------
+#
+# Makefile for src/bin/pg_test_json
+#
+# Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/bin/pg_test_json/Makefile
+#
+#-------------------------------------------------------------------------
+
+PGFILEDESC = "pg_test_json - the PostgreSQL interactive json syntax tester"
+PGAPPICON=win32
+
+subdir = src/bin/pg_test_json
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+# make this available to TAP test scripts
+export with_readline
+
+REFDOCDIR= $(top_srcdir)/doc/src/sgml/ref
+
+override CPPFLAGS := -I. -I$(srcdir) -I$(libpq_srcdir) $(CPPFLAGS)
+LDFLAGS_INTERNAL += -L$(top_builddir)/src/fe_utils -lpgfeutils $(libpq_pgport)
+
+OBJS = \
+	$(WIN32RES) \
+	pg_test_json.o
+
+all: pg_test_json
+
+pg_test_json: $(OBJS) | submake-libpq submake-libpgport submake-libpgfeutils
+	$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
+
+install: all installdirs
+	$(INSTALL_PROGRAM) pg_test_json$(X) '$(DESTDIR)$(bindir)/pg_test_json$(X)'
+
+installdirs:
+	$(MKDIR_P) '$(DESTDIR)$(bindir)'
+
+uninstall:
+	rm -f '$(DESTDIR)$(bindir)/pg_test_json$(X)'
+
+clean distclean maintainer-clean:
+	rm -f pg_test_json$(X) $(OBJS)
diff --git a/src/bin/pg_test_json/nls.mk b/src/bin/pg_test_json/nls.mk
new file mode 100644
index 0000000000..72de0728db
--- /dev/null
+++ b/src/bin/pg_test_json/nls.mk
@@ -0,0 +1,4 @@
+# src/bin/pg_test_json/nls.mk
+CATALOG_NAME     = pg_test_json
+AVAIL_LANGUAGES  =
+GETTEXT_FILES    = pg_test_json.c
diff --git a/src/bin/pg_test_json/pg_test_json.c b/src/bin/pg_test_json/pg_test_json.c
new file mode 100644
index 0000000000..dd8bebafb9
--- /dev/null
+++ b/src/bin/pg_test_json/pg_test_json.c
@@ -0,0 +1,80 @@
+/*
+ *	pg_test_json.c
+ *		tests validity of json strings against parser implementation.
+ */
+
+#include "postgres_fe.h"
+
+#include "common/jsonapi.h"
+#include "libpq-fe.h"
+
+static const char *progname;
+
+static void handle_args(int argc, char *argv[]);
+static void parse_json(const char *str);
+
+int
+main(int argc, char *argv[])
+{
+	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_test_json"));
+	progname = get_progname(argv[0]);
+
+	handle_args(argc, argv);
+
+	return 0;
+}
+
+static void
+handle_args(int argc, char *argv[])
+{
+	int			argidx;			/* Command line argument position */
+
+	if (argc > 1)
+	{
+		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
+		{
+			printf(_("Usage: %s jsonstr [, ...]\n"), progname);
+			exit(0);
+		}
+		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
+		{
+			puts("pg_test_json (PostgreSQL) " PG_VERSION);
+			exit(0);
+		}
+	}
+
+	for (argidx = 1; argidx < argc; argidx++)
+		parse_json(argv[argidx]);
+}
+
+static void
+parse_json(const char *str)
+{
+	char *json;
+	unsigned int json_len;
+	JsonLexContext *lex;
+	int client_encoding;
+	JsonParseErrorType parse_result;
+
+	json_len = (unsigned int) strlen(str);
+	client_encoding = PQenv2encoding();
+
+#if 0
+	fprintf(stdout, _("%s: preparing for parse of string of length %u....\n"),
+				progname, json_len);
+#endif
+	json = strdup(str);
+#if 0
+	fprintf(stdout, _("%s: duplicated string of length %u.\n"),
+				progname, json_len);
+#endif
+	lex = makeJsonLexContextCstringLen(json, strlen(json), client_encoding, true /* need_escapes */);
+#if 0
+	fprintf(stdout, _("%s: constructed JsonLexContext for utf8 json string of length %u.\n"),
+				progname, json_len);
+#endif
+	parse_result = pg_parse_json(lex, &nullSemAction);
+	fprintf(stdout, _("%s: %s: %s\n"),
+					progname, str, (JSON_SUCCESS == parse_result ? "VALID" : "INVALID"));
+	return;
+}
-- 
2.21.1 (Apple Git-122.3)

