Skip to content

Commit 8eee65c

Browse files
committed
ltree support for multibyte encodings. Patch was made by
laser <laserlist@pgsqldb.com> with some editorization by me.
1 parent 995fb74 commit 8eee65c

File tree

5 files changed

+136
-87
lines changed

5 files changed

+136
-87
lines changed

contrib/ltree/lquery_op.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
/*
22
* op function for ltree and lquery
33
* Teodor Sigaev <teodor@stack.net>
4-
* $PostgreSQL: pgsql/contrib/ltree/lquery_op.c,v 1.12 2008/05/12 00:00:42 alvherre Exp $
4+
* $PostgreSQL: pgsql/contrib/ltree/lquery_op.c,v 1.13 2008/06/30 18:30:48 teodor Exp $
55
*/
66
#include "postgres.h"
77

88
#include <ctype.h>
99

1010
#include "utils/array.h"
11+
#include "utils/formatting.h"
1112
#include "ltree.h"
1213

1314
PG_FUNCTION_INFO_V1(ltq_regex);
@@ -32,23 +33,24 @@ static char *
3233
getlexeme(char *start, char *end, int *len)
3334
{
3435
char *ptr;
35-
36-
while (start < end && *start == '_')
37-
start++;
36+
int charlen;
37+
38+
while (start < end && (charlen = pg_mblen(start)) == 1 && t_iseq(start,'_') )
39+
start += charlen;
3840

3941
ptr = start;
40-
if (ptr == end)
42+
if (ptr >= end)
4143
return NULL;
4244

43-
while (ptr < end && *ptr != '_')
44-
ptr++;
45+
while (ptr < end && !( (charlen = pg_mblen(ptr)) == 1 && t_iseq(ptr, '_') ) )
46+
ptr += charlen;
4547

4648
*len = ptr - start;
4749
return start;
4850
}
4951

5052
bool
51-
compare_subnode(ltree_level * t, char *qn, int len, int (*cmpptr) (const char *, const char *, size_t), bool anyend)
53+
compare_subnode(ltree_level * t, char *qn, int len, int (*cmpptr) (const char *, const char *, size_t), bool anyend)
5254
{
5355
char *endt = t->name + t->len;
5456
char *endq = qn + len;
@@ -85,6 +87,21 @@ bool
8587
return true;
8688
}
8789

90+
int
91+
ltree_strncasecmp(const char *a, const char *b, size_t s)
92+
{
93+
char *al = str_tolower(a, s);
94+
char *bl = str_tolower(b, s);
95+
int res;
96+
97+
res = strncmp(al, bl,s);
98+
99+
pfree(al);
100+
pfree(bl);
101+
102+
return res;
103+
}
104+
88105
static bool
89106
checkLevel(lquery_level * curq, ltree_level * curt)
90107
{
@@ -94,7 +111,7 @@ checkLevel(lquery_level * curq, ltree_level * curt)
94111

95112
for (i = 0; i < curq->numvar; i++)
96113
{
97-
cmpptr = (curvar->flag & LVAR_INCASE) ? pg_strncasecmp : strncmp;
114+
cmpptr = (curvar->flag & LVAR_INCASE) ? ltree_strncasecmp : strncmp;
98115

99116
if (curvar->flag & LVAR_SUBLEXEME)
100117
{

contrib/ltree/ltree.h

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
/* $PostgreSQL: pgsql/contrib/ltree/ltree.h,v 1.20 2008/05/12 00:00:42 alvherre Exp $ */
1+
/* $PostgreSQL: pgsql/contrib/ltree/ltree.h,v 1.21 2008/06/30 18:30:48 teodor Exp $ */
22

33
#ifndef __LTREE_H__
44
#define __LTREE_H__
55

6+
#include "postgres.h"
67
#include "fmgr.h"
8+
#include "tsearch/ts_locale.h"
79

810
typedef struct
911
{
10-
uint8 len;
12+
uint16 len;
1113
char name[1];
1214
} ltree_level;
1315

14-
#define LEVEL_HDRSIZE (sizeof(uint8))
16+
#define LEVEL_HDRSIZE (offsetof(ltree_level,name))
1517
#define LEVEL_NEXT(x) ( (ltree_level*)( ((char*)(x)) + MAXALIGN(((ltree_level*)(x))->len + LEVEL_HDRSIZE) ) )
1618

1719
typedef struct
@@ -21,7 +23,7 @@ typedef struct
2123
char data[1];
2224
} ltree;
2325

24-
#define LTREE_HDRSIZE MAXALIGN(VARHDRSZ + sizeof(uint16))
26+
#define LTREE_HDRSIZE MAXALIGN( offsetof(ltree, data) )
2527
#define LTREE_FIRST(x) ( (ltree_level*)( ((char*)(x))+LTREE_HDRSIZE ) )
2628

2729

@@ -30,12 +32,12 @@ typedef struct
3032
typedef struct
3133
{
3234
int4 val;
33-
uint8 len;
35+
uint16 len;
3436
uint8 flag;
3537
char name[1];
3638
} lquery_variant;
3739

38-
#define LVAR_HDRSIZE MAXALIGN(sizeof(uint8)*2 + sizeof(int4))
40+
#define LVAR_HDRSIZE MAXALIGN(offsetof(lquery_variant, name))
3941
#define LVAR_NEXT(x) ( (lquery_variant*)( ((char*)(x)) + MAXALIGN(((lquery_variant*)(x))->len) + LVAR_HDRSIZE ) )
4042

4143
#define LVAR_ANYEND 0x01
@@ -52,7 +54,7 @@ typedef struct
5254
char variants[1];
5355
} lquery_level;
5456

55-
#define LQL_HDRSIZE MAXALIGN( sizeof(uint16)*5 )
57+
#define LQL_HDRSIZE MAXALIGN( offsetof(lquery_level,variants) )
5658
#define LQL_NEXT(x) ( (lquery_level*)( ((char*)(x)) + MAXALIGN(((lquery_level*)(x))->totallen) ) )
5759
#define LQL_FIRST(x) ( (lquery_variant*)( ((char*)(x))+LQL_HDRSIZE ) )
5860

@@ -73,12 +75,12 @@ typedef struct
7375
char data[1];
7476
} lquery;
7577

76-
#define LQUERY_HDRSIZE MAXALIGN(VARHDRSZ + 3*sizeof(uint16))
78+
#define LQUERY_HDRSIZE MAXALIGN( offsetof(lquery, data) )
7779
#define LQUERY_FIRST(x) ( (lquery_level*)( ((char*)(x))+LQUERY_HDRSIZE ) )
7880

7981
#define LQUERY_HASNOT 0x01
8082

81-
#define ISALNUM(x) ( isalnum((unsigned char)(x)) || (x) == '_' )
83+
#define ISALNUM(x) ( t_isalpha(x) || t_isdigit(x) || ( pg_mblen(x) == 1 && t_iseq((x), '_') ) )
8284

8385
/* full text query */
8486

@@ -156,9 +158,10 @@ bool ltree_execute(ITEM * curitem, void *checkval,
156158

157159
int ltree_compare(const ltree * a, const ltree * b);
158160
bool inner_isparent(const ltree * c, const ltree * p);
159-
bool compare_subnode(ltree_level * t, char *q, int len,
160-
int (*cmpptr) (const char *, const char *, size_t), bool anyend);
161+
bool compare_subnode(ltree_level * t, char *q, int len,
162+
int (*cmpptr) (const char *, const char *, size_t), bool anyend);
161163
ltree *lca_inner(ltree ** a, int len);
164+
int ltree_strncasecmp(const char *a, const char *b, size_t s);
162165

163166
#define PG_GETARG_LTREE(x) ((ltree*)DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(x))))
164167
#define PG_GETARG_LTREE_COPY(x) ((ltree*)DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(x))))

0 commit comments

Comments
 (0)