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 (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers