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 
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 void finish_nodeitem(nodeitem *lptr, const char *ptr,
28  bool is_lquery, int pos);
29 
30 
31 /*
32  * expects a null terminated string
33  * returns an ltree
34  */
35 static ltree *
36 parse_ltree(const char *buf)
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 ereport(ERROR, \
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  ereport(ERROR,
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 (ISALNUM(ptr))
78  {
79  lptr->start = ptr;
80  lptr->wlen = 0;
81  state = LTPRS_WAITDELIM;
82  }
83  else
84  UNCHAR;
85  break;
86  case LTPRS_WAITDELIM:
87  if (t_iseq(ptr, '.'))
88  {
89  finish_nodeitem(lptr, ptr, false, pos);
90  totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
91  lptr++;
92  state = LTPRS_WAITNAME;
93  }
94  else if (!ISALNUM(ptr))
95  UNCHAR;
96  break;
97  default:
98  elog(ERROR, "internal error in ltree parser");
99  }
100 
101  ptr += charlen;
102  lptr->wlen++;
103  pos++;
104  }
105 
106  if (state == LTPRS_WAITDELIM)
107  {
108  finish_nodeitem(lptr, ptr, false, pos);
109  totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
110  lptr++;
111  }
112  else if (!(state == LTPRS_WAITNAME && lptr == list))
113  ereport(ERROR,
114  (errcode(ERRCODE_SYNTAX_ERROR),
115  errmsg("ltree syntax error"),
116  errdetail("Unexpected end of input.")));
117 
118  result = (ltree *) palloc0(LTREE_HDRSIZE + totallen);
119  SET_VARSIZE(result, LTREE_HDRSIZE + totallen);
120  result->numlevel = lptr - list;
121  curlevel = LTREE_FIRST(result);
122  lptr = list;
123  while (lptr - list < result->numlevel)
124  {
125  curlevel->len = (uint16) lptr->len;
126  memcpy(curlevel->name, lptr->start, lptr->len);
127  curlevel = LEVEL_NEXT(curlevel);
128  lptr++;
129  }
130 
131  pfree(list);
132  return result;
133 
134 #undef UNCHAR
135 }
136 
137 /*
138  * expects an ltree
139  * returns a null terminated string
140  */
141 static char *
143 {
144  char *buf,
145  *ptr;
146  int i;
147  ltree_level *curlevel;
148 
149  ptr = buf = (char *) palloc(VARSIZE(in));
150  curlevel = LTREE_FIRST(in);
151  for (i = 0; i < in->numlevel; i++)
152  {
153  if (i != 0)
154  {
155  *ptr = '.';
156  ptr++;
157  }
158  memcpy(ptr, curlevel->name, curlevel->len);
159  ptr += curlevel->len;
160  curlevel = LEVEL_NEXT(curlevel);
161  }
162 
163  *ptr = '\0';
164  return buf;
165 }
166 
167 /*
168  * Basic ltree I/O functions
169  */
171 Datum
173 {
174  char *buf = (char *) PG_GETARG_POINTER(0);
175 
177 }
178 
180 Datum
182 {
183  ltree *in = PG_GETARG_LTREE_P(0);
184 
186 }
187 
188 /*
189  * ltree type send function
190  *
191  * The type is sent as text in binary mode, so this is almost the same
192  * as the output function, but it's prefixed with a version number so we
193  * can change the binary format sent in future if necessary. For now,
194  * only version 1 is supported.
195  */
197 Datum
199 {
200  ltree *in = PG_GETARG_LTREE_P(0);
202  int version = 1;
203  char *res = deparse_ltree(in);
204 
205  pq_begintypsend(&buf);
206  pq_sendint8(&buf, version);
207  pq_sendtext(&buf, res, strlen(res));
208  pfree(res);
209 
211 }
212 
213 /*
214  * ltree type recv function
215  *
216  * The type is sent as text in binary mode, so this is almost the same
217  * as the input function, but it's prefixed with a version number so we
218  * can change the binary format sent in future if necessary. For now,
219  * only version 1 is supported.
220  */
222 Datum
224 {
226  int version = pq_getmsgint(buf, 1);
227  char *str;
228  int nbytes;
229  ltree *res;
230 
231  if (version != 1)
232  elog(ERROR, "unsupported ltree version number %d", version);
233 
234  str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
235  res = parse_ltree(str);
236  pfree(str);
237 
238  PG_RETURN_POINTER(res);
239 }
240 
241 
242 #define LQPRS_WAITLEVEL 0
243 #define LQPRS_WAITDELIM 1
244 #define LQPRS_WAITOPEN 2
245 #define LQPRS_WAITFNUM 3
246 #define LQPRS_WAITSNUM 4
247 #define LQPRS_WAITND 5
248 #define LQPRS_WAITCLOSE 6
249 #define LQPRS_WAITEND 7
250 #define LQPRS_WAITVAR 8
251 
252 
253 #define GETVAR(x) ( *((nodeitem**)LQL_FIRST(x)) )
254 #define ITEMSIZE MAXALIGN(LQL_HDRSIZE+sizeof(nodeitem*))
255 #define NEXTLEV(x) ( (lquery_level*)( ((char*)(x)) + ITEMSIZE) )
256 
257 /*
258  * expects a null terminated string
259  * returns an lquery
260  */
261 static lquery *
262 parse_lquery(const char *buf)
263 {
264  const char *ptr;
265  int num = 0,
266  totallen = 0,
267  numOR = 0;
268  int state = LQPRS_WAITLEVEL;
269  lquery *result;
270  nodeitem *lptr = NULL;
271  lquery_level *cur,
272  *curqlevel,
273  *tmpql;
274  lquery_variant *lrptr = NULL;
275  bool hasnot = false;
276  bool wasbad = false;
277  int charlen;
278  int pos = 1; /* character position for error messages */
279 
280 #define UNCHAR ereport(ERROR, \
281  errcode(ERRCODE_SYNTAX_ERROR), \
282  errmsg("lquery syntax error at character %d", \
283  pos))
284 
285  ptr = buf;
286  while (*ptr)
287  {
288  charlen = pg_mblen(ptr);
289 
290  if (t_iseq(ptr, '.'))
291  num++;
292  else if (t_iseq(ptr, '|'))
293  numOR++;
294 
295  ptr += charlen;
296  }
297 
298  num++;
299  if (num > LQUERY_MAX_LEVELS)
300  ereport(ERROR,
301  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
302  errmsg("number of lquery items (%d) exceeds the maximum allowed (%d)",
303  num, LQUERY_MAX_LEVELS)));
304  curqlevel = tmpql = (lquery_level *) palloc0(ITEMSIZE * num);
305  ptr = buf;
306  while (*ptr)
307  {
308  charlen = pg_mblen(ptr);
309 
310  switch (state)
311  {
312  case LQPRS_WAITLEVEL:
313  if (ISALNUM(ptr))
314  {
315  GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
316  lptr->start = ptr;
317  state = LQPRS_WAITDELIM;
318  curqlevel->numvar = 1;
319  }
320  else if (t_iseq(ptr, '!'))
321  {
322  GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
323  lptr->start = ptr + 1;
324  lptr->wlen = -1; /* compensate for counting ! below */
325  state = LQPRS_WAITDELIM;
326  curqlevel->numvar = 1;
327  curqlevel->flag |= LQL_NOT;
328  hasnot = true;
329  }
330  else if (t_iseq(ptr, '*'))
331  state = LQPRS_WAITOPEN;
332  else
333  UNCHAR;
334  break;
335  case LQPRS_WAITVAR:
336  if (ISALNUM(ptr))
337  {
338  lptr++;
339  lptr->start = ptr;
340  state = LQPRS_WAITDELIM;
341  curqlevel->numvar++;
342  }
343  else
344  UNCHAR;
345  break;
346  case LQPRS_WAITDELIM:
347  if (t_iseq(ptr, '@'))
348  {
349  lptr->flag |= LVAR_INCASE;
350  curqlevel->flag |= LVAR_INCASE;
351  }
352  else if (t_iseq(ptr, '*'))
353  {
354  lptr->flag |= LVAR_ANYEND;
355  curqlevel->flag |= LVAR_ANYEND;
356  }
357  else if (t_iseq(ptr, '%'))
358  {
359  lptr->flag |= LVAR_SUBLEXEME;
360  curqlevel->flag |= LVAR_SUBLEXEME;
361  }
362  else if (t_iseq(ptr, '|'))
363  {
364  finish_nodeitem(lptr, ptr, true, pos);
365  state = LQPRS_WAITVAR;
366  }
367  else if (t_iseq(ptr, '{'))
368  {
369  finish_nodeitem(lptr, ptr, true, pos);
370  curqlevel->flag |= LQL_COUNT;
371  state = LQPRS_WAITFNUM;
372  }
373  else if (t_iseq(ptr, '.'))
374  {
375  finish_nodeitem(lptr, ptr, true, pos);
376  state = LQPRS_WAITLEVEL;
377  curqlevel = NEXTLEV(curqlevel);
378  }
379  else if (ISALNUM(ptr))
380  {
381  /* disallow more chars after a flag */
382  if (lptr->flag)
383  UNCHAR;
384  }
385  else
386  UNCHAR;
387  break;
388  case LQPRS_WAITOPEN:
389  if (t_iseq(ptr, '{'))
390  state = LQPRS_WAITFNUM;
391  else if (t_iseq(ptr, '.'))
392  {
393  /* We only get here for '*', so these are correct defaults */
394  curqlevel->low = 0;
395  curqlevel->high = LTREE_MAX_LEVELS;
396  curqlevel = NEXTLEV(curqlevel);
397  state = LQPRS_WAITLEVEL;
398  }
399  else
400  UNCHAR;
401  break;
402  case LQPRS_WAITFNUM:
403  if (t_iseq(ptr, ','))
404  state = LQPRS_WAITSNUM;
405  else if (t_isdigit(ptr))
406  {
407  int low = atoi(ptr);
408 
409  if (low < 0 || low > LTREE_MAX_LEVELS)
410  ereport(ERROR,
411  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
412  errmsg("lquery syntax error"),
413  errdetail("Low limit (%d) exceeds the maximum allowed (%d), at character %d.",
414  low, LTREE_MAX_LEVELS, pos)));
415 
416  curqlevel->low = (uint16) low;
417  state = LQPRS_WAITND;
418  }
419  else
420  UNCHAR;
421  break;
422  case LQPRS_WAITSNUM:
423  if (t_isdigit(ptr))
424  {
425  int high = atoi(ptr);
426 
427  if (high < 0 || high > LTREE_MAX_LEVELS)
428  ereport(ERROR,
429  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
430  errmsg("lquery syntax error"),
431  errdetail("High limit (%d) exceeds the maximum allowed (%d), at character %d.",
432  high, LTREE_MAX_LEVELS, pos)));
433  else if (curqlevel->low > high)
434  ereport(ERROR,
435  (errcode(ERRCODE_SYNTAX_ERROR),
436  errmsg("lquery syntax error"),
437  errdetail("Low limit (%d) is greater than high limit (%d), at character %d.",
438  curqlevel->low, high, pos)));
439 
440  curqlevel->high = (uint16) high;
441  state = LQPRS_WAITCLOSE;
442  }
443  else if (t_iseq(ptr, '}'))
444  {
445  curqlevel->high = LTREE_MAX_LEVELS;
446  state = LQPRS_WAITEND;
447  }
448  else
449  UNCHAR;
450  break;
451  case LQPRS_WAITCLOSE:
452  if (t_iseq(ptr, '}'))
453  state = LQPRS_WAITEND;
454  else if (!t_isdigit(ptr))
455  UNCHAR;
456  break;
457  case LQPRS_WAITND:
458  if (t_iseq(ptr, '}'))
459  {
460  curqlevel->high = curqlevel->low;
461  state = LQPRS_WAITEND;
462  }
463  else if (t_iseq(ptr, ','))
464  state = LQPRS_WAITSNUM;
465  else if (!t_isdigit(ptr))
466  UNCHAR;
467  break;
468  case LQPRS_WAITEND:
469  if (t_iseq(ptr, '.'))
470  {
471  state = LQPRS_WAITLEVEL;
472  curqlevel = NEXTLEV(curqlevel);
473  }
474  else
475  UNCHAR;
476  break;
477  default:
478  elog(ERROR, "internal error in lquery parser");
479  }
480 
481  ptr += charlen;
482  if (state == LQPRS_WAITDELIM)
483  lptr->wlen++;
484  pos++;
485  }
486 
487  if (state == LQPRS_WAITDELIM)
488  finish_nodeitem(lptr, ptr, true, pos);
489  else if (state == LQPRS_WAITOPEN)
490  curqlevel->high = LTREE_MAX_LEVELS;
491  else if (state != LQPRS_WAITEND)
492  ereport(ERROR,
493  (errcode(ERRCODE_SYNTAX_ERROR),
494  errmsg("lquery syntax error"),
495  errdetail("Unexpected end of input.")));
496 
497  curqlevel = tmpql;
498  totallen = LQUERY_HDRSIZE;
499  while ((char *) curqlevel - (char *) tmpql < num * ITEMSIZE)
500  {
501  totallen += LQL_HDRSIZE;
502  if (curqlevel->numvar)
503  {
504  lptr = GETVAR(curqlevel);
505  while (lptr - GETVAR(curqlevel) < curqlevel->numvar)
506  {
507  totallen += MAXALIGN(LVAR_HDRSIZE + lptr->len);
508  lptr++;
509  }
510  }
511  curqlevel = NEXTLEV(curqlevel);
512  }
513 
514  result = (lquery *) palloc0(totallen);
515  SET_VARSIZE(result, totallen);
516  result->numlevel = num;
517  result->firstgood = 0;
518  result->flag = 0;
519  if (hasnot)
520  result->flag |= LQUERY_HASNOT;
521  cur = LQUERY_FIRST(result);
522  curqlevel = tmpql;
523  while ((char *) curqlevel - (char *) tmpql < num * ITEMSIZE)
524  {
525  memcpy(cur, curqlevel, LQL_HDRSIZE);
526  cur->totallen = LQL_HDRSIZE;
527  if (curqlevel->numvar)
528  {
529  lrptr = LQL_FIRST(cur);
530  lptr = GETVAR(curqlevel);
531  while (lptr - GETVAR(curqlevel) < curqlevel->numvar)
532  {
533  cur->totallen += MAXALIGN(LVAR_HDRSIZE + lptr->len);
534  lrptr->len = lptr->len;
535  lrptr->flag = lptr->flag;
536  lrptr->val = ltree_crc32_sz(lptr->start, lptr->len);
537  memcpy(lrptr->name, lptr->start, lptr->len);
538  lptr++;
539  lrptr = LVAR_NEXT(lrptr);
540  }
541  pfree(GETVAR(curqlevel));
542  if (cur->numvar > 1 || cur->flag != 0)
543  {
544  /* Not a simple match */
545  wasbad = true;
546  }
547  else if (wasbad == false)
548  {
549  /* count leading simple matches */
550  (result->firstgood)++;
551  }
552  }
553  else
554  {
555  /* '*', so this isn't a simple match */
556  wasbad = true;
557  }
558  curqlevel = NEXTLEV(curqlevel);
559  cur = LQL_NEXT(cur);
560  }
561 
562  pfree(tmpql);
563  return result;
564 
565 #undef UNCHAR
566 }
567 
568 /*
569  * Close out parsing an ltree or lquery nodeitem:
570  * compute the correct length, and complain if it's not OK
571  */
572 static void
573 finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos)
574 {
575  if (is_lquery)
576  {
577  /*
578  * Back up over any flag characters, and discount them from length and
579  * position.
580  */
581  while (ptr > lptr->start && strchr("@*%", ptr[-1]) != NULL)
582  {
583  ptr--;
584  lptr->wlen--;
585  pos--;
586  }
587  }
588 
589  /* Now compute the byte length, which we weren't tracking before. */
590  lptr->len = ptr - lptr->start;
591 
592  /* Complain if it's empty or too long */
593  if (lptr->len == 0)
594  ereport(ERROR,
595  (errcode(ERRCODE_SYNTAX_ERROR),
596  is_lquery ?
597  errmsg("lquery syntax error at character %d", pos) :
598  errmsg("ltree syntax error at character %d", pos),
599  errdetail("Empty labels are not allowed.")));
600  if (lptr->wlen > LTREE_LABEL_MAX_CHARS)
601  ereport(ERROR,
602  (errcode(ERRCODE_NAME_TOO_LONG),
603  errmsg("label string is too long"),
604  errdetail("Label length is %d, must be at most %d, at character %d.",
605  lptr->wlen, LTREE_LABEL_MAX_CHARS, pos)));
606 }
607 
608 /*
609  * expects an lquery
610  * returns a null terminated string
611  */
612 static char *
614 {
615  char *buf,
616  *ptr;
617  int i,
618  j,
619  totallen = 1;
620  lquery_level *curqlevel;
621  lquery_variant *curtlevel;
622 
623  curqlevel = LQUERY_FIRST(in);
624  for (i = 0; i < in->numlevel; i++)
625  {
626  totallen++;
627  if (curqlevel->numvar)
628  {
629  totallen += 1 + (curqlevel->numvar * 4) + curqlevel->totallen;
630  if (curqlevel->flag & LQL_COUNT)
631  totallen += 2 * 11 + 3;
632  }
633  else
634  totallen += 2 * 11 + 4;
635  curqlevel = LQL_NEXT(curqlevel);
636  }
637 
638  ptr = buf = (char *) palloc(totallen);
639  curqlevel = LQUERY_FIRST(in);
640  for (i = 0; i < in->numlevel; i++)
641  {
642  if (i != 0)
643  {
644  *ptr = '.';
645  ptr++;
646  }
647  if (curqlevel->numvar)
648  {
649  if (curqlevel->flag & LQL_NOT)
650  {
651  *ptr = '!';
652  ptr++;
653  }
654  curtlevel = LQL_FIRST(curqlevel);
655  for (j = 0; j < curqlevel->numvar; j++)
656  {
657  if (j != 0)
658  {
659  *ptr = '|';
660  ptr++;
661  }
662  memcpy(ptr, curtlevel->name, curtlevel->len);
663  ptr += curtlevel->len;
664  if ((curtlevel->flag & LVAR_SUBLEXEME))
665  {
666  *ptr = '%';
667  ptr++;
668  }
669  if ((curtlevel->flag & LVAR_INCASE))
670  {
671  *ptr = '@';
672  ptr++;
673  }
674  if ((curtlevel->flag & LVAR_ANYEND))
675  {
676  *ptr = '*';
677  ptr++;
678  }
679  curtlevel = LVAR_NEXT(curtlevel);
680  }
681  }
682  else
683  {
684  *ptr = '*';
685  ptr++;
686  }
687 
688  if ((curqlevel->flag & LQL_COUNT) || curqlevel->numvar == 0)
689  {
690  if (curqlevel->low == curqlevel->high)
691  {
692  sprintf(ptr, "{%d}", curqlevel->low);
693  }
694  else if (curqlevel->low == 0)
695  {
696  if (curqlevel->high == LTREE_MAX_LEVELS)
697  {
698  if (curqlevel->numvar == 0)
699  {
700  /* This is default for '*', so print nothing */
701  *ptr = '\0';
702  }
703  else
704  sprintf(ptr, "{,}");
705  }
706  else
707  sprintf(ptr, "{,%d}", curqlevel->high);
708  }
709  else if (curqlevel->high == LTREE_MAX_LEVELS)
710  {
711  sprintf(ptr, "{%d,}", curqlevel->low);
712  }
713  else
714  sprintf(ptr, "{%d,%d}", curqlevel->low, curqlevel->high);
715  ptr = strchr(ptr, '\0');
716  }
717 
718  curqlevel = LQL_NEXT(curqlevel);
719  }
720 
721  *ptr = '\0';
722  return buf;
723 }
724 
725 /*
726  * Basic lquery I/O functions
727  */
729 Datum
731 {
732  char *buf = (char *) PG_GETARG_POINTER(0);
733 
735 }
736 
738 Datum
740 {
741  lquery *in = PG_GETARG_LQUERY_P(0);
742 
744 }
745 
746 /*
747  * lquery type send function
748  *
749  * The type is sent as text in binary mode, so this is almost the same
750  * as the output function, but it's prefixed with a version number so we
751  * can change the binary format sent in future if necessary. For now,
752  * only version 1 is supported.
753  */
755 Datum
757 {
758  lquery *in = PG_GETARG_LQUERY_P(0);
760  int version = 1;
761  char *res = deparse_lquery(in);
762 
763  pq_begintypsend(&buf);
764  pq_sendint8(&buf, version);
765  pq_sendtext(&buf, res, strlen(res));
766  pfree(res);
767 
769 }
770 
771 /*
772  * lquery type recv function
773  *
774  * The type is sent as text in binary mode, so this is almost the same
775  * as the input function, but it's prefixed with a version number so we
776  * can change the binary format sent in future if necessary. For now,
777  * only version 1 is supported.
778  */
780 Datum
782 {
784  int version = pq_getmsgint(buf, 1);
785  char *str;
786  int nbytes;
787  lquery *res;
788 
789  if (version != 1)
790  elog(ERROR, "unsupported lquery version number %d", version);
791 
792  str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
793  res = parse_lquery(str);
794  pfree(str);
795 
796  PG_RETURN_POINTER(res);
797 }
uint16 firstgood
Definition: ltree.h:104
#define GETVAR(x)
Definition: ltree_io.c:253
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
Datum lquery_send(PG_FUNCTION_ARGS)
Definition: ltree_io.c:756
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:23
Datum ltree_send(PG_FUNCTION_ARGS)
Definition: ltree_io.c:198
#define LVAR_INCASE
Definition: ltree.h:62
uint8 flag
Definition: ltree.h:49
Datum lquery_recv(PG_FUNCTION_ARGS)
Definition: ltree_io.c:781
static char * deparse_lquery(const lquery *in)
Definition: ltree_io.c:613
#define LQPRS_WAITVAR
Definition: ltree_io.c:250
#define LQPRS_WAITFNUM
Definition: ltree_io.c:245
unsigned int ltree_crc32_sz(const char *buf, int size)
Definition: crc32.c:23
uint16 low
Definition: ltree.h:80
#define LQUERY_FIRST(x)
Definition: ltree.h:111
uint16 len
Definition: ltree.h:48
#define ISALNUM(x)
Definition: ltree.h:116
uint16 len
Definition: ltree.h:22
#define LVAR_ANYEND
Definition: ltree.h:61
#define LQPRS_WAITCLOSE
Definition: ltree_io.c:248
#define LQPRS_WAITOPEN
Definition: ltree_io.c:244
#define VARSIZE(PTR)
Definition: postgres.h:303
int len
Definition: ltree_io.c:19
#define NEXTLEV(x)
Definition: ltree_io.c:255
int wlen
Definition: ltree_io.c:21
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
Datum ltree_in(PG_FUNCTION_ARGS)
Definition: ltree_io.c:172
Definition: ltree.h:100
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:50
StringInfoData * StringInfo
Definition: stringinfo.h:44
#define LQL_FIRST(x)
Definition: ltree.h:88
PG_FUNCTION_INFO_V1(ltree_in)
#define LQL_NEXT(x)
Definition: ltree.h:87
#define LTREE_HDRSIZE
Definition: ltree.h:37
struct cursor * cur
Definition: ecpg.c:28
int errcode(int sqlerrcode)
Definition: elog.c:691
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:174
#define PG_GETARG_LTREE_P(n)
Definition: ltree.h:204
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
uint16 flag
Definition: ltree.h:105
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
uint16 totallen
Definition: ltree.h:77
#define LQPRS_WAITND
Definition: ltree_io.c:247
#define LVAR_NEXT(x)
Definition: ltree.h:59
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
int flag
Definition: ltree_io.c:20
#define PG_GETARG_LQUERY_P(n)
Definition: ltree.h:209
int t_isdigit(const char *ptr)
Definition: ts_locale.c:37
#define sprintf
Definition: port.h:217
unsigned short uint16
Definition: c.h:428
void pfree(void *pointer)
Definition: mcxt.c:1057
uint16 flag
Definition: ltree.h:78
#define ERROR
Definition: elog.h:43
#define LQUERY_MAX_LEVELS
Definition: ltree.h:112
#define LQL_COUNT
Definition: ltree.h:91
#define LTPRS_WAITNAME
Definition: ltree_io.c:24
#define LQPRS_WAITDELIM
Definition: ltree_io.c:243
#define LTREE_LABEL_MAX_CHARS
Definition: ltree.h:18
#define LQL_NOT
Definition: ltree.h:90
static char * buf
Definition: pg_test_fsync.c:68
#define t_iseq(x, c)
Definition: ts_locale.h:46
#define UNCHAR
Datum ltree_out(PG_FUNCTION_ARGS)
Definition: ltree_io.c:181
int errdetail(const char *fmt,...)
Definition: elog.c:1035
#define LQPRS_WAITSNUM
Definition: ltree_io.c:246
Datum lquery_out(PG_FUNCTION_ARGS)
Definition: ltree_io.c:739
static char * deparse_ltree(const ltree *in)
Definition: ltree_io.c:142
#define LEVEL_NEXT(x)
Definition: ltree.h:27
Definition: ltree.h:29
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:548
const char * start
Definition: ltree_io.c:18
static ltree * parse_ltree(const char *buf)
Definition: ltree_io.c:36
uint16 numlevel
Definition: ltree.h:32
#define LQUERY_HDRSIZE
Definition: ltree.h:110
void * palloc0(Size size)
Definition: mcxt.c:981
#define ITEMSIZE
Definition: ltree_io.c:254
uintptr_t Datum
Definition: postgres.h:367
#define LQPRS_WAITLEVEL
Definition: ltree_io.c:242
#define ereport(elevel,...)
Definition: elog.h:155
Datum ltree_recv(PG_FUNCTION_ARGS)
Definition: ltree_io.c:223
int32 val
Definition: ltree.h:47
#define LQPRS_WAITEND
Definition: ltree_io.c:249
uint16 numlevel
Definition: ltree.h:103
Definition: regguts.h:298
#define LTPRS_WAITDELIM
Definition: ltree_io.c:25
#define LVAR_SUBLEXEME
Definition: ltree.h:63
uint16 numvar
Definition: ltree.h:79
#define MAXALIGN(LEN)
Definition: c.h:753
int pg_mblen(const char *mbstr)
Definition: mbutils.c:907
Datum lquery_in(PG_FUNCTION_ARGS)
Definition: ltree_io.c:730
void * palloc(Size size)
Definition: mcxt.c:950
#define LVAR_HDRSIZE
Definition: ltree.h:58
int errmsg(const char *fmt,...)
Definition: elog.c:902
#define LTREE_FIRST(x)
Definition: ltree.h:38
#define elog(elevel,...)
Definition: elog.h:228
int i
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define LQUERY_HASNOT
Definition: ltree.h:114
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
#define LTREE_MAX_LEVELS
Definition: ltree.h:39
static void pq_sendint8(StringInfo buf, uint8 i)
Definition: pqformat.h:129
static void finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos)
Definition: ltree_io.c:573
static lquery * parse_lquery(const char *buf)
Definition: ltree_io.c:262
#define LQL_HDRSIZE
Definition: ltree.h:86
uint16 high
Definition: ltree.h:81
#define LEVEL_HDRSIZE
Definition: ltree.h:26