Ejemplo n.º 1
0
int
ltree_compare(const ltree *a, const ltree *b)
{
    ltree_level *al = LTREE_FIRST(a);
    ltree_level *bl = LTREE_FIRST(b);
    int			an = a->numlevel;
    int			bn = b->numlevel;
    int			res = 0;

    while (an > 0 && bn > 0)
    {
        if ((res = strncmp(al->name, bl->name, Min(al->len, bl->len))) == 0)
        {
            if (al->len != bl->len)
                return (al->len - bl->len) * 10 * (an + 1);
        }
        else
            return res * 10 * (an + 1);

        an--;
        bn--;
        al = LEVEL_NEXT(al);
        bl = LEVEL_NEXT(bl);
    }

    return (a->numlevel - b->numlevel) * 10 * (an + 1);
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
Datum
ltree2text(PG_FUNCTION_ARGS)
{
    ltree	   *in = PG_GETARG_LTREE(0);
    char	   *ptr;
    int			i;
    ltree_level *curlevel;
    text	   *out;

    out = (text *) palloc(VARSIZE(in) + 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);
    }

    SET_VARSIZE(out, ptr - ((char *) out));
    PG_FREE_IF_COPY(in, 0);

    PG_RETURN_POINTER(out);
}
static bool
checkcondition_str(void *checkval, ITEM *val)
{
	ltree_level *level = LTREE_FIRST(((CHKVAL *) checkval)->node);
	int			tlen = ((CHKVAL *) checkval)->node->numlevel;
	char	   *op = ((CHKVAL *) checkval)->operand + val->distance;
	int			(*cmpptr) (const char *, const char *, size_t);

	cmpptr = (val->flag & LVAR_INCASE) ? ltree_strncasecmp : strncmp;
	while (tlen > 0)
	{
		if (val->flag & LVAR_SUBLEXEME)
		{
			if (compare_subnode(level, op, val->length, cmpptr, (val->flag & LVAR_ANYEND)))
				return true;
		}
		else if (
				 (
				  val->length == level->len ||
				  (level->len > val->length && (val->flag & LVAR_ANYEND))
				  ) &&
				 (*cmpptr) (op, level->name, val->length) == 0)
			return true;

		tlen--;
		level = LEVEL_NEXT(level);
	}

	return false;
}
Datum
ltree_out(PG_FUNCTION_ARGS)
{
	ltree	   *in = PG_GETARG_LTREE(0);
	char	   *buf,
			   *ptr;
	int			i;
	ltree_level *curlevel;

	ptr = buf = (char *) palloc(VARSIZE(in));
	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);
	}

	*ptr = '\0';
	PG_FREE_IF_COPY(in, 0);

	PG_RETURN_POINTER(buf);
}
Ejemplo n.º 6
0
Datum
ltree_to_plpython(PG_FUNCTION_ARGS)
{
	ltree	   *in = PG_GETARG_LTREE_P(0);
	int			i;
	PyObject   *list;
	ltree_level *curlevel;

	list = PyList_New(in->numlevel);
	if (!list)
		ereport(ERROR,
				(errcode(ERRCODE_OUT_OF_MEMORY),
				 errmsg("out of memory")));

	curlevel = LTREE_FIRST(in);
	for (i = 0; i < in->numlevel; i++)
	{
		PyList_SetItem(list, i, PyString_FromStringAndSize(curlevel->name, curlevel->len));
		curlevel = LEVEL_NEXT(curlevel);
	}

	PG_FREE_IF_COPY(in, 0);

	return PointerGetDatum(list);
}
Ejemplo n.º 7
0
static ltree *
inner_subltree(ltree *t, int4 startpos, int4 endpos)
{
    char	   *start = NULL,
                *end = NULL;
    ltree_level *ptr = LTREE_FIRST(t);
    ltree	   *res;
    int			i;

    if (startpos < 0 || endpos < 0 || startpos >= t->numlevel || startpos > endpos)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("invalid positions")));

    if (endpos > t->numlevel)
        endpos = t->numlevel;

    start = end = (char *) ptr;
    for (i = 0; i < endpos; i++)
    {
        if (i == startpos)
            start = (char *) ptr;
        if (i == endpos - 1)
        {
            end = (char *) LEVEL_NEXT(ptr);
            break;
        }
        ptr = LEVEL_NEXT(ptr);
    }

    res = (ltree *) palloc(LTREE_HDRSIZE + (end - start));
    SET_VARSIZE(res, LTREE_HDRSIZE + (end - start));
    res->numlevel = endpos - startpos;

    memcpy(LTREE_FIRST(res), start, end - start);

    return res;
}
Ejemplo n.º 8
0
bool
inner_isparent(const ltree *c, const ltree *p)
{
    ltree_level *cl = LTREE_FIRST(c);
    ltree_level *pl = LTREE_FIRST(p);
    int			pn = p->numlevel;

    if (pn > c->numlevel)
        return false;

    while (pn > 0)
    {
        if (cl->len != pl->len)
            return false;
        if (strncmp(cl->name, pl->name, cl->len))
            return false;

        pn--;
        cl = LEVEL_NEXT(cl);
        pl = LEVEL_NEXT(pl);
    }
    return true;
}
Ejemplo n.º 9
0
static void
hashing(BITVECP sign, ltree * t)
{
	int			tlen = t->numlevel;
	ltree_level *cur = LTREE_FIRST(t);
	int			hash;

	while (tlen > 0)
	{
		hash = ltree_crc32_sz(cur->name, cur->len);
		AHASH(sign, hash);
		cur = LEVEL_NEXT(cur);
		tlen--;
	}
}
Ejemplo n.º 10
0
ltree *
lca_inner(ltree **a, int len)
{
    int			tmp,
                num = ((*a)->numlevel) ? (*a)->numlevel - 1 : 0;
    ltree	  **ptr = a + 1;
    int			i,
                reslen = LTREE_HDRSIZE;
    ltree_level *l1,
                *l2;
    ltree	   *res;


    if ((*a)->numlevel == 0)
        return NULL;

    while (ptr - a < len)
    {
        if ((*ptr)->numlevel == 0)
            return NULL;
        else if ((*ptr)->numlevel == 1)
            num = 0;
        else
        {
            l1 = LTREE_FIRST(*a);
            l2 = LTREE_FIRST(*ptr);
            tmp = num;
            num = 0;
            for (i = 0; i < Min(tmp, (*ptr)->numlevel - 1); i++)
            {
                if (l1->len == l2->len && strncmp(l1->name, l2->name, l1->len) == 0)
                    num = i + 1;
                else
                    break;
                l1 = LEVEL_NEXT(l1);
                l2 = LEVEL_NEXT(l2);
            }
        }
        ptr++;
    }

    l1 = LTREE_FIRST(*a);
    for (i = 0; i < num; i++)
    {
        reslen += MAXALIGN(l1->len + LEVEL_HDRSIZE);
        l1 = LEVEL_NEXT(l1);
    }

    res = (ltree *) palloc(reslen);
    SET_VARSIZE(res, reslen);
    res->numlevel = num;

    l1 = LTREE_FIRST(*a);
    l2 = LTREE_FIRST(res);

    for (i = 0; i < num; i++)
    {
        memcpy(l2, l1, MAXALIGN(l1->len + LEVEL_HDRSIZE));
        l1 = LEVEL_NEXT(l1);
        l2 = LEVEL_NEXT(l2);
    }

    return res;
}
Datum
ltree_in(PG_FUNCTION_ARGS)
{
	char	   *buf = (char *) PG_GETARG_POINTER(0);
	char	   *ptr;
	nodeitem   *list,
			   *lptr;
	int			num = 0,
				totallen = 0;
	int			state = LTPRS_WAITNAME;
	ltree	   *result;
	ltree_level *curlevel;
	int			charlen;
	int			pos = 0;

	ptr = buf;
	while (*ptr)
	{
		charlen = pg_mblen(ptr);
		if (charlen == 1 && t_iseq(ptr, '.'))
			num++;
		ptr += charlen;
	}

	if (num + 1 > MaxAllocSize / sizeof(nodeitem))
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
			 errmsg("number of levels (%d) exceeds the maximum allowed (%d)",
					num + 1, (int) (MaxAllocSize / sizeof(nodeitem)))));
	list = lptr = (nodeitem *) palloc(sizeof(nodeitem) * (num + 1));
	ptr = buf;
	while (*ptr)
	{
		charlen = pg_mblen(ptr);

		if (state == LTPRS_WAITNAME)
		{
			if (ISALNUM(ptr))
			{
				lptr->start = ptr;
				lptr->wlen = 0;
				state = LTPRS_WAITDELIM;
			}
			else
				UNCHAR;
		}
		else if (state == LTPRS_WAITDELIM)
		{
			if (charlen == 1 && t_iseq(ptr, '.'))
			{
				lptr->len = ptr - lptr->start;
				if (lptr->wlen > 255)
					ereport(ERROR,
							(errcode(ERRCODE_NAME_TOO_LONG),
							 errmsg("name of level is too long"),
							 errdetail("Name length is %d, must "
									   "be < 256, in position %d.",
									   lptr->wlen, pos)));

				totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
				lptr++;
				state = LTPRS_WAITNAME;
			}
			else if (!ISALNUM(ptr))
				UNCHAR;
		}
		else
			/* internal error */
			elog(ERROR, "internal error in parser");

		ptr += charlen;
		lptr->wlen++;
		pos++;
	}

	if (state == LTPRS_WAITDELIM)
	{
		lptr->len = ptr - lptr->start;
		if (lptr->wlen > 255)
			ereport(ERROR,
					(errcode(ERRCODE_NAME_TOO_LONG),
					 errmsg("name of level is too long"),
					 errdetail("Name length is %d, must "
							   "be < 256, in position %d.",
							   lptr->wlen, pos)));

		totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
		lptr++;
	}
	else if (!(state == LTPRS_WAITNAME && lptr == list))
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
				 errmsg("syntax error"),
				 errdetail("Unexpected end of line.")));

	result = (ltree *) palloc0(LTREE_HDRSIZE + totallen);
	SET_VARSIZE(result, LTREE_HDRSIZE + totallen);
	result->numlevel = lptr - list;
	curlevel = LTREE_FIRST(result);
	lptr = list;
	while (lptr - list < result->numlevel)
	{
		curlevel->len = (uint16) lptr->len;
		memcpy(curlevel->name, lptr->start, lptr->len);
		curlevel = LEVEL_NEXT(curlevel);
		lptr++;
	}

	pfree(list);
	PG_RETURN_POINTER(result);
}
Ejemplo n.º 12
0
static bool
checkCond(lquery_level * curq, int query_numlevel, ltree_level * curt, int tree_numlevel, FieldNot * ptr)
{
	uint32		low_pos = 0,
				high_pos = 0,
				cur_tpos = 0;
	int			tlen = tree_numlevel,
				qlen = query_numlevel;
	int			isok;
	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)
		{
			prevt = curt;
			while (cur_tpos < low_pos)
			{
				curt = LEVEL_NEXT(curt);
				tlen--;
				cur_tpos++;
				if (tlen == 0)
					return false;
				if (ptr && ptr->q)
					ptr->nt++;
			}

			if (ptr && curq->flag & LQL_NOT)
			{
				if (!(prevq && prevq->numvar == 0))
					prevq = curq;
				if (ptr->q == NULL)
				{
					ptr->t = prevt;
					ptr->q = prevq;
					ptr->nt = 1;
					ptr->nq = 1 + ((prevq == curq) ? 0 : 1);
					ptr->posq = query_numlevel - qlen - ((prevq == curq) ? 0 : 1);
					ptr->post = cur_tpos;
				}
				else
				{
					ptr->nt++;
					ptr->nq++;
				}

				if (qlen == 1 && ptr->q->numvar == 0)
					ptr->nt = tree_numlevel - ptr->post;
				curt = LEVEL_NEXT(curt);
				tlen--;
				cur_tpos++;
				if (high_pos < cur_tpos)
					high_pos++;
			}
			else
			{
				isok = false;
				while (cur_tpos <= high_pos && tlen > 0 && !isok)
				{
					isok = checkLevel(curq, curt);
					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++;
				}
				if (!isok)
					return false;

				if (ptr && ptr->q)
				{
					if (checkCond(ptr->q, ptr->nq, ptr->t, ptr->nt, NULL))
						return false;
					ptr->q = NULL;
				}
				low_pos = cur_tpos;
				high_pos = cur_tpos;
			}
		}
		else
		{
			low_pos = cur_tpos + curq->low;
			high_pos = cur_tpos + curq->high;
			if (ptr && ptr->q)
			{
				ptr->nq++;
				if (qlen == 1)
					ptr->nt = tree_numlevel - ptr->post;
			}
		}

		prevq = curq;
		curq = LQL_NEXT(curq);
		qlen--;
	}

	if (low_pos > tree_numlevel || tree_numlevel > high_pos)
		return false;

	while (qlen > 0)
	{
		if (curq->numvar)
		{
			if (!(curq->flag & LQL_NOT))
				return false;
		}
		else
		{
			low_pos = cur_tpos + curq->low;
			high_pos = cur_tpos + curq->high;
		}

		curq = LQL_NEXT(curq);
		qlen--;
	}

	if (low_pos > tree_numlevel || tree_numlevel > high_pos)
		return false;

	if (ptr && ptr->q && checkCond(ptr->q, ptr->nq, ptr->t, ptr->nt, NULL))
		return false;

	return true;
}