PostgreSQL Source Code git master
Loading...
Searching...
No Matches
ltree_io.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "common/int.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 chardeparse_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 chardeparse_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 260 of file ltree_io.c.

◆ ITEMSIZE

Definition at line 261 of file ltree_io.c.

◆ LQPRS_WAITCLOSE

#define LQPRS_WAITCLOSE   6

Definition at line 255 of file ltree_io.c.

◆ LQPRS_WAITDELIM

#define LQPRS_WAITDELIM   1

Definition at line 250 of file ltree_io.c.

◆ LQPRS_WAITEND

#define LQPRS_WAITEND   7

Definition at line 256 of file ltree_io.c.

◆ LQPRS_WAITFNUM

#define LQPRS_WAITFNUM   3

Definition at line 252 of file ltree_io.c.

◆ LQPRS_WAITLEVEL

#define LQPRS_WAITLEVEL   0

Definition at line 249 of file ltree_io.c.

◆ LQPRS_WAITND

#define LQPRS_WAITND   5

Definition at line 254 of file ltree_io.c.

◆ LQPRS_WAITOPEN

#define LQPRS_WAITOPEN   2

Definition at line 251 of file ltree_io.c.

◆ LQPRS_WAITSNUM

#define LQPRS_WAITSNUM   4

Definition at line 253 of file ltree_io.c.

◆ LQPRS_WAITVAR

#define LQPRS_WAITVAR   8

Definition at line 257 of file ltree_io.c.

◆ LTPRS_WAITDELIM

#define LTPRS_WAITDELIM   1

Definition at line 26 of file ltree_io.c.

◆ LTPRS_WAITNAME

#define LTPRS_WAITNAME   0

Definition at line 25 of file ltree_io.c.

◆ NEXTLEV

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

Definition at line 262 of file ltree_io.c.

◆ UNCHAR [1/2]

#define UNCHAR
Value:
ereturn(escontext, NULL,\
errmsg("ltree syntax error at character %d", \
pos))
int errcode(int sqlerrcode)
Definition elog.c:875
#define ereturn(context, dummy_value,...)
Definition elog.h:280
static char * errmsg
static int fb(int x)

◆ UNCHAR [2/2]

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

Function Documentation

◆ deparse_lquery()

static char * deparse_lquery ( const lquery in)
static

Definition at line 642 of file ltree_io.c.

643{
644 char *buf,
645 *ptr;
646 int i,
647 j,
648 totallen = 1;
651
653 for (i = 0; i < in->numlevel; i++)
654 {
655 totallen++;
656 if (curqlevel->numvar)
657 {
658 totallen += 1 + (curqlevel->numvar * 4) + curqlevel->totallen;
659 if (curqlevel->flag & LQL_COUNT)
660 totallen += 2 * 11 + 3;
661 }
662 else
663 totallen += 2 * 11 + 4;
665 }
666
667 ptr = buf = (char *) palloc(totallen);
669 for (i = 0; i < in->numlevel; i++)
670 {
671 if (i != 0)
672 {
673 *ptr = '.';
674 ptr++;
675 }
676 if (curqlevel->numvar)
677 {
678 if (curqlevel->flag & LQL_NOT)
679 {
680 *ptr = '!';
681 ptr++;
682 }
684 for (j = 0; j < curqlevel->numvar; j++)
685 {
686 if (j != 0)
687 {
688 *ptr = '|';
689 ptr++;
690 }
691 memcpy(ptr, curtlevel->name, curtlevel->len);
692 ptr += curtlevel->len;
693 if ((curtlevel->flag & LVAR_SUBLEXEME))
694 {
695 *ptr = '%';
696 ptr++;
697 }
698 if ((curtlevel->flag & LVAR_INCASE))
699 {
700 *ptr = '@';
701 ptr++;
702 }
703 if ((curtlevel->flag & LVAR_ANYEND))
704 {
705 *ptr = '*';
706 ptr++;
707 }
709 }
710 }
711 else
712 {
713 *ptr = '*';
714 ptr++;
715 }
716
717 if ((curqlevel->flag & LQL_COUNT) || curqlevel->numvar == 0)
718 {
719 if (curqlevel->low == curqlevel->high)
720 {
721 sprintf(ptr, "{%d}", curqlevel->low);
722 }
723 else if (curqlevel->low == 0)
724 {
725 if (curqlevel->high == LTREE_MAX_LEVELS)
726 {
727 if (curqlevel->numvar == 0)
728 {
729 /* This is default for '*', so print nothing */
730 *ptr = '\0';
731 }
732 else
733 sprintf(ptr, "{,}");
734 }
735 else
736 sprintf(ptr, "{,%d}", curqlevel->high);
737 }
738 else if (curqlevel->high == LTREE_MAX_LEVELS)
739 {
740 sprintf(ptr, "{%d,}", curqlevel->low);
741 }
742 else
743 sprintf(ptr, "{%d,%d}", curqlevel->low, curqlevel->high);
744 ptr = strchr(ptr, '\0');
745 }
746
748 }
749
750 *ptr = '\0';
751 return buf;
752}
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
int j
Definition isn.c:78
int i
Definition isn.c:77
#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:1390
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define sprintf
Definition port.h:263
uint16 numlevel
Definition ltree.h:116

References buf, fb(), i, j, LQL_COUNT, LQL_FIRST, LQL_NEXT, LQL_NOT, LQUERY_FIRST, LTREE_MAX_LEVELS, LVAR_ANYEND, LVAR_INCASE, LVAR_NEXT, LVAR_SUBLEXEME, memcpy(), lquery::numlevel, palloc(), and sprintf.

Referenced by lquery_out(), and lquery_send().

◆ deparse_ltree()

static char * deparse_ltree ( const ltree in)
static

Definition at line 145 of file ltree_io.c.

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

References buf, fb(), i, LEVEL_NEXT, LTREE_FIRST, memcpy(), 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 600 of file ltree_io.c.

602{
603 if (is_lquery)
604 {
605 /*
606 * Back up over any flag characters, and discount them from length and
607 * position.
608 */
609 while (ptr > lptr->start && strchr("@*%", ptr[-1]) != NULL)
610 {
611 ptr--;
612 lptr->wlen--;
613 pos--;
614 }
615 }
616
617 /* Now compute the byte length, which we weren't tracking before. */
618 lptr->len = ptr - lptr->start;
619
620 /* Complain if it's empty or too long */
621 if (lptr->len == 0)
622 ereturn(escontext, false,
624 is_lquery ?
625 errmsg("lquery syntax error at character %d", pos) :
626 errmsg("ltree syntax error at character %d", pos),
627 errdetail("Empty labels are not allowed.")));
628 if (lptr->wlen > LTREE_LABEL_MAX_CHARS)
629 ereturn(escontext, false,
631 errmsg("label string is too long"),
632 errdetail("Label length is %d, must be at most %d, at character %d.",
633 lptr->wlen, LTREE_LABEL_MAX_CHARS, pos)));
634 return true;
635}
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define LTREE_LABEL_MAX_CHARS
Definition ltree.h:18

References ereturn, errcode(), errdetail(), errmsg, fb(), and LTREE_LABEL_MAX_CHARS.

Referenced by parse_lquery(), and parse_ltree().

◆ lquery_in()

Datum lquery_in ( PG_FUNCTION_ARGS  )

Definition at line 759 of file ltree_io.c.

760{
761 char *buf = (char *) PG_GETARG_POINTER(0);
762 lquery *res;
763
764 if ((res = parse_lquery(buf, fcinfo->context)) == NULL)
766
768}
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
#define PG_RETURN_NULL()
Definition fmgr.h:346
#define PG_RETURN_POINTER(x)
Definition fmgr.h:363
static lquery * parse_lquery(const char *buf, struct Node *escontext)
Definition ltree_io.c:269

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

◆ lquery_out()

Datum lquery_out ( PG_FUNCTION_ARGS  )

Definition at line 772 of file ltree_io.c.

773{
774 lquery *in = PG_GETARG_LQUERY_P(0);
775
777}
#define PG_GETARG_LQUERY_P(n)
Definition ltree.h:224
static char * deparse_lquery(const lquery *in)
Definition ltree_io.c:642

References deparse_lquery(), PG_GETARG_LQUERY_P, and PG_RETURN_POINTER.

◆ lquery_recv()

Datum lquery_recv ( PG_FUNCTION_ARGS  )

Definition at line 814 of file ltree_io.c.

815{
817 int version = pq_getmsgint(buf, 1);
818 char *str;
819 int nbytes;
820 lquery *res;
821
822 if (version != 1)
823 elog(ERROR, "unsupported lquery version number %d", version);
824
825 str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
826 res = parse_lquery(str, NULL);
827 pfree(str);
828
830}
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
const char * str
void pfree(void *pointer)
Definition mcxt.c:1619
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition pqformat.c:414
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition pqformat.c:545
struct StringInfoData * StringInfo
Definition string.h:15

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

◆ lquery_send()

Datum lquery_send ( PG_FUNCTION_ARGS  )

Definition at line 789 of file ltree_io.c.

790{
791 lquery *in = PG_GETARG_LQUERY_P(0);
793 int version = 1;
794 char *res = deparse_lquery(in);
795
797 pq_sendint8(&buf, version);
798 pq_sendtext(&buf, res, strlen(res));
799 pfree(res);
800
802}
#define PG_RETURN_BYTEA_P(x)
Definition fmgr.h:373
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition pqformat.c:172
void pq_begintypsend(StringInfo buf)
Definition pqformat.c:325
bytea * pq_endtypsend(StringInfo buf)
Definition pqformat.c:345
static void pq_sendint8(StringInfo buf, uint8 i)
Definition pqformat.h:128

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

◆ ltree_in()

Datum ltree_in ( PG_FUNCTION_ARGS  )

Definition at line 175 of file ltree_io.c.

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

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

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

◆ ltree_out()

Datum ltree_out ( PG_FUNCTION_ARGS  )

Definition at line 188 of file ltree_io.c.

189{
190 ltree *in = PG_GETARG_LTREE_P(0);
191
193}
#define PG_GETARG_LTREE_P(n)
Definition ltree.h:219
static char * deparse_ltree(const ltree *in)
Definition ltree_io.c:145

References deparse_ltree(), PG_GETARG_LTREE_P, and PG_RETURN_POINTER.

◆ ltree_recv()

Datum ltree_recv ( PG_FUNCTION_ARGS  )

Definition at line 230 of file ltree_io.c.

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

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

◆ ltree_send()

Datum ltree_send ( PG_FUNCTION_ARGS  )

Definition at line 205 of file ltree_io.c.

206{
207 ltree *in = PG_GETARG_LTREE_P(0);
209 int version = 1;
210 char *res = deparse_ltree(in);
211
213 pq_sendint8(&buf, version);
214 pq_sendtext(&buf, res, strlen(res));
215 pfree(res);
216
218}

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

◆ parse_lquery()

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

Definition at line 269 of file ltree_io.c.

270{
271 const char *ptr;
272 int num = 0,
273 totallen = 0,
274 numOR = 0;
276 lquery *result;
277 nodeitem *lptr = NULL;
279 *curqlevel,
280 *tmpql;
282 bool hasnot = false;
283 bool wasbad = false;
284 int charlen;
285 int pos = 1; /* character position for error messages */
286
287#define UNCHAR ereturn(escontext, NULL,\
288 errcode(ERRCODE_SYNTAX_ERROR), \
289 errmsg("lquery syntax error at character %d", \
290 pos))
291
292 ptr = buf;
293 while (*ptr)
294 {
295 charlen = pg_mblen_cstr(ptr);
296
297 if (t_iseq(ptr, '.'))
298 num++;
299 else if (t_iseq(ptr, '|'))
300 numOR++;
301
302 ptr += charlen;
303 }
304
305 num++;
306 if (num > LQUERY_MAX_LEVELS)
307 ereturn(escontext, NULL,
309 errmsg("number of lquery items (%d) exceeds the maximum allowed (%d)",
310 num, LQUERY_MAX_LEVELS)));
312 ptr = buf;
313 while (*ptr)
314 {
315 charlen = pg_mblen_cstr(ptr);
316
317 switch (state)
318 {
319 case LQPRS_WAITLEVEL:
320 if (ISLABEL(ptr))
321 {
323 lptr->start = ptr;
325 curqlevel->numvar = 1;
326 }
327 else if (t_iseq(ptr, '!'))
328 {
330 lptr->start = ptr + 1;
331 lptr->wlen = -1; /* compensate for counting ! below */
333 curqlevel->numvar = 1;
335 hasnot = true;
336 }
337 else if (t_iseq(ptr, '*'))
339 else
340 UNCHAR;
341 break;
342 case LQPRS_WAITVAR:
343 if (ISLABEL(ptr))
344 {
345 lptr++;
346 lptr->start = ptr;
348 if (pg_add_u16_overflow(curqlevel->numvar, 1, &curqlevel->numvar))
349 ereturn(escontext, NULL,
351 errmsg("lquery level has too many variants"),
352 errdetail("Number of variants exceeds the maximum allowed (%d).",
353 PG_UINT16_MAX)));
354 }
355 else
356 UNCHAR;
357 break;
358 case LQPRS_WAITDELIM:
359 if (t_iseq(ptr, '@'))
360 {
361 lptr->flag |= LVAR_INCASE;
362 curqlevel->flag |= LVAR_INCASE;
363 }
364 else if (t_iseq(ptr, '*'))
365 {
366 lptr->flag |= LVAR_ANYEND;
367 curqlevel->flag |= LVAR_ANYEND;
368 }
369 else if (t_iseq(ptr, '%'))
370 {
371 lptr->flag |= LVAR_SUBLEXEME;
372 curqlevel->flag |= LVAR_SUBLEXEME;
373 }
374 else if (t_iseq(ptr, '|'))
375 {
376 if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
377 return NULL;
379 }
380 else if (t_iseq(ptr, '{'))
381 {
382 if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
383 return NULL;
386 }
387 else if (t_iseq(ptr, '.'))
388 {
389 if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
390 return NULL;
393 }
394 else if (ISLABEL(ptr))
395 {
396 /* disallow more chars after a flag */
397 if (lptr->flag)
398 UNCHAR;
399 }
400 else
401 UNCHAR;
402 break;
403 case LQPRS_WAITOPEN:
404 if (t_iseq(ptr, '{'))
406 else if (t_iseq(ptr, '.'))
407 {
408 /* We only get here for '*', so these are correct defaults */
409 curqlevel->low = 0;
413 }
414 else
415 UNCHAR;
416 break;
417 case LQPRS_WAITFNUM:
418 if (t_iseq(ptr, ','))
420 else if (isdigit((unsigned char) *ptr))
421 {
422 int low = atoi(ptr);
423
425 ereturn(escontext, NULL,
427 errmsg("lquery syntax error"),
428 errdetail("Low limit (%d) exceeds the maximum allowed (%d), at character %d.",
429 low, LTREE_MAX_LEVELS, pos)));
430
431 curqlevel->low = (uint16) low;
433 }
434 else
435 UNCHAR;
436 break;
437 case LQPRS_WAITSNUM:
438 if (isdigit((unsigned char) *ptr))
439 {
440 int high = atoi(ptr);
441
443 ereturn(escontext, NULL,
445 errmsg("lquery syntax error"),
446 errdetail("High limit (%d) exceeds the maximum allowed (%d), at character %d.",
447 high, LTREE_MAX_LEVELS, pos)));
448 else if (curqlevel->low > high)
449 ereturn(escontext, NULL,
451 errmsg("lquery syntax error"),
452 errdetail("Low limit (%d) is greater than high limit (%d), at character %d.",
453 curqlevel->low, high, pos)));
454
455 curqlevel->high = (uint16) high;
457 }
458 else if (t_iseq(ptr, '}'))
459 {
462 }
463 else
464 UNCHAR;
465 break;
466 case LQPRS_WAITCLOSE:
467 if (t_iseq(ptr, '}'))
469 else if (!isdigit((unsigned char) *ptr))
470 UNCHAR;
471 break;
472 case LQPRS_WAITND:
473 if (t_iseq(ptr, '}'))
474 {
475 curqlevel->high = curqlevel->low;
477 }
478 else if (t_iseq(ptr, ','))
480 else if (!isdigit((unsigned char) *ptr))
481 UNCHAR;
482 break;
483 case LQPRS_WAITEND:
484 if (t_iseq(ptr, '.'))
485 {
488 }
489 else
490 UNCHAR;
491 break;
492 default:
493 elog(ERROR, "internal error in lquery parser");
494 }
495
496 ptr += charlen;
497 if (state == LQPRS_WAITDELIM)
498 lptr->wlen++;
499 pos++;
500 }
501
502 if (state == LQPRS_WAITDELIM)
503 {
504 if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
505 return NULL;
506 }
507 else if (state == LQPRS_WAITOPEN)
509 else if (state != LQPRS_WAITEND)
510 ereturn(escontext, NULL,
512 errmsg("lquery syntax error"),
513 errdetail("Unexpected end of input.")));
514
516 totallen = LQUERY_HDRSIZE;
517 while ((char *) curqlevel - (char *) tmpql < num * ITEMSIZE)
518 {
519 totallen += LQL_HDRSIZE;
520 if (curqlevel->numvar)
521 {
523 while (lptr - GETVAR(curqlevel) < curqlevel->numvar)
524 {
525 totallen += MAXALIGN(LVAR_HDRSIZE + lptr->len);
526 lptr++;
527 }
528 }
530 }
531
532 result = (lquery *) palloc0(totallen);
533 SET_VARSIZE(result, totallen);
534 result->numlevel = num;
535 result->firstgood = 0;
536 result->flag = 0;
537 if (hasnot)
538 result->flag |= LQUERY_HASNOT;
541 while ((char *) curqlevel - (char *) tmpql < num * ITEMSIZE)
542 {
544 cur->totallen = LQL_HDRSIZE;
545 if (curqlevel->numvar)
546 {
549 while (lptr - GETVAR(curqlevel) < curqlevel->numvar)
550 {
551 int newlen = cur->totallen + MAXALIGN(LVAR_HDRSIZE + lptr->len);
552
553 if (newlen > PG_UINT16_MAX)
554 ereturn(escontext, NULL,
556 errmsg("lquery level is too large"),
557 errdetail("Total size of level exceeds the maximum allowed (%d bytes).",
558 PG_UINT16_MAX)));
559 cur->totallen = (uint16) newlen;
560
561 lrptr->len = lptr->len;
562 lrptr->flag = lptr->flag;
563 lrptr->val = ltree_crc32_sz(lptr->start, lptr->len);
564 memcpy(lrptr->name, lptr->start, lptr->len);
565 lptr++;
567 }
569 if (cur->numvar > 1 || cur->flag != 0)
570 {
571 /* Not a simple match */
572 wasbad = true;
573 }
574 else if (wasbad == false)
575 {
576 /* count leading simple matches */
577 (result->firstgood)++;
578 }
579 }
580 else
581 {
582 /* '*', so this isn't a simple match */
583 wasbad = true;
584 }
586 cur = LQL_NEXT(cur);
587 }
588
589 pfree(tmpql);
590 return result;
591
592#undef UNCHAR
593}
#define MAXALIGN(LEN)
Definition c.h:896
uint16_t uint16
Definition c.h:623
#define PG_UINT16_MAX
Definition c.h:671
uint32 result
unsigned int ltree_crc32_sz(const char *buf, int size)
Definition crc32.c:22
struct cursor * cur
Definition ecpg.c:29
#define palloc0_array(type, count)
Definition fe_memutils.h:92
static bool pg_add_u16_overflow(uint16 a, uint16 b, uint16 *result)
Definition int.h:368
#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:253
#define ITEMSIZE
Definition ltree_io.c:261
#define NEXTLEV(x)
Definition ltree_io.c:262
#define LQPRS_WAITEND
Definition ltree_io.c:256
#define LQPRS_WAITOPEN
Definition ltree_io.c:251
#define LQPRS_WAITVAR
Definition ltree_io.c:257
#define LQPRS_WAITFNUM
Definition ltree_io.c:252
#define LQPRS_WAITCLOSE
Definition ltree_io.c:255
#define LQPRS_WAITLEVEL
Definition ltree_io.c:249
#define LQPRS_WAITDELIM
Definition ltree_io.c:250
#define UNCHAR
static bool finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos, struct Node *escontext)
Definition ltree_io.c:600
#define LQPRS_WAITND
Definition ltree_io.c:254
#define GETVAR(x)
Definition ltree_io.c:260
int pg_mblen_cstr(const char *mbstr)
Definition mbutils.c:1045
void * palloc0(Size size)
Definition mcxt.c:1420
char flag
Definition regguts.h:334
#define t_iseq(x, c)
Definition ts_locale.h:38
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432

References buf, cur, elog, ereturn, errcode(), errdetail(), errmsg, ERROR, fb(), finish_nodeitem(), state::flag, GETVAR, ISLABEL, ITEMSIZE, 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, memcpy(), NEXTLEV, palloc0(), palloc0_array, pfree(), pg_add_u16_overflow(), pg_mblen_cstr(), PG_UINT16_MAX, result, SET_VARSIZE(), t_iseq, and UNCHAR.

Referenced by lquery_in(), and lquery_recv().

◆ parse_ltree()

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

Definition at line 37 of file ltree_io.c.

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

References buf, elog, ereturn, errcode(), errdetail(), errmsg, ERROR, fb(), finish_nodeitem(), ISLABEL, LEVEL_HDRSIZE, LEVEL_NEXT, LTPRS_WAITDELIM, LTPRS_WAITNAME, LTREE_FIRST, LTREE_HDRSIZE, LTREE_MAX_LEVELS, MAXALIGN, memcpy(), palloc0(), palloc_array, pfree(), pg_mblen_cstr(), result, SET_VARSIZE(), t_iseq, and UNCHAR.

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  )