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(©lex, lex, sizeof(JsonLexContext));
+ copylex.strval = NULL; /* not interested in values here */
+
+ copylex.lex_level++;
+
+ lex_expect(JSON_PARSE_ARRAY_START, ©lex, JSON_TOKEN_ARRAY_START);
+ if (lex_peek(©lex) != JSON_TOKEN_ARRAY_END)
+ {
+ count++;
+ parse_array_element(©lex, &nullSemAction);
+
+ while (lex_accept(©lex, JSON_TOKEN_COMMA, NULL))
+ {
+ count++;
+ parse_array_element(©lex, &nullSemAction);
+ }
+ }
+
+ lex_expect(JSON_PARSE_ARRAY_NEXT, ©lex, 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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers