@@ -24,16 +24,16 @@ typedef struct
2424#define LTPRS_WAITNAME 0
2525#define LTPRS_WAITDELIM 1
2626
27- static void finish_nodeitem (nodeitem * lptr , const char * ptr ,
28- bool is_lquery , int pos );
27+ static bool finish_nodeitem (nodeitem * lptr , const char * ptr ,
28+ bool is_lquery , int pos , struct Node * escontext );
2929
3030
3131/*
3232 * expects a null terminated string
3333 * returns an ltree
3434 */
3535static ltree *
36- parse_ltree (const char * buf )
36+ parse_ltree (const char * buf , struct Node * escontext )
3737{
3838 const char * ptr ;
3939 nodeitem * list ,
@@ -46,7 +46,7 @@ parse_ltree(const char *buf)
4646 int charlen ;
4747 int pos = 1 ; /* character position for error messages */
4848
49- #define UNCHAR ereport(ERROR, \
49+ #define UNCHAR ereturn(escontext, NULL, \
5050 errcode(ERRCODE_SYNTAX_ERROR), \
5151 errmsg("ltree syntax error at character %d", \
5252 pos))
@@ -61,7 +61,7 @@ parse_ltree(const char *buf)
6161 }
6262
6363 if (num + 1 > LTREE_MAX_LEVELS )
64- ereport ( ERROR ,
64+ ereturn ( escontext , NULL ,
6565 (errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
6666 errmsg ("number of ltree labels (%d) exceeds the maximum allowed (%d)" ,
6767 num + 1 , LTREE_MAX_LEVELS )));
@@ -86,7 +86,8 @@ parse_ltree(const char *buf)
8686 case LTPRS_WAITDELIM :
8787 if (t_iseq (ptr , '.' ))
8888 {
89- finish_nodeitem (lptr , ptr , false, pos );
89+ if (!finish_nodeitem (lptr , ptr , false, pos , escontext ))
90+ return NULL ;
9091 totallen += MAXALIGN (lptr -> len + LEVEL_HDRSIZE );
9192 lptr ++ ;
9293 state = LTPRS_WAITNAME ;
@@ -105,12 +106,13 @@ parse_ltree(const char *buf)
105106
106107 if (state == LTPRS_WAITDELIM )
107108 {
108- finish_nodeitem (lptr , ptr , false, pos );
109+ if (!finish_nodeitem (lptr , ptr , false, pos , escontext ))
110+ return NULL ;
109111 totallen += MAXALIGN (lptr -> len + LEVEL_HDRSIZE );
110112 lptr ++ ;
111113 }
112114 else if (!(state == LTPRS_WAITNAME && lptr == list ))
113- ereport ( ERROR ,
115+ ereturn ( escontext , NULL ,
114116 (errcode (ERRCODE_SYNTAX_ERROR ),
115117 errmsg ("ltree syntax error" ),
116118 errdetail ("Unexpected end of input." )));
@@ -172,8 +174,12 @@ Datum
172174ltree_in (PG_FUNCTION_ARGS )
173175{
174176 char * buf = (char * ) PG_GETARG_POINTER (0 );
177+ ltree * res ;
175178
176- PG_RETURN_POINTER (parse_ltree (buf ));
179+ if ((res = parse_ltree (buf , fcinfo -> context )) == NULL )
180+ PG_RETURN_NULL ();
181+
182+ PG_RETURN_POINTER (res );
177183}
178184
179185PG_FUNCTION_INFO_V1 (ltree_out );
@@ -232,7 +238,7 @@ ltree_recv(PG_FUNCTION_ARGS)
232238 elog (ERROR , "unsupported ltree version number %d" , version );
233239
234240 str = pq_getmsgtext (buf , buf -> len - buf -> cursor , & nbytes );
235- res = parse_ltree (str );
241+ res = parse_ltree (str , NULL );
236242 pfree (str );
237243
238244 PG_RETURN_POINTER (res );
@@ -259,7 +265,7 @@ ltree_recv(PG_FUNCTION_ARGS)
259265 * returns an lquery
260266 */
261267static lquery *
262- parse_lquery (const char * buf )
268+ parse_lquery (const char * buf , struct Node * escontext )
263269{
264270 const char * ptr ;
265271 int num = 0 ,
@@ -277,7 +283,7 @@ parse_lquery(const char *buf)
277283 int charlen ;
278284 int pos = 1 ; /* character position for error messages */
279285
280- #define UNCHAR ereport(ERROR, \
286+ #define UNCHAR ereturn(escontext, NULL, \
281287 errcode(ERRCODE_SYNTAX_ERROR), \
282288 errmsg("lquery syntax error at character %d", \
283289 pos))
@@ -297,7 +303,7 @@ parse_lquery(const char *buf)
297303
298304 num ++ ;
299305 if (num > LQUERY_MAX_LEVELS )
300- ereport ( ERROR ,
306+ ereturn ( escontext , NULL ,
301307 (errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
302308 errmsg ("number of lquery items (%d) exceeds the maximum allowed (%d)" ,
303309 num , LQUERY_MAX_LEVELS )));
@@ -361,18 +367,21 @@ parse_lquery(const char *buf)
361367 }
362368 else if (t_iseq (ptr , '|' ))
363369 {
364- finish_nodeitem (lptr , ptr , true, pos );
370+ if (!finish_nodeitem (lptr , ptr , true, pos , escontext ))
371+ return NULL ;
365372 state = LQPRS_WAITVAR ;
366373 }
367374 else if (t_iseq (ptr , '{' ))
368375 {
369- finish_nodeitem (lptr , ptr , true, pos );
376+ if (!finish_nodeitem (lptr , ptr , true, pos , escontext ))
377+ return NULL ;
370378 curqlevel -> flag |= LQL_COUNT ;
371379 state = LQPRS_WAITFNUM ;
372380 }
373381 else if (t_iseq (ptr , '.' ))
374382 {
375- finish_nodeitem (lptr , ptr , true, pos );
383+ if (!finish_nodeitem (lptr , ptr , true, pos , escontext ))
384+ return NULL ;
376385 state = LQPRS_WAITLEVEL ;
377386 curqlevel = NEXTLEV (curqlevel );
378387 }
@@ -407,7 +416,7 @@ parse_lquery(const char *buf)
407416 int low = atoi (ptr );
408417
409418 if (low < 0 || low > LTREE_MAX_LEVELS )
410- ereport ( ERROR ,
419+ ereturn ( escontext , NULL ,
411420 (errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
412421 errmsg ("lquery syntax error" ),
413422 errdetail ("Low limit (%d) exceeds the maximum allowed (%d), at character %d." ,
@@ -425,13 +434,13 @@ parse_lquery(const char *buf)
425434 int high = atoi (ptr );
426435
427436 if (high < 0 || high > LTREE_MAX_LEVELS )
428- ereport ( ERROR ,
437+ ereturn ( escontext , NULL ,
429438 (errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
430439 errmsg ("lquery syntax error" ),
431440 errdetail ("High limit (%d) exceeds the maximum allowed (%d), at character %d." ,
432441 high , LTREE_MAX_LEVELS , pos )));
433442 else if (curqlevel -> low > high )
434- ereport ( ERROR ,
443+ ereturn ( escontext , NULL ,
435444 (errcode (ERRCODE_SYNTAX_ERROR ),
436445 errmsg ("lquery syntax error" ),
437446 errdetail ("Low limit (%d) is greater than high limit (%d), at character %d." ,
@@ -485,11 +494,14 @@ parse_lquery(const char *buf)
485494 }
486495
487496 if (state == LQPRS_WAITDELIM )
488- finish_nodeitem (lptr , ptr , true, pos );
497+ {
498+ if (!finish_nodeitem (lptr , ptr , true, pos , escontext ))
499+ return false;
500+ }
489501 else if (state == LQPRS_WAITOPEN )
490502 curqlevel -> high = LTREE_MAX_LEVELS ;
491503 else if (state != LQPRS_WAITEND )
492- ereport ( ERROR ,
504+ ereturn ( escontext , NULL ,
493505 (errcode (ERRCODE_SYNTAX_ERROR ),
494506 errmsg ("lquery syntax error" ),
495507 errdetail ("Unexpected end of input." )));
@@ -569,8 +581,9 @@ parse_lquery(const char *buf)
569581 * Close out parsing an ltree or lquery nodeitem:
570582 * compute the correct length, and complain if it's not OK
571583 */
572- static void
573- finish_nodeitem (nodeitem * lptr , const char * ptr , bool is_lquery , int pos )
584+ static bool
585+ finish_nodeitem (nodeitem * lptr , const char * ptr , bool is_lquery , int pos ,
586+ struct Node * escontext )
574587{
575588 if (is_lquery )
576589 {
@@ -591,18 +604,19 @@ finish_nodeitem(nodeitem *lptr, const char *ptr, bool is_lquery, int pos)
591604
592605 /* Complain if it's empty or too long */
593606 if (lptr -> len == 0 )
594- ereport ( ERROR ,
607+ ereturn ( escontext , false ,
595608 (errcode (ERRCODE_SYNTAX_ERROR ),
596609 is_lquery ?
597610 errmsg ("lquery syntax error at character %d" , pos ) :
598611 errmsg ("ltree syntax error at character %d" , pos ),
599612 errdetail ("Empty labels are not allowed." )));
600613 if (lptr -> wlen > LTREE_LABEL_MAX_CHARS )
601- ereport ( ERROR ,
614+ ereturn ( escontext , false ,
602615 (errcode (ERRCODE_NAME_TOO_LONG ),
603616 errmsg ("label string is too long" ),
604617 errdetail ("Label length is %d, must be at most %d, at character %d." ,
605618 lptr -> wlen , LTREE_LABEL_MAX_CHARS , pos )));
619+ return true;
606620}
607621
608622/*
@@ -730,8 +744,12 @@ Datum
730744lquery_in (PG_FUNCTION_ARGS )
731745{
732746 char * buf = (char * ) PG_GETARG_POINTER (0 );
747+ lquery * res ;
748+
749+ if ((res = parse_lquery (buf , fcinfo -> context )) == NULL )
750+ PG_RETURN_NULL ();
733751
734- PG_RETURN_POINTER (parse_lquery ( buf ) );
752+ PG_RETURN_POINTER (res );
735753}
736754
737755PG_FUNCTION_INFO_V1 (lquery_out );
@@ -790,7 +808,7 @@ lquery_recv(PG_FUNCTION_ARGS)
790808 elog (ERROR , "unsupported lquery version number %d" , version );
791809
792810 str = pq_getmsgtext (buf , buf -> len - buf -> cursor , & nbytes );
793- res = parse_lquery (str );
811+ res = parse_lquery (str , NULL );
794812 pfree (str );
795813
796814 PG_RETURN_POINTER (res );
0 commit comments