@@ -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{
3838const char * ptr ;
3939nodeitem * list ,
@@ -46,7 +46,7 @@ parse_ltree(const char *buf)
4646int charlen ;
4747int 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
6363if (num + 1 > LTREE_MAX_LEVELS )
64- ereport ( ERROR ,
64+ ereturn ( escontext , NULL ,
6565(errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
6666errmsg ("number of ltree labels (%d) exceeds the maximum allowed (%d)" ,
6767num + 1 ,LTREE_MAX_LEVELS )));
@@ -86,7 +86,8 @@ parse_ltree(const char *buf)
8686case LTPRS_WAITDELIM :
8787if (t_iseq (ptr ,'.' ))
8888{
89- finish_nodeitem (lptr ,ptr , false,pos );
89+ if (!finish_nodeitem (lptr ,ptr , false,pos ,escontext ))
90+ return NULL ;
9091totallen += MAXALIGN (lptr -> len + LEVEL_HDRSIZE );
9192lptr ++ ;
9293state = LTPRS_WAITNAME ;
@@ -105,12 +106,13 @@ parse_ltree(const char *buf)
105106
106107if (state == LTPRS_WAITDELIM )
107108{
108- finish_nodeitem (lptr ,ptr , false,pos );
109+ if (!finish_nodeitem (lptr ,ptr , false,pos ,escontext ))
110+ return NULL ;
109111totallen += MAXALIGN (lptr -> len + LEVEL_HDRSIZE );
110112lptr ++ ;
111113}
112114else if (!(state == LTPRS_WAITNAME && lptr == list ))
113- ereport ( ERROR ,
115+ ereturn ( escontext , NULL ,
114116(errcode (ERRCODE_SYNTAX_ERROR ),
115117errmsg ("ltree syntax error" ),
116118errdetail ("Unexpected end of input." )));
@@ -172,8 +174,12 @@ Datum
172174ltree_in (PG_FUNCTION_ARGS )
173175{
174176char * 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)
232238elog (ERROR ,"unsupported ltree version number %d" ,version );
233239
234240str = pq_getmsgtext (buf ,buf -> len - buf -> cursor ,& nbytes );
235- res = parse_ltree (str );
241+ res = parse_ltree (str , NULL );
236242pfree (str );
237243
238244PG_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{
264270const char * ptr ;
265271int num = 0 ,
@@ -277,7 +283,7 @@ parse_lquery(const char *buf)
277283int charlen ;
278284int 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
298304num ++ ;
299305if (num > LQUERY_MAX_LEVELS )
300- ereport ( ERROR ,
306+ ereturn ( escontext , NULL ,
301307(errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
302308errmsg ("number of lquery items (%d) exceeds the maximum allowed (%d)" ,
303309num ,LQUERY_MAX_LEVELS )));
@@ -361,18 +367,21 @@ parse_lquery(const char *buf)
361367}
362368else if (t_iseq (ptr ,'|' ))
363369{
364- finish_nodeitem (lptr ,ptr , true,pos );
370+ if (!finish_nodeitem (lptr ,ptr , true,pos ,escontext ))
371+ return NULL ;
365372state = LQPRS_WAITVAR ;
366373}
367374else if (t_iseq (ptr ,'{' ))
368375{
369- finish_nodeitem (lptr ,ptr , true,pos );
376+ if (!finish_nodeitem (lptr ,ptr , true,pos ,escontext ))
377+ return NULL ;
370378curqlevel -> flag |=LQL_COUNT ;
371379state = LQPRS_WAITFNUM ;
372380}
373381else if (t_iseq (ptr ,'.' ))
374382{
375- finish_nodeitem (lptr ,ptr , true,pos );
383+ if (!finish_nodeitem (lptr ,ptr , true,pos ,escontext ))
384+ return NULL ;
376385state = LQPRS_WAITLEVEL ;
377386curqlevel = NEXTLEV (curqlevel );
378387}
@@ -407,7 +416,7 @@ parse_lquery(const char *buf)
407416int low = atoi (ptr );
408417
409418if (low < 0 || low > LTREE_MAX_LEVELS )
410- ereport ( ERROR ,
419+ ereturn ( escontext , NULL ,
411420(errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
412421errmsg ("lquery syntax error" ),
413422errdetail ("Low limit (%d) exceeds the maximum allowed (%d), at character %d." ,
@@ -425,13 +434,13 @@ parse_lquery(const char *buf)
425434int high = atoi (ptr );
426435
427436if (high < 0 || high > LTREE_MAX_LEVELS )
428- ereport ( ERROR ,
437+ ereturn ( escontext , NULL ,
429438(errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
430439errmsg ("lquery syntax error" ),
431440errdetail ("High limit (%d) exceeds the maximum allowed (%d), at character %d." ,
432441high ,LTREE_MAX_LEVELS ,pos )));
433442else if (curqlevel -> low > high )
434- ereport ( ERROR ,
443+ ereturn ( escontext , NULL ,
435444(errcode (ERRCODE_SYNTAX_ERROR ),
436445errmsg ("lquery syntax error" ),
437446errdetail ("Low limit (%d) is greater than high limit (%d), at character %d." ,
@@ -485,11 +494,14 @@ parse_lquery(const char *buf)
485494}
486495
487496if (state == LQPRS_WAITDELIM )
488- finish_nodeitem (lptr ,ptr , true,pos );
497+ {
498+ if (!finish_nodeitem (lptr ,ptr , true,pos ,escontext ))
499+ return false;
500+ }
489501else if (state == LQPRS_WAITOPEN )
490502curqlevel -> high = LTREE_MAX_LEVELS ;
491503else if (state != LQPRS_WAITEND )
492- ereport ( ERROR ,
504+ ereturn ( escontext , NULL ,
493505(errcode (ERRCODE_SYNTAX_ERROR ),
494506errmsg ("lquery syntax error" ),
495507errdetail ("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{
575588if (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 */
593606if (lptr -> len == 0 )
594- ereport ( ERROR ,
607+ ereturn ( escontext , false ,
595608(errcode (ERRCODE_SYNTAX_ERROR ),
596609is_lquery ?
597610errmsg ("lquery syntax error at character %d" ,pos ) :
598611errmsg ("ltree syntax error at character %d" ,pos ),
599612errdetail ("Empty labels are not allowed." )));
600613if (lptr -> wlen > LTREE_LABEL_MAX_CHARS )
601- ereport ( ERROR ,
614+ ereturn ( escontext , false ,
602615(errcode (ERRCODE_NAME_TOO_LONG ),
603616errmsg ("label string is too long" ),
604617errdetail ("Label length is %d, must be at most %d, at character %d." ,
605618lptr -> wlen ,LTREE_LABEL_MAX_CHARS ,pos )));
619+ return true;
606620}
607621
608622/*
@@ -730,8 +744,12 @@ Datum
730744lquery_in (PG_FUNCTION_ARGS )
731745{
732746char * 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)
790808elog (ERROR ,"unsupported lquery version number %d" ,version );
791809
792810str = pq_getmsgtext (buf ,buf -> len - buf -> cursor ,& nbytes );
793- res = parse_lquery (str );
811+ res = parse_lquery (str , NULL );
794812pfree (str );
795813
796814PG_RETURN_POINTER (res );