mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
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
This commit is contained in:
@ -193,6 +193,23 @@ int4 nlevel
|
|||||||
Note, that arguments start, end, OFFSET, LEN have meaning of level of the
|
Note, that arguments start, end, OFFSET, LEN have meaning of level of the
|
||||||
node !
|
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,ltree,...) (up to 8 arguments)
|
||||||
ltree lca(ltree[])
|
ltree lca(ltree[])
|
||||||
Returns Lowest Common Ancestor (lca)
|
Returns Lowest Common Ancestor (lca)
|
||||||
@ -432,6 +449,9 @@ appreciate your input. So far, below some (rather obvious) results:
|
|||||||
|
|
||||||
CHANGES
|
CHANGES
|
||||||
|
|
||||||
|
Mar 28, 2003
|
||||||
|
Added functions index(ltree,ltree,offset), text2ltree(text),
|
||||||
|
ltree2text(text)
|
||||||
Feb 7, 2003
|
Feb 7, 2003
|
||||||
Add ? operation
|
Add ? operation
|
||||||
Fix ~ operation bug: eg '1.1.1' ~ '*.1'
|
Fix ~ operation bug: eg '1.1.1' ~ '*.1'
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
\set ECHO none
|
\set ECHO none
|
||||||
psql:ltree.sql:9: NOTICE: ProcedureCreate: type ltree is not yet defined
|
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:14: NOTICE: Argument type "ltree" is only a shell
|
||||||
psql:ltree.sql:281: NOTICE: ProcedureCreate: type lquery is not yet defined
|
psql:ltree.sql:301: NOTICE: ProcedureCreate: type lquery is not yet defined
|
||||||
psql:ltree.sql:286: NOTICE: Argument type "lquery" is only a shell
|
psql:ltree.sql:306: NOTICE: Argument type "lquery" is only a shell
|
||||||
psql:ltree.sql:392: NOTICE: ProcedureCreate: type ltxtquery is not yet defined
|
psql:ltree.sql:412: NOTICE: ProcedureCreate: type ltxtquery is not yet defined
|
||||||
psql:ltree.sql:397: NOTICE: Argument type "ltxtquery" is only a shell
|
psql:ltree.sql:417: NOTICE: Argument type "ltxtquery" is only a shell
|
||||||
psql:ltree.sql:459: NOTICE: ProcedureCreate: type ltree_gist is not yet defined
|
psql:ltree.sql:479: NOTICE: ProcedureCreate: type ltree_gist is not yet defined
|
||||||
psql:ltree.sql:464: NOTICE: Argument type "ltree_gist" is only a shell
|
psql:ltree.sql:484: NOTICE: Argument type "ltree_gist" is only a shell
|
||||||
SELECT ''::ltree;
|
SELECT ''::ltree;
|
||||||
ltree
|
ltree
|
||||||
-------
|
-------
|
||||||
@ -31,6 +31,18 @@ SELECT '1.2._3'::ltree;
|
|||||||
1.2._3
|
1.2._3
|
||||||
(1 row)
|
(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);
|
SELECT subltree('Top.Child1.Child2',1,2);
|
||||||
subltree
|
subltree
|
||||||
----------
|
----------
|
||||||
@ -85,6 +97,114 @@ SELECT subpath('Top.Child1.Child2',1);
|
|||||||
Child1.Child2
|
Child1.Child2
|
||||||
(1 row)
|
(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;
|
SELECT 'Top.Child1.Child2'::ltree || 'Child3'::text;
|
||||||
?column?
|
?column?
|
||||||
--------------------------
|
--------------------------
|
||||||
|
@ -137,11 +137,31 @@ RETURNS ltree
|
|||||||
AS 'MODULE_PATHNAME'
|
AS 'MODULE_PATHNAME'
|
||||||
LANGUAGE 'C' WITH (isstrict,iscachable);
|
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)
|
CREATE FUNCTION nlevel(ltree)
|
||||||
RETURNS int4
|
RETURNS int4
|
||||||
AS 'MODULE_PATHNAME'
|
AS 'MODULE_PATHNAME'
|
||||||
LANGUAGE 'C' WITH (isstrict,iscachable);
|
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)
|
CREATE FUNCTION lca(_ltree)
|
||||||
RETURNS ltree
|
RETURNS ltree
|
||||||
AS 'MODULE_PATHNAME','_lca'
|
AS 'MODULE_PATHNAME','_lca'
|
||||||
|
@ -19,10 +19,13 @@ PG_FUNCTION_INFO_V1(ltree_isparent);
|
|||||||
PG_FUNCTION_INFO_V1(ltree_risparent);
|
PG_FUNCTION_INFO_V1(ltree_risparent);
|
||||||
PG_FUNCTION_INFO_V1(subltree);
|
PG_FUNCTION_INFO_V1(subltree);
|
||||||
PG_FUNCTION_INFO_V1(subpath);
|
PG_FUNCTION_INFO_V1(subpath);
|
||||||
|
PG_FUNCTION_INFO_V1(ltree_index);
|
||||||
PG_FUNCTION_INFO_V1(ltree_addltree);
|
PG_FUNCTION_INFO_V1(ltree_addltree);
|
||||||
PG_FUNCTION_INFO_V1(ltree_addtext);
|
PG_FUNCTION_INFO_V1(ltree_addtext);
|
||||||
PG_FUNCTION_INFO_V1(ltree_textadd);
|
PG_FUNCTION_INFO_V1(ltree_textadd);
|
||||||
PG_FUNCTION_INFO_V1(lca);
|
PG_FUNCTION_INFO_V1(lca);
|
||||||
|
PG_FUNCTION_INFO_V1(ltree2text);
|
||||||
|
PG_FUNCTION_INFO_V1(text2ltree);
|
||||||
Datum ltree_cmp(PG_FUNCTION_ARGS);
|
Datum ltree_cmp(PG_FUNCTION_ARGS);
|
||||||
Datum ltree_lt(PG_FUNCTION_ARGS);
|
Datum ltree_lt(PG_FUNCTION_ARGS);
|
||||||
Datum ltree_le(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 nlevel(PG_FUNCTION_ARGS);
|
||||||
Datum subltree(PG_FUNCTION_ARGS);
|
Datum subltree(PG_FUNCTION_ARGS);
|
||||||
Datum subpath(PG_FUNCTION_ARGS);
|
Datum subpath(PG_FUNCTION_ARGS);
|
||||||
|
Datum ltree_index(PG_FUNCTION_ARGS);
|
||||||
Datum ltree_addltree(PG_FUNCTION_ARGS);
|
Datum ltree_addltree(PG_FUNCTION_ARGS);
|
||||||
Datum ltree_addtext(PG_FUNCTION_ARGS);
|
Datum ltree_addtext(PG_FUNCTION_ARGS);
|
||||||
Datum ltree_textadd(PG_FUNCTION_ARGS);
|
Datum ltree_textadd(PG_FUNCTION_ARGS);
|
||||||
Datum lca(PG_FUNCTION_ARGS);
|
Datum lca(PG_FUNCTION_ARGS);
|
||||||
|
Datum ltree2text(PG_FUNCTION_ARGS);
|
||||||
|
Datum text2ltree(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
int
|
int
|
||||||
ltree_compare(const ltree * a, const ltree * b)
|
ltree_compare(const ltree * a, const ltree * b)
|
||||||
@ -317,6 +323,57 @@ ltree_addtext(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_POINTER(r);
|
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
|
Datum
|
||||||
ltree_textadd(PG_FUNCTION_ARGS)
|
ltree_textadd(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
@ -431,3 +488,55 @@ lca(PG_FUNCTION_ARGS)
|
|||||||
else
|
else
|
||||||
PG_RETURN_NULL();
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,6 +7,9 @@ SELECT '1'::ltree;
|
|||||||
SELECT '1.2'::ltree;
|
SELECT '1.2'::ltree;
|
||||||
SELECT '1.2._3'::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 subltree('Top.Child1.Child2',1,2);
|
||||||
SELECT subpath('Top.Child1.Child2',1,2);
|
SELECT subpath('Top.Child1.Child2',1,2);
|
||||||
SELECT subpath('Top.Child1.Child2',-1,1);
|
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',0);
|
||||||
SELECT subpath('Top.Child1.Child2',1);
|
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'::text;
|
||||||
SELECT 'Top.Child1.Child2'::ltree || 'Child3'::ltree;
|
SELECT 'Top.Child1.Child2'::ltree || 'Child3'::ltree;
|
||||||
SELECT 'Top_0'::ltree || 'Top.Child1.Child2'::ltree;
|
SELECT 'Top_0'::ltree || 'Top.Child1.Child2'::ltree;
|
||||||
|
Reference in New Issue
Block a user