From f4bf98b23b7915bfdce7b47460e0451630fd01a6 Mon Sep 17 00:00:00 2001 From: Artur Zakirov Date: Wed, 13 Jan 2021 15:10:56 +0100 Subject: [PATCH 1/5] Added tests for Pull Request #15 --- expected/wltree.out | 26 ++++++++++++++++++++++++++ sql/wltree.sql | 5 +++++ 2 files changed, 31 insertions(+) diff --git a/expected/wltree.out b/expected/wltree.out index dca23e7..aa596b5 100644 --- a/expected/wltree.out +++ b/expected/wltree.out @@ -53,6 +53,16 @@ SELECT 'foö::bär::ba@ : 4*'::ltree; foö::bär::ba@ : 4* (1 row) +SELECT '::1'::ltree; +ERROR: syntax error +LINE 1: SELECT '::1'::ltree; + ^ +DETAIL: Unexpected delimeter in position 1 +SELECT '::'::ltree; +ERROR: syntax error +LINE 1: SELECT '::'::ltree; + ^ +DETAIL: Unexpected delimeter in position 1 SELECT ltree2text('1::2::3::34::sdf'); ltree2text ------------------ @@ -497,6 +507,22 @@ SELECT 'foö::bär::ba\@ \: 4\*'::lquery; foö::bär::ba@ : 4* (1 row) +SELECT '::1'::lquery; +ERROR: syntax error +LINE 1: SELECT '::1'::lquery; + ^ +DETAIL: Unexpected delimeter in position 1 +SELECT '::'::lquery; +ERROR: syntax error +LINE 1: SELECT '::'::lquery; + ^ +DETAIL: Unexpected delimeter in position 1 +SELECT '1:2'::lquery; + lquery +-------- + 1:2 +(1 row) + SELECT nlevel('1::2::3::4'); nlevel -------- diff --git a/sql/wltree.sql b/sql/wltree.sql index a6ff5be..eee7369 100644 --- a/sql/wltree.sql +++ b/sql/wltree.sql @@ -9,6 +9,8 @@ SELECT '1::2'::ltree; SELECT '1::2::_3'::ltree; SELECT '1::2::3 : 4'::ltree; SELECT 'foö::bär::ba@ : 4*'::ltree; +SELECT '::1'::ltree; +SELECT '::'::ltree; SELECT ltree2text('1::2::3::34::sdf'); SELECT text2ltree('1::2::3::34::sdf'); @@ -92,6 +94,9 @@ SELECT '\*1::\|'::lquery; SELECT '\!1::\|'::lquery; SELECT '\*1::\{4'::lquery; SELECT 'foö::bär::ba\@ \: 4\*'::lquery; +SELECT '::1'::lquery; +SELECT '::'::lquery; +SELECT '1:2'::lquery; SELECT nlevel('1::2::3::4'); SELECT '1::2'::ltree < '2::2'::ltree; From 9edfad00ac25ef6e619e7f1d3cd92425c787dfb2 Mon Sep 17 00:00:00 2001 From: Artur Zakirov Date: Wed, 13 Jan 2021 17:49:58 +0100 Subject: [PATCH 2/5] wltree's delimiter consists of two characters. Its source code heavily relies on this fact, for this we need to check both characters in advance. Related with Pull Request #15 Issue #20 --- expected/wltree.out | 24 ++++-- ltree_io.c | 181 +++++++++++++++++++++++--------------------- sql/wltree.sql | 10 ++- 3 files changed, 115 insertions(+), 100 deletions(-) diff --git a/expected/wltree.out b/expected/wltree.out index aa596b5..b229bf8 100644 --- a/expected/wltree.out +++ b/expected/wltree.out @@ -53,16 +53,16 @@ SELECT 'foö::bär::ba@ : 4*'::ltree; foö::bär::ba@ : 4* (1 row) -SELECT '::1'::ltree; +SELECT '::1'::ltree; -- fails ERROR: syntax error LINE 1: SELECT '::1'::ltree; ^ -DETAIL: Unexpected delimeter in position 1 -SELECT '::'::ltree; +DETAIL: Unexpected delimeter in position 0 +SELECT '::'::ltree; -- fails ERROR: syntax error LINE 1: SELECT '::'::ltree; ^ -DETAIL: Unexpected delimeter in position 1 +DETAIL: Unexpected delimeter in position 0 SELECT ltree2text('1::2::3::34::sdf'); ltree2text ------------------ @@ -507,22 +507,30 @@ SELECT 'foö::bär::ba\@ \: 4\*'::lquery; foö::bär::ba@ : 4* (1 row) -SELECT '::1'::lquery; +SELECT '::1'::lquery; -- fails ERROR: syntax error LINE 1: SELECT '::1'::lquery; ^ -DETAIL: Unexpected delimeter in position 1 -SELECT '::'::lquery; +DETAIL: Unexpected delimeter in position 0 +SELECT '::'::lquery; -- fails ERROR: syntax error LINE 1: SELECT '::'::lquery; ^ -DETAIL: Unexpected delimeter in position 1 +DETAIL: Unexpected delimeter in position 0 SELECT '1:2'::lquery; lquery -------- 1:2 (1 row) +SELECT '*:1'::lquery; -- fails +ERROR: syntax error at position 1: ':' +LINE 1: SELECT '*:1'::lquery; + ^ +SELECT '*.1'::lquery; -- fails +ERROR: syntax error at position 1: '.' +LINE 1: SELECT '*.1'::lquery; + ^ SELECT nlevel('1::2::3::4'); nlevel -------- diff --git a/ltree_io.c b/ltree_io.c index 1194e60..b518e1b 100644 --- a/ltree_io.c +++ b/ltree_io.c @@ -40,7 +40,26 @@ typedef struct #define LTPRS_WAITNAME 0 #define LTPRS_WAITDELIM 1 -#define LTPRS_WAITDELIMEND 2 + +/* + * Check if the current character is delimiter. wltree's delimiter has multiple + * characters, we need to check all of them in advance. + * + * Returns true if sequential characters are equal to wltree's delimiter. + */ +static bool +is_delimiter(char *start_ptr, int charlen) +{ + if (charlen == 1 && t_iseq(start_ptr, NODE_DELIMITER_CHAR)) + { + char *ptr = start_ptr + charlen; + + if (pg_mblen(ptr) == 1 && t_iseq(ptr, NODE_DELIMITER_CHAR)) + return true; + } + + return false; +} Datum ltree_in(PG_FUNCTION_ARGS) @@ -56,28 +75,17 @@ ltree_in(PG_FUNCTION_ARGS) ltree_level *curlevel; int charlen; int pos = 0; + bool delimiter = false; ptr = buf; while (*ptr) { charlen = pg_mblen(ptr); - if (charlen == 1) + if (is_delimiter(ptr, charlen)) { - if (t_iseq(ptr, NODE_DELIMITER_CHAR)) - { - if (state == LTPRS_WAITDELIMEND) - { - num++; - state = LTPRS_WAITDELIM; - } - else - state = LTPRS_WAITDELIMEND; - } - else - { - state = LTPRS_WAITDELIM; - } + ptr += charlen; + num++; } ptr += charlen; @@ -90,6 +98,7 @@ ltree_in(PG_FUNCTION_ARGS) while (*ptr) { charlen = pg_mblen(ptr); + delimiter = false; if (state == LTPRS_WAITNAME) { @@ -97,15 +106,21 @@ ltree_in(PG_FUNCTION_ARGS) lptr->wlen = 0; /* handle corner case when label starts with a delimiter character */ - state = (charlen == 1 && t_iseq(ptr, NODE_DELIMITER_CHAR)) ? - LTPRS_WAITDELIMEND : LTPRS_WAITDELIM; + if (is_delimiter(ptr, charlen)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"), + errdetail("Unexpected delimeter in position %d", + pos))); + state = LTPRS_WAITDELIM; } - else if (state == LTPRS_WAITDELIMEND) + else if (state == LTPRS_WAITDELIM) { - if (charlen == 1 && t_iseq(ptr, NODE_DELIMITER_CHAR)) + if (is_delimiter(ptr, charlen)) { - lptr->len = ptr - lptr->start - 1; - lptr->wlen--; + delimiter = true; + + lptr->len = ptr - lptr->start; if (lptr->wlen > 255) ereport(ERROR, (errcode(ERRCODE_NAME_TOO_LONG), @@ -113,12 +128,6 @@ ltree_in(PG_FUNCTION_ARGS) errdetail("Name length is %d, must " "be < 256, in position %d.", lptr->wlen, pos))); - if (lptr->wlen == 0) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("syntax error"), - errdetail("Unexpected delimeter in position %d", - pos))); totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE); lptr++; @@ -127,21 +136,28 @@ ltree_in(PG_FUNCTION_ARGS) else state = LTPRS_WAITDELIM; } - else if (state == LTPRS_WAITDELIM) - { - if (charlen == 1 && t_iseq(ptr, NODE_DELIMITER_CHAR)) - state = LTPRS_WAITDELIMEND; - } else /* internal error */ elog(ERROR, "internal error in parser"); - ptr += charlen; - lptr->wlen++; - pos++; + /* + * wltree's delimiter is two characters, we need additional + * increment here. + */ + if (delimiter) + { + ptr += charlen * 2; + pos += 2; + } + else + { + ptr += charlen; + pos++; + lptr->wlen++; + } } - if (state == LTPRS_WAITDELIM || state == LTPRS_WAITDELIMEND) + if (state == LTPRS_WAITDELIM) { lptr->len = ptr - lptr->start; if (lptr->wlen > 255) @@ -218,7 +234,6 @@ ltree_out(PG_FUNCTION_ARGS) #define LQPRS_WAITCLOSE 6 #define LQPRS_WAITEND 7 #define LQPRS_WAITVAR 8 -#define LQPRS_WAITDELIMEND 9 #define GETVAR(x) ( *((nodeitem**)LQL_FIRST(x)) ) @@ -243,6 +258,7 @@ lquery_in(PG_FUNCTION_ARGS) bool hasnot = false; bool wasbad = false; bool escaped_char = false; + bool delimiter = false; int charlen; int pos = 0; @@ -253,31 +269,18 @@ lquery_in(PG_FUNCTION_ARGS) if (charlen == 1) { - if (! escaped_char && t_iseq(ptr, NODE_DELIMITER_CHAR)) - if (state == LQPRS_WAITDELIMEND) - { - num++; - state = LQPRS_WAITDELIM; - } - else - state = LQPRS_WAITDELIMEND; + if (!escaped_char && is_delimiter(ptr, charlen)) + num++; else if (! escaped_char && t_iseq(ptr, '|')) { escaped_char = false; - state = LQPRS_WAITDELIM; numOR++; } else - { escaped_char = t_iseq(ptr, ESCAPE_CHAR) && ! escaped_char; - state = LQPRS_WAITDELIM; - } } else - { escaped_char = false; - state = LQPRS_WAITDELIM; - } ptr += charlen; } @@ -291,6 +294,7 @@ lquery_in(PG_FUNCTION_ARGS) while (*ptr) { charlen = pg_mblen(ptr); + delimiter = false; if (state == LQPRS_WAITLEVEL) { if (! escaped_char && charlen == 1 && t_iseq(ptr, '!')) @@ -312,8 +316,13 @@ lquery_in(PG_FUNCTION_ARGS) lptr->escnum = 0; /* handle corner case when label starts with a delimiter character */ - state = (! escaped_char && charlen == 1 && t_iseq(ptr, NODE_DELIMITER_CHAR)) ? - LQPRS_WAITDELIMEND : LQPRS_WAITDELIM; + if (!escaped_char && is_delimiter(ptr, charlen)) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error"), + errdetail("Unexpected delimeter in position %d", + pos))); + state = LQPRS_WAITDELIM; curqlevel->numvar = 1; escaped_char = (charlen == 1 && t_iseq(ptr, ESCAPE_CHAR)) && ! escaped_char; @@ -365,29 +374,16 @@ lquery_in(PG_FUNCTION_ARGS) state = LQPRS_WAITVAR; } - else if (! escaped_char && charlen == 1 && t_iseq(ptr, NODE_DELIMITER_CHAR)) + else if (!escaped_char && is_delimiter(ptr, charlen)) { if (lptr->start == ptr) UNCHAR; - state = LQPRS_WAITDELIMEND; - } - else - { - escaped_char = (charlen == 1 && t_iseq(ptr, ESCAPE_CHAR)) && ! escaped_char; - if (lptr->flag) - UNCHAR; - } - } - else if (state == LQPRS_WAITDELIMEND) - { - if (charlen == 1 && t_iseq(ptr, NODE_DELIMITER_CHAR)) - { if (lptr != NULL) { lptr->len = ptr - lptr->start - ((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) - ((lptr->flag & LVAR_INCASE) ? 1 : 0) - - ((lptr->flag & LVAR_ANYEND) ? 1 : 0) - 1; + ((lptr->flag & LVAR_ANYEND) ? 1 : 0); if (lptr->wlen > 255) ereport(ERROR, (errcode(ERRCODE_NAME_TOO_LONG), @@ -395,31 +391,31 @@ lquery_in(PG_FUNCTION_ARGS) errdetail("Name length is %d, must " "be < 256, in position %d.", lptr->wlen, pos))); - if (lptr->wlen == 0) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("syntax error"), - errdetail("Unexpected delimeter in position %d", - pos))); } + delimiter = true; escaped_char = false; state = LQPRS_WAITLEVEL; curqlevel = NEXTLEV(curqlevel); } else - state = LTPRS_WAITDELIM; + { + escaped_char = (charlen == 1 && t_iseq(ptr, ESCAPE_CHAR)) && ! escaped_char; + if (lptr->flag) + UNCHAR; + } } else if (state == LQPRS_WAITOPEN) { if (charlen == 1 && t_iseq(ptr, '{')) state = LQPRS_WAITFNUM; - else if (charlen == 1 && t_iseq(ptr, NODE_DELIMITER_CHAR)) + else if (is_delimiter(ptr, charlen)) { - lptr = NULL; + delimiter = true; curqlevel->low = 0; curqlevel->high = 0xffff; - state = LQPRS_WAITDELIMEND; + state = LQPRS_WAITLEVEL; + curqlevel = NEXTLEV(curqlevel); } else UNCHAR; @@ -472,10 +468,11 @@ lquery_in(PG_FUNCTION_ARGS) } else if (state == LQPRS_WAITEND) { - if (charlen == 1 && t_iseq(ptr, NODE_DELIMITER_CHAR)) + if (is_delimiter(ptr, charlen)) { - lptr = NULL; - state = LQPRS_WAITDELIMEND; + delimiter = true; + state = LQPRS_WAITLEVEL; + curqlevel = NEXTLEV(curqlevel); } else UNCHAR; @@ -484,15 +481,23 @@ lquery_in(PG_FUNCTION_ARGS) /* internal error */ elog(ERROR, "internal error in parser"); - ptr += charlen; - if (state == LQPRS_WAITDELIM) - lptr->wlen++; + if (delimiter) + { + ptr += charlen * 2; + pos += 2; + } + else + { + ptr += charlen; + if (state == LQPRS_WAITDELIM) + lptr->wlen++; + pos++; + } if (escaped_char) lptr->escnum++; - pos++; } - if (state == LQPRS_WAITDELIM || state == LQPRS_WAITDELIMEND) + if (state == LQPRS_WAITDELIM) { if (lptr->start == ptr) ereport(ERROR, diff --git a/sql/wltree.sql b/sql/wltree.sql index eee7369..ae88bbf 100644 --- a/sql/wltree.sql +++ b/sql/wltree.sql @@ -9,8 +9,8 @@ SELECT '1::2'::ltree; SELECT '1::2::_3'::ltree; SELECT '1::2::3 : 4'::ltree; SELECT 'foö::bär::ba@ : 4*'::ltree; -SELECT '::1'::ltree; -SELECT '::'::ltree; +SELECT '::1'::ltree; -- fails +SELECT '::'::ltree; -- fails SELECT ltree2text('1::2::3::34::sdf'); SELECT text2ltree('1::2::3::34::sdf'); @@ -94,9 +94,11 @@ SELECT '\*1::\|'::lquery; SELECT '\!1::\|'::lquery; SELECT '\*1::\{4'::lquery; SELECT 'foö::bär::ba\@ \: 4\*'::lquery; -SELECT '::1'::lquery; -SELECT '::'::lquery; +SELECT '::1'::lquery; -- fails +SELECT '::'::lquery; -- fails SELECT '1:2'::lquery; +SELECT '*:1'::lquery; -- fails +SELECT '*.1'::lquery; -- fails SELECT nlevel('1::2::3::4'); SELECT '1::2'::ltree < '2::2'::ltree; From 31c39f54bcfb32fd1b756094e57d84949328ffdd Mon Sep 17 00:00:00 2001 From: Artur Zakirov Date: Tue, 9 Mar 2021 11:54:18 +0100 Subject: [PATCH 3/5] Remove .travis.yml. We alredy have Github Actions. --- .travis.yml | 62 ----------------------------------------------------- 1 file changed, 62 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7616c18..0000000 --- a/.travis.yml +++ /dev/null @@ -1,62 +0,0 @@ -sudo: required -dist: xenial -language: c -matrix: - fast_finish: true - include: - - addons: - postgresql: 9.3 - apt: - packages: - - postgresql-9.3 - - postgresql-client-9.3 - - postgresql-server-dev-9.3 - env: - - POSTGRESQL=9.3 - - PGPORT=5433 - - addons: - postgresql: 9.4 - apt: - packages: - - postgresql-server-dev-9.4 - env: - - POSTGRESQL=9.4 - - addons: - postgresql: 9.5 - apt: - packages: - - postgresql-server-dev-9.5 - env: - - POSTGRESQL=9.5 - - addons: - postgresql: 9.6 - apt: - packages: - - postgresql-server-dev-9.6 - env: - - POSTGRESQL=9.6 - - addons: - postgresql: 10 - apt: - packages: - - postgresql-server-dev-10 - env: - - POSTGRESQL=10 - - addons: - postgresql: 11 - apt: - packages: - - postgresql-11 - - postgresql-client-11 - - postgresql-server-dev-11 - env: - - POSTGRESQL=11 - - PGPORT=5433 -script: - - sudo make install && make installcheck - -after_failure: - - cat regression.diffs - -after_success: - - bash <(curl -s https://codecov.io/bash) From d0464dec0b7e365fbe4424f34c46097881020dc3 Mon Sep 17 00:00:00 2001 From: Artur Zakirov Date: Wed, 10 Mar 2021 16:48:53 +0100 Subject: [PATCH 4/5] Properly calculate number of labels in lquery --- expected/wltree.out | 12 ++++++++++++ ltree_io.c | 15 +++++++++++---- sql/wltree.sql | 2 ++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/expected/wltree.out b/expected/wltree.out index b229bf8..a8fee79 100644 --- a/expected/wltree.out +++ b/expected/wltree.out @@ -507,6 +507,18 @@ SELECT 'foö::bär::ba\@ \: 4\*'::lquery; foö::bär::ba@ : 4* (1 row) +SELECT 'a:::'::lquery; + lquery +-------- + a::: +(1 row) + +SELECT 'a:::b'::lquery; + lquery +-------- + a:::b +(1 row) + SELECT '::1'::lquery; -- fails ERROR: syntax error LINE 1: SELECT '::1'::lquery; diff --git a/ltree_io.c b/ltree_io.c index b518e1b..7841802 100644 --- a/ltree_io.c +++ b/ltree_io.c @@ -84,11 +84,11 @@ ltree_in(PG_FUNCTION_ARGS) if (is_delimiter(ptr, charlen)) { - ptr += charlen; + ptr += charlen * 2; num++; } - - ptr += charlen; + else + ptr += charlen; } num++; @@ -266,11 +266,15 @@ lquery_in(PG_FUNCTION_ARGS) while (*ptr) { charlen = pg_mblen(ptr); + delimiter = false; if (charlen == 1) { if (!escaped_char && is_delimiter(ptr, charlen)) + { + delimiter = true; num++; + } else if (! escaped_char && t_iseq(ptr, '|')) { escaped_char = false; @@ -282,7 +286,10 @@ lquery_in(PG_FUNCTION_ARGS) else escaped_char = false; - ptr += charlen; + if (delimiter) + ptr += charlen * 2; + else + ptr += charlen; } num++; diff --git a/sql/wltree.sql b/sql/wltree.sql index ae88bbf..f9ff359 100644 --- a/sql/wltree.sql +++ b/sql/wltree.sql @@ -94,6 +94,8 @@ SELECT '\*1::\|'::lquery; SELECT '\!1::\|'::lquery; SELECT '\*1::\{4'::lquery; SELECT 'foö::bär::ba\@ \: 4\*'::lquery; +SELECT 'a:::'::lquery; +SELECT 'a:::b'::lquery; SELECT '::1'::lquery; -- fails SELECT '::'::lquery; -- fails SELECT '1:2'::lquery; From 91f3d23eeee1a81ba233ee6fa62850992920f563 Mon Sep 17 00:00:00 2001 From: Artur Zakirov Date: Thu, 11 Mar 2021 18:20:15 +0100 Subject: [PATCH 5/5] Add NODE_DELIMITER_LEN, simplify the code --- ltree.h | 1 + ltree_io.c | 45 +++++++++++++++++++-------------------------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/ltree.h b/ltree.h index 3018854..39abd26 100644 --- a/ltree.h +++ b/ltree.h @@ -7,6 +7,7 @@ #include "tsearch/ts_locale.h" #define NODE_DELIMITER_CHAR ':' +#define NODE_DELIMITER_LEN 2 #define ESCAPE_CHAR '\\' typedef int32 int4; diff --git a/ltree_io.c b/ltree_io.c index 7841802..0049fe0 100644 --- a/ltree_io.c +++ b/ltree_io.c @@ -47,14 +47,14 @@ typedef struct * * Returns true if sequential characters are equal to wltree's delimiter. */ -static bool +static inline bool is_delimiter(char *start_ptr, int charlen) { if (charlen == 1 && t_iseq(start_ptr, NODE_DELIMITER_CHAR)) { char *ptr = start_ptr + charlen; - if (pg_mblen(ptr) == 1 && t_iseq(ptr, NODE_DELIMITER_CHAR)) + if (*ptr && pg_mblen(ptr) == 1 && t_iseq(ptr, NODE_DELIMITER_CHAR)) return true; } @@ -84,7 +84,7 @@ ltree_in(PG_FUNCTION_ARGS) if (is_delimiter(ptr, charlen)) { - ptr += charlen * 2; + ptr += NODE_DELIMITER_LEN; num++; } else @@ -98,7 +98,7 @@ ltree_in(PG_FUNCTION_ARGS) while (*ptr) { charlen = pg_mblen(ptr); - delimiter = false; + delimiter = is_delimiter(ptr, charlen); if (state == LTPRS_WAITNAME) { @@ -106,7 +106,7 @@ ltree_in(PG_FUNCTION_ARGS) lptr->wlen = 0; /* handle corner case when label starts with a delimiter character */ - if (is_delimiter(ptr, charlen)) + if (delimiter) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("syntax error"), @@ -116,10 +116,8 @@ ltree_in(PG_FUNCTION_ARGS) } else if (state == LTPRS_WAITDELIM) { - if (is_delimiter(ptr, charlen)) + if (delimiter) { - delimiter = true; - lptr->len = ptr - lptr->start; if (lptr->wlen > 255) ereport(ERROR, @@ -146,8 +144,8 @@ ltree_in(PG_FUNCTION_ARGS) */ if (delimiter) { - ptr += charlen * 2; - pos += 2; + ptr += NODE_DELIMITER_LEN; + pos += NODE_DELIMITER_LEN; } else { @@ -266,15 +264,12 @@ lquery_in(PG_FUNCTION_ARGS) while (*ptr) { charlen = pg_mblen(ptr); - delimiter = false; + delimiter = is_delimiter(ptr, charlen); if (charlen == 1) { - if (!escaped_char && is_delimiter(ptr, charlen)) - { - delimiter = true; + if (!escaped_char && delimiter) num++; - } else if (! escaped_char && t_iseq(ptr, '|')) { escaped_char = false; @@ -287,7 +282,7 @@ lquery_in(PG_FUNCTION_ARGS) escaped_char = false; if (delimiter) - ptr += charlen * 2; + ptr += NODE_DELIMITER_LEN; else ptr += charlen; } @@ -301,7 +296,8 @@ lquery_in(PG_FUNCTION_ARGS) while (*ptr) { charlen = pg_mblen(ptr); - delimiter = false; + delimiter = is_delimiter(ptr, charlen); + if (state == LQPRS_WAITLEVEL) { if (! escaped_char && charlen == 1 && t_iseq(ptr, '!')) @@ -323,7 +319,7 @@ lquery_in(PG_FUNCTION_ARGS) lptr->escnum = 0; /* handle corner case when label starts with a delimiter character */ - if (!escaped_char && is_delimiter(ptr, charlen)) + if (!escaped_char && delimiter) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("syntax error"), @@ -381,7 +377,7 @@ lquery_in(PG_FUNCTION_ARGS) state = LQPRS_WAITVAR; } - else if (!escaped_char && is_delimiter(ptr, charlen)) + else if (!escaped_char && delimiter) { if (lptr->start == ptr) UNCHAR; @@ -400,7 +396,6 @@ lquery_in(PG_FUNCTION_ARGS) lptr->wlen, pos))); } - delimiter = true; escaped_char = false; state = LQPRS_WAITLEVEL; curqlevel = NEXTLEV(curqlevel); @@ -416,9 +411,8 @@ lquery_in(PG_FUNCTION_ARGS) { if (charlen == 1 && t_iseq(ptr, '{')) state = LQPRS_WAITFNUM; - else if (is_delimiter(ptr, charlen)) + else if (delimiter) { - delimiter = true; curqlevel->low = 0; curqlevel->high = 0xffff; state = LQPRS_WAITLEVEL; @@ -475,9 +469,8 @@ lquery_in(PG_FUNCTION_ARGS) } else if (state == LQPRS_WAITEND) { - if (is_delimiter(ptr, charlen)) + if (delimiter) { - delimiter = true; state = LQPRS_WAITLEVEL; curqlevel = NEXTLEV(curqlevel); } @@ -490,8 +483,8 @@ lquery_in(PG_FUNCTION_ARGS) if (delimiter) { - ptr += charlen * 2; - pos += 2; + ptr += NODE_DELIMITER_LEN; + pos += NODE_DELIMITER_LEN; } else {