On 06/12/2015 12:29 PM, I wrote:



I agree that the json case looks a bit nasty. Maybe a better approach would be to provide a function that, given a JsonLexContext, returns the number of array elements of the current array. In get_array_start we could call that if the relevant path element is negative and adjust it accordingly.





Here's some code for the count piece of that.

cheers

andrew

diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 26d3843..a11b965 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -341,6 +341,53 @@ pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
 }
 
 /*
+ * json_count_array
+ *
+ * designed to be called from the array_start routine
+ *
+ * gives the number of elements in the array at whatever nesting level it is at.
+ *
+ */
+int
+json_count_array_elements(JsonLexContext *lex)
+{
+	JsonLexContext copylex;
+	int count = 0;
+
+	if (lex_peek(lex) != JSON_TOKEN_ARRAY_START)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), /* XX FIX */
+				 errmsg("json_count_array must be called at the start of an array")));
+
+	/*
+	 * It's safe to do this with a shallow copy because the lexical routines
+	 * don't scribble on the input. They do scribble on the other pointers etc,
+	 * so doing this with a copy makes that safe.
+	 */
+	memcpy(&copylex, lex, sizeof(JsonLexContext));
+	copylex.strval = NULL; /* not interested in values here */
+
+	copylex.lex_level++;
+
+	lex_expect(JSON_PARSE_ARRAY_START, &copylex, JSON_TOKEN_ARRAY_START);
+	if (lex_peek(&copylex) != JSON_TOKEN_ARRAY_END)
+	{
+		count++;
+		parse_array_element(&copylex, &nullSemAction);
+
+		while (lex_accept(&copylex, JSON_TOKEN_COMMA, NULL))
+		{
+			count++;
+			parse_array_element(&copylex, &nullSemAction);
+		}
+	}
+
+	lex_expect(JSON_PARSE_ARRAY_NEXT, &copylex, JSON_TOKEN_ARRAY_END);
+
+	return count;
+}
+
+/*
  *	Recursive Descent parse routines. There is one for each structural
  *	element in a json document:
  *	  - scalar (string, number, true, false, null)
diff --git a/src/include/utils/jsonapi.h b/src/include/utils/jsonapi.h
index 296d20a..1abb8b9 100644
--- a/src/include/utils/jsonapi.h
+++ b/src/include/utils/jsonapi.h
@@ -104,6 +104,13 @@ typedef struct JsonSemAction
 extern void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem);
 
 /*
+ * json_count_array does a fast secondary parse to determine the number
+ * of elements in the current array. It must be called from an array_start
+ * action.
+ */
+extern int json_count_array_elements(JsonLexContext *lex);
+
+/*
  * constructors for JsonLexContext, with or without strval element.
  * If supplied, the strval element will contain a de-escaped version of
  * the lexeme. However, doing this imposes a performance penalty, so
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to