aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2003-02-19 03:50:09 +0000
committerBruce Momjian <bruce@momjian.us>2003-02-19 03:50:09 +0000
commit71e1f531d36b1fb54d0fa2568c26c4f1f44cab3f (patch)
treee32ce7ccd6279c74a073178433fc569c31733669
parenta286f7321083f06e395959dffeb9b87f028defa0 (diff)
downloadpostgresql-71e1f531d36b1fb54d0fa2568c26c4f1f44cab3f.tar.gz
postgresql-71e1f531d36b1fb54d0fa2568c26c4f1f44cab3f.zip
Please apply patches for contrib/ltree.
ltree_73.patch.gz - for 7.3 : Fix ~ operation bug: eg '1.1.1' ~ '*.1' ltree_74.patch.gz - for current CVS Fix ~ operation bug: eg '1.1.1' ~ '*.1' Add ? operation Optimize index storage Last change needs drop/create all ltree indexes, so only for 7.4 Teodor Sigaev
-rw-r--r--contrib/ltree/README.ltree14
-rw-r--r--contrib/ltree/_ltree_gist.c29
-rw-r--r--contrib/ltree/_ltree_op.c38
-rw-r--r--contrib/ltree/expected/ltree.out324
-rw-r--r--contrib/ltree/lquery_op.c69
-rw-r--r--contrib/ltree/ltree.h6
-rw-r--r--contrib/ltree/ltree.sql.in97
-rw-r--r--contrib/ltree/ltree_gist.c30
-rw-r--r--contrib/ltree/sql/ltree.sql30
9 files changed, 509 insertions, 128 deletions
diff --git a/contrib/ltree/README.ltree b/contrib/ltree/README.ltree
index a23f7b09458..e9471b4e355 100644
--- a/contrib/ltree/README.ltree
+++ b/contrib/ltree/README.ltree
@@ -110,6 +110,9 @@ ltree <@ ltree
equal).
ltree ~ lquery, lquery ~ ltree
- return TRUE if node represented by ltree satisfies lquery.
+ltree ? lquery[], lquery ? ltree[]
+ - return TRUE if node represented by ltree satisfies at least one lquery
+ from array.
ltree @ ltxtquery, ltxtquery @ ltree
- return TRUE if node represented by ltree satisfies ltxtquery.
ltree || ltree, ltree || text, text || ltree
@@ -123,6 +126,9 @@ ltree @> ltree[], ltree[] <@ ltree
- returns TRUE if array ltree[] contains a descendant of ltree.
ltree[] ~ lquery, lquery ~ ltree[]
- returns TRUE if array ltree[] contains label paths matched lquery.
+ltree[] ? lquery[], lquery[] ? ltree[]
+ - returns TRUE if array ltree[] contains label paths matched atleaset one
+ lquery from array.
ltree[] @ ltxtquery, ltxtquery @ ltree[]
- returns TRUE if array ltree[] contains label paths matched ltxtquery
(full text search).
@@ -142,11 +148,11 @@ Various indices could be created to speed up execution of operations:
* B-tree index over ltree:
<, <=, =, =>, >
* GiST index over ltree:
- <, <=, =, =>, >, @>, <@, @, ~
+ <, <=, =, =>, >, @>, <@, @, ~, ?
Example:
create index path_gist_idx on test using gist (path);
* GiST index over ltree[]:
- ltree[]<@ ltree, ltree @> ltree[], @, ~.
+ ltree[]<@ ltree, ltree @> ltree[], @, ~, ?.
Example:
create index path_gist_idx on test using gist (array_path);
Notices: This index is lossy.
@@ -426,6 +432,10 @@ appreciate your input. So far, below some (rather obvious) results:
CHANGES
+Feb 7, 2003
+ Add ? operation
+ Fix ~ operation bug: eg '1.1.1' ~ '*.1'
+ Optimize index storage
Aug 9, 2002
Fixed very stupid but important bug :-)
July 31, 2002
diff --git a/contrib/ltree/_ltree_gist.c b/contrib/ltree/_ltree_gist.c
index d8efd8096d0..1791f5bd8d4 100644
--- a/contrib/ltree/_ltree_gist.c
+++ b/contrib/ltree/_ltree_gist.c
@@ -96,7 +96,7 @@ _ltree_compress(PG_FUNCTION_ARGS)
entry->rel, entry->page,
entry->offset, key->len, FALSE);
}
- else
+ else if ( !LTG_ISALLTRUE(entry->key) )
{
int4 i,
len;
@@ -105,10 +105,9 @@ _ltree_compress(PG_FUNCTION_ARGS)
BITVECP sign = LTG_SIGN(DatumGetPointer(entry->key));
ALOOPBYTE(
- if (sign[i] != 0xff)
+ if ((sign[i]&0xff) != 0xff)
PG_RETURN_POINTER(retval);
);
-
len = LTG_HDRSIZE;
key = (ltree_gist *) palloc(len);
key->len = len;
@@ -222,7 +221,7 @@ _ltree_penalty(PG_FUNCTION_ARGS)
if (LTG_ISALLTRUE(origval))
{
- *penalty = 0.0;
+ *penalty = 0.1;
PG_RETURN_POINTER(penalty);
}
@@ -489,7 +488,7 @@ _ltree_picksplit(PG_FUNCTION_ARGS)
);
}
- if (size_alpha - size_l < size_beta - size_r + WISH_F(v->spl_nleft, v->spl_nright, 0.1))
+ if (size_alpha - size_l < size_beta - size_r + WISH_F(v->spl_nleft, v->spl_nright, 0.00001))
{
if (!LTG_ISALLTRUE(datum_l))
{
@@ -613,6 +612,22 @@ gist_qe(ltree_gist * key, lquery * query)
return true;
}
+static bool
+_arrq_cons(ltree_gist *key, ArrayType *_query) {
+ lquery *query = (lquery *) ARR_DATA_PTR(_query);
+ int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
+
+ if (ARR_NDIM(_query) != 1)
+ elog(ERROR, "Dimension of array != 1");
+
+ while (num > 0) {
+ if ( gist_qe(key, query) )
+ return true;
+ num--;
+ query = (lquery*)NEXTVAL(query);
+ }
+ return false;
+}
Datum
_ltree_consistent(PG_FUNCTION_ARGS)
@@ -641,6 +656,10 @@ _ltree_consistent(PG_FUNCTION_ARGS)
case 15:
res = gist_qtxt(key, (ltxtquery *) query);
break;
+ case 16:
+ case 17:
+ res = _arrq_cons(key, (ArrayType *) query);
+ break;
default:
elog(ERROR, "Unknown StrategyNumber: %d", strategy);
}
diff --git a/contrib/ltree/_ltree_op.c b/contrib/ltree/_ltree_op.c
index 59de0a51e4a..f7cd8f2ab6a 100644
--- a/contrib/ltree/_ltree_op.c
+++ b/contrib/ltree/_ltree_op.c
@@ -13,6 +13,8 @@ PG_FUNCTION_INFO_V1(_ltree_risparent);
PG_FUNCTION_INFO_V1(_ltree_r_risparent);
PG_FUNCTION_INFO_V1(_ltq_regex);
PG_FUNCTION_INFO_V1(_ltq_rregex);
+PG_FUNCTION_INFO_V1(_lt_q_regex);
+PG_FUNCTION_INFO_V1(_lt_q_rregex);
PG_FUNCTION_INFO_V1(_ltxtq_exec);
PG_FUNCTION_INFO_V1(_ltxtq_rexec);
@@ -127,6 +129,42 @@ _ltq_rregex(PG_FUNCTION_ARGS)
}
Datum
+_lt_q_regex(PG_FUNCTION_ARGS)
+{
+ ArrayType *_tree = PG_GETARG_ARRAYTYPE_P(0);
+ ArrayType *_query = PG_GETARG_ARRAYTYPE_P(1);
+ lquery *query = (lquery *) ARR_DATA_PTR(_query);
+ bool res = false;
+ int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
+
+ if (ARR_NDIM(_query) != 1)
+ elog(ERROR, "Dimension of array != 1");
+
+ while (num > 0) {
+ if ( array_iterator(_tree, ltq_regex, (void*)query, NULL) ) {
+ res = true;
+ break;
+ }
+ num--;
+ query = (lquery*)NEXTVAL(query);
+ }
+
+ PG_FREE_IF_COPY(_tree, 0);
+ PG_FREE_IF_COPY(_query, 1);
+ PG_RETURN_BOOL(res);
+}
+
+Datum
+_lt_q_rregex(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_DATUM(DirectFunctionCall2(_lt_q_regex,
+ PG_GETARG_DATUM(1),
+ PG_GETARG_DATUM(0)
+ ));
+}
+
+
+Datum
_ltxtq_exec(PG_FUNCTION_ARGS)
{
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
diff --git a/contrib/ltree/expected/ltree.out b/contrib/ltree/expected/ltree.out
index 1b6526c5e9c..f4ab1f63783 100644
--- a/contrib/ltree/expected/ltree.out
+++ b/contrib/ltree/expected/ltree.out
@@ -3,10 +3,10 @@ psql:ltree.sql:9: NOTICE: ProcedureCreate: type ltree is not yet defined
psql:ltree.sql:14: NOTICE: Argument type "ltree" is only a shell
psql:ltree.sql:281: NOTICE: ProcedureCreate: type lquery is not yet defined
psql:ltree.sql:286: NOTICE: Argument type "lquery" is only a shell
-psql:ltree.sql:345: NOTICE: ProcedureCreate: type ltxtquery is not yet defined
-psql:ltree.sql:350: NOTICE: Argument type "ltxtquery" is only a shell
-psql:ltree.sql:412: NOTICE: ProcedureCreate: type ltree_gist is not yet defined
-psql:ltree.sql:417: NOTICE: Argument type "ltree_gist" is only a shell
+psql:ltree.sql:392: NOTICE: ProcedureCreate: type ltxtquery is not yet defined
+psql:ltree.sql:397: NOTICE: Argument type "ltxtquery" is only a shell
+psql:ltree.sql:459: NOTICE: ProcedureCreate: type ltree_gist is not yet defined
+psql:ltree.sql:464: NOTICE: Argument type "ltree_gist" is only a shell
SELECT ''::ltree;
ltree
-------
@@ -963,6 +963,36 @@ SELECT '{j.k.l.m, g.b.c.d.e}'::ltree[] ~ 'A*@|g.b.c.d.e';
t
(1 row)
+SELECT 'a.b.c.d.e'::ltree ? '{A.b.c.d.e}';
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT 'a.b.c.d.e'::ltree ? '{a.b.c.d.e}';
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT 'a.b.c.d.e'::ltree ? '{A.b.c.d.e, a.*}';
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT '{a.b.c.d.e,B.df}'::ltree[] ? '{A.b.c.d.e}';
+ ?column?
+----------
+ f
+(1 row)
+
+SELECT '{a.b.c.d.e,B.df}'::ltree[] ? '{A.b.c.d.e,*.df}';
+ ?column?
+----------
+ t
+(1 row)
+
--exractors
SELECT ('{3456,1.2.3.34}'::ltree[] ?@> '1.2.3.4') is null;
?column?
@@ -3058,6 +3088,50 @@ SELECT * FROM ltreetest WHERE t <@ '1.1.1' order by t asc;
1.1.1.2.1
(4 rows)
+SELECT * FROM ltreetest WHERE t @ '23 & 1' order by t asc;
+ t
+--------------------------------
+ 1.10.23.25.5.11
+ 1.10.4.18.22.23.24
+ 1.12.25.26.22.8.15.23
+ 1.19.22.11.14.7.32.23.19.14
+ 1.21.28.4.23
+ 1.26.15.23.5.31.29.11.19.28.1
+ 1.27.22.23.2.26.32.17.7.9
+ 10.12.9.6.6.26.14.8.23.1.25
+ 12.27.23.32.1.1.9.29.13
+ 14.1.15.25.27.23.25.26.28.10
+ 14.27.29.23.4.1.17.32.6.25.22
+ 15.11.26.1.30.6.23.5
+ 19.22.29.32.1.21.26.24.23.17
+ 19.9.32.23.13.24.1
+ 21.23.17.8.23.11.8.1
+ 22.30.31.24.23.22.5.20.28.1
+ 23.1.23.18.12.29
+ 23.12.1.5.32.25.8.24.1.25
+ 23.12.32.22.19.1.22.4
+ 23.17.22.1.23.4.29.32.4.1
+ 23.17.25.4.1.16.29.10
+ 23.19.17.31.29.13.1.12.5.25
+ 23.22.10.1.14.24
+ 23.28.1
+ 23.3.32.21.5.14.10.17.1
+ 27.29.1.5.30.6.22.16.23.2.28
+ 28.23.2.30.3.8.1.15.15.14.13
+ 29.23.1.21.31.8
+ 29.23.15.25.1.6.6.10
+ 30.23.10.1.10.7.22.28.18.11.17
+ 31.30.23.7.7.24.32.10.11.1.31
+ 32.1.23.20.14.12.23.5.32.15
+ 32.15.20.28.5.1.23.4
+ 5.13.23.19.28.26.27.6.1.22
+ 6.18.1.4.18.23
+ 7.23.1.24.29.13.31.19.23.17.7
+ 8.16.1.16.28.6.3.22.6.23
+ 8.2.18.23.5.16.17.1
+ 9.5.9.3.23.9.25.14.1.29.28
+(39 rows)
+
SELECT * FROM ltreetest WHERE t ~ '1.1.1.*' order by t asc;
t
-----------
@@ -3071,9 +3145,17 @@ SELECT * FROM ltreetest WHERE t ~ '*.1' order by t asc;
t
--------------------------------
1
+ 1.1
+ 1.1.1
+ 1.1.1.1
+ 1.1.1.2.1
+ 1.1.2.1
+ 1.26.15.23.5.31.29.11.19.28.1
+ 10.13.22.1.8.30.9.24.1.2.1
10.22.1
10.26.30.15.1
11.1
+ 12.1.1
17.25.2.13.10.27.13.1
18.13.6.12.26.26.26.29.18.20.1
19.20.25.7.27.28.27.17.9.3.1
@@ -3083,6 +3165,7 @@ SELECT * FROM ltreetest WHERE t ~ '*.1' order by t asc;
21.18.2.1
21.23.17.8.23.11.8.1
22.30.31.24.23.22.5.20.28.1
+ 23.17.22.1.23.4.29.32.4.1
23.28.1
23.3.32.21.5.14.10.17.1
25.6.12.16.1
@@ -3095,14 +3178,7 @@ SELECT * FROM ltreetest WHERE t ~ '*.1' order by t asc;
8.2.18.23.5.16.17.1
8.32.30.1
9.21.20.29.1
-(25 rows)
-
-SELECT * FROM ltreetest WHERE t ~ '23.*.1' order by t asc;
- t
--------------------------
- 23.28.1
- 23.3.32.21.5.14.10.17.1
-(2 rows)
+(34 rows)
SELECT * FROM ltreetest WHERE t ~ '23.*{1}.1' order by t asc;
t
@@ -3110,49 +3186,28 @@ SELECT * FROM ltreetest WHERE t ~ '23.*{1}.1' order by t asc;
23.28.1
(1 row)
-SELECT * FROM ltreetest WHERE t @ '23 & 1' order by t asc;
- t
---------------------------------
- 1.10.23.25.5.11
- 1.10.4.18.22.23.24
- 1.12.25.26.22.8.15.23
- 1.19.22.11.14.7.32.23.19.14
- 1.21.28.4.23
- 1.26.15.23.5.31.29.11.19.28.1
- 1.27.22.23.2.26.32.17.7.9
- 10.12.9.6.6.26.14.8.23.1.25
- 12.27.23.32.1.1.9.29.13
- 14.1.15.25.27.23.25.26.28.10
- 14.27.29.23.4.1.17.32.6.25.22
- 15.11.26.1.30.6.23.5
- 19.22.29.32.1.21.26.24.23.17
- 19.9.32.23.13.24.1
- 21.23.17.8.23.11.8.1
- 22.30.31.24.23.22.5.20.28.1
- 23.1.23.18.12.29
- 23.12.1.5.32.25.8.24.1.25
- 23.12.32.22.19.1.22.4
+SELECT * FROM ltreetest WHERE t ~ '23.*.1' order by t asc;
+ t
+---------------------------
23.17.22.1.23.4.29.32.4.1
- 23.17.25.4.1.16.29.10
- 23.19.17.31.29.13.1.12.5.25
- 23.22.10.1.14.24
23.28.1
23.3.32.21.5.14.10.17.1
- 27.29.1.5.30.6.22.16.23.2.28
- 28.23.2.30.3.8.1.15.15.14.13
- 29.23.1.21.31.8
- 29.23.15.25.1.6.6.10
- 30.23.10.1.10.7.22.28.18.11.17
- 31.30.23.7.7.24.32.10.11.1.31
- 32.1.23.20.14.12.23.5.32.15
- 32.15.20.28.5.1.23.4
- 5.13.23.19.28.26.27.6.1.22
- 6.18.1.4.18.23
- 7.23.1.24.29.13.31.19.23.17.7
- 8.16.1.16.28.6.3.22.6.23
- 8.2.18.23.5.16.17.1
- 9.5.9.3.23.9.25.14.1.29.28
-(39 rows)
+(3 rows)
+
+SELECT * FROM ltreetest WHERE t ~ '23.*.2' order by t asc;
+ t
+------------------
+ 23.20.12.16.15.2
+(1 row)
+
+SELECT * FROM ltreetest WHERE t ? '{23.*.1,23.*.2}' order by t asc;
+ t
+---------------------------
+ 23.17.22.1.23.4.29.32.4.1
+ 23.20.12.16.15.2
+ 23.28.1
+ 23.3.32.21.5.14.10.17.1
+(4 rows)
create unique index tstidx on ltreetest (t);
set enable_seqscan=off;
@@ -7253,6 +7308,50 @@ SELECT * FROM ltreetest WHERE t <@ '1.1.1' order by t asc;
1.1.1.2.1
(4 rows)
+SELECT * FROM ltreetest WHERE t @ '23 & 1' order by t asc;
+ t
+--------------------------------
+ 1.10.23.25.5.11
+ 1.10.4.18.22.23.24
+ 1.12.25.26.22.8.15.23
+ 1.19.22.11.14.7.32.23.19.14
+ 1.21.28.4.23
+ 1.26.15.23.5.31.29.11.19.28.1
+ 1.27.22.23.2.26.32.17.7.9
+ 10.12.9.6.6.26.14.8.23.1.25
+ 12.27.23.32.1.1.9.29.13
+ 14.1.15.25.27.23.25.26.28.10
+ 14.27.29.23.4.1.17.32.6.25.22
+ 15.11.26.1.30.6.23.5
+ 19.22.29.32.1.21.26.24.23.17
+ 19.9.32.23.13.24.1
+ 21.23.17.8.23.11.8.1
+ 22.30.31.24.23.22.5.20.28.1
+ 23.1.23.18.12.29
+ 23.12.1.5.32.25.8.24.1.25
+ 23.12.32.22.19.1.22.4
+ 23.17.22.1.23.4.29.32.4.1
+ 23.17.25.4.1.16.29.10
+ 23.19.17.31.29.13.1.12.5.25
+ 23.22.10.1.14.24
+ 23.28.1
+ 23.3.32.21.5.14.10.17.1
+ 27.29.1.5.30.6.22.16.23.2.28
+ 28.23.2.30.3.8.1.15.15.14.13
+ 29.23.1.21.31.8
+ 29.23.15.25.1.6.6.10
+ 30.23.10.1.10.7.22.28.18.11.17
+ 31.30.23.7.7.24.32.10.11.1.31
+ 32.1.23.20.14.12.23.5.32.15
+ 32.15.20.28.5.1.23.4
+ 5.13.23.19.28.26.27.6.1.22
+ 6.18.1.4.18.23
+ 7.23.1.24.29.13.31.19.23.17.7
+ 8.16.1.16.28.6.3.22.6.23
+ 8.2.18.23.5.16.17.1
+ 9.5.9.3.23.9.25.14.1.29.28
+(39 rows)
+
SELECT * FROM ltreetest WHERE t ~ '1.1.1.*' order by t asc;
t
-----------
@@ -7266,9 +7365,17 @@ SELECT * FROM ltreetest WHERE t ~ '*.1' order by t asc;
t
--------------------------------
1
+ 1.1
+ 1.1.1
+ 1.1.1.1
+ 1.1.1.2.1
+ 1.1.2.1
+ 1.26.15.23.5.31.29.11.19.28.1
+ 10.13.22.1.8.30.9.24.1.2.1
10.22.1
10.26.30.15.1
11.1
+ 12.1.1
17.25.2.13.10.27.13.1
18.13.6.12.26.26.26.29.18.20.1
19.20.25.7.27.28.27.17.9.3.1
@@ -7278,6 +7385,7 @@ SELECT * FROM ltreetest WHERE t ~ '*.1' order by t asc;
21.18.2.1
21.23.17.8.23.11.8.1
22.30.31.24.23.22.5.20.28.1
+ 23.17.22.1.23.4.29.32.4.1
23.28.1
23.3.32.21.5.14.10.17.1
25.6.12.16.1
@@ -7290,14 +7398,7 @@ SELECT * FROM ltreetest WHERE t ~ '*.1' order by t asc;
8.2.18.23.5.16.17.1
8.32.30.1
9.21.20.29.1
-(25 rows)
-
-SELECT * FROM ltreetest WHERE t ~ '23.*.1' order by t asc;
- t
--------------------------
- 23.28.1
- 23.3.32.21.5.14.10.17.1
-(2 rows)
+(34 rows)
SELECT * FROM ltreetest WHERE t ~ '23.*{1}.1' order by t asc;
t
@@ -7305,49 +7406,28 @@ SELECT * FROM ltreetest WHERE t ~ '23.*{1}.1' order by t asc;
23.28.1
(1 row)
-SELECT * FROM ltreetest WHERE t @ '23 & 1' order by t asc;
- t
---------------------------------
- 1.10.23.25.5.11
- 1.10.4.18.22.23.24
- 1.12.25.26.22.8.15.23
- 1.19.22.11.14.7.32.23.19.14
- 1.21.28.4.23
- 1.26.15.23.5.31.29.11.19.28.1
- 1.27.22.23.2.26.32.17.7.9
- 10.12.9.6.6.26.14.8.23.1.25
- 12.27.23.32.1.1.9.29.13
- 14.1.15.25.27.23.25.26.28.10
- 14.27.29.23.4.1.17.32.6.25.22
- 15.11.26.1.30.6.23.5
- 19.22.29.32.1.21.26.24.23.17
- 19.9.32.23.13.24.1
- 21.23.17.8.23.11.8.1
- 22.30.31.24.23.22.5.20.28.1
- 23.1.23.18.12.29
- 23.12.1.5.32.25.8.24.1.25
- 23.12.32.22.19.1.22.4
+SELECT * FROM ltreetest WHERE t ~ '23.*.1' order by t asc;
+ t
+---------------------------
23.17.22.1.23.4.29.32.4.1
- 23.17.25.4.1.16.29.10
- 23.19.17.31.29.13.1.12.5.25
- 23.22.10.1.14.24
23.28.1
23.3.32.21.5.14.10.17.1
- 27.29.1.5.30.6.22.16.23.2.28
- 28.23.2.30.3.8.1.15.15.14.13
- 29.23.1.21.31.8
- 29.23.15.25.1.6.6.10
- 30.23.10.1.10.7.22.28.18.11.17
- 31.30.23.7.7.24.32.10.11.1.31
- 32.1.23.20.14.12.23.5.32.15
- 32.15.20.28.5.1.23.4
- 5.13.23.19.28.26.27.6.1.22
- 6.18.1.4.18.23
- 7.23.1.24.29.13.31.19.23.17.7
- 8.16.1.16.28.6.3.22.6.23
- 8.2.18.23.5.16.17.1
- 9.5.9.3.23.9.25.14.1.29.28
-(39 rows)
+(3 rows)
+
+SELECT * FROM ltreetest WHERE t ~ '23.*.2' order by t asc;
+ t
+------------------
+ 23.20.12.16.15.2
+(1 row)
+
+SELECT * FROM ltreetest WHERE t ? '{23.*.1,23.*.2}' order by t asc;
+ t
+---------------------------
+ 23.17.22.1.23.4.29.32.4.1
+ 23.20.12.16.15.2
+ 23.28.1
+ 23.3.32.21.5.14.10.17.1
+(4 rows)
create table _ltreetest (t ltree[]);
\copy _ltreetest FROM 'data/_ltree.data'
@@ -7363,6 +7443,12 @@ SELECT count(*) FROM _ltreetest WHERE t <@ '1.1.1' ;
19
(1 row)
+SELECT count(*) FROM _ltreetest WHERE t @ '23 & 1' ;
+ count
+-------
+ 147
+(1 row)
+
SELECT count(*) FROM _ltreetest WHERE t ~ '1.1.1.*' ;
count
-------
@@ -7372,25 +7458,31 @@ SELECT count(*) FROM _ltreetest WHERE t ~ '1.1.1.*' ;
SELECT count(*) FROM _ltreetest WHERE t ~ '*.1' ;
count
-------
- 83
+ 109
+(1 row)
+
+SELECT count(*) FROM _ltreetest WHERE t ~ '23.*{1}.1' ;
+ count
+-------
+ 5
(1 row)
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.1' ;
count
-------
- 10
+ 11
(1 row)
-SELECT count(*) FROM _ltreetest WHERE t ~ '23.*{1}.1' ;
+SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.2' ;
count
-------
5
(1 row)
-SELECT count(*) FROM _ltreetest WHERE t @ '23 & 1' ;
+SELECT count(*) FROM _ltreetest WHERE t ? '{23.*.1,23.*.2}' ;
count
-------
- 147
+ 15
(1 row)
create index _tstidx on _ltreetest using gist (t);
@@ -7407,6 +7499,12 @@ SELECT count(*) FROM _ltreetest WHERE t <@ '1.1.1' ;
19
(1 row)
+SELECT count(*) FROM _ltreetest WHERE t @ '23 & 1' ;
+ count
+-------
+ 147
+(1 row)
+
SELECT count(*) FROM _ltreetest WHERE t ~ '1.1.1.*' ;
count
-------
@@ -7416,24 +7514,30 @@ SELECT count(*) FROM _ltreetest WHERE t ~ '1.1.1.*' ;
SELECT count(*) FROM _ltreetest WHERE t ~ '*.1' ;
count
-------
- 83
+ 109
+(1 row)
+
+SELECT count(*) FROM _ltreetest WHERE t ~ '23.*{1}.1' ;
+ count
+-------
+ 5
(1 row)
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.1' ;
count
-------
- 10
+ 11
(1 row)
-SELECT count(*) FROM _ltreetest WHERE t ~ '23.*{1}.1' ;
+SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.2' ;
count
-------
5
(1 row)
-SELECT count(*) FROM _ltreetest WHERE t @ '23 & 1' ;
+SELECT count(*) FROM _ltreetest WHERE t ? '{23.*.1,23.*.2}' ;
count
-------
- 147
+ 15
(1 row)
diff --git a/contrib/ltree/lquery_op.c b/contrib/ltree/lquery_op.c
index e24cc8559fc..1156723d58a 100644
--- a/contrib/ltree/lquery_op.c
+++ b/contrib/ltree/lquery_op.c
@@ -5,10 +5,16 @@
#include "ltree.h"
#include <ctype.h>
+#include "utils/array.h"
PG_FUNCTION_INFO_V1(ltq_regex);
PG_FUNCTION_INFO_V1(ltq_rregex);
+PG_FUNCTION_INFO_V1(lt_q_regex);
+PG_FUNCTION_INFO_V1(lt_q_rregex);
+
+#define NEXTVAL(x) ( (lquery*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
+
typedef struct
{
lquery_level *q;
@@ -39,7 +45,7 @@ getlexem(char *start, char *end, int *len)
}
bool
- compare_subnode(ltree_level * t, char *qn, int len, int (*cmpptr) (const char *, const char *, size_t), bool anyend)
+compare_subnode(ltree_level * t, char *qn, int len, int (*cmpptr) (const char *, const char *, size_t), bool anyend)
{
char *endt = t->name + t->len;
char *endq = qn + len;
@@ -117,6 +123,11 @@ printFieldNot(FieldNot *fn ) {
}
*/
+static struct {
+ bool muse;
+ uint32 high_pos;
+} SomeStack = {false,0,};
+
static bool
checkCond(lquery_level * curq, int query_numlevel, ltree_level * curt, int tree_numlevel, FieldNot * ptr)
{
@@ -129,6 +140,14 @@ checkCond(lquery_level * curq, int query_numlevel, ltree_level * curt, int tree_
lquery_level *prevq = NULL;
ltree_level *prevt = NULL;
+ if ( SomeStack.muse ) {
+ high_pos = SomeStack.high_pos;
+ qlen--;
+ prevq = curq;
+ curq = LQL_NEXT(curq);
+ SomeStack.muse = false;
+ }
+
while (tlen > 0 && qlen > 0)
{
if (curq->numvar)
@@ -181,6 +200,15 @@ checkCond(lquery_level * curq, int query_numlevel, ltree_level * curt, int tree_
curt = LEVEL_NEXT(curt);
tlen--;
cur_tpos++;
+ if ( isok && prevq && prevq->numvar==0 && tlen>0 && cur_tpos <= high_pos ) {
+ FieldNot tmpptr;
+ if ( ptr )
+ memcpy(&tmpptr,ptr,sizeof(FieldNot));
+ SomeStack.high_pos = high_pos-cur_tpos;
+ SomeStack.muse = true;
+ if ( checkCond(prevq, qlen+1, curt, tlen, (ptr) ? &tmpptr : NULL) )
+ return true;
+ }
if (!isok && ptr)
ptr->nt++;
}
@@ -278,3 +306,42 @@ ltq_rregex(PG_FUNCTION_ARGS)
PG_GETARG_DATUM(0)
));
}
+
+Datum
+lt_q_regex(PG_FUNCTION_ARGS)
+{
+ ltree *tree = PG_GETARG_LTREE(0);
+ ArrayType *_query = PG_GETARG_ARRAYTYPE_P(1);
+ lquery *query = (lquery *) ARR_DATA_PTR(_query);
+ bool res = false;
+ int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
+
+ if (ARR_NDIM(_query) != 1)
+ elog(ERROR, "Dimension of array != 1");
+
+ while (num > 0) {
+ if (DatumGetBool(DirectFunctionCall2(ltq_regex,
+ PointerGetDatum(tree), PointerGetDatum(query)))) {
+
+ res = true;
+ break;
+ }
+ num--;
+ query = NEXTVAL(query);
+ }
+
+ PG_FREE_IF_COPY(tree, 0);
+ PG_FREE_IF_COPY(_query, 1);
+ PG_RETURN_BOOL(res);
+}
+
+Datum
+lt_q_rregex(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_DATUM(DirectFunctionCall2(lt_q_regex,
+ PG_GETARG_DATUM(1),
+ PG_GETARG_DATUM(0)
+ ));
+}
+
+
diff --git a/contrib/ltree/ltree.h b/contrib/ltree/ltree.h
index 606b3e3a747..1bc36e722de 100644
--- a/contrib/ltree/ltree.h
+++ b/contrib/ltree/ltree.h
@@ -140,10 +140,14 @@ Datum ltree_isparent(PG_FUNCTION_ARGS);
Datum ltree_risparent(PG_FUNCTION_ARGS);
Datum ltq_regex(PG_FUNCTION_ARGS);
Datum ltq_rregex(PG_FUNCTION_ARGS);
+Datum lt_q_regex(PG_FUNCTION_ARGS);
+Datum lt_q_rregex(PG_FUNCTION_ARGS);
Datum ltxtq_exec(PG_FUNCTION_ARGS);
Datum ltxtq_rexec(PG_FUNCTION_ARGS);
Datum _ltq_regex(PG_FUNCTION_ARGS);
Datum _ltq_rregex(PG_FUNCTION_ARGS);
+Datum _lt_q_regex(PG_FUNCTION_ARGS);
+Datum _lt_q_rregex(PG_FUNCTION_ARGS);
Datum _ltxtq_exec(PG_FUNCTION_ARGS);
Datum _ltxtq_rexec(PG_FUNCTION_ARGS);
Datum _ltree_isparent(PG_FUNCTION_ARGS);
@@ -173,7 +177,7 @@ ltree *lca_inner(ltree ** a, int len);
/* GiST support for ltree */
#define BITBYTE 8
-#define SIGLENINT 8
+#define SIGLENINT 2
#define SIGLEN ( sizeof(int4)*SIGLENINT )
#define SIGLENBIT (SIGLEN*BITBYTE)
typedef unsigned char BITVEC[SIGLEN];
diff --git a/contrib/ltree/ltree.sql.in b/contrib/ltree/ltree.sql.in
index eae1454a9aa..3bf7617fff6 100644
--- a/contrib/ltree/ltree.sql.in
+++ b/contrib/ltree/ltree.sql.in
@@ -339,6 +339,53 @@ CREATE OPERATOR ^~ (
JOIN = contjoinsel
);
+CREATE FUNCTION lt_q_regex(ltree,_lquery)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE FUNCTION lt_q_rregex(_lquery,ltree)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE OPERATOR ? (
+ LEFTARG = ltree,
+ RIGHTARG = _lquery,
+ PROCEDURE = lt_q_regex,
+ COMMUTATOR = '?',
+ RESTRICT = contsel,
+ JOIN = contjoinsel
+);
+
+CREATE OPERATOR ? (
+ LEFTARG = _lquery,
+ RIGHTARG = ltree,
+ PROCEDURE = lt_q_rregex,
+ COMMUTATOR = '?',
+ RESTRICT = contsel,
+ JOIN = contjoinsel
+);
+
+--not-indexed
+CREATE OPERATOR ^? (
+ LEFTARG = ltree,
+ RIGHTARG = _lquery,
+ PROCEDURE = lt_q_regex,
+ COMMUTATOR = '^?',
+ RESTRICT = contsel,
+ JOIN = contjoinsel
+);
+
+CREATE OPERATOR ^? (
+ LEFTARG = _lquery,
+ RIGHTARG = ltree,
+ PROCEDURE = lt_q_rregex,
+ COMMUTATOR = '^?',
+ RESTRICT = contsel,
+ JOIN = contjoinsel
+);
+
CREATE FUNCTION ltxtq_in(cstring)
RETURNS ltxtquery
AS 'MODULE_PATHNAME'
@@ -452,6 +499,8 @@ CREATE OPERATOR CLASS gist_ltree_ops
OPERATOR 13 ~ (lquery, ltree) ,
OPERATOR 14 @ (ltree, ltxtquery) ,
OPERATOR 15 @ (ltxtquery, ltree) ,
+ OPERATOR 16 ? (ltree, _lquery) ,
+ OPERATOR 17 ? (_lquery, ltree) ,
FUNCTION 1 ltree_consistent (internal, internal, int2),
FUNCTION 2 ltree_union (bytea, internal),
FUNCTION 3 ltree_compress (internal),
@@ -494,6 +543,16 @@ RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE 'C' WITH (isstrict,iscachable);
+CREATE FUNCTION _lt_q_regex(_ltree,_lquery)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE FUNCTION _lt_q_rregex(_lquery,_ltree)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C' WITH (isstrict,iscachable);
+
CREATE FUNCTION _ltxtq_exec(_ltree, ltxtquery)
RETURNS bool
AS 'MODULE_PATHNAME'
@@ -558,6 +617,24 @@ CREATE OPERATOR ~ (
JOIN = contjoinsel
);
+CREATE OPERATOR ? (
+ LEFTARG = _ltree,
+ RIGHTARG = _lquery,
+ PROCEDURE = _lt_q_regex,
+ COMMUTATOR = '?',
+ RESTRICT = contsel,
+ JOIN = contjoinsel
+);
+
+CREATE OPERATOR ? (
+ LEFTARG = _lquery,
+ RIGHTARG = _ltree,
+ PROCEDURE = _lt_q_rregex,
+ COMMUTATOR = '?',
+ RESTRICT = contsel,
+ JOIN = contjoinsel
+);
+
CREATE OPERATOR @ (
LEFTARG = _ltree,
RIGHTARG = ltxtquery,
@@ -632,6 +709,24 @@ CREATE OPERATOR ^~ (
JOIN = contjoinsel
);
+CREATE OPERATOR ^? (
+ LEFTARG = _ltree,
+ RIGHTARG = _lquery,
+ PROCEDURE = _lt_q_regex,
+ COMMUTATOR = '^?',
+ RESTRICT = contsel,
+ JOIN = contjoinsel
+);
+
+CREATE OPERATOR ^? (
+ LEFTARG = _lquery,
+ RIGHTARG = _ltree,
+ PROCEDURE = _lt_q_rregex,
+ COMMUTATOR = '^?',
+ RESTRICT = contsel,
+ JOIN = contjoinsel
+);
+
CREATE OPERATOR ^@ (
LEFTARG = _ltree,
RIGHTARG = ltxtquery,
@@ -729,6 +824,8 @@ CREATE OPERATOR CLASS gist__ltree_ops
OPERATOR 13 ~ (lquery, _ltree) RECHECK ,
OPERATOR 14 @ (_ltree, ltxtquery) RECHECK ,
OPERATOR 15 @ (ltxtquery, _ltree) RECHECK ,
+ OPERATOR 16 ? (_ltree, _lquery) RECHECK ,
+ OPERATOR 17 ? (_lquery, _ltree) RECHECK ,
FUNCTION 1 _ltree_consistent (internal, internal, int2),
FUNCTION 2 _ltree_union (bytea, internal),
FUNCTION 3 _ltree_compress (internal),
diff --git a/contrib/ltree/ltree_gist.c b/contrib/ltree/ltree_gist.c
index 5c5f4c7d6dc..41c92ac57b2 100644
--- a/contrib/ltree/ltree_gist.c
+++ b/contrib/ltree/ltree_gist.c
@@ -7,9 +7,11 @@
#include "access/gist.h"
#include "access/rtree.h"
#include "access/nbtree.h"
-
+#include "utils/array.h"
#include "crc32.h"
+#define NEXTVAL(x) ( (lquery*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
+
PG_FUNCTION_INFO_V1(ltree_gist_in);
Datum ltree_gist_in(PG_FUNCTION_ARGS);
@@ -596,6 +598,22 @@ gist_qtxt(ltree_gist * key, ltxtquery * query)
);
}
+static bool
+arrq_cons(ltree_gist *key, ArrayType *_query) {
+ lquery *query = (lquery *) ARR_DATA_PTR(_query);
+ int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
+
+ if (ARR_NDIM(_query) != 1)
+ elog(ERROR, "Dimension of array != 1");
+
+ while (num > 0) {
+ if ( gist_qe(key, query) && gist_between(key, query) )
+ return true;
+ num--;
+ query = NEXTVAL(query);
+ }
+ return false;
+}
Datum
ltree_consistent(PG_FUNCTION_ARGS)
@@ -672,6 +690,16 @@ ltree_consistent(PG_FUNCTION_ARGS)
else
res = gist_qtxt(key, (ltxtquery *) query);
break;
+ case 16:
+ case 17:
+ if (GIST_LEAF(entry))
+ res = DatumGetBool(DirectFunctionCall2(lt_q_regex,
+ PointerGetDatum(LTG_NODE(key)),
+ PointerGetDatum((ArrayType *) query)
+ ));
+ else
+ res = arrq_cons(key, (ArrayType *) query);
+ break;
default:
elog(ERROR, "Unknown StrategyNumber: %d", strategy);
}
diff --git a/contrib/ltree/sql/ltree.sql b/contrib/ltree/sql/ltree.sql
index 141bd434360..9e8f485f1e5 100644
--- a/contrib/ltree/sql/ltree.sql
+++ b/contrib/ltree/sql/ltree.sql
@@ -139,6 +139,7 @@ SELECT 'a.b.c.d.e'::ltree ~ '!b.*{1}.!c.*';
SELECT 'a.b.c.d.e'::ltree ~ '*.!b.*{1}.!c.*';
SELECT 'a.b.c.d.e'::ltree ~ '*.!b.*.!c.*';
+
SELECT 'QWER_TY'::ltree ~ 'q%@*';
SELECT 'QWER_TY'::ltree ~ 'Q_t%@*';
SELECT 'QWER_GY'::ltree ~ 'q_t%@*';
@@ -175,6 +176,11 @@ SELECT '{1.2.3.4.5, 7.12.asd}'::ltree[] @> '1.2.3.4';
SELECT '{1.3.3, 7.12.asd}'::ltree[] @> '1.2.3.4';
SELECT '{ltree.asd, tree.awdfg}'::ltree[] @ 'tree & aWdfg@'::ltxtquery;
SELECT '{j.k.l.m, g.b.c.d.e}'::ltree[] ~ 'A*@|g.b.c.d.e';
+SELECT 'a.b.c.d.e'::ltree ? '{A.b.c.d.e}';
+SELECT 'a.b.c.d.e'::ltree ? '{a.b.c.d.e}';
+SELECT 'a.b.c.d.e'::ltree ? '{A.b.c.d.e, a.*}';
+SELECT '{a.b.c.d.e,B.df}'::ltree[] ? '{A.b.c.d.e}';
+SELECT '{a.b.c.d.e,B.df}'::ltree[] ? '{A.b.c.d.e,*.df}';
--exractors
SELECT ('{3456,1.2.3.34}'::ltree[] ?@> '1.2.3.4') is null;
@@ -194,11 +200,13 @@ SELECT * FROM ltreetest WHERE t >= '12.3' order by t asc;
SELECT * FROM ltreetest WHERE t > '12.3' order by t asc;
SELECT * FROM ltreetest WHERE t @> '1.1.1' order by t asc;
SELECT * FROM ltreetest WHERE t <@ '1.1.1' order by t asc;
+SELECT * FROM ltreetest WHERE t @ '23 & 1' order by t asc;
SELECT * FROM ltreetest WHERE t ~ '1.1.1.*' order by t asc;
SELECT * FROM ltreetest WHERE t ~ '*.1' order by t asc;
-SELECT * FROM ltreetest WHERE t ~ '23.*.1' order by t asc;
SELECT * FROM ltreetest WHERE t ~ '23.*{1}.1' order by t asc;
-SELECT * FROM ltreetest WHERE t @ '23 & 1' order by t asc;
+SELECT * FROM ltreetest WHERE t ~ '23.*.1' order by t asc;
+SELECT * FROM ltreetest WHERE t ~ '23.*.2' order by t asc;
+SELECT * FROM ltreetest WHERE t ? '{23.*.1,23.*.2}' order by t asc;
create unique index tstidx on ltreetest (t);
set enable_seqscan=off;
@@ -220,31 +228,37 @@ SELECT * FROM ltreetest WHERE t >= '12.3' order by t asc;
SELECT * FROM ltreetest WHERE t > '12.3' order by t asc;
SELECT * FROM ltreetest WHERE t @> '1.1.1' order by t asc;
SELECT * FROM ltreetest WHERE t <@ '1.1.1' order by t asc;
+SELECT * FROM ltreetest WHERE t @ '23 & 1' order by t asc;
SELECT * FROM ltreetest WHERE t ~ '1.1.1.*' order by t asc;
SELECT * FROM ltreetest WHERE t ~ '*.1' order by t asc;
-SELECT * FROM ltreetest WHERE t ~ '23.*.1' order by t asc;
SELECT * FROM ltreetest WHERE t ~ '23.*{1}.1' order by t asc;
-SELECT * FROM ltreetest WHERE t @ '23 & 1' order by t asc;
+SELECT * FROM ltreetest WHERE t ~ '23.*.1' order by t asc;
+SELECT * FROM ltreetest WHERE t ~ '23.*.2' order by t asc;
+SELECT * FROM ltreetest WHERE t ? '{23.*.1,23.*.2}' order by t asc;
create table _ltreetest (t ltree[]);
\copy _ltreetest FROM 'data/_ltree.data'
SELECT count(*) FROM _ltreetest WHERE t @> '1.1.1' ;
SELECT count(*) FROM _ltreetest WHERE t <@ '1.1.1' ;
+SELECT count(*) FROM _ltreetest WHERE t @ '23 & 1' ;
SELECT count(*) FROM _ltreetest WHERE t ~ '1.1.1.*' ;
SELECT count(*) FROM _ltreetest WHERE t ~ '*.1' ;
-SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.1' ;
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*{1}.1' ;
-SELECT count(*) FROM _ltreetest WHERE t @ '23 & 1' ;
+SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.1' ;
+SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.2' ;
+SELECT count(*) FROM _ltreetest WHERE t ? '{23.*.1,23.*.2}' ;
create index _tstidx on _ltreetest using gist (t);
set enable_seqscan=off;
SELECT count(*) FROM _ltreetest WHERE t @> '1.1.1' ;
SELECT count(*) FROM _ltreetest WHERE t <@ '1.1.1' ;
+SELECT count(*) FROM _ltreetest WHERE t @ '23 & 1' ;
SELECT count(*) FROM _ltreetest WHERE t ~ '1.1.1.*' ;
SELECT count(*) FROM _ltreetest WHERE t ~ '*.1' ;
-SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.1' ;
SELECT count(*) FROM _ltreetest WHERE t ~ '23.*{1}.1' ;
-SELECT count(*) FROM _ltreetest WHERE t @ '23 & 1' ;
+SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.1' ;
+SELECT count(*) FROM _ltreetest WHERE t ~ '23.*.2' ;
+SELECT count(*) FROM _ltreetest WHERE t ? '{23.*.1,23.*.2}' ;