PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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 "common/int.h"
11#include "crc32.h"
12#include "libpq/pqformat.h"
13#include "ltree.h"
14#include "varatt.h"
15
16
17typedef struct
18{
19 const char *start;
20 int len; /* length in bytes */
21 int flag;
22 int wlen; /* length in characters */
23} nodeitem;
24
25#define LTPRS_WAITNAME 0
26#define LTPRS_WAITDELIM 1
27
28static bool finish_nodeitem(nodeitem *lptr, const char *ptr,
29 bool is_lquery, int pos, struct Node *escontext);
30
31
32/*
33 * expects a null terminated string
34 * returns an ltree
35 */
36static ltree *
37parse_ltree(const char *buf, struct Node *escontext)
38{
39 const char *ptr;
40 nodeitem *list,
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}
139
140/*
141 * expects an ltree
142 * returns a null terminated string
143 */
144static char *
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}
169
170/*
171 * Basic ltree I/O functions
172 */
174Datum
176{
177 char *buf = (char *) PG_GETARG_POINTER(0);
178 ltree *res;
179
180 if ((res = parse_ltree(buf, fcinfo->context)) == NULL)
182
184}
185
187Datum
194
195/*
196 * ltree type send function
197 *
198 * The type is sent as text in binary mode, so this is almost the same
199 * as the output function, but it's prefixed with a version number so we
200 * can change the binary format sent in future if necessary. For now,
201 * only version 1 is supported.
202 */
204Datum
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}
219
220/*
221 * ltree type recv function
222 *
223 * The type is sent as text in binary mode, so this is almost the same
224 * as the input function, but it's prefixed with a version number so we
225 * can change the binary format sent in future if necessary. For now,
226 * only version 1 is supported.
227 */
229Datum
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}
247
248
249#define LQPRS_WAITLEVEL 0
250#define LQPRS_WAITDELIM 1
251#define LQPRS_WAITOPEN 2
252#define LQPRS_WAITFNUM 3
253#define LQPRS_WAITSNUM 4
254#define LQPRS_WAITND 5
255#define LQPRS_WAITCLOSE 6
256#define LQPRS_WAITEND 7
257#define LQPRS_WAITVAR 8
258
259
260#define GETVAR(x) ( *((nodeitem**)LQL_FIRST(x)) )
261#define ITEMSIZE MAXALIGN(LQL_HDRSIZE+sizeof(nodeitem*))
262#define NEXTLEV(x) ( (lquery_level*)( ((char*)(x)) + ITEMSIZE) )
263
264/*
265 * expects a null terminated string
266 * returns an lquery
267 */
268static lquery *
269parse_lquery(const char *buf, struct Node *escontext)
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}
594
595/*
596 * Close out parsing an ltree or lquery nodeitem:
597 * compute the correct length, and complain if it's not OK
598 */
599static bool
600finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos,
601 struct Node *escontext)
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}
636
637/*
638 * expects an lquery
639 * returns a null terminated string
640 */
641static char *
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}
753
754/*
755 * Basic lquery I/O functions
756 */
758Datum
760{
761 char *buf = (char *) PG_GETARG_POINTER(0);
762 lquery *res;
763
764 if ((res = parse_lquery(buf, fcinfo->context)) == NULL)
766
768}
769
771Datum
778
779/*
780 * lquery type send function
781 *
782 * The type is sent as text in binary mode, so this is almost the same
783 * as the output function, but it's prefixed with a version number so we
784 * can change the binary format sent in future if necessary. For now,
785 * only version 1 is supported.
786 */
788Datum
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}
803
804/*
805 * lquery type recv function
806 *
807 * The type is sent as text in binary mode, so this is almost the same
808 * as the input function, but it's prefixed with a version number so we
809 * can change the binary format sent in future if necessary. For now,
810 * only version 1 is supported.
811 */
813Datum
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 MAXALIGN(LEN)
Definition c.h:896
uint16_t uint16
Definition c.h:623
#define PG_UINT16_MAX
Definition c.h:671
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
unsigned int ltree_crc32_sz(const char *buf, int size)
Definition crc32.c:22
struct cursor * cur
Definition ecpg.c:29
int errcode(int sqlerrcode)
Definition elog.c:875
#define ereturn(context, dummy_value,...)
Definition elog.h:280
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define palloc_array(type, count)
Definition fe_memutils.h:91
#define palloc0_array(type, count)
Definition fe_memutils.h:92
#define PG_RETURN_BYTEA_P(x)
Definition fmgr.h:373
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
#define PG_RETURN_NULL()
Definition fmgr.h:346
#define PG_FUNCTION_INFO_V1(funcname)
Definition fmgr.h:417
#define PG_RETURN_POINTER(x)
Definition fmgr.h:363
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
const char * str
static bool pg_add_u16_overflow(uint16 a, uint16 b, uint16 *result)
Definition int.h:368
int j
Definition isn.c:78
int i
Definition isn.c:77
#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:224
#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:219
#define LVAR_SUBLEXEME
Definition ltree.h:76
#define LQPRS_WAITSNUM
Definition ltree_io.c:253
#define ITEMSIZE
Definition ltree_io.c:261
static ltree * parse_ltree(const char *buf, struct Node *escontext)
Definition ltree_io.c:37
#define NEXTLEV(x)
Definition ltree_io.c:262
#define LQPRS_WAITEND
Definition ltree_io.c:256
Datum ltree_recv(PG_FUNCTION_ARGS)
Definition ltree_io.c:230
#define LQPRS_WAITOPEN
Definition ltree_io.c:251
Datum lquery_out(PG_FUNCTION_ARGS)
Definition ltree_io.c:772
#define LQPRS_WAITVAR
Definition ltree_io.c:257
Datum lquery_in(PG_FUNCTION_ARGS)
Definition ltree_io.c:759
Datum ltree_in(PG_FUNCTION_ARGS)
Definition ltree_io.c:175
#define LQPRS_WAITFNUM
Definition ltree_io.c:252
#define LQPRS_WAITCLOSE
Definition ltree_io.c:255
#define LQPRS_WAITLEVEL
Definition ltree_io.c:249
Datum ltree_send(PG_FUNCTION_ARGS)
Definition ltree_io.c:205
#define LQPRS_WAITDELIM
Definition ltree_io.c:250
#define LTPRS_WAITDELIM
Definition ltree_io.c:26
#define UNCHAR
Datum lquery_send(PG_FUNCTION_ARGS)
Definition ltree_io.c:789
#define LTPRS_WAITNAME
Definition ltree_io.c:25
static bool finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos, struct Node *escontext)
Definition ltree_io.c:600
static char * deparse_ltree(const ltree *in)
Definition ltree_io.c:145
#define LQPRS_WAITND
Definition ltree_io.c:254
Datum lquery_recv(PG_FUNCTION_ARGS)
Definition ltree_io.c:814
#define GETVAR(x)
Definition ltree_io.c:260
static lquery * parse_lquery(const char *buf, struct Node *escontext)
Definition ltree_io.c:269
static char * deparse_lquery(const lquery *in)
Definition ltree_io.c:642
Datum ltree_out(PG_FUNCTION_ARGS)
Definition ltree_io.c:188
int pg_mblen_cstr(const char *mbstr)
Definition mbutils.c:1045
void pfree(void *pointer)
Definition mcxt.c:1619
void * palloc0(Size size)
Definition mcxt.c:1420
void * palloc(Size size)
Definition mcxt.c:1390
static char * errmsg
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define sprintf
Definition port.h:263
uint64_t Datum
Definition postgres.h:70
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition pqformat.c:414
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:545
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
static int fb(int x)
struct StringInfoData * StringInfo
Definition string.h:15
Definition nodes.h:135
uint16 numlevel
Definition ltree.h:116
Definition ltree.h:43
uint16 numlevel
Definition ltree.h:45
int wlen
Definition ltree_io.c:22
const char * start
Definition ltree_io.c:19
int len
Definition ltree_io.c:20
int flag
Definition ltree_io.c:21
char flag
Definition regguts.h:334
#define t_iseq(x, c)
Definition ts_locale.h:38
static Size VARSIZE(const void *PTR)
Definition varatt.h:298
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432