diff --git a/contrib/ltree/expected/ltree.out b/contrib/ltree/expected/ltree.out index 27122153c7..984cd030cf 100644 --- a/contrib/ltree/expected/ltree.out +++ b/contrib/ltree/expected/ltree.out @@ -7835,10 +7835,15 @@ SELECT * FROM ltreetest WHERE t ? '{23.*.1,23.*.2}' order by t asc; drop index tstidx; create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=0)); ERROR: value 0 out of bounds for option "siglen" -DETAIL: Valid values are between "1" and "2024". +DETAIL: Valid values are between "4" and "2024". create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2025)); ERROR: value 2025 out of bounds for option "siglen" -DETAIL: Valid values are between "1" and "2024". +DETAIL: Valid values are between "4" and "2024". +create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2028)); +ERROR: value 2028 out of bounds for option "siglen" +DETAIL: Valid values are between "4" and "2024". +create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2019)); +ERROR: siglen value must be a multiple of 4 create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2024)); SELECT count(*) FROM ltreetest WHERE t < '12.3'; count diff --git a/contrib/ltree/ltree_gist.c b/contrib/ltree/ltree_gist.c index 3cba2269d8..21b7d02028 100644 --- a/contrib/ltree/ltree_gist.c +++ b/contrib/ltree/ltree_gist.c @@ -719,6 +719,18 @@ ltree_consistent(PG_FUNCTION_ARGS) PG_RETURN_BOOL(res); } +static void +ltree_gist_relopts_validator(void *parsed_options, relopt_value *vals, + int nvals) +{ + LtreeGistOptions *options = (LtreeGistOptions *) parsed_options; + + if (options->siglen != INTALIGN(options->siglen)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("siglen value must be a multiple of %d", ALIGNOF_INT))); +} + Datum ltree_gist_options(PG_FUNCTION_ARGS) { @@ -727,8 +739,11 @@ ltree_gist_options(PG_FUNCTION_ARGS) init_local_reloptions(relopts, sizeof(LtreeGistOptions)); add_local_int_reloption(relopts, "siglen", "signature length in bytes", - LTREE_SIGLEN_DEFAULT, 1, LTREE_SIGLEN_MAX, + LTREE_SIGLEN_DEFAULT, + INTALIGN(1), + LTREE_SIGLEN_MAX, offsetof(LtreeGistOptions, siglen)); + register_reloptions_validator(relopts, ltree_gist_relopts_validator); PG_RETURN_VOID(); } diff --git a/contrib/ltree/sql/ltree.sql b/contrib/ltree/sql/ltree.sql index 4623b57f7b..402096f6c4 100644 --- a/contrib/ltree/sql/ltree.sql +++ b/contrib/ltree/sql/ltree.sql @@ -331,6 +331,8 @@ SELECT * FROM ltreetest WHERE t ? '{23.*.1,23.*.2}' order by t asc; drop index tstidx; create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=0)); create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2025)); +create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2028)); +create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2019)); create index tstidx on ltreetest using gist (t gist_ltree_ops(siglen=2024)); SELECT count(*) FROM ltreetest WHERE t < '12.3'; diff --git a/doc/src/sgml/ltree.sgml b/doc/src/sgml/ltree.sgml index bb66e33944..00a6ae70da 100644 --- a/doc/src/sgml/ltree.sgml +++ b/doc/src/sgml/ltree.sgml @@ -637,7 +637,8 @@ Europe & Russia*@ & !Transportation path labels as a bitmap signature. Its optional integer parameter siglen determines the signature length in bytes. The default signature length is 8 bytes. - Valid values of signature length are between 1 and 2024 bytes. Longer + The length must be a positive multiple of int alignment + (4 bytes on most machines)) up to 2024. Longer signatures lead to a more precise search (scanning a smaller fraction of the index and fewer heap pages), at the cost of a larger index.