#include "postgres.h"
#include <ctype.h>
#include "ltree.h"
#include "crc32.h"
Go to the source code of this file.
Data Structures | |
struct | nodeitem |
Defines | |
#define | UNCHAR |
#define | LTPRS_WAITNAME 0 |
#define | LTPRS_WAITDELIM 1 |
#define | LQPRS_WAITLEVEL 0 |
#define | LQPRS_WAITDELIM 1 |
#define | LQPRS_WAITOPEN 2 |
#define | LQPRS_WAITFNUM 3 |
#define | LQPRS_WAITSNUM 4 |
#define | LQPRS_WAITND 5 |
#define | LQPRS_WAITCLOSE 6 |
#define | LQPRS_WAITEND 7 |
#define | LQPRS_WAITVAR 8 |
#define | GETVAR(x) ( *((nodeitem**)LQL_FIRST(x)) ) |
#define | ITEMSIZE MAXALIGN(LQL_HDRSIZE+sizeof(nodeitem*)) |
#define | NEXTLEV(x) ( (lquery_level*)( ((char*)(x)) + ITEMSIZE) ) |
Functions | |
PG_FUNCTION_INFO_V1 (ltree_in) | |
Datum | ltree_in (PG_FUNCTION_ARGS) |
PG_FUNCTION_INFO_V1 (ltree_out) | |
Datum | ltree_out (PG_FUNCTION_ARGS) |
PG_FUNCTION_INFO_V1 (lquery_in) | |
Datum | lquery_in (PG_FUNCTION_ARGS) |
PG_FUNCTION_INFO_V1 (lquery_out) | |
Datum | lquery_out (PG_FUNCTION_ARGS) |
#define GETVAR | ( | x | ) | ( *((nodeitem**)LQL_FIRST(x)) ) |
Definition at line 190 of file ltree_io.c.
Referenced by lquery_in().
#define ITEMSIZE MAXALIGN(LQL_HDRSIZE+sizeof(nodeitem*)) |
Definition at line 191 of file ltree_io.c.
Referenced by lquery_in().
#define LQPRS_WAITCLOSE 6 |
Definition at line 185 of file ltree_io.c.
Referenced by lquery_in().
#define LQPRS_WAITDELIM 1 |
Definition at line 180 of file ltree_io.c.
Referenced by lquery_in().
#define LQPRS_WAITEND 7 |
Definition at line 186 of file ltree_io.c.
Referenced by lquery_in().
#define LQPRS_WAITFNUM 3 |
Definition at line 182 of file ltree_io.c.
Referenced by lquery_in().
#define LQPRS_WAITLEVEL 0 |
Definition at line 179 of file ltree_io.c.
Referenced by lquery_in().
#define LQPRS_WAITND 5 |
Definition at line 184 of file ltree_io.c.
Referenced by lquery_in().
#define LQPRS_WAITOPEN 2 |
Definition at line 181 of file ltree_io.c.
Referenced by lquery_in().
#define LQPRS_WAITSNUM 4 |
Definition at line 183 of file ltree_io.c.
Referenced by lquery_in().
#define LQPRS_WAITVAR 8 |
Definition at line 187 of file ltree_io.c.
Referenced by lquery_in().
#define LTPRS_WAITDELIM 1 |
Definition at line 41 of file ltree_io.c.
Referenced by ltree_in().
#define LTPRS_WAITNAME 0 |
Definition at line 40 of file ltree_io.c.
Referenced by ltree_in().
#define NEXTLEV | ( | x | ) | ( (lquery_level*)( ((char*)(x)) + ITEMSIZE) ) |
Definition at line 192 of file ltree_io.c.
Referenced by lquery_in().
#define UNCHAR |
Datum lquery_in | ( | PG_FUNCTION_ARGS | ) |
Definition at line 195 of file ltree_io.c.
References buf, cur, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, lquery::firstgood, lquery_variant::flag, lquery::flag, nodeitem::flag, lquery_level::flag, GETVAR, lquery_level::high, ISALNUM, ITEMSIZE, lquery_variant::len, nodeitem::len, lquery_level::low, LQL_FIRST, LQL_HDRSIZE, LQL_NEXT, LQPRS_WAITCLOSE, LQPRS_WAITDELIM, LQPRS_WAITEND, LQPRS_WAITFNUM, LQPRS_WAITLEVEL, LQPRS_WAITND, LQPRS_WAITOPEN, LQPRS_WAITSNUM, LQPRS_WAITVAR, LQUERY_FIRST, ltree_crc32_sz(), LVAR_HDRSIZE, LVAR_NEXT, MAXALIGN, lquery_variant::name, NEXTLEV, lquery::numlevel, lquery_level::numvar, palloc0(), pfree(), PG_GETARG_POINTER, pg_mblen(), PG_RETURN_POINTER, SET_VARSIZE, nodeitem::start, t_isdigit, t_iseq, lquery_level::totallen, lquery_variant::val, and nodeitem::wlen.
{ char *buf = (char *) PG_GETARG_POINTER(0); char *ptr; int num = 0, totallen = 0, numOR = 0; int state = LQPRS_WAITLEVEL; lquery *result; nodeitem *lptr = NULL; lquery_level *cur, *curqlevel, *tmpql; lquery_variant *lrptr = NULL; bool hasnot = false; bool wasbad = false; int charlen; int pos = 0; ptr = buf; while (*ptr) { charlen = pg_mblen(ptr); if (charlen == 1) { if (t_iseq(ptr, '.')) num++; else if (t_iseq(ptr, '|')) numOR++; } ptr += charlen; } num++; curqlevel = tmpql = (lquery_level *) palloc0(ITEMSIZE * num); ptr = buf; while (*ptr) { charlen = pg_mblen(ptr); if (state == LQPRS_WAITLEVEL) { if (ISALNUM(ptr)) { GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1)); lptr->start = ptr; state = LQPRS_WAITDELIM; curqlevel->numvar = 1; } else if (charlen == 1 && t_iseq(ptr, '!')) { GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1)); lptr->start = ptr + 1; state = LQPRS_WAITDELIM; curqlevel->numvar = 1; curqlevel->flag |= LQL_NOT; hasnot = true; } else if (charlen == 1 && t_iseq(ptr, '*')) state = LQPRS_WAITOPEN; else UNCHAR; } else if (state == LQPRS_WAITVAR) { if (ISALNUM(ptr)) { lptr++; lptr->start = ptr; state = LQPRS_WAITDELIM; curqlevel->numvar++; } else UNCHAR; } else if (state == LQPRS_WAITDELIM) { if (charlen == 1 && t_iseq(ptr, '@')) { if (lptr->start == ptr) UNCHAR; lptr->flag |= LVAR_INCASE; curqlevel->flag |= LVAR_INCASE; } else if (charlen == 1 && t_iseq(ptr, '*')) { if (lptr->start == ptr) UNCHAR; lptr->flag |= LVAR_ANYEND; curqlevel->flag |= LVAR_ANYEND; } else if (charlen == 1 && t_iseq(ptr, '%')) { if (lptr->start == ptr) UNCHAR; lptr->flag |= LVAR_SUBLEXEME; curqlevel->flag |= LVAR_SUBLEXEME; } else if (charlen == 1 && t_iseq(ptr, '|')) { lptr->len = ptr - lptr->start - ((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) - ((lptr->flag & LVAR_INCASE) ? 1 : 0) - ((lptr->flag & LVAR_ANYEND) ? 1 : 0); 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))); state = LQPRS_WAITVAR; } else if (charlen == 1 && t_iseq(ptr, '.')) { lptr->len = ptr - lptr->start - ((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) - ((lptr->flag & LVAR_INCASE) ? 1 : 0) - ((lptr->flag & LVAR_ANYEND) ? 1 : 0); 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))); state = LQPRS_WAITLEVEL; curqlevel = NEXTLEV(curqlevel); } else if (ISALNUM(ptr)) { if (lptr->flag) UNCHAR; } else UNCHAR; } else if (state == LQPRS_WAITOPEN) { if (charlen == 1 && t_iseq(ptr, '{')) state = LQPRS_WAITFNUM; else if (charlen == 1 && t_iseq(ptr, '.')) { curqlevel->low = 0; curqlevel->high = 0xffff; curqlevel = NEXTLEV(curqlevel); state = LQPRS_WAITLEVEL; } else UNCHAR; } else if (state == LQPRS_WAITFNUM) { if (charlen == 1 && t_iseq(ptr, ',')) state = LQPRS_WAITSNUM; else if (t_isdigit(ptr)) { curqlevel->low = atoi(ptr); state = LQPRS_WAITND; } else UNCHAR; } else if (state == LQPRS_WAITSNUM) { if (t_isdigit(ptr)) { curqlevel->high = atoi(ptr); state = LQPRS_WAITCLOSE; } else if (charlen == 1 && t_iseq(ptr, '}')) { curqlevel->high = 0xffff; state = LQPRS_WAITEND; } else UNCHAR; } else if (state == LQPRS_WAITCLOSE) { if (charlen == 1 && t_iseq(ptr, '}')) state = LQPRS_WAITEND; else if (!t_isdigit(ptr)) UNCHAR; } else if (state == LQPRS_WAITND) { if (charlen == 1 && t_iseq(ptr, '}')) { curqlevel->high = curqlevel->low; state = LQPRS_WAITEND; } else if (charlen == 1 && t_iseq(ptr, ',')) state = LQPRS_WAITSNUM; else if (!t_isdigit(ptr)) UNCHAR; } else if (state == LQPRS_WAITEND) { if (charlen == 1 && t_iseq(ptr, '.')) { state = LQPRS_WAITLEVEL; curqlevel = NEXTLEV(curqlevel); } else UNCHAR; } else /* internal error */ elog(ERROR, "internal error in parser"); ptr += charlen; if (state == LQPRS_WAITDELIM) lptr->wlen++; pos++; } if (state == LQPRS_WAITDELIM) { if (lptr->start == ptr) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("syntax error"), errdetail("Unexpected end of line."))); lptr->len = ptr - lptr->start - ((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) - ((lptr->flag & LVAR_INCASE) ? 1 : 0) - ((lptr->flag & LVAR_ANYEND) ? 1 : 0); if (lptr->len == 0) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("syntax error"), errdetail("Unexpected end of line."))); 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))); } else if (state == LQPRS_WAITOPEN) curqlevel->high = 0xffff; else if (state != LQPRS_WAITEND) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("syntax error"), errdetail("Unexpected end of line."))); curqlevel = tmpql; totallen = LQUERY_HDRSIZE; while ((char *) curqlevel - (char *) tmpql < num * ITEMSIZE) { totallen += LQL_HDRSIZE; if (curqlevel->numvar) { lptr = GETVAR(curqlevel); while (lptr - GETVAR(curqlevel) < curqlevel->numvar) { totallen += MAXALIGN(LVAR_HDRSIZE + lptr->len); lptr++; } } else if (curqlevel->low > curqlevel->high) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("syntax error"), errdetail("Low limit(%d) is greater than upper(%d).", curqlevel->low, curqlevel->high))); curqlevel = NEXTLEV(curqlevel); } result = (lquery *) palloc0(totallen); SET_VARSIZE(result, totallen); result->numlevel = num; result->firstgood = 0; result->flag = 0; if (hasnot) result->flag |= LQUERY_HASNOT; cur = LQUERY_FIRST(result); curqlevel = tmpql; while ((char *) curqlevel - (char *) tmpql < num * ITEMSIZE) { memcpy(cur, curqlevel, LQL_HDRSIZE); cur->totallen = LQL_HDRSIZE; if (curqlevel->numvar) { lrptr = LQL_FIRST(cur); lptr = GETVAR(curqlevel); while (lptr - GETVAR(curqlevel) < curqlevel->numvar) { cur->totallen += MAXALIGN(LVAR_HDRSIZE + lptr->len); lrptr->len = lptr->len; lrptr->flag = lptr->flag; lrptr->val = ltree_crc32_sz(lptr->start, lptr->len); memcpy(lrptr->name, lptr->start, lptr->len); lptr++; lrptr = LVAR_NEXT(lrptr); } pfree(GETVAR(curqlevel)); if (cur->numvar > 1 || cur->flag != 0) wasbad = true; else if (wasbad == false) (result->firstgood)++; } else wasbad = true; curqlevel = NEXTLEV(curqlevel); cur = LQL_NEXT(cur); } pfree(tmpql); PG_RETURN_POINTER(result); }
Datum lquery_out | ( | PG_FUNCTION_ARGS | ) |
Definition at line 518 of file ltree_io.c.
References buf, lquery_variant::flag, lquery_level::flag, lquery_level::high, i, lquery_variant::len, lquery_level::low, LQL_FIRST, LQL_NEXT, LQL_NOT, LQUERY_FIRST, LVAR_ANYEND, LVAR_INCASE, LVAR_NEXT, LVAR_SUBLEXEME, lquery_variant::name, lquery::numlevel, lquery_level::numvar, palloc(), PG_FREE_IF_COPY, PG_GETARG_LQUERY, PG_RETURN_POINTER, and lquery_level::totallen.
{ lquery *in = PG_GETARG_LQUERY(0); char *buf, *ptr; int i, j, totallen = 1; lquery_level *curqlevel; lquery_variant *curtlevel; curqlevel = LQUERY_FIRST(in); for (i = 0; i < in->numlevel; i++) { totallen++; if (curqlevel->numvar) totallen += 1 + (curqlevel->numvar * 4) + curqlevel->totallen; else totallen += 2 * 11 + 4; curqlevel = LQL_NEXT(curqlevel); } ptr = buf = (char *) palloc(totallen); curqlevel = LQUERY_FIRST(in); for (i = 0; i < in->numlevel; i++) { if (i != 0) { *ptr = '.'; ptr++; } if (curqlevel->numvar) { if (curqlevel->flag & LQL_NOT) { *ptr = '!'; ptr++; } curtlevel = LQL_FIRST(curqlevel); for (j = 0; j < curqlevel->numvar; j++) { if (j != 0) { *ptr = '|'; ptr++; } memcpy(ptr, curtlevel->name, curtlevel->len); ptr += curtlevel->len; if ((curtlevel->flag & LVAR_SUBLEXEME)) { *ptr = '%'; ptr++; } if ((curtlevel->flag & LVAR_INCASE)) { *ptr = '@'; ptr++; } if ((curtlevel->flag & LVAR_ANYEND)) { *ptr = '*'; ptr++; } curtlevel = LVAR_NEXT(curtlevel); } } else { if (curqlevel->low == curqlevel->high) { sprintf(ptr, "*{%d}", curqlevel->low); } else if (curqlevel->low == 0) { if (curqlevel->high == 0xffff) { *ptr = '*'; *(ptr + 1) = '\0'; } else sprintf(ptr, "*{,%d}", curqlevel->high); } else if (curqlevel->high == 0xffff) { sprintf(ptr, "*{%d,}", curqlevel->low); } else sprintf(ptr, "*{%d,%d}", curqlevel->low, curqlevel->high); ptr = strchr(ptr, '\0'); } curqlevel = LQL_NEXT(curqlevel); } *ptr = '\0'; PG_FREE_IF_COPY(in, 0); PG_RETURN_POINTER(buf); }
Datum ltree_in | ( | PG_FUNCTION_ARGS | ) |
Definition at line 44 of file ltree_io.c.
References buf, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, ISALNUM, ltree_level::len, nodeitem::len, LEVEL_HDRSIZE, LEVEL_NEXT, sort-test::list, LTPRS_WAITDELIM, LTPRS_WAITNAME, LTREE_FIRST, LTREE_HDRSIZE, MAXALIGN, ltree_level::name, ltree::numlevel, palloc(), palloc0(), pfree(), PG_GETARG_POINTER, pg_mblen(), PG_RETURN_POINTER, SET_VARSIZE, nodeitem::start, t_iseq, and nodeitem::wlen.
Referenced by ltree_addtext(), ltree_textadd(), and text2ltree().
{ 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; } 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); }
Datum ltree_out | ( | PG_FUNCTION_ARGS | ) |
Definition at line 151 of file ltree_io.c.
References buf, i, ltree_level::len, LEVEL_NEXT, LTREE_FIRST, ltree_level::name, ltree::numlevel, palloc(), PG_FREE_IF_COPY, PG_GETARG_LTREE, PG_RETURN_POINTER, and VARSIZE.
{ 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); }
PG_FUNCTION_INFO_V1 | ( | lquery_in | ) |
PG_FUNCTION_INFO_V1 | ( | ltree_in | ) |
PG_FUNCTION_INFO_V1 | ( | lquery_out | ) |
PG_FUNCTION_INFO_V1 | ( | ltree_out | ) |