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 
16 typedef 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 
27 static 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  */
35 static ltree *
36 parse_ltree(const char *buf, struct Node *escontext)
37 {
38  const char *ptr;
39  nodeitem *list,
40  *lptr;
41  int num = 0,
42  totallen = 0;
43  int state = LTPRS_WAITNAME;
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  */
143 static 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  */
173 Datum
175 {
176  char *buf = (char *) PG_GETARG_POINTER(0);
177  ltree *res;
178 
179  if ((res = parse_ltree(buf, fcinfo->context)) == NULL)
180  PG_RETURN_NULL();
181 
183 }
184 
186 Datum
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  */
203 Datum
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  */
228 Datum
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  */
267 static lquery *
268 parse_lquery(const char *buf, struct Node *escontext)
269 {
270  const char *ptr;
271  int num = 0,
272  totallen = 0,
273  numOR = 0;
274  int state = LQPRS_WAITLEVEL;
275  lquery *result;
276  nodeitem *lptr = NULL;
277  lquery_level *cur,
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 (t_isdigit(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 (t_isdigit(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 (!t_isdigit(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 (!t_isdigit(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  */
584 static bool
585 finish_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  */
626 static 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  */
743 Datum
745 {
746  char *buf = (char *) PG_GETARG_POINTER(0);
747  lquery *res;
748 
749  if ((res = parse_lquery(buf, fcinfo->context)) == NULL)
750  PG_RETURN_NULL();
751 
753 }
754 
756 Datum
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  */
773 Datum
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  */
798 Datum
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:765
uint16_t uint16
Definition: c.h:484
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:73
int i
Definition: isn.c:72
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
#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
static char * deparse_ltree(const ltree *in)
Definition: ltree_io.c:144
#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
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
static lquery * parse_lquery(const char *buf, struct Node *escontext)
Definition: ltree_io.c:268
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
static char * deparse_lquery(const lquery *in)
Definition: ltree_io.c:627
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 ltree * parse_ltree(const char *buf, struct Node *escontext)
Definition: ltree_io.c:36
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
Datum lquery_recv(PG_FUNCTION_ARGS)
Definition: ltree_io.c:799
#define GETVAR(x)
Definition: ltree_io.c:259
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:1521
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:240
uintptr_t Datum
Definition: postgres.h:64
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:129
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
int t_isdigit(const char *ptr)
Definition: ts_locale.c:35
#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