PostgreSQL Source Code git master
ltree_io.c
Go to the documentation of this file.
1/*
2 * in/out function for ltree and lquery
3 * Teodor Sigaev <teodor@stack.net>
4 * contrib/ltree/ltree_io.c
5 */
6#include "postgres.h"
7
8#include <ctype.h>
9
10#include "crc32.h"
11#include "libpq/pqformat.h"
12#include "ltree.h"
13#include "varatt.h"
14
15
16typedef struct
17{
18 const char *start;
19 int len; /* length in bytes */
20 int flag;
21 int wlen; /* length in characters */
22} nodeitem;
23
24#define LTPRS_WAITNAME 0
25#define LTPRS_WAITDELIM 1
26
27static bool finish_nodeitem(nodeitem *lptr, const char *ptr,
28 bool is_lquery, int pos, struct Node *escontext);
29
30
31/*
32 * expects a null terminated string
33 * returns an ltree
34 */
35static ltree *
36parse_ltree(const char *buf, struct Node *escontext)
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}
138
139/*
140 * expects an ltree
141 * returns a null terminated string
142 */
143static char *
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}
168
169/*
170 * Basic ltree I/O functions
171 */
173Datum
175{
176 char *buf = (char *) PG_GETARG_POINTER(0);
177 ltree *res;
178
179 if ((res = parse_ltree(buf, fcinfo->context)) == NULL)
181
183}
184
186Datum
188{
189 ltree *in = PG_GETARG_LTREE_P(0);
190
192}
193
194/*
195 * ltree type send function
196 *
197 * The type is sent as text in binary mode, so this is almost the same
198 * as the output function, but it's prefixed with a version number so we
199 * can change the binary format sent in future if necessary. For now,
200 * only version 1 is supported.
201 */
203Datum
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}
218
219/*
220 * ltree type recv function
221 *
222 * The type is sent as text in binary mode, so this is almost the same
223 * as the input function, but it's prefixed with a version number so we
224 * can change the binary format sent in future if necessary. For now,
225 * only version 1 is supported.
226 */
228Datum
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}
246
247
248#define LQPRS_WAITLEVEL 0
249#define LQPRS_WAITDELIM 1
250#define LQPRS_WAITOPEN 2
251#define LQPRS_WAITFNUM 3
252#define LQPRS_WAITSNUM 4
253#define LQPRS_WAITND 5
254#define LQPRS_WAITCLOSE 6
255#define LQPRS_WAITEND 7
256#define LQPRS_WAITVAR 8
257
258
259#define GETVAR(x) ( *((nodeitem**)LQL_FIRST(x)) )
260#define ITEMSIZE MAXALIGN(LQL_HDRSIZE+sizeof(nodeitem*))
261#define NEXTLEV(x) ( (lquery_level*)( ((char*)(x)) + ITEMSIZE) )
262
263/*
264 * expects a null terminated string
265 * returns an lquery
266 */
267static lquery *
268parse_lquery(const char *buf, struct Node *escontext)
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}
579
580/*
581 * Close out parsing an ltree or lquery nodeitem:
582 * compute the correct length, and complain if it's not OK
583 */
584static bool
585finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos,
586 struct Node *escontext)
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}
621
622/*
623 * expects an lquery
624 * returns a null terminated string
625 */
626static char *
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}
738
739/*
740 * Basic lquery I/O functions
741 */
743Datum
745{
746 char *buf = (char *) PG_GETARG_POINTER(0);
747 lquery *res;
748
749 if ((res = parse_lquery(buf, fcinfo->context)) == NULL)
751
753}
754
756Datum
758{
759 lquery *in = PG_GETARG_LQUERY_P(0);
760
762}
763
764/*
765 * lquery type send function
766 *
767 * The type is sent as text in binary mode, so this is almost the same
768 * as the output function, but it's prefixed with a version number so we
769 * can change the binary format sent in future if necessary. For now,
770 * only version 1 is supported.
771 */
773Datum
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}
788
789/*
790 * lquery type recv function
791 *
792 * The type is sent as text in binary mode, so this is almost the same
793 * as the input function, but it's prefixed with a version number so we
794 * can change the binary format sent in future if necessary. For now,
795 * only version 1 is supported.
796 */
798Datum
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 MAXALIGN(LEN)
Definition: c.h:782
uint16_t uint16
Definition: c.h:501
unsigned int ltree_crc32_sz(const char *buf, int size)
Definition: crc32.c:24
struct cursor * cur
Definition: ecpg.c:29
int errdetail(const char *fmt,...)
Definition: elog.c:1203
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
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#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
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
const char * str
int j
Definition: isn.c:75
int i
Definition: isn.c:74
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:78
#define LEVEL_HDRSIZE
Definition: ltree.h:39
#define LTREE_MAX_LEVELS
Definition: ltree.h:52
#define LTREE_FIRST(x)
Definition: ltree.h:51
#define LVAR_INCASE
Definition: ltree.h:75
#define PG_GETARG_LQUERY_P(n)
Definition: ltree.h:223
#define LEVEL_NEXT(x)
Definition: ltree.h:40
#define LVAR_ANYEND
Definition: ltree.h:74
#define LQUERY_MAX_LEVELS
Definition: ltree.h:125
#define LTREE_LABEL_MAX_CHARS
Definition: ltree.h:18
#define LQL_HDRSIZE
Definition: ltree.h:99
#define LQL_FIRST(x)
Definition: ltree.h:101
#define ISLABEL(x)
Definition: ltree.h:130
#define LQUERY_HDRSIZE
Definition: ltree.h:123
#define LVAR_NEXT(x)
Definition: ltree.h:72
#define LQL_NEXT(x)
Definition: ltree.h:100
#define LQL_COUNT
Definition: ltree.h:104
#define LTREE_HDRSIZE
Definition: ltree.h:50
#define LQUERY_HASNOT
Definition: ltree.h:127
#define LQUERY_FIRST(x)
Definition: ltree.h:124
#define LVAR_HDRSIZE
Definition: ltree.h:71
#define LQL_NOT
Definition: ltree.h:103
#define PG_GETARG_LTREE_P(n)
Definition: ltree.h:218
#define LVAR_SUBLEXEME
Definition: ltree.h:76
#define LQPRS_WAITSNUM
Definition: ltree_io.c:252
#define ITEMSIZE
Definition: ltree_io.c:260
static ltree * parse_ltree(const char *buf, struct Node *escontext)
Definition: ltree_io.c:36
#define NEXTLEV(x)
Definition: ltree_io.c:261
#define LQPRS_WAITEND
Definition: ltree_io.c:255
Datum ltree_recv(PG_FUNCTION_ARGS)
Definition: ltree_io.c:229
#define LQPRS_WAITOPEN
Definition: ltree_io.c:250
Datum lquery_out(PG_FUNCTION_ARGS)
Definition: ltree_io.c:757
#define LQPRS_WAITVAR
Definition: ltree_io.c:256
Datum lquery_in(PG_FUNCTION_ARGS)
Definition: ltree_io.c:744
Datum ltree_in(PG_FUNCTION_ARGS)
Definition: ltree_io.c:174
#define LQPRS_WAITFNUM
Definition: ltree_io.c:251
#define LQPRS_WAITCLOSE
Definition: ltree_io.c:254
PG_FUNCTION_INFO_V1(ltree_in)
#define LQPRS_WAITLEVEL
Definition: ltree_io.c:248
Datum ltree_send(PG_FUNCTION_ARGS)
Definition: ltree_io.c:204
#define LQPRS_WAITDELIM
Definition: ltree_io.c:249
#define LTPRS_WAITDELIM
Definition: ltree_io.c:25
#define UNCHAR
Datum lquery_send(PG_FUNCTION_ARGS)
Definition: ltree_io.c:774
#define LTPRS_WAITNAME
Definition: ltree_io.c:24
static bool finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos, struct Node *escontext)
Definition: ltree_io.c:585
static char * deparse_ltree(const ltree *in)
Definition: ltree_io.c:144
#define LQPRS_WAITND
Definition: ltree_io.c:253
Datum lquery_recv(PG_FUNCTION_ARGS)
Definition: ltree_io.c:799
#define GETVAR(x)
Definition: ltree_io.c:259
static lquery * parse_lquery(const char *buf, struct Node *escontext)
Definition: ltree_io.c:268
static char * deparse_lquery(const lquery *in)
Definition: ltree_io.c:627
Datum ltree_out(PG_FUNCTION_ARGS)
Definition: ltree_io.c:187
int pg_mblen(const char *mbstr)
Definition: mbutils.c:1023
void pfree(void *pointer)
Definition: mcxt.c:1524
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
static char * buf
Definition: pg_test_fsync.c:72
#define sprintf
Definition: port.h:241
uintptr_t Datum
Definition: postgres.h:69
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:172
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:546
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
StringInfoData * StringInfo
Definition: stringinfo.h:54
Definition: nodes.h:131
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
int32 val
Definition: ltree.h:60
uint16 len
Definition: ltree.h:61
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:63
Definition: ltree.h:114
uint16 firstgood
Definition: ltree.h:117
uint16 numlevel
Definition: ltree.h:116
uint16 flag
Definition: ltree.h:118
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:36
uint16 len
Definition: ltree.h:35
Definition: ltree.h:43
uint16 numlevel
Definition: ltree.h:45
int wlen
Definition: ltree_io.c:21
const char * start
Definition: ltree_io.c:18
int len
Definition: ltree_io.c:19
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
#define VARSIZE(PTR)
Definition: varatt.h:279