mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +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:
parent
122b0ccfef
commit
2743d9ae4a
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user