]> granicus.if.org Git - postgresql/commitdiff
Please, apply patch for contrib/ltree to current CVS and 7.3.2
authorBruce Momjian <bruce@momjian.us>
Mon, 31 Mar 2003 20:59:20 +0000 (20:59 +0000)
committerBruce Momjian <bruce@momjian.us>
Mon, 31 Mar 2003 20:59:20 +0000 (20:59 +0000)
CHANGES

Mar 28, 2003
Added finctions index(ltree,ltree,offset), text2ltree(text),
ltree2text(text)

Teodor Sigaev

contrib/ltree/README.ltree
contrib/ltree/expected/ltree.out
contrib/ltree/ltree.sql.in
contrib/ltree/ltree_op.c
contrib/ltree/sql/ltree.sql

index 08735f95d58cc9c62af7f27a7fd2dceae1bc37f8..f7d0e207787221245dc4c0ee15cbd5003774db18 100644 (file)
@@ -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
index d78d67c3ad06bd2db8957a06f936e34ce0e1a135..0622034ce64197063d0982f37a09786f235ae23b 100644 (file)
@@ -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?         
 --------------------------
index eae1454a9aad9b6b2541a6f4546a85605f8be8ff..d6db2b4aaf344a459de45dabcf2646a1402468f1 100644 (file)
@@ -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'
index 4dcf6f736321eac1d352f1accb99601cad697b75..28fcfb7f7e3bfe4c053311ba54da113fd4e48924 100644 (file)
@@ -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)
@@ -317,6 +323,57 @@ ltree_addtext(PG_FUNCTION_ARGS)
        PG_RETURN_POINTER(r);
 }
 
+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)
 {
@@ -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);
+}
+
+       
+
+
index 141bd43436069dfe2f9304c3bc45cba54562ae93..cbb7e21545fee867f0269d1bb8aaa6cbe5ffad54 100644 (file)
@@ -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;