11
11
* Portions Copyright (c) 1994, Regents of the University of California
12
12
*
13
13
* IDENTIFICATION
14
- *$PostgreSQL: pgsql/src/backend/utils/adt/like.c,v 1.64 2006/03/05 15:58:42 momjian Exp $
14
+ *$PostgreSQL: pgsql/src/backend/utils/adt/like.c,v 1.65 2006/09/04 18:32:55 tgl Exp $
15
15
*
16
16
*-------------------------------------------------------------------------
17
17
*/
@@ -64,50 +64,23 @@ wchareq(char *p1, char *p2)
64
64
return 1 ;
65
65
}
66
66
67
- /*--------------------
68
- * Support routine for MatchTextIC. Compares given multibyte streams
69
- * as wide characters ignoring case.
70
- * If they match, returns 1 otherwise returns 0.
71
- *--------------------
67
+ /*
68
+ * Formerly we had a routine iwchareq() here that tried to do case-insensitive
69
+ * comparison of multibyte characters. It did not work at all, however,
70
+ * because it relied on tolower() which has a single-byte API ... and
71
+ * towlower() wouldn't be much better since we have no suitably cheap way
72
+ * of getting a single character transformed to the system's wchar_t format.
73
+ * So now, we just downcase the strings using lower() and apply regular LIKE
74
+ * comparison. This should be revisited when we install better locale support.
75
+ *
76
+ * Note that MBMatchText and MBMatchTextIC do exactly the same thing now.
77
+ * Is it worth refactoring to avoid duplicated code? They might become
78
+ * different again in the future.
72
79
*/
73
- #define CHARMAX 0x80
74
-
75
- static int
76
- iwchareq (char * p1 ,char * p2 )
77
- {
78
- pg_wchar c1 [2 ],
79
- c2 [2 ];
80
- int l ;
81
-
82
- /*
83
- * short cut. if *p1 and *p2 is lower than CHARMAX, then we could assume
84
- * they are ASCII
85
- */
86
- if ((unsignedchar )* p1 < CHARMAX && (unsignedchar )* p2 < CHARMAX )
87
- return (tolower ((unsignedchar )* p1 )== tolower ((unsignedchar )* p2 ));
88
-
89
- /*
90
- * if one of them is an ASCII while the other is not, then they must be
91
- * different characters
92
- */
93
- else if ((unsignedchar )* p1 < CHARMAX || (unsignedchar )* p2 < CHARMAX )
94
- return 0 ;
95
-
96
- /*
97
- * ok, p1 and p2 are both > CHARMAX, then they must be multibyte
98
- * characters
99
- */
100
- l = pg_mblen (p1 );
101
- (void )pg_mb2wchar_with_len (p1 ,c1 ,l );
102
- c1 [0 ]= tolower (c1 [0 ]);
103
- l = pg_mblen (p2 );
104
- (void )pg_mb2wchar_with_len (p2 ,c2 ,l );
105
- c2 [0 ]= tolower (c2 [0 ]);
106
- return (c1 [0 ]== c2 [0 ]);
107
- }
108
80
81
+ /* Set up to compile like_match.c for multibyte characters */
109
82
#define CHAREQ (p1 ,p2 ) wchareq(p1, p2)
110
- #define ICHAREQ (p1 ,p2 )iwchareq (p1, p2)
83
+ #define ICHAREQ (p1 ,p2 )wchareq (p1, p2)
111
84
#define NextChar (p ,plen ) \
112
85
do { int __l = pg_mblen(p); (p) +=__l; (plen) -=__l; } while (0)
113
86
#define CopyAdvChar (dst ,src ,srclen ) \
@@ -120,7 +93,9 @@ iwchareq(char *p1, char *p2)
120
93
#define MatchText MBMatchText
121
94
#define MatchTextIC MBMatchTextIC
122
95
#define do_like_escape MB_do_like_escape
96
+
123
97
#include "like_match.c"
98
+
124
99
#undef CHAREQ
125
100
#undef ICHAREQ
126
101
#undef NextChar
@@ -129,15 +104,19 @@ iwchareq(char *p1, char *p2)
129
104
#undef MatchTextIC
130
105
#undef do_like_escape
131
106
107
+ /* Set up to compile like_match.c for single-byte characters */
132
108
#define CHAREQ (p1 ,p2 ) (*(p1) == *(p2))
133
109
#define ICHAREQ (p1 ,p2 ) (tolower((unsigned char) *(p1)) == tolower((unsigned char) *(p2)))
134
110
#define NextChar (p ,plen ) ((p)++, (plen)--)
135
111
#define CopyAdvChar (dst ,src ,srclen ) (*(dst)++ = *(src)++, (srclen)--)
136
112
113
+ #include "like_match.c"
114
+
115
+ /* And some support for BYTEA */
137
116
#define BYTEA_CHAREQ (p1 ,p2 ) (*(p1) == *(p2))
138
117
#define BYTEA_NextChar (p ,plen ) ((p)++, (plen)--)
139
118
#define BYTEA_CopyAdvChar (dst ,src ,srclen ) (*(dst)++ = *(src)++, (srclen)--)
140
- #include "like_match.c"
119
+
141
120
142
121
/*
143
122
*interface routines called by the function manager
@@ -296,15 +275,32 @@ nameiclike(PG_FUNCTION_ARGS)
296
275
int slen ,
297
276
plen ;
298
277
299
- s = NameStr (* str );
300
- slen = strlen (s );
301
- p = VARDATA (pat );
302
- plen = (VARSIZE (pat )- VARHDRSZ );
303
-
304
278
if (pg_database_encoding_max_length ()== 1 )
279
+ {
280
+ s = NameStr (* str );
281
+ slen = strlen (s );
282
+ p = VARDATA (pat );
283
+ plen = (VARSIZE (pat )- VARHDRSZ );
305
284
result = (MatchTextIC (s ,slen ,p ,plen )== LIKE_TRUE );
285
+ }
306
286
else
287
+ {
288
+ /* Force inputs to lower case to achieve case insensitivity */
289
+ text * strtext ;
290
+
291
+ strtext = DatumGetTextP (DirectFunctionCall1 (name_text ,
292
+ NameGetDatum (str )));
293
+ strtext = DatumGetTextP (DirectFunctionCall1 (lower ,
294
+ PointerGetDatum (strtext )));
295
+ pat = DatumGetTextP (DirectFunctionCall1 (lower ,
296
+ PointerGetDatum (pat )));
297
+
298
+ s = VARDATA (strtext );
299
+ slen = (VARSIZE (strtext )- VARHDRSZ );
300
+ p = VARDATA (pat );
301
+ plen = (VARSIZE (pat )- VARHDRSZ );
307
302
result = (MBMatchTextIC (s ,slen ,p ,plen )== LIKE_TRUE );
303
+ }
308
304
309
305
PG_RETURN_BOOL (result );
310
306
}
@@ -320,15 +316,32 @@ nameicnlike(PG_FUNCTION_ARGS)
320
316
int slen ,
321
317
plen ;
322
318
323
- s = NameStr (* str );
324
- slen = strlen (s );
325
- p = VARDATA (pat );
326
- plen = (VARSIZE (pat )- VARHDRSZ );
327
-
328
319
if (pg_database_encoding_max_length ()== 1 )
320
+ {
321
+ s = NameStr (* str );
322
+ slen = strlen (s );
323
+ p = VARDATA (pat );
324
+ plen = (VARSIZE (pat )- VARHDRSZ );
329
325
result = (MatchTextIC (s ,slen ,p ,plen )!= LIKE_TRUE );
326
+ }
330
327
else
328
+ {
329
+ /* Force inputs to lower case to achieve case insensitivity */
330
+ text * strtext ;
331
+
332
+ strtext = DatumGetTextP (DirectFunctionCall1 (name_text ,
333
+ NameGetDatum (str )));
334
+ strtext = DatumGetTextP (DirectFunctionCall1 (lower ,
335
+ PointerGetDatum (strtext )));
336
+ pat = DatumGetTextP (DirectFunctionCall1 (lower ,
337
+ PointerGetDatum (pat )));
338
+
339
+ s = VARDATA (strtext );
340
+ slen = (VARSIZE (strtext )- VARHDRSZ );
341
+ p = VARDATA (pat );
342
+ plen = (VARSIZE (pat )- VARHDRSZ );
331
343
result = (MBMatchTextIC (s ,slen ,p ,plen )!= LIKE_TRUE );
344
+ }
332
345
333
346
PG_RETURN_BOOL (result );
334
347
}
@@ -344,15 +357,27 @@ texticlike(PG_FUNCTION_ARGS)
344
357
int slen ,
345
358
plen ;
346
359
347
- s = VARDATA (str );
348
- slen = (VARSIZE (str )- VARHDRSZ );
349
- p = VARDATA (pat );
350
- plen = (VARSIZE (pat )- VARHDRSZ );
351
-
352
360
if (pg_database_encoding_max_length ()== 1 )
361
+ {
362
+ s = VARDATA (str );
363
+ slen = (VARSIZE (str )- VARHDRSZ );
364
+ p = VARDATA (pat );
365
+ plen = (VARSIZE (pat )- VARHDRSZ );
353
366
result = (MatchTextIC (s ,slen ,p ,plen )== LIKE_TRUE );
367
+ }
354
368
else
369
+ {
370
+ /* Force inputs to lower case to achieve case insensitivity */
371
+ str = DatumGetTextP (DirectFunctionCall1 (lower ,
372
+ PointerGetDatum (str )));
373
+ pat = DatumGetTextP (DirectFunctionCall1 (lower ,
374
+ PointerGetDatum (pat )));
375
+ s = VARDATA (str );
376
+ slen = (VARSIZE (str )- VARHDRSZ );
377
+ p = VARDATA (pat );
378
+ plen = (VARSIZE (pat )- VARHDRSZ );
355
379
result = (MBMatchTextIC (s ,slen ,p ,plen )== LIKE_TRUE );
380
+ }
356
381
357
382
PG_RETURN_BOOL (result );
358
383
}
@@ -368,15 +393,27 @@ texticnlike(PG_FUNCTION_ARGS)
368
393
int slen ,
369
394
plen ;
370
395
371
- s = VARDATA (str );
372
- slen = (VARSIZE (str )- VARHDRSZ );
373
- p = VARDATA (pat );
374
- plen = (VARSIZE (pat )- VARHDRSZ );
375
-
376
396
if (pg_database_encoding_max_length ()== 1 )
397
+ {
398
+ s = VARDATA (str );
399
+ slen = (VARSIZE (str )- VARHDRSZ );
400
+ p = VARDATA (pat );
401
+ plen = (VARSIZE (pat )- VARHDRSZ );
377
402
result = (MatchTextIC (s ,slen ,p ,plen )!= LIKE_TRUE );
403
+ }
378
404
else
405
+ {
406
+ /* Force inputs to lower case to achieve case insensitivity */
407
+ str = DatumGetTextP (DirectFunctionCall1 (lower ,
408
+ PointerGetDatum (str )));
409
+ pat = DatumGetTextP (DirectFunctionCall1 (lower ,
410
+ PointerGetDatum (pat )));
411
+ s = VARDATA (str );
412
+ slen = (VARSIZE (str )- VARHDRSZ );
413
+ p = VARDATA (pat );
414
+ plen = (VARSIZE (pat )- VARHDRSZ );
379
415
result = (MBMatchTextIC (s ,slen ,p ,plen )!= LIKE_TRUE );
416
+ }
380
417
381
418
PG_RETURN_BOOL (result );
382
419
}