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 "utils/memutils.h"
14 #include "varatt.h"
15 
16 
17 typedef 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 
28 static 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  */
36 static ltree *
37 parse_ltree(const char *buf, struct Node *escontext)
38 {
39  const char *ptr;
40  nodeitem *list,
41  *lptr;
42  int num = 0,
43  totallen = 0;
44  int state = LTPRS_WAITNAME;
45  ltree *result;
46  ltree_level *curlevel;
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(ptr);
59  if (t_iseq(ptr, '.'))
60  num++;
61  ptr += charlen;
62  }
63 
64  if (num + 1 > LTREE_MAX_LEVELS)
65  ereturn(escontext, NULL,
66  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
67  errmsg("number of ltree labels (%d) exceeds the maximum allowed (%d)",
68  num + 1, LTREE_MAX_LEVELS)));
69  list = lptr = (nodeitem *) palloc(sizeof(nodeitem) * (num + 1));
70  ptr = buf;
71  while (*ptr)
72  {
73  charlen = pg_mblen(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,
117  (errcode(ERRCODE_SYNTAX_ERROR),
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;
124  curlevel = LTREE_FIRST(result);
125  lptr = list;
126  while (lptr - list < result->numlevel)
127  {
128  curlevel->len = (uint16) lptr->len;
129  memcpy(curlevel->name, lptr->start, lptr->len);
130  curlevel = LEVEL_NEXT(curlevel);
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  */
144 static char *
146 {
147  char *buf,
148  *ptr;
149  int i;
150  ltree_level *curlevel;
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;
163  curlevel = LEVEL_NEXT(curlevel);
164  }
165 
166  *ptr = '\0';
167  return buf;
168 }
169 
170 /*
171  * Basic ltree I/O functions
172  */
174 Datum
176 {
177  char *buf = (char *) PG_GETARG_POINTER(0);
178  ltree *res;
179 
180  if ((res = parse_ltree(buf, fcinfo->context)) == NULL)
181  PG_RETURN_NULL();
182 
184 }
185 
187 Datum
189 {
190  ltree *in = PG_GETARG_LTREE_P(0);
191 
193 }
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  */
204 Datum
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  */
229 Datum
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  */
268 static lquery *
269 parse_lquery(const char *buf, struct Node *escontext)
270 {
271  const char *ptr;
272  int num = 0,
273  totallen = 0,
274  numOR = 0;
275  int state = LQPRS_WAITLEVEL;
276  lquery *result;
277  nodeitem *lptr = NULL;
278  lquery_level *cur,
279  *curqlevel,
280  *tmpql;
281  lquery_variant *lrptr = NULL;
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(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,
308  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
309  errmsg("number of lquery items (%d) exceeds the maximum allowed (%d)",
310  num, LQUERY_MAX_LEVELS)));
311  curqlevel = tmpql = (lquery_level *) palloc0(ITEMSIZE * num);
312  ptr = buf;
313  while (*ptr)
314  {
315  charlen = pg_mblen(ptr);
316 
317  switch (state)
318  {
319  case LQPRS_WAITLEVEL:
320  if (ISLABEL(ptr))
321  {
322  GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
323  lptr->start = ptr;
325  curqlevel->numvar = 1;
326  }
327  else if (t_iseq(ptr, '!'))
328  {
329  GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
330  lptr->start = ptr + 1;
331  lptr->wlen = -1; /* compensate for counting ! below */
333  curqlevel->numvar = 1;
334  curqlevel->flag |= LQL_NOT;
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  curqlevel->numvar++;
349  }
350  else
351  UNCHAR;
352  break;
353  case LQPRS_WAITDELIM:
354  if (t_iseq(ptr, '@'))
355  {
356  lptr->flag |= LVAR_INCASE;
357  curqlevel->flag |= LVAR_INCASE;
358  }
359  else if (t_iseq(ptr, '*'))
360  {
361  lptr->flag |= LVAR_ANYEND;
362  curqlevel->flag |= LVAR_ANYEND;
363  }
364  else if (t_iseq(ptr, '%'))
365  {
366  lptr->flag |= LVAR_SUBLEXEME;
367  curqlevel->flag |= LVAR_SUBLEXEME;
368  }
369  else if (t_iseq(ptr, '|'))
370  {
371  if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
372  return NULL;
374  }
375  else if (t_iseq(ptr, '{'))
376  {
377  if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
378  return NULL;
379  curqlevel->flag |= LQL_COUNT;
381  }
382  else if (t_iseq(ptr, '.'))
383  {
384  if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
385  return NULL;
387  curqlevel = NEXTLEV(curqlevel);
388  }
389  else if (ISLABEL(ptr))
390  {
391  /* disallow more chars after a flag */
392  if (lptr->flag)
393  UNCHAR;
394  }
395  else
396  UNCHAR;
397  break;
398  case LQPRS_WAITOPEN:
399  if (t_iseq(ptr, '{'))
401  else if (t_iseq(ptr, '.'))
402  {
403  /* We only get here for '*', so these are correct defaults */
404  curqlevel->low = 0;
405  curqlevel->high = LTREE_MAX_LEVELS;
406  curqlevel = NEXTLEV(curqlevel);
408  }
409  else
410  UNCHAR;
411  break;
412  case LQPRS_WAITFNUM:
413  if (t_iseq(ptr, ','))
415  else if (t_isdigit(ptr))
416  {
417  int low = atoi(ptr);
418 
419  if (low < 0 || low > LTREE_MAX_LEVELS)
420  ereturn(escontext, NULL,
421  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
422  errmsg("lquery syntax error"),
423  errdetail("Low limit (%d) exceeds the maximum allowed (%d), at character %d.",
424  low, LTREE_MAX_LEVELS, pos)));
425 
426  curqlevel->low = (uint16) low;
428  }
429  else
430  UNCHAR;
431  break;
432  case LQPRS_WAITSNUM:
433  if (t_isdigit(ptr))
434  {
435  int high = atoi(ptr);
436 
437  if (high < 0 || high > LTREE_MAX_LEVELS)
438  ereturn(escontext, NULL,
439  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
440  errmsg("lquery syntax error"),
441  errdetail("High limit (%d) exceeds the maximum allowed (%d), at character %d.",
442  high, LTREE_MAX_LEVELS, pos)));
443  else if (curqlevel->low > high)
444  ereturn(escontext, NULL,
445  (errcode(ERRCODE_SYNTAX_ERROR),
446  errmsg("lquery syntax error"),
447  errdetail("Low limit (%d) is greater than high limit (%d), at character %d.",
448  curqlevel->low, high, pos)));
449 
450  curqlevel->high = (uint16) high;
452  }
453  else if (t_iseq(ptr, '}'))
454  {
455  curqlevel->high = LTREE_MAX_LEVELS;
457  }
458  else
459  UNCHAR;
460  break;
461  case LQPRS_WAITCLOSE:
462  if (t_iseq(ptr, '}'))
464  else if (!t_isdigit(ptr))
465  UNCHAR;
466  break;
467  case LQPRS_WAITND:
468  if (t_iseq(ptr, '}'))
469  {
470  curqlevel->high = curqlevel->low;
472  }
473  else if (t_iseq(ptr, ','))
475  else if (!t_isdigit(ptr))
476  UNCHAR;
477  break;
478  case LQPRS_WAITEND:
479  if (t_iseq(ptr, '.'))
480  {
482  curqlevel = NEXTLEV(curqlevel);
483  }
484  else
485  UNCHAR;
486  break;
487  default:
488  elog(ERROR, "internal error in lquery parser");
489  }
490 
491  ptr += charlen;
492  if (state == LQPRS_WAITDELIM)
493  lptr->wlen++;
494  pos++;
495  }
496 
497  if (state == LQPRS_WAITDELIM)
498  {
499  if (!finish_nodeitem(lptr, ptr, true, pos, escontext))
500  return NULL;
501  }
502  else if (state == LQPRS_WAITOPEN)
503  curqlevel->high = LTREE_MAX_LEVELS;
504  else if (state != LQPRS_WAITEND)
505  ereturn(escontext, NULL,
506  (errcode(ERRCODE_SYNTAX_ERROR),
507  errmsg("lquery syntax error"),
508  errdetail("Unexpected end of input.")));
509 
510  curqlevel = tmpql;
511  totallen = LQUERY_HDRSIZE;
512  while ((char *) curqlevel - (char *) tmpql < num * ITEMSIZE)
513  {
514  totallen += LQL_HDRSIZE;
515  if (curqlevel->numvar)
516  {
517  lptr = GETVAR(curqlevel);
518  while (lptr - GETVAR(curqlevel) < curqlevel->numvar)
519  {
520  totallen += MAXALIGN(LVAR_HDRSIZE + lptr->len);
521  lptr++;
522  }
523  }
524  curqlevel = NEXTLEV(curqlevel);
525  }
526 
527  result = (lquery *) palloc0(totallen);
528  SET_VARSIZE(result, totallen);
529  result->numlevel = num;
530  result->firstgood = 0;
531  result->flag = 0;
532  if (hasnot)
533  result->flag |= LQUERY_HASNOT;
534  cur = LQUERY_FIRST(result);
535  curqlevel = tmpql;
536  while ((char *) curqlevel - (char *) tmpql < num * ITEMSIZE)
537  {
538  memcpy(cur, curqlevel, LQL_HDRSIZE);
539  cur->totallen = LQL_HDRSIZE;
540  if (curqlevel->numvar)
541  {
542  lrptr = LQL_FIRST(cur);
543  lptr = GETVAR(curqlevel);
544  while (lptr - GETVAR(curqlevel) < curqlevel->numvar)
545  {
546  cur->totallen += MAXALIGN(LVAR_HDRSIZE + lptr->len);
547  lrptr->len = lptr->len;
548  lrptr->flag = lptr->flag;
549  lrptr->val = ltree_crc32_sz(lptr->start, lptr->len);
550  memcpy(lrptr->name, lptr->start, lptr->len);
551  lptr++;
552  lrptr = LVAR_NEXT(lrptr);
553  }
554  pfree(GETVAR(curqlevel));
555  if (cur->numvar > 1 || cur->flag != 0)
556  {
557  /* Not a simple match */
558  wasbad = true;
559  }
560  else if (wasbad == false)
561  {
562  /* count leading simple matches */
563  (result->firstgood)++;
564  }
565  }
566  else
567  {
568  /* '*', so this isn't a simple match */
569  wasbad = true;
570  }
571  curqlevel = NEXTLEV(curqlevel);
572  cur = LQL_NEXT(cur);
573  }
574 
575  pfree(tmpql);
576  return result;
577 
578 #undef UNCHAR
579 }
580 
581 /*
582  * Close out parsing an ltree or lquery nodeitem:
583  * compute the correct length, and complain if it's not OK
584  */
585 static bool
586 finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos,
587  struct Node *escontext)
588 {
589  if (is_lquery)
590  {
591  /*
592  * Back up over any flag characters, and discount them from length and
593  * position.
594  */
595  while (ptr > lptr->start && strchr("@*%", ptr[-1]) != NULL)
596  {
597  ptr--;
598  lptr->wlen--;
599  pos--;
600  }
601  }
602 
603  /* Now compute the byte length, which we weren't tracking before. */
604  lptr->len = ptr - lptr->start;
605 
606  /* Complain if it's empty or too long */
607  if (lptr->len == 0)
608  ereturn(escontext, false,
609  (errcode(ERRCODE_SYNTAX_ERROR),
610  is_lquery ?
611  errmsg("lquery syntax error at character %d", pos) :
612  errmsg("ltree syntax error at character %d", pos),
613  errdetail("Empty labels are not allowed.")));
614  if (lptr->wlen > LTREE_LABEL_MAX_CHARS)
615  ereturn(escontext, false,
616  (errcode(ERRCODE_NAME_TOO_LONG),
617  errmsg("label string is too long"),
618  errdetail("Label length is %d, must be at most %d, at character %d.",
619  lptr->wlen, LTREE_LABEL_MAX_CHARS, pos)));
620  return true;
621 }
622 
623 /*
624  * expects an lquery
625  * returns a null terminated string
626  */
627 static char *
629 {
630  char *buf,
631  *ptr;
632  int i,
633  j,
634  totallen = 1;
635  lquery_level *curqlevel;
636  lquery_variant *curtlevel;
637 
638  curqlevel = LQUERY_FIRST(in);
639  for (i = 0; i < in->numlevel; i++)
640  {
641  totallen++;
642  if (curqlevel->numvar)
643  {
644  totallen += 1 + (curqlevel->numvar * 4) + curqlevel->totallen;
645  if (curqlevel->flag & LQL_COUNT)
646  totallen += 2 * 11 + 3;
647  }
648  else
649  totallen += 2 * 11 + 4;
650  curqlevel = LQL_NEXT(curqlevel);
651  }
652 
653  ptr = buf = (char *) palloc(totallen);
654  curqlevel = LQUERY_FIRST(in);
655  for (i = 0; i < in->numlevel; i++)
656  {
657  if (i != 0)
658  {
659  *ptr = '.';
660  ptr++;
661  }
662  if (curqlevel->numvar)
663  {
664  if (curqlevel->flag & LQL_NOT)
665  {
666  *ptr = '!';
667  ptr++;
668  }
669  curtlevel = LQL_FIRST(curqlevel);
670  for (j = 0; j < curqlevel->numvar; j++)
671  {
672  if (j != 0)
673  {
674  *ptr = '|';
675  ptr++;
676  }
677  memcpy(ptr, curtlevel->name, curtlevel->len);
678  ptr += curtlevel->len;
679  if ((curtlevel->flag & LVAR_SUBLEXEME))
680  {
681  *ptr = '%';
682  ptr++;
683  }
684  if ((curtlevel->flag & LVAR_INCASE))
685  {
686  *ptr = '@';
687  ptr++;
688  }
689  if ((curtlevel->flag & LVAR_ANYEND))
690  {
691  *ptr = '*';
692  ptr++;
693  }
694  curtlevel = LVAR_NEXT(curtlevel);
695  }
696  }
697  else
698  {
699  *ptr = '*';
700  ptr++;
701  }
702 
703  if ((curqlevel->flag & LQL_COUNT) || curqlevel->numvar == 0)
704  {
705  if (curqlevel->low == curqlevel->high)
706  {
707  sprintf(ptr, "{%d}", curqlevel->low);
708  }
709  else if (curqlevel->low == 0)
710  {
711  if (curqlevel->high == LTREE_MAX_LEVELS)
712  {
713  if (curqlevel->numvar == 0)
714  {
715  /* This is default for '*', so print nothing */
716  *ptr = '\0';
717  }
718  else
719  sprintf(ptr, "{,}");
720  }
721  else
722  sprintf(ptr, "{,%d}", curqlevel->high);
723  }
724  else if (curqlevel->high == LTREE_MAX_LEVELS)
725  {
726  sprintf(ptr, "{%d,}", curqlevel->low);
727  }
728  else
729  sprintf(ptr, "{%d,%d}", curqlevel->low, curqlevel->high);
730  ptr = strchr(ptr, '\0');
731  }
732 
733  curqlevel = LQL_NEXT(curqlevel);
734  }
735 
736  *ptr = '\0';
737  return buf;
738 }
739 
740 /*
741  * Basic lquery I/O functions
742  */
744 Datum
746 {
747  char *buf = (char *) PG_GETARG_POINTER(0);
748  lquery *res;
749 
750  if ((res = parse_lquery(buf, fcinfo->context)) == NULL)
751  PG_RETURN_NULL();
752 
754 }
755 
757 Datum
759 {
760  lquery *in = PG_GETARG_LQUERY_P(0);
761 
763 }
764 
765 /*
766  * lquery type send function
767  *
768  * The type is sent as text in binary mode, so this is almost the same
769  * as the output function, but it's prefixed with a version number so we
770  * can change the binary format sent in future if necessary. For now,
771  * only version 1 is supported.
772  */
774 Datum
776 {
777  lquery *in = PG_GETARG_LQUERY_P(0);
779  int version = 1;
780  char *res = deparse_lquery(in);
781 
783  pq_sendint8(&buf, version);
784  pq_sendtext(&buf, res, strlen(res));
785  pfree(res);
786 
788 }
789 
790 /*
791  * lquery type recv function
792  *
793  * The type is sent as text in binary mode, so this is almost the same
794  * as the input function, but it's prefixed with a version number so we
795  * can change the binary format sent in future if necessary. For now,
796  * only version 1 is supported.
797  */
799 Datum
801 {
803  int version = pq_getmsgint(buf, 1);
804  char *str;
805  int nbytes;
806  lquery *res;
807 
808  if (version != 1)
809  elog(ERROR, "unsupported lquery version number %d", version);
810 
811  str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
812  res = parse_lquery(str, NULL);
813  pfree(str);
814 
816 }
unsigned short uint16
Definition: c.h:505
#define MAXALIGN(LEN)
Definition: c.h:811
unsigned int ltree_crc32_sz(const char *buf, int size)
Definition: crc32.c:24
struct cursor * cur
Definition: ecpg.c:28
int errdetail(const char *fmt,...)
Definition: elog.c:1205
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ereturn(context, dummy_value,...)
Definition: elog.h:276
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#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:74
int i
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
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: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:145
#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
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:758
#define LQPRS_WAITVAR
Definition: ltree_io.c:257
static lquery * parse_lquery(const char *buf, struct Node *escontext)
Definition: ltree_io.c:269
Datum lquery_in(PG_FUNCTION_ARGS)
Definition: ltree_io.c:745
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
static char * deparse_lquery(const lquery *in)
Definition: ltree_io.c:628
PG_FUNCTION_INFO_V1(ltree_in)
#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:775
#define LTPRS_WAITNAME
Definition: ltree_io.c:25
static ltree * parse_ltree(const char *buf, struct Node *escontext)
Definition: ltree_io.c:37
static bool finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos, struct Node *escontext)
Definition: ltree_io.c:586
#define LQPRS_WAITND
Definition: ltree_io.c:254
Datum lquery_recv(PG_FUNCTION_ARGS)
Definition: ltree_io.c:800
#define GETVAR(x)
Definition: ltree_io.c:260
Datum ltree_out(PG_FUNCTION_ARGS)
Definition: ltree_io.c:188
int pg_mblen(const char *mbstr)
Definition: mbutils.c:1023
void pfree(void *pointer)
Definition: mcxt.c:1520
void * palloc0(Size size)
Definition: mcxt.c:1346
void * palloc(Size size)
Definition: mcxt.c:1316
static char * buf
Definition: pg_test_fsync.c:73
#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:22
const char * start
Definition: ltree_io.c:19
int len
Definition: ltree_io.c:20
int flag
Definition: ltree_io.c:21
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