1.2._3
(1 row)
+-- empty labels not allowed
+SELECT '.2.3'::ltree;
+ERROR: ltree syntax error at character 1
+LINE 1: SELECT '.2.3'::ltree;
+ ^
+SELECT '1..3'::ltree;
+ERROR: ltree syntax error at character 3
+LINE 1: SELECT '1..3'::ltree;
+ ^
+SELECT '1.2.'::ltree;
+ERROR: ltree syntax error
+LINE 1: SELECT '1.2.'::ltree;
+ ^
+DETAIL: Unexpected end of input.
+SELECT repeat('x', 255)::ltree;
+ repeat
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+(1 row)
+
+SELECT repeat('x', 256)::ltree;
+ERROR: label string is too long
+DETAIL: Label length is 256, must be at most 255, at character 257.
SELECT ltree2text('1.2.3.34.sdf');
ltree2text
--------------
foo.bar{,}.!a*|b{1,}.c{,44}.d{3,4}
(1 row)
+SELECT 'foo*@@*'::lquery;
+ lquery
+--------
+ foo@*
+(1 row)
+
SELECT 'qwerty%@*.tu'::lquery;
lquery
--------------
qwerty%@*.tu
(1 row)
+-- empty labels not allowed
+SELECT '.2.3'::lquery;
+ERROR: lquery syntax error at character 1
+LINE 1: SELECT '.2.3'::lquery;
+ ^
+SELECT '1..3'::lquery;
+ERROR: lquery syntax error at character 3
+LINE 1: SELECT '1..3'::lquery;
+ ^
+SELECT '1.2.'::lquery;
+ERROR: lquery syntax error
+LINE 1: SELECT '1.2.'::lquery;
+ ^
+DETAIL: Unexpected end of input.
+SELECT '@.2.3'::lquery;
+ERROR: lquery syntax error at character 1
+LINE 1: SELECT '@.2.3'::lquery;
+ ^
+SELECT '1.@.3'::lquery;
+ERROR: lquery syntax error at character 3
+LINE 1: SELECT '1.@.3'::lquery;
+ ^
+SELECT '1.2.@'::lquery;
+ERROR: lquery syntax error at character 5
+LINE 1: SELECT '1.2.@'::lquery;
+ ^
+SELECT '!.2.3'::lquery;
+ERROR: lquery syntax error at character 2
+LINE 1: SELECT '!.2.3'::lquery;
+ ^
+DETAIL: Empty labels are not allowed.
+SELECT '1.!.3'::lquery;
+ERROR: lquery syntax error at character 4
+LINE 1: SELECT '1.!.3'::lquery;
+ ^
+DETAIL: Empty labels are not allowed.
+SELECT '1.2.!'::lquery;
+ERROR: lquery syntax error at character 6
+LINE 1: SELECT '1.2.!'::lquery;
+ ^
+DETAIL: Empty labels are not allowed.
+SELECT '1.2.3|@.4'::lquery;
+ERROR: lquery syntax error at character 7
+LINE 1: SELECT '1.2.3|@.4'::lquery;
+ ^
+SELECT (repeat('x', 255) || '*@@*')::lquery;
+ lquery
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@*
+(1 row)
+
+SELECT (repeat('x', 256) || '*@@*')::lquery;
+ERROR: label string is too long
+DETAIL: Label length is 256, must be at most 255, at character 257.
+SELECT ('!' || repeat('x', 255))::lquery;
+ lquery
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ !xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+(1 row)
+
+SELECT ('!' || repeat('x', 256))::lquery;
+ERROR: label string is too long
+DETAIL: Label length is 256, must be at most 255, at character 258.
SELECT nlevel('1.2.3.4');
nlevel
--------
t
(1 row)
+SELECT 'QWER_TY'::ltree ~ 'q%@*%@*';
+ ?column?
+----------
+ t
+(1 row)
+
SELECT 'QWER_TY'::ltree ~ 'Q_t%@*';
?column?
----------
#define LTPRS_WAITNAME 0
#define LTPRS_WAITDELIM 1
+static void finish_nodeitem(nodeitem *lptr, const char *ptr,
+ bool is_lquery, int pos);
+
+
/*
* expects a null terminated string
* returns an ltree
while (*ptr)
{
charlen = pg_mblen(ptr);
- if (charlen == 1 && t_iseq(ptr, '.'))
+ if (t_iseq(ptr, '.'))
num++;
ptr += charlen;
}
{
charlen = pg_mblen(ptr);
- if (state == LTPRS_WAITNAME)
+ switch (state)
{
- if (ISALNUM(ptr))
- {
- lptr->start = ptr;
- lptr->wlen = 0;
- state = LTPRS_WAITDELIM;
- }
- else
- UNCHAR;
- }
- else if (state == LTPRS_WAITDELIM)
- {
- if (charlen == 1 && t_iseq(ptr, '.'))
- {
- lptr->len = ptr - lptr->start;
- if (lptr->wlen > LTREE_LABEL_MAX_CHARS)
- ereport(ERROR,
- (errcode(ERRCODE_NAME_TOO_LONG),
- errmsg("label string is too long"),
- errdetail("Label length is %d, must be at most %d, at character %d.",
- lptr->wlen, LTREE_LABEL_MAX_CHARS,
- pos)));
-
- totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
- lptr++;
- state = LTPRS_WAITNAME;
- }
- else if (!ISALNUM(ptr))
- UNCHAR;
+ case LTPRS_WAITNAME:
+ if (ISALNUM(ptr))
+ {
+ lptr->start = ptr;
+ lptr->wlen = 0;
+ state = LTPRS_WAITDELIM;
+ }
+ else
+ UNCHAR;
+ break;
+ case LTPRS_WAITDELIM:
+ if (t_iseq(ptr, '.'))
+ {
+ finish_nodeitem(lptr, ptr, false, pos);
+ totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
+ lptr++;
+ state = LTPRS_WAITNAME;
+ }
+ else if (!ISALNUM(ptr))
+ UNCHAR;
+ break;
+ default:
+ elog(ERROR, "internal error in ltree parser");
}
- else
- /* internal error */
- elog(ERROR, "internal error in parser");
ptr += charlen;
lptr->wlen++;
if (state == LTPRS_WAITDELIM)
{
- lptr->len = ptr - lptr->start;
- if (lptr->wlen > LTREE_LABEL_MAX_CHARS)
- ereport(ERROR,
- (errcode(ERRCODE_NAME_TOO_LONG),
- errmsg("label string is too long"),
- errdetail("Label length is %d, must be at most %d, at character %d.",
- lptr->wlen, LTREE_LABEL_MAX_CHARS, pos)));
-
+ finish_nodeitem(lptr, ptr, false, pos);
totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
lptr++;
}
{
charlen = pg_mblen(ptr);
- if (charlen == 1)
- {
- if (t_iseq(ptr, '.'))
- num++;
- else if (t_iseq(ptr, '|'))
- numOR++;
- }
+ if (t_iseq(ptr, '.'))
+ num++;
+ else if (t_iseq(ptr, '|'))
+ numOR++;
ptr += charlen;
}
{
charlen = pg_mblen(ptr);
- if (state == LQPRS_WAITLEVEL)
- {
- if (ISALNUM(ptr))
- {
- GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
- lptr->start = ptr;
- state = LQPRS_WAITDELIM;
- curqlevel->numvar = 1;
- }
- else if (charlen == 1 && t_iseq(ptr, '!'))
- {
- GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
- lptr->start = ptr + 1;
- state = LQPRS_WAITDELIM;
- curqlevel->numvar = 1;
- curqlevel->flag |= LQL_NOT;
- hasnot = true;
- }
- else if (charlen == 1 && t_iseq(ptr, '*'))
- state = LQPRS_WAITOPEN;
- else
- UNCHAR;
- }
- else if (state == LQPRS_WAITVAR)
- {
- if (ISALNUM(ptr))
- {
- lptr++;
- lptr->start = ptr;
- state = LQPRS_WAITDELIM;
- curqlevel->numvar++;
- }
- else
- UNCHAR;
- }
- else if (state == LQPRS_WAITDELIM)
+ switch (state)
{
- if (charlen == 1 && t_iseq(ptr, '@'))
- {
- if (lptr->start == ptr)
+ case LQPRS_WAITLEVEL:
+ if (ISALNUM(ptr))
+ {
+ GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
+ lptr->start = ptr;
+ state = LQPRS_WAITDELIM;
+ curqlevel->numvar = 1;
+ }
+ else if (t_iseq(ptr, '!'))
+ {
+ GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
+ lptr->start = ptr + 1;
+ lptr->wlen = -1; /* compensate for counting ! below */
+ state = LQPRS_WAITDELIM;
+ curqlevel->numvar = 1;
+ curqlevel->flag |= LQL_NOT;
+ hasnot = true;
+ }
+ else if (t_iseq(ptr, '*'))
+ state = LQPRS_WAITOPEN;
+ else
UNCHAR;
- lptr->flag |= LVAR_INCASE;
- curqlevel->flag |= LVAR_INCASE;
- }
- else if (charlen == 1 && t_iseq(ptr, '*'))
- {
- if (lptr->start == ptr)
+ break;
+ case LQPRS_WAITVAR:
+ if (ISALNUM(ptr))
+ {
+ lptr++;
+ lptr->start = ptr;
+ state = LQPRS_WAITDELIM;
+ curqlevel->numvar++;
+ }
+ else
UNCHAR;
- lptr->flag |= LVAR_ANYEND;
- curqlevel->flag |= LVAR_ANYEND;
- }
- else if (charlen == 1 && t_iseq(ptr, '%'))
- {
- if (lptr->start == ptr)
+ break;
+ case LQPRS_WAITDELIM:
+ if (t_iseq(ptr, '@'))
+ {
+ lptr->flag |= LVAR_INCASE;
+ curqlevel->flag |= LVAR_INCASE;
+ }
+ else if (t_iseq(ptr, '*'))
+ {
+ lptr->flag |= LVAR_ANYEND;
+ curqlevel->flag |= LVAR_ANYEND;
+ }
+ else if (t_iseq(ptr, '%'))
+ {
+ lptr->flag |= LVAR_SUBLEXEME;
+ curqlevel->flag |= LVAR_SUBLEXEME;
+ }
+ else if (t_iseq(ptr, '|'))
+ {
+ finish_nodeitem(lptr, ptr, true, pos);
+ state = LQPRS_WAITVAR;
+ }
+ else if (t_iseq(ptr, '{'))
+ {
+ finish_nodeitem(lptr, ptr, true, pos);
+ curqlevel->flag |= LQL_COUNT;
+ state = LQPRS_WAITFNUM;
+ }
+ else if (t_iseq(ptr, '.'))
+ {
+ finish_nodeitem(lptr, ptr, true, pos);
+ state = LQPRS_WAITLEVEL;
+ curqlevel = NEXTLEV(curqlevel);
+ }
+ else if (ISALNUM(ptr))
+ {
+ /* disallow more chars after a flag */
+ if (lptr->flag)
+ UNCHAR;
+ }
+ else
UNCHAR;
- lptr->flag |= LVAR_SUBLEXEME;
- curqlevel->flag |= LVAR_SUBLEXEME;
- }
- else if (charlen == 1 && t_iseq(ptr, '|'))
- {
- lptr->len = ptr - lptr->start -
- ((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) -
- ((lptr->flag & LVAR_INCASE) ? 1 : 0) -
- ((lptr->flag & LVAR_ANYEND) ? 1 : 0);
- if (lptr->wlen > LTREE_LABEL_MAX_CHARS)
- ereport(ERROR,
- (errcode(ERRCODE_NAME_TOO_LONG),
- errmsg("label string is too long"),
- errdetail("Label length is %d, must be at most %d, at character %d.",
- lptr->wlen, LTREE_LABEL_MAX_CHARS,
- pos)));
-
- state = LQPRS_WAITVAR;
- }
- else if (charlen == 1 && t_iseq(ptr, '{'))
- {
- lptr->len = ptr - lptr->start -
- ((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) -
- ((lptr->flag & LVAR_INCASE) ? 1 : 0) -
- ((lptr->flag & LVAR_ANYEND) ? 1 : 0);
- if (lptr->wlen > LTREE_LABEL_MAX_CHARS)
- ereport(ERROR,
- (errcode(ERRCODE_NAME_TOO_LONG),
- errmsg("label string is too long"),
- errdetail("Label length is %d, must be at most %d, at character %d.",
- lptr->wlen, LTREE_LABEL_MAX_CHARS,
- pos)));
-
- curqlevel->flag |= LQL_COUNT;
- state = LQPRS_WAITFNUM;
- }
- else if (charlen == 1 && t_iseq(ptr, '.'))
- {
- lptr->len = ptr - lptr->start -
- ((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) -
- ((lptr->flag & LVAR_INCASE) ? 1 : 0) -
- ((lptr->flag & LVAR_ANYEND) ? 1 : 0);
- if (lptr->wlen > LTREE_LABEL_MAX_CHARS)
- ereport(ERROR,
- (errcode(ERRCODE_NAME_TOO_LONG),
- errmsg("label string is too long"),
- errdetail("Label length is %d, must be at most %d, at character %d.",
- lptr->wlen, LTREE_LABEL_MAX_CHARS,
- pos)));
-
- state = LQPRS_WAITLEVEL;
- curqlevel = NEXTLEV(curqlevel);
- }
- else if (ISALNUM(ptr))
- {
- if (lptr->flag)
+ break;
+ case LQPRS_WAITOPEN:
+ if (t_iseq(ptr, '{'))
+ state = LQPRS_WAITFNUM;
+ else if (t_iseq(ptr, '.'))
+ {
+ /* We only get here for '*', so these are correct defaults */
+ curqlevel->low = 0;
+ curqlevel->high = LTREE_MAX_LEVELS;
+ curqlevel = NEXTLEV(curqlevel);
+ state = LQPRS_WAITLEVEL;
+ }
+ else
UNCHAR;
- }
- else
- UNCHAR;
- }
- else if (state == LQPRS_WAITOPEN)
- {
- if (charlen == 1 && t_iseq(ptr, '{'))
- state = LQPRS_WAITFNUM;
- else if (charlen == 1 && t_iseq(ptr, '.'))
- {
- /* We only get here for '*', so these are correct defaults */
- curqlevel->low = 0;
- curqlevel->high = LTREE_MAX_LEVELS;
- curqlevel = NEXTLEV(curqlevel);
- state = LQPRS_WAITLEVEL;
- }
- else
- UNCHAR;
- }
- else if (state == LQPRS_WAITFNUM)
- {
- if (charlen == 1 && t_iseq(ptr, ','))
- state = LQPRS_WAITSNUM;
- else if (t_isdigit(ptr))
- {
- int low = atoi(ptr);
+ break;
+ case LQPRS_WAITFNUM:
+ if (t_iseq(ptr, ','))
+ state = LQPRS_WAITSNUM;
+ else if (t_isdigit(ptr))
+ {
+ int low = atoi(ptr);
- if (low < 0 || low > LTREE_MAX_LEVELS)
- ereport(ERROR,
- (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
- errmsg("lquery syntax error"),
- errdetail("Low limit (%d) exceeds the maximum allowed (%d), at character %d.",
- low, LTREE_MAX_LEVELS, pos)));
+ if (low < 0 || low > LTREE_MAX_LEVELS)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("lquery syntax error"),
+ errdetail("Low limit (%d) exceeds the maximum allowed (%d), at character %d.",
+ low, LTREE_MAX_LEVELS, pos)));
- curqlevel->low = (uint16) low;
- state = LQPRS_WAITND;
- }
- else
- UNCHAR;
- }
- else if (state == LQPRS_WAITSNUM)
- {
- if (t_isdigit(ptr))
- {
- int high = atoi(ptr);
-
- if (high < 0 || high > LTREE_MAX_LEVELS)
- ereport(ERROR,
- (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
- errmsg("lquery syntax error"),
- errdetail("High limit (%d) exceeds the maximum allowed (%d), at character %d.",
- high, LTREE_MAX_LEVELS, pos)));
- else if (curqlevel->low > high)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("lquery syntax error"),
- errdetail("Low limit (%d) is greater than high limit (%d), at character %d.",
- curqlevel->low, high, pos)));
-
- curqlevel->high = (uint16) high;
- state = LQPRS_WAITCLOSE;
- }
- else if (charlen == 1 && t_iseq(ptr, '}'))
- {
- curqlevel->high = LTREE_MAX_LEVELS;
- state = LQPRS_WAITEND;
- }
- else
- UNCHAR;
- }
- else if (state == LQPRS_WAITCLOSE)
- {
- if (charlen == 1 && t_iseq(ptr, '}'))
- state = LQPRS_WAITEND;
- else if (!t_isdigit(ptr))
- UNCHAR;
- }
- else if (state == LQPRS_WAITND)
- {
- if (charlen == 1 && t_iseq(ptr, '}'))
- {
- curqlevel->high = curqlevel->low;
- state = LQPRS_WAITEND;
- }
- else if (charlen == 1 && t_iseq(ptr, ','))
- state = LQPRS_WAITSNUM;
- else if (!t_isdigit(ptr))
- UNCHAR;
- }
- else if (state == LQPRS_WAITEND)
- {
- if (charlen == 1 && t_iseq(ptr, '.'))
- {
- state = LQPRS_WAITLEVEL;
- curqlevel = NEXTLEV(curqlevel);
- }
- else
- UNCHAR;
+ curqlevel->low = (uint16) low;
+ state = LQPRS_WAITND;
+ }
+ else
+ UNCHAR;
+ break;
+ case LQPRS_WAITSNUM:
+ if (t_isdigit(ptr))
+ {
+ int high = atoi(ptr);
+
+ if (high < 0 || high > LTREE_MAX_LEVELS)
+ ereport(ERROR,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("lquery syntax error"),
+ errdetail("High limit (%d) exceeds the maximum allowed (%d), at character %d.",
+ high, LTREE_MAX_LEVELS, pos)));
+ else if (curqlevel->low > high)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("lquery syntax error"),
+ errdetail("Low limit (%d) is greater than high limit (%d), at character %d.",
+ curqlevel->low, high, pos)));
+
+ curqlevel->high = (uint16) high;
+ state = LQPRS_WAITCLOSE;
+ }
+ else if (t_iseq(ptr, '}'))
+ {
+ curqlevel->high = LTREE_MAX_LEVELS;
+ state = LQPRS_WAITEND;
+ }
+ else
+ UNCHAR;
+ break;
+ case LQPRS_WAITCLOSE:
+ if (t_iseq(ptr, '}'))
+ state = LQPRS_WAITEND;
+ else if (!t_isdigit(ptr))
+ UNCHAR;
+ break;
+ case LQPRS_WAITND:
+ if (t_iseq(ptr, '}'))
+ {
+ curqlevel->high = curqlevel->low;
+ state = LQPRS_WAITEND;
+ }
+ else if (t_iseq(ptr, ','))
+ state = LQPRS_WAITSNUM;
+ else if (!t_isdigit(ptr))
+ UNCHAR;
+ break;
+ case LQPRS_WAITEND:
+ if (t_iseq(ptr, '.'))
+ {
+ state = LQPRS_WAITLEVEL;
+ curqlevel = NEXTLEV(curqlevel);
+ }
+ else
+ UNCHAR;
+ break;
+ default:
+ elog(ERROR, "internal error in lquery parser");
}
- else
- /* internal error */
- elog(ERROR, "internal error in parser");
ptr += charlen;
if (state == LQPRS_WAITDELIM)
}
if (state == LQPRS_WAITDELIM)
- {
- if (lptr->start == ptr)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("lquery syntax error"),
- errdetail("Unexpected end of input.")));
-
- lptr->len = ptr - lptr->start -
- ((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) -
- ((lptr->flag & LVAR_INCASE) ? 1 : 0) -
- ((lptr->flag & LVAR_ANYEND) ? 1 : 0);
- if (lptr->len == 0)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("lquery syntax error"),
- errdetail("Unexpected end of input.")));
-
- if (lptr->wlen > LTREE_LABEL_MAX_CHARS)
- ereport(ERROR,
- (errcode(ERRCODE_NAME_TOO_LONG),
- errmsg("label string is too long"),
- errdetail("Label length is %d, must be at most %d, at character %d.",
- lptr->wlen, LTREE_LABEL_MAX_CHARS, pos)));
- }
+ finish_nodeitem(lptr, ptr, true, pos);
else if (state == LQPRS_WAITOPEN)
curqlevel->high = LTREE_MAX_LEVELS;
else if (state != LQPRS_WAITEND)
#undef UNCHAR
}
+/*
+ * Close out parsing an ltree or lquery nodeitem:
+ * compute the correct length, and complain if it's not OK
+ */
+static void
+finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos)
+{
+ if (is_lquery)
+ {
+ /*
+ * Back up over any flag characters, and discount them from length and
+ * position.
+ */
+ while (ptr > lptr->start && strchr("@*%", ptr[-1]) != NULL)
+ {
+ ptr--;
+ lptr->wlen--;
+ pos--;
+ }
+ }
+
+ /* Now compute the byte length, which we weren't tracking before. */
+ lptr->len = ptr - lptr->start;
+
+ /* Complain if it's empty or too long */
+ if (lptr->len == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ is_lquery ?
+ errmsg("lquery syntax error at character %d", pos) :
+ errmsg("ltree syntax error at character %d", pos),
+ errdetail("Empty labels are not allowed.")));
+ if (lptr->wlen > LTREE_LABEL_MAX_CHARS)
+ ereport(ERROR,
+ (errcode(ERRCODE_NAME_TOO_LONG),
+ errmsg("label string is too long"),
+ errdetail("Label length is %d, must be at most %d, at character %d.",
+ lptr->wlen, LTREE_LABEL_MAX_CHARS, pos)));
+}
+
/*
* expects an lquery
* returns a null terminated string