PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ltree_io.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "crc32.h"
#include "libpq/pqformat.h"
#include "ltree.h"
#include "varatt.h"
Include dependency graph for ltree_io.c:

Go to the source code of this file.

Data Structures

struct  nodeitem
 

Macros

#define LTPRS_WAITNAME   0
 
#define LTPRS_WAITDELIM   1
 
#define UNCHAR
 
#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) )
 
#define UNCHAR
 

Functions

static bool finish_nodeitem (nodeitem *lptr, const char *ptr, bool is_lquery, int pos, struct Node *escontext)
 
static ltreeparse_ltree (const char *buf, struct Node *escontext)
 
static char * deparse_ltree (const ltree *in)
 
 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 (ltree_send)
 
Datum ltree_send (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (ltree_recv)
 
Datum ltree_recv (PG_FUNCTION_ARGS)
 
static lqueryparse_lquery (const char *buf, struct Node *escontext)
 
static char * deparse_lquery (const lquery *in)
 
 PG_FUNCTION_INFO_V1 (lquery_in)
 
Datum lquery_in (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (lquery_out)
 
Datum lquery_out (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (lquery_send)
 
Datum lquery_send (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (lquery_recv)
 
Datum lquery_recv (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ GETVAR

#define GETVAR (   x)    ( *((nodeitem**)LQL_FIRST(x)) )

Definition at line 259 of file ltree_io.c.

◆ ITEMSIZE

#define ITEMSIZE   MAXALIGN(LQL_HDRSIZE+sizeof(nodeitem*))

Definition at line 260 of file ltree_io.c.

◆ LQPRS_WAITCLOSE

#define LQPRS_WAITCLOSE   6

Definition at line 254 of file ltree_io.c.

◆ LQPRS_WAITDELIM

#define LQPRS_WAITDELIM   1

Definition at line 249 of file ltree_io.c.

◆ LQPRS_WAITEND

#define LQPRS_WAITEND   7

Definition at line 255 of file ltree_io.c.

◆ LQPRS_WAITFNUM

#define LQPRS_WAITFNUM   3

Definition at line 251 of file ltree_io.c.

◆ LQPRS_WAITLEVEL

#define LQPRS_WAITLEVEL   0

Definition at line 248 of file ltree_io.c.

◆ LQPRS_WAITND

#define LQPRS_WAITND   5

Definition at line 253 of file ltree_io.c.

◆ LQPRS_WAITOPEN

#define LQPRS_WAITOPEN   2

Definition at line 250 of file ltree_io.c.

◆ LQPRS_WAITSNUM

#define LQPRS_WAITSNUM   4

Definition at line 252 of file ltree_io.c.

◆ LQPRS_WAITVAR

#define LQPRS_WAITVAR   8

Definition at line 256 of file ltree_io.c.

◆ LTPRS_WAITDELIM

#define LTPRS_WAITDELIM   1

Definition at line 25 of file ltree_io.c.

◆ LTPRS_WAITNAME

#define LTPRS_WAITNAME   0

Definition at line 24 of file ltree_io.c.

◆ NEXTLEV

#define NEXTLEV (   x)    ( (lquery_level*)( ((char*)(x)) + ITEMSIZE) )

Definition at line 261 of file ltree_io.c.

◆ UNCHAR [1/2]

#define UNCHAR
Value:
ereturn(escontext, NULL,\
errcode(ERRCODE_SYNTAX_ERROR), \
errmsg("ltree syntax error at character %d", \
pos))
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereturn(context, dummy_value,...)
Definition: elog.h:277

◆ UNCHAR [2/2]

#define UNCHAR
Value:
ereturn(escontext, NULL,\
errcode(ERRCODE_SYNTAX_ERROR), \
errmsg("lquery syntax error at character %d", \
pos))

Function Documentation

◆ deparse_lquery()

static char * deparse_lquery ( const lquery in)
static

Definition at line 627 of file ltree_io.c.

628{
629 char *buf,
630 *ptr;
631 int i,
632 j,
633 totallen = 1;
634 lquery_level *curqlevel;
635 lquery_variant *curtlevel;
636
637 curqlevel = LQUERY_FIRST(in);
638 for (i = 0; i < in->numlevel; i++)
639 {
640 totallen++;
641 if (curqlevel->numvar)
642 {
643 totallen += 1 + (curqlevel->numvar * 4) + curqlevel->totallen;
644 if (curqlevel->flag & LQL_COUNT)
645 totallen += 2 * 11 + 3;
646 }
647 else
648 totallen += 2 * 11 + 4;
649 curqlevel = LQL_NEXT(curqlevel);
650 }
651
652 ptr = buf = (char *) palloc(totallen);
653 curqlevel = LQUERY_FIRST(in);
654 for (i = 0; i < in->numlevel; i++)
655 {
656 if (i != 0)
657 {
658 *ptr = '.';
659 ptr++;
660 }
661 if (curqlevel->numvar)
662 {
663 if (curqlevel->flag & LQL_NOT)
664 {
665 *ptr = '!';
666 ptr++;
667 }
668 curtlevel = LQL_FIRST(curqlevel);
669 for (j = 0; j < curqlevel->numvar; j++)
670 {
671 if (j != 0)
672 {
673 *ptr = '|';
674 ptr++;
675 }
676 memcpy(ptr, curtlevel->name, curtlevel->len);
677 ptr += curtlevel->len;
678 if ((curtlevel->flag & LVAR_SUBLEXEME))
679 {
680 *ptr = '%';
681 ptr++;
682 }
683 if ((curtlevel->flag & LVAR_INCASE))
684 {
685 *ptr = '@';
686 ptr++;
687 }
688 if ((curtlevel->flag & LVAR_ANYEND))
689 {
690 *ptr = '*';
691 ptr++;
692 }
693 curtlevel = LVAR_NEXT(curtlevel);
694 }
695 }
696 else
697 {
698 *ptr = '*';
699 ptr++;
700 }
701
702 if ((curqlevel->flag & LQL_COUNT) || curqlevel->numvar == 0)
703 {
704 if (curqlevel->low == curqlevel->high)
705 {
706 sprintf(ptr, "{%d}", curqlevel->low);
707 }
708 else if (curqlevel->low == 0)
709 {
710 if (curqlevel->high == LTREE_MAX_LEVELS)
711 {
712 if (curqlevel->numvar == 0)
713 {
714 /* This is default for '*', so print nothing */
715 *ptr = '\0';
716 }
717 else
718 sprintf(ptr, "{,}");
719 }
720 else
721 sprintf(ptr, "{,%d}", curqlevel->high);
722 }
723 else if (curqlevel->high == LTREE_MAX_LEVELS)
724 {
725 sprintf(ptr, "{%d,}", curqlevel->low);
726 }
727 else
728 sprintf(ptr, "{%d,%d}", curqlevel->low, curqlevel->high);
729 ptr = strchr(ptr, '\0');
730 }
731
732 curqlevel = LQL_NEXT(curqlevel);
733 }
734
735 *ptr = '\0';
736 return buf;
737}
int j
Definition: isn.c:73
int i
Definition: isn.c:72
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
#define LTREE_MAX_LEVELS
Definition: ltree.h:52
#define LVAR_INCASE
Definition: ltree.h:75
#define LVAR_ANYEND
Definition: ltree.h:74
#define LQL_FIRST(x)
Definition: ltree.h:101
#define LVAR_NEXT(x)
Definition: ltree.h:72
#define LQL_NEXT(x)
Definition: ltree.h:100
#define LQL_COUNT
Definition: ltree.h:104
#define LQUERY_FIRST(x)
Definition: ltree.h:124
#define LQL_NOT
Definition: ltree.h:103
#define LVAR_SUBLEXEME
Definition: ltree.h:76
void * palloc(Size size)
Definition: mcxt.c:1317
static char * buf
Definition: pg_test_fsync.c:72
#define sprintf
Definition: port.h:240
uint16 numvar
Definition: ltree.h:92
uint16 high
Definition: ltree.h:94
uint16 flag
Definition: ltree.h:91
uint16 low
Definition: ltree.h:93
uint16 totallen
Definition: ltree.h:90
uint8 flag
Definition: ltree.h:62
uint16 len
Definition: ltree.h:61
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:63
uint16 numlevel
Definition: ltree.h:116

References buf, lquery_variant::flag, lquery_level::flag, lquery_level::high, i, if(), j, lquery_variant::len, lquery_level::low, LQL_COUNT, LQL_FIRST, LQL_NEXT, LQL_NOT, LQUERY_FIRST, LTREE_MAX_LEVELS, LVAR_ANYEND, LVAR_INCASE, LVAR_NEXT, LVAR_SUBLEXEME, lquery_variant::name, lquery::numlevel, lquery_level::numvar, palloc(), sprintf, and lquery_level::totallen.

Referenced by lquery_out(), and lquery_send().

◆ deparse_ltree()

static char * deparse_ltree ( const ltree in)
static

Definition at line 144 of file ltree_io.c.

145{
146 char *buf,
147 *ptr;
148 int i;
149 ltree_level *curlevel;
150
151 ptr = buf = (char *) palloc(VARSIZE(in));
152 curlevel = LTREE_FIRST(in);
153 for (i = 0; i < in->numlevel; i++)
154 {
155 if (i != 0)
156 {
157 *ptr = '.';
158 ptr++;
159 }
160 memcpy(ptr, curlevel->name, curlevel->len);
161 ptr += curlevel->len;
162 curlevel = LEVEL_NEXT(curlevel);
163 }
164
165 *ptr = '\0';
166 return buf;
167}
#define LTREE_FIRST(x)
Definition: ltree.h:51
#define LEVEL_NEXT(x)
Definition: ltree.h:40
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:36
uint16 len
Definition: ltree.h:35
uint16 numlevel
Definition: ltree.h:45
#define VARSIZE(PTR)
Definition: varatt.h:279

References buf, i, ltree_level::len, LEVEL_NEXT, LTREE_FIRST, ltree_level::name, ltree::numlevel, palloc(), and VARSIZE.

Referenced by ltree_out(), and ltree_send().

◆ finish_nodeitem()

static bool finish_nodeitem ( nodeitem lptr,
const char *  ptr,
bool  is_lquery,
int  pos,
struct Node escontext 
)
static

Definition at line 585 of file ltree_io.c.

587{
588 if (is_lquery)
589 {
590 /*
591 * Back up over any flag characters, and discount them from length and
592 * position.
593 */
594 while (ptr > lptr->start && strchr("@*%", ptr[-1]) != NULL)
595 {
596 ptr--;
597 lptr->wlen--;
598 pos--;
599 }
600 }
601
602 /* Now compute the byte length, which we weren't tracking before. */
603 lptr->len = ptr - lptr->start;
604
605 /* Complain if it's empty or too long */
606 if (lptr->len == 0)
607 ereturn(escontext, false,
608 (errcode(ERRCODE_SYNTAX_ERROR),
609 is_lquery ?
610 errmsg("lquery syntax error at character %d", pos) :
611 errmsg("ltree syntax error at character %d", pos),
612 errdetail("Empty labels are not allowed.")));
613 if (lptr->wlen > LTREE_LABEL_MAX_CHARS)
614 ereturn(escontext, false,
615 (errcode(ERRCODE_NAME_TOO_LONG),
616 errmsg("label string is too long"),
617 errdetail("Label length is %d, must be at most %d, at character %d.",
618 lptr->wlen, LTREE_LABEL_MAX_CHARS, pos)));
619 return true;
620}
int errdetail(const char *fmt,...)
Definition: elog.c:1203
#define LTREE_LABEL_MAX_CHARS
Definition: ltree.h:18
int wlen
Definition: ltree_io.c:21
const char * start
Definition: ltree_io.c:18
int len
Definition: ltree_io.c:19

References ereturn, errcode(), errdetail(), errmsg(), nodeitem::len, LTREE_LABEL_MAX_CHARS, nodeitem::start, and nodeitem::wlen.

Referenced by parse_lquery(), and parse_ltree().

◆ lquery_in()

Datum lquery_in ( PG_FUNCTION_ARGS  )

Definition at line 744 of file ltree_io.c.

745{
746 char *buf = (char *) PG_GETARG_POINTER(0);
747 lquery *res;
748
749 if ((res = parse_lquery(buf, fcinfo->context)) == NULL)
751
753}
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
static lquery * parse_lquery(const char *buf, struct Node *escontext)
Definition: ltree_io.c:268
Definition: ltree.h:114

References buf, parse_lquery(), PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_POINTER, and res.

◆ lquery_out()

Datum lquery_out ( PG_FUNCTION_ARGS  )

Definition at line 757 of file ltree_io.c.

758{
759 lquery *in = PG_GETARG_LQUERY_P(0);
760
762}
#define PG_GETARG_LQUERY_P(n)
Definition: ltree.h:223
static char * deparse_lquery(const lquery *in)
Definition: ltree_io.c:627

References deparse_lquery(), PG_GETARG_LQUERY_P, and PG_RETURN_POINTER.

◆ lquery_recv()

Datum lquery_recv ( PG_FUNCTION_ARGS  )

Definition at line 799 of file ltree_io.c.

800{
802 int version = pq_getmsgint(buf, 1);
803 char *str;
804 int nbytes;
805 lquery *res;
806
807 if (version != 1)
808 elog(ERROR, "unsupported lquery version number %d", version);
809
810 str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
811 res = parse_lquery(str, NULL);
812 pfree(str);
813
815}
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
const char * str
void pfree(void *pointer)
Definition: mcxt.c:1521
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:546
StringInfoData * StringInfo
Definition: stringinfo.h:54

References buf, elog, ERROR, parse_lquery(), pfree(), PG_GETARG_POINTER, PG_RETURN_POINTER, pq_getmsgint(), pq_getmsgtext(), res, and str.

◆ lquery_send()

Datum lquery_send ( PG_FUNCTION_ARGS  )

Definition at line 774 of file ltree_io.c.

775{
776 lquery *in = PG_GETARG_LQUERY_P(0);
778 int version = 1;
779 char *res = deparse_lquery(in);
780
782 pq_sendint8(&buf, version);
783 pq_sendtext(&buf, res, strlen(res));
784 pfree(res);
785
787}
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:172
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendint8(StringInfo buf, uint8 i)
Definition: pqformat.h:128

References buf, deparse_lquery(), pfree(), PG_GETARG_LQUERY_P, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendint8(), pq_sendtext(), and res.

◆ ltree_in()

Datum ltree_in ( PG_FUNCTION_ARGS  )

Definition at line 174 of file ltree_io.c.

175{
176 char *buf = (char *) PG_GETARG_POINTER(0);
177 ltree *res;
178
179 if ((res = parse_ltree(buf, fcinfo->context)) == NULL)
181
183}
static ltree * parse_ltree(const char *buf, struct Node *escontext)
Definition: ltree_io.c:36
Definition: ltree.h:43

References buf, parse_ltree(), PG_GETARG_POINTER, PG_RETURN_NULL, PG_RETURN_POINTER, and res.

Referenced by ltree_addtext(), ltree_textadd(), and text2ltree().

◆ ltree_out()

Datum ltree_out ( PG_FUNCTION_ARGS  )

Definition at line 187 of file ltree_io.c.

188{
189 ltree *in = PG_GETARG_LTREE_P(0);
190
192}
#define PG_GETARG_LTREE_P(n)
Definition: ltree.h:218
static char * deparse_ltree(const ltree *in)
Definition: ltree_io.c:144

References deparse_ltree(), PG_GETARG_LTREE_P, and PG_RETURN_POINTER.

◆ ltree_recv()

Datum ltree_recv ( PG_FUNCTION_ARGS  )

Definition at line 229 of file ltree_io.c.

230{
232 int version = pq_getmsgint(buf, 1);
233 char *str;
234 int nbytes;
235 ltree *res;
236
237 if (version != 1)
238 elog(ERROR, "unsupported ltree version number %d", version);
239
240 str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
241 res = parse_ltree(str, NULL);
242 pfree(str);
243
245}

References buf, elog, ERROR, parse_ltree(), pfree(), PG_GETARG_POINTER, PG_RETURN_POINTER, pq_getmsgint(), pq_getmsgtext(), res, and str.

◆ ltree_send()

Datum ltree_send ( PG_FUNCTION_ARGS  )

Definition at line 204 of file ltree_io.c.

205{
206 ltree *in = PG_GETARG_LTREE_P(0);
208 int version = 1;
209 char *res = deparse_ltree(in);
210
212 pq_sendint8(&buf, version);
213 pq_sendtext(&buf, res, strlen(res));
214 pfree(res);
215
217}

References buf, deparse_ltree(), pfree(), PG_GETARG_LTREE_P, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendint8(), pq_sendtext(), and res.

◆ parse_lquery()

static lquery * parse_lquery ( const char *  buf,
struct Node escontext 
)
static

Definition at line 268 of file ltree_io.c.

269{
270 const char *ptr;
271 int num = 0,
272 totallen = 0,
273 numOR = 0;
275 lquery *result;
276 nodeitem *lptr = NULL;
278 *curqlevel,
279 *tmpql;
280 lquery_variant *lrptr = NULL;
281 bool hasnot = false;
282 bool wasbad = false;
283 int charlen;
284 int pos = 1; /* character position for error messages */
285
286#define UNCHAR ereturn(escontext, NULL,\
287 errcode(ERRCODE_SYNTAX_ERROR), \
288 errmsg("lquery syntax error at character %d", \
289 pos))
290
291 ptr = buf;
292 while (*ptr)
293 {
294 charlen = pg_mblen(ptr);
295
296 if (t_iseq(ptr, '.'))
297 num++;
298 else if (t_iseq(ptr, '|'))
299 numOR++;
300
301 ptr += charlen;
302 }
303
304 num++;
305 if (num > LQUERY_MAX_LEVELS)
306 ereturn(escontext, NULL,
307 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
308 errmsg("number of lquery items (%d) exceeds the maximum allowed (%d)",
309 num, LQUERY_MAX_LEVELS)));
310 curqlevel = tmpql = (lquery_level *) palloc0(ITEMSIZE * num);
311 ptr = buf;
312 while (*ptr)
313 {
314 charlen = pg_mblen(ptr);
315
316 switch (state)
317 {
318 case LQPRS_WAITLEVEL:
319 if (ISLABEL(ptr))
320 {
321 GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
322 lptr->start = ptr;
324 curqlevel->numvar = 1;
325 }
326 else if (t_iseq(ptr, '!'))
327 {
328 GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
329 lptr->start = ptr + 1;
330 lptr->wlen = -1; /* compensate for counting ! below */
332 curqlevel->numvar = 1;
333 curqlevel->flag |= LQL_NOT;
334 hasnot = true;
335 }
336 else if (t_iseq(ptr, '*'))
338 else
339 UNCHAR;
340 break;
341 case LQPRS_WAITVAR:
342 if (ISLABEL(ptr))
343 {
344 lptr++;
345 lptr->start = ptr;
347 curqlevel->numvar++;
348 }
349 else
350 UNCHAR;
351 break;
352 case LQPRS_WAITDELIM:
353 if (t_iseq(ptr, '@'))
354 {
355 lptr->flag |= LVAR_INCASE;
356 curqlevel->flag |= LVAR_INCASE;
357 }
358 else if (t_iseq(ptr, '*'))
359 {
360 lptr->flag |= LVAR_ANYEND;
361 curqlevel->flag |= LVAR_ANYEND;
362 }
363 else if (t_iseq(ptr, '%'))
364 {
365 lptr->flag |= LVAR_SUBLEXEME;
366 curqlevel->flag |= LVAR_SUBLEXEME;
367 }
368 else if (t_iseq(ptr, '|'))
369 {
370 if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
371 return NULL;
373 }
374 else if (t_iseq(ptr, '{'))
375 {
376 if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
377 return NULL;
378 curqlevel->flag |= LQL_COUNT;
380 }
381 else if (t_iseq(ptr, '.'))
382 {
383 if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
384 return NULL;
386 curqlevel = NEXTLEV(curqlevel);
387 }
388 else if (ISLABEL(ptr))
389 {
390 /* disallow more chars after a flag */
391 if (lptr->flag)
392 UNCHAR;
393 }
394 else
395 UNCHAR;
396 break;
397 case LQPRS_WAITOPEN:
398 if (t_iseq(ptr, '{'))
400 else if (t_iseq(ptr, '.'))
401 {
402 /* We only get here for '*', so these are correct defaults */
403 curqlevel->low = 0;
404 curqlevel->high = LTREE_MAX_LEVELS;
405 curqlevel = NEXTLEV(curqlevel);
407 }
408 else
409 UNCHAR;
410 break;
411 case LQPRS_WAITFNUM:
412 if (t_iseq(ptr, ','))
414 else if (isdigit((unsigned char) *ptr))
415 {
416 int low = atoi(ptr);
417
418 if (low < 0 || low > LTREE_MAX_LEVELS)
419 ereturn(escontext, NULL,
420 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
421 errmsg("lquery syntax error"),
422 errdetail("Low limit (%d) exceeds the maximum allowed (%d), at character %d.",
423 low, LTREE_MAX_LEVELS, pos)));
424
425 curqlevel->low = (uint16) low;
427 }
428 else
429 UNCHAR;
430 break;
431 case LQPRS_WAITSNUM:
432 if (isdigit((unsigned char) *ptr))
433 {
434 int high = atoi(ptr);
435
436 if (high < 0 || high > LTREE_MAX_LEVELS)
437 ereturn(escontext, NULL,
438 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
439 errmsg("lquery syntax error"),
440 errdetail("High limit (%d) exceeds the maximum allowed (%d), at character %d.",
441 high, LTREE_MAX_LEVELS, pos)));
442 else if (curqlevel->low > high)
443 ereturn(escontext, NULL,
444 (errcode(ERRCODE_SYNTAX_ERROR),
445 errmsg("lquery syntax error"),
446 errdetail("Low limit (%d) is greater than high limit (%d), at character %d.",
447 curqlevel->low, high, pos)));
448
449 curqlevel->high = (uint16) high;
451 }
452 else if (t_iseq(ptr, '}'))
453 {
454 curqlevel->high = LTREE_MAX_LEVELS;
456 }
457 else
458 UNCHAR;
459 break;
460 case LQPRS_WAITCLOSE:
461 if (t_iseq(ptr, '}'))
463 else if (!isdigit((unsigned char) *ptr))
464 UNCHAR;
465 break;
466 case LQPRS_WAITND:
467 if (t_iseq(ptr, '}'))
468 {
469 curqlevel->high = curqlevel->low;
471 }
472 else if (t_iseq(ptr, ','))
474 else if (!isdigit((unsigned char) *ptr))
475 UNCHAR;
476 break;
477 case LQPRS_WAITEND:
478 if (t_iseq(ptr, '.'))
479 {
481 curqlevel = NEXTLEV(curqlevel);
482 }
483 else
484 UNCHAR;
485 break;
486 default:
487 elog(ERROR, "internal error in lquery parser");
488 }
489
490 ptr += charlen;
491 if (state == LQPRS_WAITDELIM)
492 lptr->wlen++;
493 pos++;
494 }
495
496 if (state == LQPRS_WAITDELIM)
497 {
498 if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
499 return NULL;
500 }
501 else if (state == LQPRS_WAITOPEN)
502 curqlevel->high = LTREE_MAX_LEVELS;
503 else if (state != LQPRS_WAITEND)
504 ereturn(escontext, NULL,
505 (errcode(ERRCODE_SYNTAX_ERROR),
506 errmsg("lquery syntax error"),
507 errdetail("Unexpected end of input.")));
508
509 curqlevel = tmpql;
510 totallen = LQUERY_HDRSIZE;
511 while ((char *) curqlevel - (char *) tmpql < num * ITEMSIZE)
512 {
513 totallen += LQL_HDRSIZE;
514 if (curqlevel->numvar)
515 {
516 lptr = GETVAR(curqlevel);
517 while (lptr - GETVAR(curqlevel) < curqlevel->numvar)
518 {
519 totallen += MAXALIGN(LVAR_HDRSIZE + lptr->len);
520 lptr++;
521 }
522 }
523 curqlevel = NEXTLEV(curqlevel);
524 }
525
526 result = (lquery *) palloc0(totallen);
527 SET_VARSIZE(result, totallen);
528 result->numlevel = num;
529 result->firstgood = 0;
530 result->flag = 0;
531 if (hasnot)
532 result->flag |= LQUERY_HASNOT;
533 cur = LQUERY_FIRST(result);
534 curqlevel = tmpql;
535 while ((char *) curqlevel - (char *) tmpql < num * ITEMSIZE)
536 {
537 memcpy(cur, curqlevel, LQL_HDRSIZE);
538 cur->totallen = LQL_HDRSIZE;
539 if (curqlevel->numvar)
540 {
541 lrptr = LQL_FIRST(cur);
542 lptr = GETVAR(curqlevel);
543 while (lptr - GETVAR(curqlevel) < curqlevel->numvar)
544 {
545 cur->totallen += MAXALIGN(LVAR_HDRSIZE + lptr->len);
546 lrptr->len = lptr->len;
547 lrptr->flag = lptr->flag;
548 lrptr->val = ltree_crc32_sz(lptr->start, lptr->len);
549 memcpy(lrptr->name, lptr->start, lptr->len);
550 lptr++;
551 lrptr = LVAR_NEXT(lrptr);
552 }
553 pfree(GETVAR(curqlevel));
554 if (cur->numvar > 1 || cur->flag != 0)
555 {
556 /* Not a simple match */
557 wasbad = true;
558 }
559 else if (wasbad == false)
560 {
561 /* count leading simple matches */
562 (result->firstgood)++;
563 }
564 }
565 else
566 {
567 /* '*', so this isn't a simple match */
568 wasbad = true;
569 }
570 curqlevel = NEXTLEV(curqlevel);
571 cur = LQL_NEXT(cur);
572 }
573
574 pfree(tmpql);
575 return result;
576
577#undef UNCHAR
578}
#define MAXALIGN(LEN)
Definition: c.h:768
uint16_t uint16
Definition: c.h:487
unsigned int ltree_crc32_sz(const char *buf, int size)
Definition: crc32.c:24
struct cursor * cur
Definition: ecpg.c:29
#define LQUERY_MAX_LEVELS
Definition: ltree.h:125
#define LQL_HDRSIZE
Definition: ltree.h:99
#define ISLABEL(x)
Definition: ltree.h:130
#define LQUERY_HDRSIZE
Definition: ltree.h:123
#define LQUERY_HASNOT
Definition: ltree.h:127
#define LVAR_HDRSIZE
Definition: ltree.h:71
#define LQPRS_WAITSNUM
Definition: ltree_io.c:252
#define ITEMSIZE
Definition: ltree_io.c:260
#define NEXTLEV(x)
Definition: ltree_io.c:261
#define LQPRS_WAITEND
Definition: ltree_io.c:255
#define LQPRS_WAITOPEN
Definition: ltree_io.c:250
#define LQPRS_WAITVAR
Definition: ltree_io.c:256
#define LQPRS_WAITFNUM
Definition: ltree_io.c:251
#define LQPRS_WAITCLOSE
Definition: ltree_io.c:254
#define LQPRS_WAITLEVEL
Definition: ltree_io.c:248
#define LQPRS_WAITDELIM
Definition: ltree_io.c:249
#define UNCHAR
static bool finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos, struct Node *escontext)
Definition: ltree_io.c:585
#define LQPRS_WAITND
Definition: ltree_io.c:253
#define GETVAR(x)
Definition: ltree_io.c:259
int pg_mblen(const char *mbstr)
Definition: mbutils.c:1023
void * palloc0(Size size)
Definition: mcxt.c:1347
int32 val
Definition: ltree.h:60
uint16 firstgood
Definition: ltree.h:117
uint16 flag
Definition: ltree.h:118
int flag
Definition: ltree_io.c:20
Definition: regguts.h:323
#define t_iseq(x, c)
Definition: ts_locale.h:38
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

References buf, cur, elog, ereturn, errcode(), errdetail(), errmsg(), ERROR, finish_nodeitem(), lquery::firstgood, lquery_variant::flag, lquery_level::flag, lquery::flag, nodeitem::flag, GETVAR, lquery_level::high, ISLABEL, ITEMSIZE, lquery_variant::len, nodeitem::len, lquery_level::low, LQL_COUNT, LQL_FIRST, LQL_HDRSIZE, LQL_NEXT, LQL_NOT, LQPRS_WAITCLOSE, LQPRS_WAITDELIM, LQPRS_WAITEND, LQPRS_WAITFNUM, LQPRS_WAITLEVEL, LQPRS_WAITND, LQPRS_WAITOPEN, LQPRS_WAITSNUM, LQPRS_WAITVAR, LQUERY_FIRST, LQUERY_HASNOT, LQUERY_HDRSIZE, LQUERY_MAX_LEVELS, ltree_crc32_sz(), LTREE_MAX_LEVELS, LVAR_ANYEND, LVAR_HDRSIZE, LVAR_INCASE, LVAR_NEXT, LVAR_SUBLEXEME, MAXALIGN, lquery_variant::name, NEXTLEV, lquery::numlevel, lquery_level::numvar, palloc0(), pfree(), pg_mblen(), SET_VARSIZE, nodeitem::start, t_iseq, UNCHAR, lquery_variant::val, and nodeitem::wlen.

Referenced by lquery_in(), and lquery_recv().

◆ parse_ltree()

static ltree * parse_ltree ( const char *  buf,
struct Node escontext 
)
static

Definition at line 36 of file ltree_io.c.

37{
38 const char *ptr;
40 *lptr;
41 int num = 0,
42 totallen = 0;
44 ltree *result;
45 ltree_level *curlevel;
46 int charlen;
47 int pos = 1; /* character position for error messages */
48
49#define UNCHAR ereturn(escontext, NULL,\
50 errcode(ERRCODE_SYNTAX_ERROR), \
51 errmsg("ltree syntax error at character %d", \
52 pos))
53
54 ptr = buf;
55 while (*ptr)
56 {
57 charlen = pg_mblen(ptr);
58 if (t_iseq(ptr, '.'))
59 num++;
60 ptr += charlen;
61 }
62
63 if (num + 1 > LTREE_MAX_LEVELS)
64 ereturn(escontext, NULL,
65 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
66 errmsg("number of ltree labels (%d) exceeds the maximum allowed (%d)",
67 num + 1, LTREE_MAX_LEVELS)));
68 list = lptr = (nodeitem *) palloc(sizeof(nodeitem) * (num + 1));
69 ptr = buf;
70 while (*ptr)
71 {
72 charlen = pg_mblen(ptr);
73
74 switch (state)
75 {
76 case LTPRS_WAITNAME:
77 if (ISLABEL(ptr))
78 {
79 lptr->start = ptr;
80 lptr->wlen = 0;
82 }
83 else
84 UNCHAR;
85 break;
86 case LTPRS_WAITDELIM:
87 if (t_iseq(ptr, '.'))
88 {
89 if (!finish_nodeitem(lptr, ptr, false, pos, escontext))
90 return NULL;
91 totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
92 lptr++;
94 }
95 else if (!ISLABEL(ptr))
96 UNCHAR;
97 break;
98 default:
99 elog(ERROR, "internal error in ltree parser");
100 }
101
102 ptr += charlen;
103 lptr->wlen++;
104 pos++;
105 }
106
107 if (state == LTPRS_WAITDELIM)
108 {
109 if (!finish_nodeitem(lptr, ptr, false, pos, escontext))
110 return NULL;
111 totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
112 lptr++;
113 }
114 else if (!(state == LTPRS_WAITNAME && lptr == list))
115 ereturn(escontext, NULL,
116 (errcode(ERRCODE_SYNTAX_ERROR),
117 errmsg("ltree syntax error"),
118 errdetail("Unexpected end of input.")));
119
120 result = (ltree *) palloc0(LTREE_HDRSIZE + totallen);
121 SET_VARSIZE(result, LTREE_HDRSIZE + totallen);
122 result->numlevel = lptr - list;
123 curlevel = LTREE_FIRST(result);
124 lptr = list;
125 while (lptr - list < result->numlevel)
126 {
127 curlevel->len = (uint16) lptr->len;
128 memcpy(curlevel->name, lptr->start, lptr->len);
129 curlevel = LEVEL_NEXT(curlevel);
130 lptr++;
131 }
132
133 pfree(list);
134 return result;
135
136#undef UNCHAR
137}
#define LEVEL_HDRSIZE
Definition: ltree.h:39
#define LTREE_HDRSIZE
Definition: ltree.h:50
#define LTPRS_WAITDELIM
Definition: ltree_io.c:25
#define LTPRS_WAITNAME
Definition: ltree_io.c:24

References buf, elog, ereturn, errcode(), errdetail(), errmsg(), ERROR, finish_nodeitem(), ISLABEL, ltree_level::len, nodeitem::len, LEVEL_HDRSIZE, LEVEL_NEXT, sort-test::list, LTPRS_WAITDELIM, LTPRS_WAITNAME, LTREE_FIRST, LTREE_HDRSIZE, LTREE_MAX_LEVELS, MAXALIGN, ltree_level::name, ltree::numlevel, palloc(), palloc0(), pfree(), pg_mblen(), SET_VARSIZE, nodeitem::start, t_iseq, UNCHAR, and nodeitem::wlen.

Referenced by ltree_in(), and ltree_recv().

◆ PG_FUNCTION_INFO_V1() [1/8]

PG_FUNCTION_INFO_V1 ( lquery_in  )

◆ PG_FUNCTION_INFO_V1() [2/8]

PG_FUNCTION_INFO_V1 ( lquery_out  )

◆ PG_FUNCTION_INFO_V1() [3/8]

PG_FUNCTION_INFO_V1 ( lquery_recv  )

◆ PG_FUNCTION_INFO_V1() [4/8]

PG_FUNCTION_INFO_V1 ( lquery_send  )

◆ PG_FUNCTION_INFO_V1() [5/8]

PG_FUNCTION_INFO_V1 ( ltree_in  )

◆ PG_FUNCTION_INFO_V1() [6/8]

PG_FUNCTION_INFO_V1 ( ltree_out  )

◆ PG_FUNCTION_INFO_V1() [7/8]

PG_FUNCTION_INFO_V1 ( ltree_recv  )

◆ PG_FUNCTION_INFO_V1() [8/8]

PG_FUNCTION_INFO_V1 ( ltree_send  )