PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
ltree_io.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "ltree.h"
#include "utils/memutils.h"
#include "crc32.h"
Include dependency graph for ltree_io.c:

Go to the source code of this file.

Data Structures

struct  nodeitem
 

Macros

#define UNCHAR
 
#define LTPRS_WAITNAME   0
 
#define LTPRS_WAITDELIM   1
 
#define LQPRS_WAITLEVEL   0
 
#define LQPRS_WAITDELIM   1
 
#define LQPRS_WAITOPEN   2
 
#define LQPRS_WAITFNUM   3
 
#define LQPRS_WAITSNUM   4
 
#define LQPRS_WAITND   5
 
#define LQPRS_WAITCLOSE   6
 
#define LQPRS_WAITEND   7
 
#define LQPRS_WAITVAR   8
 
#define GETVAR(x)   ( *((nodeitem**)LQL_FIRST(x)) )
 
#define ITEMSIZE   MAXALIGN(LQL_HDRSIZE+sizeof(nodeitem*))
 
#define NEXTLEV(x)   ( (lquery_level*)( ((char*)(x)) + ITEMSIZE) )
 

Functions

 PG_FUNCTION_INFO_V1 (ltree_in)
 
 PG_FUNCTION_INFO_V1 (ltree_out)
 
 PG_FUNCTION_INFO_V1 (lquery_in)
 
 PG_FUNCTION_INFO_V1 (lquery_out)
 
Datum ltree_in (PG_FUNCTION_ARGS)
 
Datum ltree_out (PG_FUNCTION_ARGS)
 
Datum lquery_in (PG_FUNCTION_ARGS)
 
Datum lquery_out (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

#define GETVAR (   x)    ( *((nodeitem**)LQL_FIRST(x)) )

Definition at line 189 of file ltree_io.c.

Referenced by lquery_in().

#define ITEMSIZE   MAXALIGN(LQL_HDRSIZE+sizeof(nodeitem*))

Definition at line 190 of file ltree_io.c.

Referenced by lquery_in().

#define LQPRS_WAITCLOSE   6

Definition at line 184 of file ltree_io.c.

Referenced by lquery_in().

#define LQPRS_WAITDELIM   1

Definition at line 179 of file ltree_io.c.

Referenced by lquery_in().

#define LQPRS_WAITEND   7

Definition at line 185 of file ltree_io.c.

Referenced by lquery_in().

#define LQPRS_WAITFNUM   3

Definition at line 181 of file ltree_io.c.

Referenced by lquery_in().

#define LQPRS_WAITLEVEL   0

Definition at line 178 of file ltree_io.c.

Referenced by lquery_in().

#define LQPRS_WAITND   5

Definition at line 183 of file ltree_io.c.

Referenced by lquery_in().

#define LQPRS_WAITOPEN   2

Definition at line 180 of file ltree_io.c.

Referenced by lquery_in().

#define LQPRS_WAITSNUM   4

Definition at line 182 of file ltree_io.c.

Referenced by lquery_in().

#define LQPRS_WAITVAR   8

Definition at line 186 of file ltree_io.c.

Referenced by lquery_in().

#define LTPRS_WAITDELIM   1

Definition at line 35 of file ltree_io.c.

Referenced by ltree_in().

#define LTPRS_WAITNAME   0

Definition at line 34 of file ltree_io.c.

Referenced by ltree_in().

#define NEXTLEV (   x)    ( (lquery_level*)( ((char*)(x)) + ITEMSIZE) )

Definition at line 191 of file ltree_io.c.

Referenced by lquery_in().

#define UNCHAR
Value:
(errcode(ERRCODE_SYNTAX_ERROR), \
errmsg("syntax error at position %d", \
pos)));
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
int errmsg(const char *fmt,...)
Definition: elog.c:797

Definition at line 20 of file ltree_io.c.

Referenced by lquery_in(), and ltree_in().

Function Documentation

Datum lquery_in ( PG_FUNCTION_ARGS  )

Definition at line 194 of file ltree_io.c.

References buf, cur, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, lquery::firstgood, nodeitem::flag, lquery_variant::flag, lquery_level::flag, lquery::flag, GETVAR, lquery_level::high, ISALNUM, ITEMSIZE, nodeitem::len, lquery_variant::len, lquery_level::low, LQL_FIRST, LQL_HDRSIZE, LQL_NEXT, LQL_NOT, LQPRS_WAITCLOSE, LQPRS_WAITDELIM, LQPRS_WAITEND, LQPRS_WAITFNUM, LQPRS_WAITLEVEL, LQPRS_WAITND, LQPRS_WAITOPEN, LQPRS_WAITSNUM, LQPRS_WAITVAR, LQUERY_FIRST, LQUERY_HASNOT, LQUERY_HDRSIZE, ltree_crc32_sz(), LVAR_ANYEND, LVAR_HDRSIZE, LVAR_INCASE, LVAR_NEXT, LVAR_SUBLEXEME, MAXALIGN, MaxAllocSize, lquery_variant::name, NEXTLEV, NULL, lquery::numlevel, lquery_level::numvar, palloc0(), pfree(), PG_GETARG_POINTER, pg_mblen(), PG_RETURN_POINTER, result, SET_VARSIZE, nodeitem::start, t_isdigit, t_iseq, lquery_level::totallen, UNCHAR, lquery_variant::val, and nodeitem::wlen.

195 {
196  char *buf = (char *) PG_GETARG_POINTER(0);
197  char *ptr;
198  int num = 0,
199  totallen = 0,
200  numOR = 0;
201  int state = LQPRS_WAITLEVEL;
202  lquery *result;
203  nodeitem *lptr = NULL;
204  lquery_level *cur,
205  *curqlevel,
206  *tmpql;
207  lquery_variant *lrptr = NULL;
208  bool hasnot = false;
209  bool wasbad = false;
210  int charlen;
211  int pos = 0;
212 
213  ptr = buf;
214  while (*ptr)
215  {
216  charlen = pg_mblen(ptr);
217 
218  if (charlen == 1)
219  {
220  if (t_iseq(ptr, '.'))
221  num++;
222  else if (t_iseq(ptr, '|'))
223  numOR++;
224  }
225 
226  ptr += charlen;
227  }
228 
229  num++;
230  if (num > MaxAllocSize / ITEMSIZE)
231  ereport(ERROR,
232  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
233  errmsg("number of levels (%d) exceeds the maximum allowed (%d)",
234  num, (int) (MaxAllocSize / ITEMSIZE))));
235  curqlevel = tmpql = (lquery_level *) palloc0(ITEMSIZE * num);
236  ptr = buf;
237  while (*ptr)
238  {
239  charlen = pg_mblen(ptr);
240 
241  if (state == LQPRS_WAITLEVEL)
242  {
243  if (ISALNUM(ptr))
244  {
245  GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
246  lptr->start = ptr;
247  state = LQPRS_WAITDELIM;
248  curqlevel->numvar = 1;
249  }
250  else if (charlen == 1 && t_iseq(ptr, '!'))
251  {
252  GETVAR(curqlevel) = lptr = (nodeitem *) palloc0(sizeof(nodeitem) * (numOR + 1));
253  lptr->start = ptr + 1;
254  state = LQPRS_WAITDELIM;
255  curqlevel->numvar = 1;
256  curqlevel->flag |= LQL_NOT;
257  hasnot = true;
258  }
259  else if (charlen == 1 && t_iseq(ptr, '*'))
260  state = LQPRS_WAITOPEN;
261  else
262  UNCHAR;
263  }
264  else if (state == LQPRS_WAITVAR)
265  {
266  if (ISALNUM(ptr))
267  {
268  lptr++;
269  lptr->start = ptr;
270  state = LQPRS_WAITDELIM;
271  curqlevel->numvar++;
272  }
273  else
274  UNCHAR;
275  }
276  else if (state == LQPRS_WAITDELIM)
277  {
278  if (charlen == 1 && t_iseq(ptr, '@'))
279  {
280  if (lptr->start == ptr)
281  UNCHAR;
282  lptr->flag |= LVAR_INCASE;
283  curqlevel->flag |= LVAR_INCASE;
284  }
285  else if (charlen == 1 && t_iseq(ptr, '*'))
286  {
287  if (lptr->start == ptr)
288  UNCHAR;
289  lptr->flag |= LVAR_ANYEND;
290  curqlevel->flag |= LVAR_ANYEND;
291  }
292  else if (charlen == 1 && t_iseq(ptr, '%'))
293  {
294  if (lptr->start == ptr)
295  UNCHAR;
296  lptr->flag |= LVAR_SUBLEXEME;
297  curqlevel->flag |= LVAR_SUBLEXEME;
298  }
299  else if (charlen == 1 && t_iseq(ptr, '|'))
300  {
301  lptr->len = ptr - lptr->start -
302  ((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) -
303  ((lptr->flag & LVAR_INCASE) ? 1 : 0) -
304  ((lptr->flag & LVAR_ANYEND) ? 1 : 0);
305  if (lptr->wlen > 255)
306  ereport(ERROR,
307  (errcode(ERRCODE_NAME_TOO_LONG),
308  errmsg("name of level is too long"),
309  errdetail("Name length is %d, must "
310  "be < 256, in position %d.",
311  lptr->wlen, pos)));
312 
313  state = LQPRS_WAITVAR;
314  }
315  else if (charlen == 1 && t_iseq(ptr, '.'))
316  {
317  lptr->len = ptr - lptr->start -
318  ((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) -
319  ((lptr->flag & LVAR_INCASE) ? 1 : 0) -
320  ((lptr->flag & LVAR_ANYEND) ? 1 : 0);
321  if (lptr->wlen > 255)
322  ereport(ERROR,
323  (errcode(ERRCODE_NAME_TOO_LONG),
324  errmsg("name of level is too long"),
325  errdetail("Name length is %d, must "
326  "be < 256, in position %d.",
327  lptr->wlen, pos)));
328 
329  state = LQPRS_WAITLEVEL;
330  curqlevel = NEXTLEV(curqlevel);
331  }
332  else if (ISALNUM(ptr))
333  {
334  if (lptr->flag)
335  UNCHAR;
336  }
337  else
338  UNCHAR;
339  }
340  else if (state == LQPRS_WAITOPEN)
341  {
342  if (charlen == 1 && t_iseq(ptr, '{'))
343  state = LQPRS_WAITFNUM;
344  else if (charlen == 1 && t_iseq(ptr, '.'))
345  {
346  curqlevel->low = 0;
347  curqlevel->high = 0xffff;
348  curqlevel = NEXTLEV(curqlevel);
349  state = LQPRS_WAITLEVEL;
350  }
351  else
352  UNCHAR;
353  }
354  else if (state == LQPRS_WAITFNUM)
355  {
356  if (charlen == 1 && t_iseq(ptr, ','))
357  state = LQPRS_WAITSNUM;
358  else if (t_isdigit(ptr))
359  {
360  curqlevel->low = atoi(ptr);
361  state = LQPRS_WAITND;
362  }
363  else
364  UNCHAR;
365  }
366  else if (state == LQPRS_WAITSNUM)
367  {
368  if (t_isdigit(ptr))
369  {
370  curqlevel->high = atoi(ptr);
371  state = LQPRS_WAITCLOSE;
372  }
373  else if (charlen == 1 && t_iseq(ptr, '}'))
374  {
375  curqlevel->high = 0xffff;
376  state = LQPRS_WAITEND;
377  }
378  else
379  UNCHAR;
380  }
381  else if (state == LQPRS_WAITCLOSE)
382  {
383  if (charlen == 1 && t_iseq(ptr, '}'))
384  state = LQPRS_WAITEND;
385  else if (!t_isdigit(ptr))
386  UNCHAR;
387  }
388  else if (state == LQPRS_WAITND)
389  {
390  if (charlen == 1 && t_iseq(ptr, '}'))
391  {
392  curqlevel->high = curqlevel->low;
393  state = LQPRS_WAITEND;
394  }
395  else if (charlen == 1 && t_iseq(ptr, ','))
396  state = LQPRS_WAITSNUM;
397  else if (!t_isdigit(ptr))
398  UNCHAR;
399  }
400  else if (state == LQPRS_WAITEND)
401  {
402  if (charlen == 1 && t_iseq(ptr, '.'))
403  {
404  state = LQPRS_WAITLEVEL;
405  curqlevel = NEXTLEV(curqlevel);
406  }
407  else
408  UNCHAR;
409  }
410  else
411  /* internal error */
412  elog(ERROR, "internal error in parser");
413 
414  ptr += charlen;
415  if (state == LQPRS_WAITDELIM)
416  lptr->wlen++;
417  pos++;
418  }
419 
420  if (state == LQPRS_WAITDELIM)
421  {
422  if (lptr->start == ptr)
423  ereport(ERROR,
424  (errcode(ERRCODE_SYNTAX_ERROR),
425  errmsg("syntax error"),
426  errdetail("Unexpected end of line.")));
427 
428  lptr->len = ptr - lptr->start -
429  ((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) -
430  ((lptr->flag & LVAR_INCASE) ? 1 : 0) -
431  ((lptr->flag & LVAR_ANYEND) ? 1 : 0);
432  if (lptr->len == 0)
433  ereport(ERROR,
434  (errcode(ERRCODE_SYNTAX_ERROR),
435  errmsg("syntax error"),
436  errdetail("Unexpected end of line.")));
437 
438  if (lptr->wlen > 255)
439  ereport(ERROR,
440  (errcode(ERRCODE_NAME_TOO_LONG),
441  errmsg("name of level is too long"),
442  errdetail("Name length is %d, must "
443  "be < 256, in position %d.",
444  lptr->wlen, pos)));
445  }
446  else if (state == LQPRS_WAITOPEN)
447  curqlevel->high = 0xffff;
448  else if (state != LQPRS_WAITEND)
449  ereport(ERROR,
450  (errcode(ERRCODE_SYNTAX_ERROR),
451  errmsg("syntax error"),
452  errdetail("Unexpected end of line.")));
453 
454  curqlevel = tmpql;
455  totallen = LQUERY_HDRSIZE;
456  while ((char *) curqlevel - (char *) tmpql < num * ITEMSIZE)
457  {
458  totallen += LQL_HDRSIZE;
459  if (curqlevel->numvar)
460  {
461  lptr = GETVAR(curqlevel);
462  while (lptr - GETVAR(curqlevel) < curqlevel->numvar)
463  {
464  totallen += MAXALIGN(LVAR_HDRSIZE + lptr->len);
465  lptr++;
466  }
467  }
468  else if (curqlevel->low > curqlevel->high)
469  ereport(ERROR,
470  (errcode(ERRCODE_SYNTAX_ERROR),
471  errmsg("syntax error"),
472  errdetail("Low limit(%d) is greater than upper(%d).",
473  curqlevel->low, curqlevel->high)));
474 
475  curqlevel = NEXTLEV(curqlevel);
476  }
477 
478  result = (lquery *) palloc0(totallen);
479  SET_VARSIZE(result, totallen);
480  result->numlevel = num;
481  result->firstgood = 0;
482  result->flag = 0;
483  if (hasnot)
484  result->flag |= LQUERY_HASNOT;
485  cur = LQUERY_FIRST(result);
486  curqlevel = tmpql;
487  while ((char *) curqlevel - (char *) tmpql < num * ITEMSIZE)
488  {
489  memcpy(cur, curqlevel, LQL_HDRSIZE);
490  cur->totallen = LQL_HDRSIZE;
491  if (curqlevel->numvar)
492  {
493  lrptr = LQL_FIRST(cur);
494  lptr = GETVAR(curqlevel);
495  while (lptr - GETVAR(curqlevel) < curqlevel->numvar)
496  {
497  cur->totallen += MAXALIGN(LVAR_HDRSIZE + lptr->len);
498  lrptr->len = lptr->len;
499  lrptr->flag = lptr->flag;
500  lrptr->val = ltree_crc32_sz(lptr->start, lptr->len);
501  memcpy(lrptr->name, lptr->start, lptr->len);
502  lptr++;
503  lrptr = LVAR_NEXT(lrptr);
504  }
505  pfree(GETVAR(curqlevel));
506  if (cur->numvar > 1 || cur->flag != 0)
507  wasbad = true;
508  else if (wasbad == false)
509  (result->firstgood)++;
510  }
511  else
512  wasbad = true;
513  curqlevel = NEXTLEV(curqlevel);
514  cur = LQL_NEXT(cur);
515  }
516 
517  pfree(tmpql);
518  PG_RETURN_POINTER(result);
519 }
uint16 firstgood
Definition: ltree.h:73
#define GETVAR(x)
Definition: ltree_io.c:189
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define LVAR_INCASE
Definition: ltree.h:44
uint8 flag
Definition: ltree.h:36
#define LQPRS_WAITVAR
Definition: ltree_io.c:186
#define LQPRS_WAITFNUM
Definition: ltree_io.c:181
char * start
Definition: ltree_io.c:28
uint16 low
Definition: ltree.h:52
#define LQUERY_FIRST(x)
Definition: ltree.h:79
uint16 len
Definition: ltree.h:35
#define ISALNUM(x)
Definition: ltree.h:83
#define LVAR_ANYEND
Definition: ltree.h:43
#define LQPRS_WAITCLOSE
Definition: ltree_io.c:184
#define LQPRS_WAITOPEN
Definition: ltree_io.c:180
int len
Definition: ltree_io.c:29
#define NEXTLEV(x)
Definition: ltree_io.c:191
int wlen
Definition: ltree_io.c:31
Definition: ltree.h:69
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:37
#define LQL_FIRST(x)
Definition: ltree.h:59
#define LQL_NEXT(x)
Definition: ltree.h:58
struct cursor * cur
Definition: ecpg.c:28
int errcode(int sqlerrcode)
Definition: elog.c:575
return result
Definition: formatting.c:1633
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
uint16 flag
Definition: ltree.h:74
#define t_isdigit(x)
Definition: ts_locale.h:57
uint16 totallen
Definition: ltree.h:49
#define LQPRS_WAITND
Definition: ltree_io.c:183
#define LVAR_NEXT(x)
Definition: ltree.h:41
unsigned int ltree_crc32_sz(char *buf, int size)
Definition: crc32.c:23
int flag
Definition: ltree_io.c:30
void pfree(void *pointer)
Definition: mcxt.c:950
uint16 flag
Definition: ltree.h:50
#define ERROR
Definition: elog.h:43
#define LQPRS_WAITDELIM
Definition: ltree_io.c:179
#define LQL_NOT
Definition: ltree.h:61
static char * buf
Definition: pg_test_fsync.c:66
#define t_iseq(x, c)
Definition: ts_locale.h:61
#define UNCHAR
Definition: ltree_io.c:20
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define LQPRS_WAITSNUM
Definition: ltree_io.c:182
#define ereport(elevel, rest)
Definition: elog.h:122
#define MaxAllocSize
Definition: memutils.h:40
#define LQUERY_HDRSIZE
Definition: ltree.h:78
void * palloc0(Size size)
Definition: mcxt.c:878
#define ITEMSIZE
Definition: ltree_io.c:190
#define LQPRS_WAITLEVEL
Definition: ltree_io.c:178
int32 val
Definition: ltree.h:34
#define LQPRS_WAITEND
Definition: ltree_io.c:185
#define NULL
Definition: c.h:229
uint16 numlevel
Definition: ltree.h:72
Definition: regguts.h:298
#define LVAR_SUBLEXEME
Definition: ltree.h:45
uint16 numvar
Definition: ltree.h:51
#define MAXALIGN(LEN)
Definition: c.h:588
int pg_mblen(const char *mbstr)
Definition: mbutils.c:771
#define LVAR_HDRSIZE
Definition: ltree.h:40
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define LQUERY_HASNOT
Definition: ltree.h:81
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
#define elog
Definition: elog.h:219
#define LQL_HDRSIZE
Definition: ltree.h:57
uint16 high
Definition: ltree.h:53
Datum lquery_out ( PG_FUNCTION_ARGS  )

Definition at line 522 of file ltree_io.c.

References buf, lquery_variant::flag, lquery_level::flag, lquery_level::high, i, lquery_variant::len, lquery_level::low, LQL_FIRST, LQL_NEXT, LQL_NOT, LQUERY_FIRST, LVAR_ANYEND, LVAR_INCASE, LVAR_NEXT, LVAR_SUBLEXEME, lquery_variant::name, lquery::numlevel, lquery_level::numvar, palloc(), PG_FREE_IF_COPY, PG_GETARG_LQUERY, PG_RETURN_POINTER, and lquery_level::totallen.

523 {
524  lquery *in = PG_GETARG_LQUERY(0);
525  char *buf,
526  *ptr;
527  int i,
528  j,
529  totallen = 1;
530  lquery_level *curqlevel;
531  lquery_variant *curtlevel;
532 
533  curqlevel = LQUERY_FIRST(in);
534  for (i = 0; i < in->numlevel; i++)
535  {
536  totallen++;
537  if (curqlevel->numvar)
538  totallen += 1 + (curqlevel->numvar * 4) + curqlevel->totallen;
539  else
540  totallen += 2 * 11 + 4;
541  curqlevel = LQL_NEXT(curqlevel);
542  }
543 
544  ptr = buf = (char *) palloc(totallen);
545  curqlevel = LQUERY_FIRST(in);
546  for (i = 0; i < in->numlevel; i++)
547  {
548  if (i != 0)
549  {
550  *ptr = '.';
551  ptr++;
552  }
553  if (curqlevel->numvar)
554  {
555  if (curqlevel->flag & LQL_NOT)
556  {
557  *ptr = '!';
558  ptr++;
559  }
560  curtlevel = LQL_FIRST(curqlevel);
561  for (j = 0; j < curqlevel->numvar; j++)
562  {
563  if (j != 0)
564  {
565  *ptr = '|';
566  ptr++;
567  }
568  memcpy(ptr, curtlevel->name, curtlevel->len);
569  ptr += curtlevel->len;
570  if ((curtlevel->flag & LVAR_SUBLEXEME))
571  {
572  *ptr = '%';
573  ptr++;
574  }
575  if ((curtlevel->flag & LVAR_INCASE))
576  {
577  *ptr = '@';
578  ptr++;
579  }
580  if ((curtlevel->flag & LVAR_ANYEND))
581  {
582  *ptr = '*';
583  ptr++;
584  }
585  curtlevel = LVAR_NEXT(curtlevel);
586  }
587  }
588  else
589  {
590  if (curqlevel->low == curqlevel->high)
591  {
592  sprintf(ptr, "*{%d}", curqlevel->low);
593  }
594  else if (curqlevel->low == 0)
595  {
596  if (curqlevel->high == 0xffff)
597  {
598  *ptr = '*';
599  *(ptr + 1) = '\0';
600  }
601  else
602  sprintf(ptr, "*{,%d}", curqlevel->high);
603  }
604  else if (curqlevel->high == 0xffff)
605  {
606  sprintf(ptr, "*{%d,}", curqlevel->low);
607  }
608  else
609  sprintf(ptr, "*{%d,%d}", curqlevel->low, curqlevel->high);
610  ptr = strchr(ptr, '\0');
611  }
612 
613  curqlevel = LQL_NEXT(curqlevel);
614  }
615 
616  *ptr = '\0';
617  PG_FREE_IF_COPY(in, 0);
618 
619  PG_RETURN_POINTER(buf);
620 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define LVAR_INCASE
Definition: ltree.h:44
uint8 flag
Definition: ltree.h:36
uint16 low
Definition: ltree.h:52
#define LQUERY_FIRST(x)
Definition: ltree.h:79
uint16 len
Definition: ltree.h:35
#define LVAR_ANYEND
Definition: ltree.h:43
Definition: ltree.h:69
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:37
#define LQL_FIRST(x)
Definition: ltree.h:59
#define LQL_NEXT(x)
Definition: ltree.h:58
uint16 totallen
Definition: ltree.h:49
#define LVAR_NEXT(x)
Definition: ltree.h:41
uint16 flag
Definition: ltree.h:50
#define LQL_NOT
Definition: ltree.h:61
static char * buf
Definition: pg_test_fsync.c:66
#define PG_GETARG_LQUERY(x)
Definition: ltree.h:170
uint16 numlevel
Definition: ltree.h:72
#define LVAR_SUBLEXEME
Definition: ltree.h:45
uint16 numvar
Definition: ltree.h:51
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:225
void * palloc(Size size)
Definition: mcxt.c:849
int i
uint16 high
Definition: ltree.h:53
Datum ltree_in ( PG_FUNCTION_ARGS  )

Definition at line 38 of file ltree_io.c.

References buf, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, ISALNUM, ltree_level::len, nodeitem::len, LEVEL_HDRSIZE, LEVEL_NEXT, sort-test::list, LTPRS_WAITDELIM, LTPRS_WAITNAME, LTREE_FIRST, LTREE_HDRSIZE, MAXALIGN, MaxAllocSize, ltree_level::name, ltree::numlevel, palloc(), palloc0(), pfree(), PG_GETARG_POINTER, pg_mblen(), PG_RETURN_POINTER, result, SET_VARSIZE, nodeitem::start, t_iseq, UNCHAR, and nodeitem::wlen.

Referenced by ltree_addtext(), ltree_textadd(), and text2ltree().

39 {
40  char *buf = (char *) PG_GETARG_POINTER(0);
41  char *ptr;
42  nodeitem *list,
43  *lptr;
44  int num = 0,
45  totallen = 0;
46  int state = LTPRS_WAITNAME;
47  ltree *result;
48  ltree_level *curlevel;
49  int charlen;
50  int pos = 0;
51 
52  ptr = buf;
53  while (*ptr)
54  {
55  charlen = pg_mblen(ptr);
56  if (charlen == 1 && t_iseq(ptr, '.'))
57  num++;
58  ptr += charlen;
59  }
60 
61  if (num + 1 > MaxAllocSize / sizeof(nodeitem))
62  ereport(ERROR,
63  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
64  errmsg("number of levels (%d) exceeds the maximum allowed (%d)",
65  num + 1, (int) (MaxAllocSize / sizeof(nodeitem)))));
66  list = lptr = (nodeitem *) palloc(sizeof(nodeitem) * (num + 1));
67  ptr = buf;
68  while (*ptr)
69  {
70  charlen = pg_mblen(ptr);
71 
72  if (state == LTPRS_WAITNAME)
73  {
74  if (ISALNUM(ptr))
75  {
76  lptr->start = ptr;
77  lptr->wlen = 0;
78  state = LTPRS_WAITDELIM;
79  }
80  else
81  UNCHAR;
82  }
83  else if (state == LTPRS_WAITDELIM)
84  {
85  if (charlen == 1 && t_iseq(ptr, '.'))
86  {
87  lptr->len = ptr - lptr->start;
88  if (lptr->wlen > 255)
89  ereport(ERROR,
90  (errcode(ERRCODE_NAME_TOO_LONG),
91  errmsg("name of level is too long"),
92  errdetail("Name length is %d, must "
93  "be < 256, in position %d.",
94  lptr->wlen, pos)));
95 
96  totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
97  lptr++;
98  state = LTPRS_WAITNAME;
99  }
100  else if (!ISALNUM(ptr))
101  UNCHAR;
102  }
103  else
104  /* internal error */
105  elog(ERROR, "internal error in parser");
106 
107  ptr += charlen;
108  lptr->wlen++;
109  pos++;
110  }
111 
112  if (state == LTPRS_WAITDELIM)
113  {
114  lptr->len = ptr - lptr->start;
115  if (lptr->wlen > 255)
116  ereport(ERROR,
117  (errcode(ERRCODE_NAME_TOO_LONG),
118  errmsg("name of level is too long"),
119  errdetail("Name length is %d, must "
120  "be < 256, in position %d.",
121  lptr->wlen, pos)));
122 
123  totallen += MAXALIGN(lptr->len + LEVEL_HDRSIZE);
124  lptr++;
125  }
126  else if (!(state == LTPRS_WAITNAME && lptr == list))
127  ereport(ERROR,
128  (errcode(ERRCODE_SYNTAX_ERROR),
129  errmsg("syntax error"),
130  errdetail("Unexpected end of line.")));
131 
132  result = (ltree *) palloc0(LTREE_HDRSIZE + totallen);
133  SET_VARSIZE(result, LTREE_HDRSIZE + totallen);
134  result->numlevel = lptr - list;
135  curlevel = LTREE_FIRST(result);
136  lptr = list;
137  while (lptr - list < result->numlevel)
138  {
139  curlevel->len = (uint16) lptr->len;
140  memcpy(curlevel->name, lptr->start, lptr->len);
141  curlevel = LEVEL_NEXT(curlevel);
142  lptr++;
143  }
144 
145  pfree(list);
146  PG_RETURN_POINTER(result);
147 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:13
char * start
Definition: ltree_io.c:28
#define ISALNUM(x)
Definition: ltree.h:83
uint16 len
Definition: ltree.h:12
int len
Definition: ltree_io.c:29
int wlen
Definition: ltree_io.c:31
#define LTREE_HDRSIZE
Definition: ltree.h:26
int errcode(int sqlerrcode)
Definition: elog.c:575
return result
Definition: formatting.c:1633
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
unsigned short uint16
Definition: c.h:267
void pfree(void *pointer)
Definition: mcxt.c:950
#define ERROR
Definition: elog.h:43
#define LTPRS_WAITNAME
Definition: ltree_io.c:34
static char * buf
Definition: pg_test_fsync.c:66
#define t_iseq(x, c)
Definition: ts_locale.h:61
#define UNCHAR
Definition: ltree_io.c:20
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define LEVEL_NEXT(x)
Definition: ltree.h:17
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: ltree.h:19
#define MaxAllocSize
Definition: memutils.h:40
uint16 numlevel
Definition: ltree.h:22
void * palloc0(Size size)
Definition: mcxt.c:878
Definition: regguts.h:298
#define LTPRS_WAITDELIM
Definition: ltree_io.c:35
#define MAXALIGN(LEN)
Definition: c.h:588
int pg_mblen(const char *mbstr)
Definition: mbutils.c:771
tuple list
Definition: sort-test.py:11
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define LTREE_FIRST(x)
Definition: ltree.h:27
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
#define elog
Definition: elog.h:219
#define LEVEL_HDRSIZE
Definition: ltree.h:16
Datum ltree_out ( PG_FUNCTION_ARGS  )

Definition at line 150 of file ltree_io.c.

References buf, i, ltree_level::len, LEVEL_NEXT, LTREE_FIRST, ltree_level::name, ltree::numlevel, palloc(), PG_FREE_IF_COPY, PG_GETARG_LTREE, PG_RETURN_POINTER, and VARSIZE.

151 {
152  ltree *in = PG_GETARG_LTREE(0);
153  char *buf,
154  *ptr;
155  int i;
156  ltree_level *curlevel;
157 
158  ptr = buf = (char *) palloc(VARSIZE(in));
159  curlevel = LTREE_FIRST(in);
160  for (i = 0; i < in->numlevel; i++)
161  {
162  if (i != 0)
163  {
164  *ptr = '.';
165  ptr++;
166  }
167  memcpy(ptr, curlevel->name, curlevel->len);
168  ptr += curlevel->len;
169  curlevel = LEVEL_NEXT(curlevel);
170  }
171 
172  *ptr = '\0';
173  PG_FREE_IF_COPY(in, 0);
174 
175  PG_RETURN_POINTER(buf);
176 }
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:13
uint16 len
Definition: ltree.h:12
#define VARSIZE(PTR)
Definition: postgres.h:304
#define PG_GETARG_LTREE(x)
Definition: ltree.h:168
static char * buf
Definition: pg_test_fsync.c:66
#define LEVEL_NEXT(x)
Definition: ltree.h:17
Definition: ltree.h:19
uint16 numlevel
Definition: ltree.h:22
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:225
void * palloc(Size size)
Definition: mcxt.c:849
#define LTREE_FIRST(x)
Definition: ltree.h:27
int i
PG_FUNCTION_INFO_V1 ( ltree_in  )
PG_FUNCTION_INFO_V1 ( ltree_out  )
PG_FUNCTION_INFO_V1 ( lquery_in  )
PG_FUNCTION_INFO_V1 ( lquery_out  )