Commit 7583f9a7 authored by Tom Lane's avatar Tom Lane

Fix regex, LIKE, and some other second-rank text-manipulation functions

to not cause needless copying of text datums that have 1-byte headers.
Greg Stark, in response to performance gripe from Guillaume Smet and
ITAGAKI Takahiro.
parent cc59049d
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/hash/hashfunc.c,v 1.52 2007/06/01 15:33:18 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/hash/hashfunc.c,v 1.53 2007/09/21 22:52:52 tgl Exp $
* *
* NOTES * NOTES
* These functions are stored in pg_amproc. For each operator class * These functions are stored in pg_amproc. For each operator class
...@@ -157,7 +157,7 @@ hashname(PG_FUNCTION_ARGS) ...@@ -157,7 +157,7 @@ hashname(PG_FUNCTION_ARGS)
Datum Datum
hashtext(PG_FUNCTION_ARGS) hashtext(PG_FUNCTION_ARGS)
{ {
text *key = PG_GETARG_TEXT_P(0); text *key = PG_GETARG_TEXT_PP(0);
Datum result; Datum result;
/* /*
...@@ -165,8 +165,8 @@ hashtext(PG_FUNCTION_ARGS) ...@@ -165,8 +165,8 @@ hashtext(PG_FUNCTION_ARGS)
* it as a separate function in case we someday want to do something * it as a separate function in case we someday want to do something
* different in non-C locales. (See also hashbpchar, if so.) * different in non-C locales. (See also hashbpchar, if so.)
*/ */
result = hash_any((unsigned char *) VARDATA(key), result = hash_any((unsigned char *) VARDATA_ANY(key),
VARSIZE(key) - VARHDRSZ); VARSIZE_ANY_EXHDR(key));
/* Avoid leaking memory for toasted inputs */ /* Avoid leaking memory for toasted inputs */
PG_FREE_IF_COPY(key, 0); PG_FREE_IF_COPY(key, 0);
...@@ -181,11 +181,11 @@ hashtext(PG_FUNCTION_ARGS) ...@@ -181,11 +181,11 @@ hashtext(PG_FUNCTION_ARGS)
Datum Datum
hashvarlena(PG_FUNCTION_ARGS) hashvarlena(PG_FUNCTION_ARGS)
{ {
struct varlena *key = PG_GETARG_VARLENA_P(0); struct varlena *key = PG_GETARG_VARLENA_PP(0);
Datum result; Datum result;
result = hash_any((unsigned char *) VARDATA(key), result = hash_any((unsigned char *) VARDATA_ANY(key),
VARSIZE(key) - VARHDRSZ); VARSIZE_ANY_EXHDR(key));
/* Avoid leaking memory for toasted inputs */ /* Avoid leaking memory for toasted inputs */
PG_FREE_IF_COPY(key, 0); PG_FREE_IF_COPY(key, 0);
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/like.c,v 1.69 2007/06/02 02:03:42 adunstan Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/like.c,v 1.70 2007/09/21 22:52:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -135,6 +135,7 @@ Generic_Text_IC_like(text *str, text *pat) ...@@ -135,6 +135,7 @@ Generic_Text_IC_like(text *str, text *pat)
/* Force inputs to lower case to achieve case insensitivity */ /* Force inputs to lower case to achieve case insensitivity */
str = DatumGetTextP(DirectFunctionCall1(lower, PointerGetDatum(str))); str = DatumGetTextP(DirectFunctionCall1(lower, PointerGetDatum(str)));
pat = DatumGetTextP(DirectFunctionCall1(lower, PointerGetDatum(pat))); pat = DatumGetTextP(DirectFunctionCall1(lower, PointerGetDatum(pat)));
/* lower's result is never packed, so OK to use old macros here */
s = VARDATA(str); s = VARDATA(str);
slen = (VARSIZE(str) - VARHDRSZ); slen = (VARSIZE(str) - VARHDRSZ);
p = VARDATA(pat); p = VARDATA(pat);
...@@ -151,7 +152,7 @@ Datum ...@@ -151,7 +152,7 @@ Datum
namelike(PG_FUNCTION_ARGS) namelike(PG_FUNCTION_ARGS)
{ {
Name str = PG_GETARG_NAME(0); Name str = PG_GETARG_NAME(0);
text *pat = PG_GETARG_TEXT_P(1); text *pat = PG_GETARG_TEXT_PP(1);
bool result; bool result;
char *s, char *s,
*p; *p;
...@@ -160,8 +161,8 @@ namelike(PG_FUNCTION_ARGS) ...@@ -160,8 +161,8 @@ namelike(PG_FUNCTION_ARGS)
s = NameStr(*str); s = NameStr(*str);
slen = strlen(s); slen = strlen(s);
p = VARDATA(pat); p = VARDATA_ANY(pat);
plen = (VARSIZE(pat) - VARHDRSZ); plen = VARSIZE_ANY_EXHDR(pat);
result = (GenericMatchText(s, slen, p, plen) == LIKE_TRUE); result = (GenericMatchText(s, slen, p, plen) == LIKE_TRUE);
...@@ -172,7 +173,7 @@ Datum ...@@ -172,7 +173,7 @@ Datum
namenlike(PG_FUNCTION_ARGS) namenlike(PG_FUNCTION_ARGS)
{ {
Name str = PG_GETARG_NAME(0); Name str = PG_GETARG_NAME(0);
text *pat = PG_GETARG_TEXT_P(1); text *pat = PG_GETARG_TEXT_PP(1);
bool result; bool result;
char *s, char *s,
*p; *p;
...@@ -181,8 +182,8 @@ namenlike(PG_FUNCTION_ARGS) ...@@ -181,8 +182,8 @@ namenlike(PG_FUNCTION_ARGS)
s = NameStr(*str); s = NameStr(*str);
slen = strlen(s); slen = strlen(s);
p = VARDATA(pat); p = VARDATA_ANY(pat);
plen = (VARSIZE(pat) - VARHDRSZ); plen = VARSIZE_ANY_EXHDR(pat);
result = (GenericMatchText(s, slen, p, plen) != LIKE_TRUE); result = (GenericMatchText(s, slen, p, plen) != LIKE_TRUE);
...@@ -192,18 +193,18 @@ namenlike(PG_FUNCTION_ARGS) ...@@ -192,18 +193,18 @@ namenlike(PG_FUNCTION_ARGS)
Datum Datum
textlike(PG_FUNCTION_ARGS) textlike(PG_FUNCTION_ARGS)
{ {
text *str = PG_GETARG_TEXT_P(0); text *str = PG_GETARG_TEXT_PP(0);
text *pat = PG_GETARG_TEXT_P(1); text *pat = PG_GETARG_TEXT_PP(1);
bool result; bool result;
char *s, char *s,
*p; *p;
int slen, int slen,
plen; plen;
s = VARDATA(str); s = VARDATA_ANY(str);
slen = (VARSIZE(str) - VARHDRSZ); slen = VARSIZE_ANY_EXHDR(str);
p = VARDATA(pat); p = VARDATA_ANY(pat);
plen = (VARSIZE(pat) - VARHDRSZ); plen = VARSIZE_ANY_EXHDR(pat);
result = (GenericMatchText(s, slen, p, plen) == LIKE_TRUE); result = (GenericMatchText(s, slen, p, plen) == LIKE_TRUE);
...@@ -213,18 +214,18 @@ textlike(PG_FUNCTION_ARGS) ...@@ -213,18 +214,18 @@ textlike(PG_FUNCTION_ARGS)
Datum Datum
textnlike(PG_FUNCTION_ARGS) textnlike(PG_FUNCTION_ARGS)
{ {
text *str = PG_GETARG_TEXT_P(0); text *str = PG_GETARG_TEXT_PP(0);
text *pat = PG_GETARG_TEXT_P(1); text *pat = PG_GETARG_TEXT_PP(1);
bool result; bool result;
char *s, char *s,
*p; *p;
int slen, int slen,
plen; plen;
s = VARDATA(str); s = VARDATA_ANY(str);
slen = (VARSIZE(str) - VARHDRSZ); slen = VARSIZE_ANY_EXHDR(str);
p = VARDATA(pat); p = VARDATA_ANY(pat);
plen = (VARSIZE(pat) - VARHDRSZ); plen = VARSIZE_ANY_EXHDR(pat);
result = (GenericMatchText(s, slen, p, plen) != LIKE_TRUE); result = (GenericMatchText(s, slen, p, plen) != LIKE_TRUE);
...@@ -234,18 +235,18 @@ textnlike(PG_FUNCTION_ARGS) ...@@ -234,18 +235,18 @@ textnlike(PG_FUNCTION_ARGS)
Datum Datum
bytealike(PG_FUNCTION_ARGS) bytealike(PG_FUNCTION_ARGS)
{ {
bytea *str = PG_GETARG_BYTEA_P(0); bytea *str = PG_GETARG_BYTEA_PP(0);
bytea *pat = PG_GETARG_BYTEA_P(1); bytea *pat = PG_GETARG_BYTEA_PP(1);
bool result; bool result;
char *s, char *s,
*p; *p;
int slen, int slen,
plen; plen;
s = VARDATA(str); s = VARDATA_ANY(str);
slen = (VARSIZE(str) - VARHDRSZ); slen = VARSIZE_ANY_EXHDR(str);
p = VARDATA(pat); p = VARDATA_ANY(pat);
plen = (VARSIZE(pat) - VARHDRSZ); plen = VARSIZE_ANY_EXHDR(pat);
result = (SB_MatchText(s, slen, p, plen) == LIKE_TRUE); result = (SB_MatchText(s, slen, p, plen) == LIKE_TRUE);
...@@ -255,18 +256,18 @@ bytealike(PG_FUNCTION_ARGS) ...@@ -255,18 +256,18 @@ bytealike(PG_FUNCTION_ARGS)
Datum Datum
byteanlike(PG_FUNCTION_ARGS) byteanlike(PG_FUNCTION_ARGS)
{ {
bytea *str = PG_GETARG_BYTEA_P(0); bytea *str = PG_GETARG_BYTEA_PP(0);
bytea *pat = PG_GETARG_BYTEA_P(1); bytea *pat = PG_GETARG_BYTEA_PP(1);
bool result; bool result;
char *s, char *s,
*p; *p;
int slen, int slen,
plen; plen;
s = VARDATA(str); s = VARDATA_ANY(str);
slen = (VARSIZE(str) - VARHDRSZ); slen = VARSIZE_ANY_EXHDR(str);
p = VARDATA(pat); p = VARDATA_ANY(pat);
plen = (VARSIZE(pat) - VARHDRSZ); plen = VARSIZE_ANY_EXHDR(pat);
result = (SB_MatchText(s, slen, p, plen) != LIKE_TRUE); result = (SB_MatchText(s, slen, p, plen) != LIKE_TRUE);
...@@ -281,7 +282,7 @@ Datum ...@@ -281,7 +282,7 @@ Datum
nameiclike(PG_FUNCTION_ARGS) nameiclike(PG_FUNCTION_ARGS)
{ {
Name str = PG_GETARG_NAME(0); Name str = PG_GETARG_NAME(0);
text *pat = PG_GETARG_TEXT_P(1); text *pat = PG_GETARG_TEXT_PP(1);
bool result; bool result;
text *strtext; text *strtext;
...@@ -296,7 +297,7 @@ Datum ...@@ -296,7 +297,7 @@ Datum
nameicnlike(PG_FUNCTION_ARGS) nameicnlike(PG_FUNCTION_ARGS)
{ {
Name str = PG_GETARG_NAME(0); Name str = PG_GETARG_NAME(0);
text *pat = PG_GETARG_TEXT_P(1); text *pat = PG_GETARG_TEXT_PP(1);
bool result; bool result;
text *strtext; text *strtext;
...@@ -310,8 +311,8 @@ nameicnlike(PG_FUNCTION_ARGS) ...@@ -310,8 +311,8 @@ nameicnlike(PG_FUNCTION_ARGS)
Datum Datum
texticlike(PG_FUNCTION_ARGS) texticlike(PG_FUNCTION_ARGS)
{ {
text *str = PG_GETARG_TEXT_P(0); text *str = PG_GETARG_TEXT_PP(0);
text *pat = PG_GETARG_TEXT_P(1); text *pat = PG_GETARG_TEXT_PP(1);
bool result; bool result;
result = (Generic_Text_IC_like(str, pat) == LIKE_TRUE); result = (Generic_Text_IC_like(str, pat) == LIKE_TRUE);
...@@ -322,8 +323,8 @@ texticlike(PG_FUNCTION_ARGS) ...@@ -322,8 +323,8 @@ texticlike(PG_FUNCTION_ARGS)
Datum Datum
texticnlike(PG_FUNCTION_ARGS) texticnlike(PG_FUNCTION_ARGS)
{ {
text *str = PG_GETARG_TEXT_P(0); text *str = PG_GETARG_TEXT_PP(0);
text *pat = PG_GETARG_TEXT_P(1); text *pat = PG_GETARG_TEXT_PP(1);
bool result; bool result;
result = (Generic_Text_IC_like(str, pat) != LIKE_TRUE); result = (Generic_Text_IC_like(str, pat) != LIKE_TRUE);
...@@ -338,8 +339,8 @@ texticnlike(PG_FUNCTION_ARGS) ...@@ -338,8 +339,8 @@ texticnlike(PG_FUNCTION_ARGS)
Datum Datum
like_escape(PG_FUNCTION_ARGS) like_escape(PG_FUNCTION_ARGS)
{ {
text *pat = PG_GETARG_TEXT_P(0); text *pat = PG_GETARG_TEXT_PP(0);
text *esc = PG_GETARG_TEXT_P(1); text *esc = PG_GETARG_TEXT_PP(1);
text *result; text *result;
if (pg_database_encoding_max_length() == 1) if (pg_database_encoding_max_length() == 1)
...@@ -357,8 +358,8 @@ like_escape(PG_FUNCTION_ARGS) ...@@ -357,8 +358,8 @@ like_escape(PG_FUNCTION_ARGS)
Datum Datum
like_escape_bytea(PG_FUNCTION_ARGS) like_escape_bytea(PG_FUNCTION_ARGS)
{ {
bytea *pat = PG_GETARG_BYTEA_P(0); bytea *pat = PG_GETARG_BYTEA_PP(0);
bytea *esc = PG_GETARG_BYTEA_P(1); bytea *esc = PG_GETARG_BYTEA_PP(1);
bytea *result = SB_do_like_escape((text *)pat, (text *)esc); bytea *result = SB_do_like_escape((text *)pat, (text *)esc);
PG_RETURN_BYTEA_P((bytea *)result); PG_RETURN_BYTEA_P((bytea *)result);
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
* Copyright (c) 1996-2007, PostgreSQL Global Development Group * Copyright (c) 1996-2007, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/like_match.c,v 1.16 2007/06/02 02:03:42 adunstan Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/like_match.c,v 1.17 2007/09/21 22:52:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -242,10 +242,10 @@ do_like_escape(text *pat, text *esc) ...@@ -242,10 +242,10 @@ do_like_escape(text *pat, text *esc)
elen; elen;
bool afterescape; bool afterescape;
p = VARDATA(pat); p = VARDATA_ANY(pat);
plen = (VARSIZE(pat) - VARHDRSZ); plen = VARSIZE_ANY_EXHDR(pat);
e = VARDATA(esc); e = VARDATA_ANY(esc);
elen = (VARSIZE(esc) - VARHDRSZ); elen = VARSIZE_ANY_EXHDR(esc);
/* /*
* Worst-case pattern growth is 2x --- unlikely, but it's hardly worth * Worst-case pattern growth is 2x --- unlikely, but it's hardly worth
...@@ -279,14 +279,14 @@ do_like_escape(text *pat, text *esc) ...@@ -279,14 +279,14 @@ do_like_escape(text *pat, text *esc)
errmsg("invalid escape string"), errmsg("invalid escape string"),
errhint("Escape string must be empty or one character."))); errhint("Escape string must be empty or one character.")));
e = VARDATA(esc); e = VARDATA_ANY(esc);
/* /*
* If specified escape is '\', just copy the pattern as-is. * If specified escape is '\', just copy the pattern as-is.
*/ */
if (*e == '\\') if (*e == '\\')
{ {
memcpy(result, pat, VARSIZE(pat)); memcpy(result, pat, VARSIZE_ANY(pat));
return result; return result;
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/fmgr.h,v 1.52 2007/07/25 12:22:52 mha Exp $ * $PostgreSQL: pgsql/src/include/fmgr.h,v 1.53 2007/09/21 22:52:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -220,6 +220,8 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena * datum); ...@@ -220,6 +220,8 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena * datum);
#define PG_GETARG_RAW_VARLENA_P(n) ((struct varlena *) PG_GETARG_POINTER(n)) #define PG_GETARG_RAW_VARLENA_P(n) ((struct varlena *) PG_GETARG_POINTER(n))
/* use this if you want the input datum de-toasted: */ /* use this if you want the input datum de-toasted: */
#define PG_GETARG_VARLENA_P(n) PG_DETOAST_DATUM(PG_GETARG_DATUM(n)) #define PG_GETARG_VARLENA_P(n) PG_DETOAST_DATUM(PG_GETARG_DATUM(n))
/* and this if you can handle 1-byte-header datums: */
#define PG_GETARG_VARLENA_PP(n) PG_DETOAST_DATUM_PACKED(PG_GETARG_DATUM(n))
/* DatumGetFoo macros for varlena types will typically look like this: */ /* DatumGetFoo macros for varlena types will typically look like this: */
#define DatumGetByteaP(X) ((bytea *) PG_DETOAST_DATUM(X)) #define DatumGetByteaP(X) ((bytea *) PG_DETOAST_DATUM(X))
#define DatumGetByteaPP(X) ((bytea *) PG_DETOAST_DATUM_PACKED(X)) #define DatumGetByteaPP(X) ((bytea *) PG_DETOAST_DATUM_PACKED(X))
......
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