From c660297094c2b06f08f27e5de6a69207ea5366a6 Mon Sep 17 00:00:00 2001 From: Zsolt Parragi Date: Tue, 11 Aug 2026 22:09:46 +0000 Subject: [PATCH 1/2] Allow maximum-length lexemes in array_to_tsvector again Commit 23d9ad77181 added a length check to array_to_tsvector() that rejects lexemes of MAXSTRLEN (2047) bytes, one byte short of what the tsvector format can represent: MAXSTRLEN is the maximum value of WordEntry.len, and tsvectorrecv() accepts lexemes of exactly that length. As a result, converting such a tsvector to an array and back with tsvector_to_array()/array_to_tsvector() started to fail. Relax the check to reject only lexemes longer than MAXSTRLEN, and report the correct maximum in the error message. --- src/backend/utils/adt/tsvector_op.c | 4 ++-- src/test/regress/expected/tstypes.out | 9 +++++++++ src/test/regress/sql/tstypes.sql | 3 +++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c index 782b91f701e..d5336774b22 100644 --- a/src/backend/utils/adt/tsvector_op.c +++ b/src/backend/utils/adt/tsvector_op.c @@ -776,12 +776,12 @@ array_to_tsvector(PG_FUNCTION_ARGS) ereport(ERROR, (errcode(ERRCODE_ZERO_LENGTH_CHARACTER_STRING), errmsg("lexeme array may not contain empty strings"))); - if (toklen >= MAXSTRLEN) + if (toklen > MAXSTRLEN) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("word is too long (%d bytes, max %d bytes)", toklen, - MAXSTRLEN - 1))); + MAXSTRLEN))); } /* Sort and de-dup, because this is required for a valid tsvector. */ diff --git a/src/test/regress/expected/tstypes.out b/src/test/regress/expected/tstypes.out index 4cfc3b9dc04..33d30cd6a09 100644 --- a/src/test/regress/expected/tstypes.out +++ b/src/test/regress/expected/tstypes.out @@ -1385,6 +1385,15 @@ SELECT array_to_tsvector(ARRAY['base','hidden','rebel','spaceship', NULL]); ERROR: lexeme array may not contain nulls SELECT array_to_tsvector(ARRAY['base','hidden','rebel','spaceship', '']); ERROR: lexeme array may not contain empty strings +-- lexeme of exactly the maximum length is accepted, one byte more is not +SELECT tsvector_to_array(array_to_tsvector(ARRAY[repeat('x', 2047)])) = ARRAY[repeat('x', 2047)]; + ?column? +---------- + t +(1 row) + +SELECT array_to_tsvector(ARRAY[repeat('x', 2048)]); +ERROR: word is too long (2048 bytes, max 2047 bytes) -- array_to_tsvector must sort and de-dup SELECT array_to_tsvector(ARRAY['foo','bar','baz','bar']); array_to_tsvector diff --git a/src/test/regress/sql/tstypes.sql b/src/test/regress/sql/tstypes.sql index dfb7a1466e0..0361e359044 100644 --- a/src/test/regress/sql/tstypes.sql +++ b/src/test/regress/sql/tstypes.sql @@ -266,6 +266,9 @@ SELECT array_to_tsvector(ARRAY['base','hidden','rebel','spaceship','strike']); -- null and empty string are disallowed, since we mustn't make an empty lexeme SELECT array_to_tsvector(ARRAY['base','hidden','rebel','spaceship', NULL]); SELECT array_to_tsvector(ARRAY['base','hidden','rebel','spaceship', '']); +-- lexeme of exactly the maximum length is accepted, one byte more is not +SELECT tsvector_to_array(array_to_tsvector(ARRAY[repeat('x', 2047)])) = ARRAY[repeat('x', 2047)]; +SELECT array_to_tsvector(ARRAY[repeat('x', 2048)]); -- array_to_tsvector must sort and de-dup SELECT array_to_tsvector(ARRAY['foo','bar','baz','bar']); -- 2.54.0