aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Momjian <bruce@momjian.us>2003-03-31 20:59:20 +0000
committerBruce Momjian <bruce@momjian.us>2003-03-31 20:59:20 +0000
commit7c100e96b7a6d8df95d99828132840417adcd8d2 (patch)
treecc35a02cc876a8d08a797694a12119095f32feed
parent28295da0a52fa4ca1c9365d390f2e8265dedeebf (diff)
downloadpostgresql-7c100e96b7a6d8df95d99828132840417adcd8d2.tar.gz
postgresql-7c100e96b7a6d8df95d99828132840417adcd8d2.zip
Please, apply patch for contrib/ltree to current CVS and 7.3.2
CHANGES Mar 28, 2003 Added finctions index(ltree,ltree,offset), text2ltree(text), ltree2text(text) Teodor Sigaev
-rw-r--r--contrib/ltree/README.ltree19
-rw-r--r--contrib/ltree/expected/ltree.out132
-rw-r--r--contrib/ltree/ltree.sql.in20
-rw-r--r--contrib/ltree/ltree_op.c109
-rw-r--r--contrib/ltree/sql/ltree.sql24
5 files changed, 298 insertions, 6 deletions
diff --git a/contrib/ltree/README.ltree b/contrib/ltree/README.ltree
index 08735f95d58..f7d0e207787 100644
--- a/contrib/ltree/README.ltree
+++ b/contrib/ltree/README.ltree
@@ -187,6 +187,22 @@ int4 nlevel
Note, that arguments start, end, OFFSET, LEN have meaning of level of the
node !
+int4 index(ltree,ltree), int4 index(ltree,ltree,OFFSET)
+ returns number of level of the first occurence of second argument in first
+ one beginning from OFFSET. if OFFSET is negative, than search begins from |
+ OFFSET| levels from the end of the path.
+ SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',3);
+ index
+ -------
+ 6
+ SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-4);
+ index
+ -------
+ 9
+
+ltree text2ltree(text), text ltree2text(text)
+ cast functions for ltree and text.
+
ltree lca(ltree,ltree,...) (up to 8 arguments)
ltree lca(ltree[])
Returns Lowest Common Ancestor (lca)
@@ -426,6 +442,9 @@ appreciate your input. So far, below some (rather obvious) results:
CHANGES
+Mar 28, 2003
+ Added finctions index(ltree,ltree,offset), text2ltree(text),
+ ltree2text(text)
Feb 7, 2003
Fix ~ operation bug: eg '1.1.1' ~ '*.1'
Aug 9, 2002
diff --git a/contrib/ltree/expected/ltree.out b/contrib/ltree/expected/ltree.out
index d78d67c3ad0..0622034ce64 100644
--- a/contrib/ltree/expected/ltree.out
+++ b/contrib/ltree/expected/ltree.out
@@ -1,12 +1,12 @@
\set ECHO none
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:301: NOTICE: ProcedureCreate: type lquery is not yet defined
+psql:ltree.sql:306: NOTICE: Argument type "lquery" is only a shell
+psql:ltree.sql:365: NOTICE: ProcedureCreate: type ltxtquery is not yet defined
+psql:ltree.sql:370: NOTICE: Argument type "ltxtquery" is only a shell
+psql:ltree.sql:432: NOTICE: ProcedureCreate: type ltree_gist is not yet defined
+psql:ltree.sql:437: NOTICE: Argument type "ltree_gist" is only a shell
SELECT ''::ltree;
ltree
-------
@@ -31,6 +31,18 @@ SELECT '1.2._3'::ltree;
1.2._3
(1 row)
+SELECT ltree2text('1.2.3.34.sdf');
+ ltree2text
+--------------
+ 1.2.3.34.sdf
+(1 row)
+
+SELECT text2ltree('1.2.3.34.sdf');
+ text2ltree
+--------------
+ 1.2.3.34.sdf
+(1 row)
+
SELECT subltree('Top.Child1.Child2',1,2);
subltree
----------
@@ -85,6 +97,114 @@ SELECT subpath('Top.Child1.Child2',1);
Child1.Child2
(1 row)
+SELECT index('1.2.3.4.5.6','1.2');
+ index
+-------
+ 0
+(1 row)
+
+SELECT index('a.1.2.3.4.5.6','1.2');
+ index
+-------
+ 1
+(1 row)
+
+SELECT index('a.1.2.3.4.5.6','1.2.3');
+ index
+-------
+ 1
+(1 row)
+
+SELECT index('a.1.2.3.4.5.6','1.2.3.j');
+ index
+-------
+ -1
+(1 row)
+
+SELECT index('a.1.2.3.4.5.6','1.2.3.j.4.5.5.5.5.5.5');
+ index
+-------
+ -1
+(1 row)
+
+SELECT index('a.1.2.3.4.5.6','1.2.3');
+ index
+-------
+ 1
+(1 row)
+
+SELECT index('a.1.2.3.4.5.6','6');
+ index
+-------
+ 6
+(1 row)
+
+SELECT index('a.1.2.3.4.5.6','6.1');
+ index
+-------
+ -1
+(1 row)
+
+SELECT index('a.1.2.3.4.5.6','5.6');
+ index
+-------
+ 5
+(1 row)
+
+SELECT index('0.1.2.3.5.4.5.6','5.6');
+ index
+-------
+ 6
+(1 row)
+
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',3);
+ index
+-------
+ 6
+(1 row)
+
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',6);
+ index
+-------
+ 6
+(1 row)
+
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',7);
+ index
+-------
+ 9
+(1 row)
+
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-7);
+ index
+-------
+ 6
+(1 row)
+
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-4);
+ index
+-------
+ 9
+(1 row)
+
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-3);
+ index
+-------
+ 9
+(1 row)
+
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-2);
+ index
+-------
+ -1
+(1 row)
+
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-20000);
+ index
+-------
+ 6
+(1 row)
+
SELECT 'Top.Child1.Child2'::ltree || 'Child3'::text;
?column?
--------------------------
diff --git a/contrib/ltree/ltree.sql.in b/contrib/ltree/ltree.sql.in
index eae1454a9aa..d6db2b4aaf3 100644
--- a/contrib/ltree/ltree.sql.in
+++ b/contrib/ltree/ltree.sql.in
@@ -137,11 +137,31 @@ RETURNS ltree
AS 'MODULE_PATHNAME'
LANGUAGE 'C' WITH (isstrict,iscachable);
+CREATE FUNCTION index(ltree,ltree)
+RETURNS int4
+AS 'MODULE_PATHNAME', 'ltree_index'
+LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE FUNCTION index(ltree,ltree,int4)
+RETURNS int4
+AS 'MODULE_PATHNAME', 'ltree_index'
+LANGUAGE 'C' WITH (isstrict,iscachable);
+
CREATE FUNCTION nlevel(ltree)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE 'C' WITH (isstrict,iscachable);
+CREATE FUNCTION ltree2text(ltree)
+RETURNS text
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE FUNCTION text2ltree(text)
+RETURNS ltree
+AS 'MODULE_PATHNAME'
+LANGUAGE 'C' WITH (isstrict,iscachable);
+
CREATE FUNCTION lca(_ltree)
RETURNS ltree
AS 'MODULE_PATHNAME','_lca'
diff --git a/contrib/ltree/ltree_op.c b/contrib/ltree/ltree_op.c
index 4dcf6f73632..28fcfb7f7e3 100644
--- a/contrib/ltree/ltree_op.c
+++ b/contrib/ltree/ltree_op.c
@@ -19,10 +19,13 @@ PG_FUNCTION_INFO_V1(ltree_isparent);
PG_FUNCTION_INFO_V1(ltree_risparent);
PG_FUNCTION_INFO_V1(subltree);
PG_FUNCTION_INFO_V1(subpath);
+PG_FUNCTION_INFO_V1(ltree_index);
PG_FUNCTION_INFO_V1(ltree_addltree);
PG_FUNCTION_INFO_V1(ltree_addtext);
PG_FUNCTION_INFO_V1(ltree_textadd);
PG_FUNCTION_INFO_V1(lca);
+PG_FUNCTION_INFO_V1(ltree2text);
+PG_FUNCTION_INFO_V1(text2ltree);
Datum ltree_cmp(PG_FUNCTION_ARGS);
Datum ltree_lt(PG_FUNCTION_ARGS);
Datum ltree_le(PG_FUNCTION_ARGS);
@@ -33,10 +36,13 @@ Datum ltree_gt(PG_FUNCTION_ARGS);
Datum nlevel(PG_FUNCTION_ARGS);
Datum subltree(PG_FUNCTION_ARGS);
Datum subpath(PG_FUNCTION_ARGS);
+Datum ltree_index(PG_FUNCTION_ARGS);
Datum ltree_addltree(PG_FUNCTION_ARGS);
Datum ltree_addtext(PG_FUNCTION_ARGS);
Datum ltree_textadd(PG_FUNCTION_ARGS);
Datum lca(PG_FUNCTION_ARGS);
+Datum ltree2text(PG_FUNCTION_ARGS);
+Datum text2ltree(PG_FUNCTION_ARGS);
int
ltree_compare(const ltree * a, const ltree * b)
@@ -318,6 +324,57 @@ ltree_addtext(PG_FUNCTION_ARGS)
}
Datum
+ltree_index(PG_FUNCTION_ARGS)
+{
+ ltree *a = PG_GETARG_LTREE(0);
+ ltree *b = PG_GETARG_LTREE(1);
+ int start=(fcinfo->nargs == 3) ? PG_GETARG_INT32(2) : 0;
+ int i,j;
+ ltree_level *startptr, *aptr, *bptr;
+ bool found=false;
+
+ if ( start < 0 ) {
+ if ( -start >= a->numlevel )
+ start=0;
+ else
+ start = (int)(a->numlevel)+start;
+ }
+
+ if ( a->numlevel - start < b->numlevel || a->numlevel==0 || b->numlevel==0 ) {
+ PG_FREE_IF_COPY(a, 0);
+ PG_FREE_IF_COPY(b, 1);
+ PG_RETURN_INT32(-1);
+ }
+
+ startptr=LTREE_FIRST(a);
+ for(i=0; i<=a->numlevel-b->numlevel; i++) {
+ if ( i>=start ) {
+ aptr=startptr;
+ bptr=LTREE_FIRST(b);
+ for(j=0;j<b->numlevel;j++) {
+ if ( !(aptr->len==bptr->len && strncmp(aptr->name,bptr->name, aptr->len)==0) )
+ break;
+ aptr=LEVEL_NEXT(aptr);
+ bptr=LEVEL_NEXT(bptr);
+ }
+
+ if ( j==b->numlevel ) {
+ found=true;
+ break;
+ }
+ }
+ startptr=LEVEL_NEXT(startptr);
+ }
+
+ if ( !found )
+ i=-1;
+
+ PG_FREE_IF_COPY(a, 0);
+ PG_FREE_IF_COPY(b, 1);
+ PG_RETURN_INT32(i);
+}
+
+Datum
ltree_textadd(PG_FUNCTION_ARGS)
{
ltree *a = PG_GETARG_LTREE(1);
@@ -431,3 +488,55 @@ lca(PG_FUNCTION_ARGS)
else
PG_RETURN_NULL();
}
+
+Datum
+text2ltree(PG_FUNCTION_ARGS)
+{
+ text *in = PG_GETARG_TEXT_P(0);
+ char *s = (char *) palloc(VARSIZE(in) - VARHDRSZ + 1);
+ ltree *out;
+
+ memcpy(s, VARDATA(in), VARSIZE(in) - VARHDRSZ);
+ s[VARSIZE(in) - VARHDRSZ] = '\0';
+
+ out = (ltree *) DatumGetPointer(DirectFunctionCall1(
+ ltree_in,
+ PointerGetDatum(s)
+ ));
+ pfree(s);
+ PG_FREE_IF_COPY(in,0);
+ PG_RETURN_POINTER(out);
+}
+
+
+Datum
+ltree2text(PG_FUNCTION_ARGS)
+{
+ ltree *in = PG_GETARG_LTREE(0);
+ char *ptr;
+ int i;
+ ltree_level *curlevel;
+ text *out;
+
+ out=(text*)palloc(in->len+VARHDRSZ);
+ ptr = VARDATA(out);
+ curlevel = LTREE_FIRST(in);
+ for (i = 0; i < in->numlevel; i++) {
+ if (i != 0) {
+ *ptr = '.';
+ ptr++;
+ }
+ memcpy(ptr, curlevel->name, curlevel->len);
+ ptr += curlevel->len;
+ curlevel = LEVEL_NEXT(curlevel);
+ }
+
+ VARATT_SIZEP(out) = VARHDRSZ + (ptr-VARDATA(out));
+ PG_FREE_IF_COPY(in, 0);
+
+ PG_RETURN_POINTER(out);
+}
+
+
+
+
diff --git a/contrib/ltree/sql/ltree.sql b/contrib/ltree/sql/ltree.sql
index 141bd434360..cbb7e21545f 100644
--- a/contrib/ltree/sql/ltree.sql
+++ b/contrib/ltree/sql/ltree.sql
@@ -7,6 +7,9 @@ SELECT '1'::ltree;
SELECT '1.2'::ltree;
SELECT '1.2._3'::ltree;
+SELECT ltree2text('1.2.3.34.sdf');
+SELECT text2ltree('1.2.3.34.sdf');
+
SELECT subltree('Top.Child1.Child2',1,2);
SELECT subpath('Top.Child1.Child2',1,2);
SELECT subpath('Top.Child1.Child2',-1,1);
@@ -17,6 +20,27 @@ SELECT subpath('Top.Child1.Child2',1,0);
SELECT subpath('Top.Child1.Child2',0);
SELECT subpath('Top.Child1.Child2',1);
+
+SELECT index('1.2.3.4.5.6','1.2');
+SELECT index('a.1.2.3.4.5.6','1.2');
+SELECT index('a.1.2.3.4.5.6','1.2.3');
+SELECT index('a.1.2.3.4.5.6','1.2.3.j');
+SELECT index('a.1.2.3.4.5.6','1.2.3.j.4.5.5.5.5.5.5');
+SELECT index('a.1.2.3.4.5.6','1.2.3');
+SELECT index('a.1.2.3.4.5.6','6');
+SELECT index('a.1.2.3.4.5.6','6.1');
+SELECT index('a.1.2.3.4.5.6','5.6');
+SELECT index('0.1.2.3.5.4.5.6','5.6');
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',3);
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',6);
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',7);
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-7);
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-4);
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-3);
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-2);
+SELECT index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-20000);
+
+
SELECT 'Top.Child1.Child2'::ltree || 'Child3'::text;
SELECT 'Top.Child1.Child2'::ltree || 'Child3'::ltree;
SELECT 'Top_0'::ltree || 'Top.Child1.Child2'::ltree;