mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-29 22:49:41 +03:00 
			
		
		
		
	Cosmetic improvements in ltree code.
Add more comments in ltree.h, and correct a misstatement or two. Use a symbol, rather than hardwired constants, for the maximum length of an ltree label. The max length is still hardwired in the associated error messages, but I want to clean that up as part of a separate patch to improve the error messages.
This commit is contained in:
		| @@ -7,9 +7,19 @@ | |||||||
| #include "tsearch/ts_locale.h" | #include "tsearch/ts_locale.h" | ||||||
| #include "utils/memutils.h" | #include "utils/memutils.h" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* ltree */ | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * We want the maximum length of a label to be encoding-independent, so | ||||||
|  |  * set it somewhat arbitrarily at 255 characters (not bytes), while using | ||||||
|  |  * uint16 fields to hold the byte length. | ||||||
|  |  */ | ||||||
|  | #define LTREE_LABEL_MAX_CHARS 255 | ||||||
|  |  | ||||||
| typedef struct | typedef struct | ||||||
| { | { | ||||||
| 	uint16		len; | 	uint16		len;			/* label string length in bytes */ | ||||||
| 	char		name[FLEXIBLE_ARRAY_MEMBER]; | 	char		name[FLEXIBLE_ARRAY_MEMBER]; | ||||||
| } ltree_level; | } ltree_level; | ||||||
|  |  | ||||||
| @@ -19,7 +29,8 @@ typedef struct | |||||||
| typedef struct | typedef struct | ||||||
| { | { | ||||||
| 	int32		vl_len_;		/* varlena header (do not touch directly!) */ | 	int32		vl_len_;		/* varlena header (do not touch directly!) */ | ||||||
| 	uint16		numlevel; | 	uint16		numlevel;		/* number of labels */ | ||||||
|  | 	/* Array of maxalign'd ltree_level structs follows: */ | ||||||
| 	char		data[FLEXIBLE_ARRAY_MEMBER]; | 	char		data[FLEXIBLE_ARRAY_MEMBER]; | ||||||
| } ltree; | } ltree; | ||||||
|  |  | ||||||
| @@ -30,25 +41,35 @@ typedef struct | |||||||
|  |  | ||||||
| /* lquery */ | /* lquery */ | ||||||
|  |  | ||||||
|  | /* lquery_variant: one branch of some OR'ed alternatives */ | ||||||
| typedef struct | typedef struct | ||||||
| { | { | ||||||
| 	int32		val; | 	int32		val;			/* CRC of label string */ | ||||||
| 	uint16		len; | 	uint16		len;			/* label string length in bytes */ | ||||||
| 	uint8		flag;			/* see LVAR_xxx flags below */ | 	uint8		flag;			/* see LVAR_xxx flags below */ | ||||||
| 	char		name[FLEXIBLE_ARRAY_MEMBER]; | 	char		name[FLEXIBLE_ARRAY_MEMBER]; | ||||||
| } lquery_variant; | } lquery_variant; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Note: these macros contain too many MAXALIGN calls and so will sometimes | ||||||
|  |  * overestimate the space needed for an lquery_variant.  However, we can't | ||||||
|  |  * change it without breaking on-disk compatibility for lquery. | ||||||
|  |  */ | ||||||
| #define LVAR_HDRSIZE   MAXALIGN(offsetof(lquery_variant, name)) | #define LVAR_HDRSIZE   MAXALIGN(offsetof(lquery_variant, name)) | ||||||
| #define LVAR_NEXT(x)	( (lquery_variant*)( ((char*)(x)) + MAXALIGN(((lquery_variant*)(x))->len) + LVAR_HDRSIZE ) ) | #define LVAR_NEXT(x)	( (lquery_variant*)( ((char*)(x)) + MAXALIGN(((lquery_variant*)(x))->len) + LVAR_HDRSIZE ) ) | ||||||
|  |  | ||||||
| #define LVAR_ANYEND 0x01 | #define LVAR_ANYEND 0x01		/* '*' flag: prefix match */ | ||||||
| #define LVAR_INCASE 0x02 | #define LVAR_INCASE 0x02		/* '@' flag: case-insensitive match */ | ||||||
| #define LVAR_SUBLEXEME	0x04 | #define LVAR_SUBLEXEME	0x04	/* '%' flag: word-wise match */ | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * In an lquery_level, "flag" contains the union of the variants' flags | ||||||
|  |  * along with possible LQL_xxx flags; so those bit sets can't overlap. | ||||||
|  |  */ | ||||||
| typedef struct | typedef struct | ||||||
| { | { | ||||||
| 	uint16		totallen;		/* total length of this level, in bytes */ | 	uint16		totallen;		/* total length of this level, in bytes */ | ||||||
| 	uint16		flag;			/* see LQL_xxx flags below */ | 	uint16		flag;			/* see LQL_xxx and LVAR_xxx flags */ | ||||||
| 	uint16		numvar;			/* number of variants; 0 means '*' */ | 	uint16		numvar;			/* number of variants; 0 means '*' */ | ||||||
| 	uint16		low;			/* minimum repeat count for '*' */ | 	uint16		low;			/* minimum repeat count for '*' */ | ||||||
| 	uint16		high;			/* maximum repeat count for '*' */ | 	uint16		high;			/* maximum repeat count for '*' */ | ||||||
| @@ -60,7 +81,7 @@ typedef struct | |||||||
| #define LQL_NEXT(x) ( (lquery_level*)( ((char*)(x)) + MAXALIGN(((lquery_level*)(x))->totallen) ) ) | #define LQL_NEXT(x) ( (lquery_level*)( ((char*)(x)) + MAXALIGN(((lquery_level*)(x))->totallen) ) ) | ||||||
| #define LQL_FIRST(x)	( (lquery_variant*)( ((char*)(x))+LQL_HDRSIZE ) ) | #define LQL_FIRST(x)	( (lquery_variant*)( ((char*)(x))+LQL_HDRSIZE ) ) | ||||||
|  |  | ||||||
| #define LQL_NOT		0x10 | #define LQL_NOT		0x10		/* level has '!' (NOT) prefix */ | ||||||
|  |  | ||||||
| #ifdef LOWER_NODE | #ifdef LOWER_NODE | ||||||
| #define FLG_CANLOOKSIGN(x) ( ( (x) & ( LQL_NOT | LVAR_ANYEND | LVAR_SUBLEXEME ) ) == 0 ) | #define FLG_CANLOOKSIGN(x) ( ( (x) & ( LQL_NOT | LVAR_ANYEND | LVAR_SUBLEXEME ) ) == 0 ) | ||||||
| @@ -73,7 +94,7 @@ typedef struct | |||||||
| { | { | ||||||
| 	int32		vl_len_;		/* varlena header (do not touch directly!) */ | 	int32		vl_len_;		/* varlena header (do not touch directly!) */ | ||||||
| 	uint16		numlevel;		/* number of lquery_levels */ | 	uint16		numlevel;		/* number of lquery_levels */ | ||||||
| 	uint16		firstgood; | 	uint16		firstgood;		/* number of leading simple-match levels */ | ||||||
| 	uint16		flag;			/* see LQUERY_xxx flags below */ | 	uint16		flag;			/* see LQUERY_xxx flags below */ | ||||||
| 	/* Array of maxalign'd lquery_level structs follows: */ | 	/* Array of maxalign'd lquery_level structs follows: */ | ||||||
| 	char		data[FLEXIBLE_ARRAY_MEMBER]; | 	char		data[FLEXIBLE_ARRAY_MEMBER]; | ||||||
|   | |||||||
| @@ -85,7 +85,7 @@ ltree_in(PG_FUNCTION_ARGS) | |||||||
| 			if (charlen == 1 && t_iseq(ptr, '.')) | 			if (charlen == 1 && t_iseq(ptr, '.')) | ||||||
| 			{ | 			{ | ||||||
| 				lptr->len = ptr - lptr->start; | 				lptr->len = ptr - lptr->start; | ||||||
| 				if (lptr->wlen > 255) | 				if (lptr->wlen > LTREE_LABEL_MAX_CHARS) | ||||||
| 					ereport(ERROR, | 					ereport(ERROR, | ||||||
| 							(errcode(ERRCODE_NAME_TOO_LONG), | 							(errcode(ERRCODE_NAME_TOO_LONG), | ||||||
| 							 errmsg("name of level is too long"), | 							 errmsg("name of level is too long"), | ||||||
| @@ -112,7 +112,7 @@ ltree_in(PG_FUNCTION_ARGS) | |||||||
| 	if (state == LTPRS_WAITDELIM) | 	if (state == LTPRS_WAITDELIM) | ||||||
| 	{ | 	{ | ||||||
| 		lptr->len = ptr - lptr->start; | 		lptr->len = ptr - lptr->start; | ||||||
| 		if (lptr->wlen > 255) | 		if (lptr->wlen > LTREE_LABEL_MAX_CHARS) | ||||||
| 			ereport(ERROR, | 			ereport(ERROR, | ||||||
| 					(errcode(ERRCODE_NAME_TOO_LONG), | 					(errcode(ERRCODE_NAME_TOO_LONG), | ||||||
| 					 errmsg("name of level is too long"), | 					 errmsg("name of level is too long"), | ||||||
| @@ -302,7 +302,7 @@ lquery_in(PG_FUNCTION_ARGS) | |||||||
| 					((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) - | 					((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) - | ||||||
| 					((lptr->flag & LVAR_INCASE) ? 1 : 0) - | 					((lptr->flag & LVAR_INCASE) ? 1 : 0) - | ||||||
| 					((lptr->flag & LVAR_ANYEND) ? 1 : 0); | 					((lptr->flag & LVAR_ANYEND) ? 1 : 0); | ||||||
| 				if (lptr->wlen > 255) | 				if (lptr->wlen > LTREE_LABEL_MAX_CHARS) | ||||||
| 					ereport(ERROR, | 					ereport(ERROR, | ||||||
| 							(errcode(ERRCODE_NAME_TOO_LONG), | 							(errcode(ERRCODE_NAME_TOO_LONG), | ||||||
| 							 errmsg("name of level is too long"), | 							 errmsg("name of level is too long"), | ||||||
| @@ -318,7 +318,7 @@ lquery_in(PG_FUNCTION_ARGS) | |||||||
| 					((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) - | 					((lptr->flag & LVAR_SUBLEXEME) ? 1 : 0) - | ||||||
| 					((lptr->flag & LVAR_INCASE) ? 1 : 0) - | 					((lptr->flag & LVAR_INCASE) ? 1 : 0) - | ||||||
| 					((lptr->flag & LVAR_ANYEND) ? 1 : 0); | 					((lptr->flag & LVAR_ANYEND) ? 1 : 0); | ||||||
| 				if (lptr->wlen > 255) | 				if (lptr->wlen > LTREE_LABEL_MAX_CHARS) | ||||||
| 					ereport(ERROR, | 					ereport(ERROR, | ||||||
| 							(errcode(ERRCODE_NAME_TOO_LONG), | 							(errcode(ERRCODE_NAME_TOO_LONG), | ||||||
| 							 errmsg("name of level is too long"), | 							 errmsg("name of level is too long"), | ||||||
| @@ -453,7 +453,7 @@ lquery_in(PG_FUNCTION_ARGS) | |||||||
| 					 errmsg("lquery syntax error"), | 					 errmsg("lquery syntax error"), | ||||||
| 					 errdetail("Unexpected end of line."))); | 					 errdetail("Unexpected end of line."))); | ||||||
|  |  | ||||||
| 		if (lptr->wlen > 255) | 		if (lptr->wlen > LTREE_LABEL_MAX_CHARS) | ||||||
| 			ereport(ERROR, | 			ereport(ERROR, | ||||||
| 					(errcode(ERRCODE_NAME_TOO_LONG), | 					(errcode(ERRCODE_NAME_TOO_LONG), | ||||||
| 					 errmsg("name of level is too long"), | 					 errmsg("name of level is too long"), | ||||||
| @@ -522,12 +522,21 @@ lquery_in(PG_FUNCTION_ARGS) | |||||||
| 			} | 			} | ||||||
| 			pfree(GETVAR(curqlevel)); | 			pfree(GETVAR(curqlevel)); | ||||||
| 			if (cur->numvar > 1 || cur->flag != 0) | 			if (cur->numvar > 1 || cur->flag != 0) | ||||||
|  | 			{ | ||||||
|  | 				/* Not a simple match */ | ||||||
| 				wasbad = true; | 				wasbad = true; | ||||||
|  | 			} | ||||||
| 			else if (wasbad == false) | 			else if (wasbad == false) | ||||||
|  | 			{ | ||||||
|  | 				/* count leading simple matches */ | ||||||
| 				(result->firstgood)++; | 				(result->firstgood)++; | ||||||
| 			} | 			} | ||||||
|  | 		} | ||||||
| 		else | 		else | ||||||
|  | 		{ | ||||||
|  | 			/* '*', so this isn't a simple match */ | ||||||
| 			wasbad = true; | 			wasbad = true; | ||||||
|  | 		} | ||||||
| 		curqlevel = NEXTLEV(curqlevel); | 		curqlevel = NEXTLEV(curqlevel); | ||||||
| 		cur = LQL_NEXT(cur); | 		cur = LQL_NEXT(cur); | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user