Commit 2743d9ae authored by Tom Lane's avatar Tom Lane

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.
parent 122b0ccf
...@@ -7,9 +7,19 @@ ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment