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.
*
*
* 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
* These functions are stored in pg_amproc. For each operator class
Datum
hashtext(PG_FUNCTION_ARGS)
{
- text *key = PG_GETARG_TEXT_P(0);
+ text *key = PG_GETARG_TEXT_PP(0);
Datum result;
/*
* it as a separate function in case we someday want to do something
* different in non-C locales. (See also hashbpchar, if so.)
*/
- result = hash_any((unsigned char *) VARDATA(key),
- VARSIZE(key) - VARHDRSZ);
+ result = hash_any((unsigned char *) VARDATA_ANY(key),
+ VARSIZE_ANY_EXHDR(key));
/* Avoid leaking memory for toasted inputs */
PG_FREE_IF_COPY(key, 0);
Datum
hashvarlena(PG_FUNCTION_ARGS)
{
- struct varlena *key = PG_GETARG_VARLENA_P(0);
+ struct varlena *key = PG_GETARG_VARLENA_PP(0);
Datum result;
- result = hash_any((unsigned char *) VARDATA(key),
- VARSIZE(key) - VARHDRSZ);
+ result = hash_any((unsigned char *) VARDATA_ANY(key),
+ VARSIZE_ANY_EXHDR(key));
/* Avoid leaking memory for toasted inputs */
PG_FREE_IF_COPY(key, 0);
* Portions Copyright (c) 1994, Regents of the University of California
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/* Force inputs to lower case to achieve case insensitivity */
str = DatumGetTextP(DirectFunctionCall1(lower, PointerGetDatum(str)));
pat = DatumGetTextP(DirectFunctionCall1(lower, PointerGetDatum(pat)));
+ /* lower's result is never packed, so OK to use old macros here */
s = VARDATA(str);
slen = (VARSIZE(str) - VARHDRSZ);
p = VARDATA(pat);
namelike(PG_FUNCTION_ARGS)
{
Name str = PG_GETARG_NAME(0);
- text *pat = PG_GETARG_TEXT_P(1);
+ text *pat = PG_GETARG_TEXT_PP(1);
bool result;
char *s,
*p;
s = NameStr(*str);
slen = strlen(s);
- p = VARDATA(pat);
- plen = (VARSIZE(pat) - VARHDRSZ);
+ p = VARDATA_ANY(pat);
+ plen = VARSIZE_ANY_EXHDR(pat);
result = (GenericMatchText(s, slen, p, plen) == LIKE_TRUE);
namenlike(PG_FUNCTION_ARGS)
{
Name str = PG_GETARG_NAME(0);
- text *pat = PG_GETARG_TEXT_P(1);
+ text *pat = PG_GETARG_TEXT_PP(1);
bool result;
char *s,
*p;
s = NameStr(*str);
slen = strlen(s);
- p = VARDATA(pat);
- plen = (VARSIZE(pat) - VARHDRSZ);
+ p = VARDATA_ANY(pat);
+ plen = VARSIZE_ANY_EXHDR(pat);
result = (GenericMatchText(s, slen, p, plen) != LIKE_TRUE);
Datum
textlike(PG_FUNCTION_ARGS)
{
- text *str = PG_GETARG_TEXT_P(0);
- text *pat = PG_GETARG_TEXT_P(1);
+ text *str = PG_GETARG_TEXT_PP(0);
+ text *pat = PG_GETARG_TEXT_PP(1);
bool result;
char *s,
*p;
int slen,
plen;
- s = VARDATA(str);
- slen = (VARSIZE(str) - VARHDRSZ);
- p = VARDATA(pat);
- plen = (VARSIZE(pat) - VARHDRSZ);
+ s = VARDATA_ANY(str);
+ slen = VARSIZE_ANY_EXHDR(str);
+ p = VARDATA_ANY(pat);
+ plen = VARSIZE_ANY_EXHDR(pat);
result = (GenericMatchText(s, slen, p, plen) == LIKE_TRUE);
Datum
textnlike(PG_FUNCTION_ARGS)
{
- text *str = PG_GETARG_TEXT_P(0);
- text *pat = PG_GETARG_TEXT_P(1);
+ text *str = PG_GETARG_TEXT_PP(0);
+ text *pat = PG_GETARG_TEXT_PP(1);
bool result;
char *s,
*p;
int slen,
plen;
- s = VARDATA(str);
- slen = (VARSIZE(str) - VARHDRSZ);
- p = VARDATA(pat);
- plen = (VARSIZE(pat) - VARHDRSZ);
+ s = VARDATA_ANY(str);
+ slen = VARSIZE_ANY_EXHDR(str);
+ p = VARDATA_ANY(pat);
+ plen = VARSIZE_ANY_EXHDR(pat);
result = (GenericMatchText(s, slen, p, plen) != LIKE_TRUE);
Datum
bytealike(PG_FUNCTION_ARGS)
{
- bytea *str = PG_GETARG_BYTEA_P(0);
- bytea *pat = PG_GETARG_BYTEA_P(1);
+ bytea *str = PG_GETARG_BYTEA_PP(0);
+ bytea *pat = PG_GETARG_BYTEA_PP(1);
bool result;
char *s,
*p;
int slen,
plen;
- s = VARDATA(str);
- slen = (VARSIZE(str) - VARHDRSZ);
- p = VARDATA(pat);
- plen = (VARSIZE(pat) - VARHDRSZ);
+ s = VARDATA_ANY(str);
+ slen = VARSIZE_ANY_EXHDR(str);
+ p = VARDATA_ANY(pat);
+ plen = VARSIZE_ANY_EXHDR(pat);
result = (SB_MatchText(s, slen, p, plen) == LIKE_TRUE);
Datum
byteanlike(PG_FUNCTION_ARGS)
{
- bytea *str = PG_GETARG_BYTEA_P(0);
- bytea *pat = PG_GETARG_BYTEA_P(1);
+ bytea *str = PG_GETARG_BYTEA_PP(0);
+ bytea *pat = PG_GETARG_BYTEA_PP(1);
bool result;
char *s,
*p;
int slen,
plen;
- s = VARDATA(str);
- slen = (VARSIZE(str) - VARHDRSZ);
- p = VARDATA(pat);
- plen = (VARSIZE(pat) - VARHDRSZ);
+ s = VARDATA_ANY(str);
+ slen = VARSIZE_ANY_EXHDR(str);
+ p = VARDATA_ANY(pat);
+ plen = VARSIZE_ANY_EXHDR(pat);
result = (SB_MatchText(s, slen, p, plen) != LIKE_TRUE);
nameiclike(PG_FUNCTION_ARGS)
{
Name str = PG_GETARG_NAME(0);
- text *pat = PG_GETARG_TEXT_P(1);
+ text *pat = PG_GETARG_TEXT_PP(1);
bool result;
text *strtext;
nameicnlike(PG_FUNCTION_ARGS)
{
Name str = PG_GETARG_NAME(0);
- text *pat = PG_GETARG_TEXT_P(1);
+ text *pat = PG_GETARG_TEXT_PP(1);
bool result;
text *strtext;
Datum
texticlike(PG_FUNCTION_ARGS)
{
- text *str = PG_GETARG_TEXT_P(0);
- text *pat = PG_GETARG_TEXT_P(1);
+ text *str = PG_GETARG_TEXT_PP(0);
+ text *pat = PG_GETARG_TEXT_PP(1);
bool result;
result = (Generic_Text_IC_like(str, pat) == LIKE_TRUE);
Datum
texticnlike(PG_FUNCTION_ARGS)
{
- text *str = PG_GETARG_TEXT_P(0);
- text *pat = PG_GETARG_TEXT_P(1);
+ text *str = PG_GETARG_TEXT_PP(0);
+ text *pat = PG_GETARG_TEXT_PP(1);
bool result;
result = (Generic_Text_IC_like(str, pat) != LIKE_TRUE);
Datum
like_escape(PG_FUNCTION_ARGS)
{
- text *pat = PG_GETARG_TEXT_P(0);
- text *esc = PG_GETARG_TEXT_P(1);
+ text *pat = PG_GETARG_TEXT_PP(0);
+ text *esc = PG_GETARG_TEXT_PP(1);
text *result;
if (pg_database_encoding_max_length() == 1)
Datum
like_escape_bytea(PG_FUNCTION_ARGS)
{
- bytea *pat = PG_GETARG_BYTEA_P(0);
- bytea *esc = PG_GETARG_BYTEA_P(1);
+ bytea *pat = PG_GETARG_BYTEA_PP(0);
+ bytea *esc = PG_GETARG_BYTEA_PP(1);
bytea *result = SB_do_like_escape((text *)pat, (text *)esc);
PG_RETURN_BYTEA_P((bytea *)result);
* Copyright (c) 1996-2007, PostgreSQL Global Development Group
*
* 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 $
*
*-------------------------------------------------------------------------
*/
elen;
bool afterescape;
- p = VARDATA(pat);
- plen = (VARSIZE(pat) - VARHDRSZ);
- e = VARDATA(esc);
- elen = (VARSIZE(esc) - VARHDRSZ);
+ p = VARDATA_ANY(pat);
+ plen = VARSIZE_ANY_EXHDR(pat);
+ e = VARDATA_ANY(esc);
+ elen = VARSIZE_ANY_EXHDR(esc);
/*
* Worst-case pattern growth is 2x --- unlikely, but it's hardly worth
errmsg("invalid escape string"),
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 (*e == '\\')
{
- memcpy(result, pat, VARSIZE(pat));
+ memcpy(result, pat, VARSIZE_ANY(pat));
return result;
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/oracle_compat.c,v 1.71 2007/09/18 17:41:17 adunstan Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/oracle_compat.c,v 1.72 2007/09/21 22:52:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
static wchar_t *
texttowcs(const text *txt)
{
- int nbytes = VARSIZE(txt) - VARHDRSZ;
+ int nbytes = VARSIZE_ANY_EXHDR(txt);
char *workstr;
wchar_t *result;
size_t ncodes;
/* Need a null-terminated version of the input */
workstr = (char *) palloc(nbytes + 1);
- memcpy(workstr, VARDATA(txt), nbytes);
+ memcpy(workstr, VARDATA_ANY(txt), nbytes);
workstr[nbytes] = '\0';
/* Output workspace cannot have more codes than input bytes */
static wchar_t *
win32_utf8_texttowcs(const text *txt)
{
- int nbytes = VARSIZE(txt) - VARHDRSZ;
+ int nbytes = VARSIZE_ANY_EXHDR(txt);
wchar_t *result;
int r;
else
{
/* Do the conversion */
- r = MultiByteToWideChar(CP_UTF8, 0, VARDATA(txt), nbytes,
+ r = MultiByteToWideChar(CP_UTF8, 0, VARDATA_ANY(txt), nbytes,
result, nbytes);
if (!r) /* assume it's NO_UNICODE_TRANSLATION */
{
/* see notes above about error reporting */
- pg_verifymbstr(VARDATA(txt), nbytes, false);
+ pg_verifymbstr(VARDATA_ANY(txt), nbytes, false);
ereport(ERROR,
(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
errmsg("invalid multibyte character for locale"),
out_text = wcstotext(workspace, i);
- nbytes = VARSIZE(out_text) - VARHDRSZ;
+ nbytes = VARSIZE(out_text) - VARHDRSZ;
result = palloc(nbytes + 1);
memcpy(result, VARDATA(out_text), nbytes);
*/
if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
{
- text *string = PG_GETARG_TEXT_P(0);
+ text *string = PG_GETARG_TEXT_PP(0);
text *result;
wchar_t *workspace;
int i;
*/
if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
{
- text *string = PG_GETARG_TEXT_P(0);
+ text *string = PG_GETARG_TEXT_PP(0);
text *result;
wchar_t *workspace;
int i;
*/
if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
{
- text *string = PG_GETARG_TEXT_P(0);
+ text *string = PG_GETARG_TEXT_PP(0);
text *result;
wchar_t *workspace;
int wasalnum = 0;
Datum
lpad(PG_FUNCTION_ARGS)
{
- text *string1 = PG_GETARG_TEXT_P(0);
+ text *string1 = PG_GETARG_TEXT_PP(0);
int32 len = PG_GETARG_INT32(1);
- text *string2 = PG_GETARG_TEXT_P(2);
+ text *string2 = PG_GETARG_TEXT_PP(2);
text *ret;
char *ptr1,
*ptr2,
+ *ptr2start,
*ptr2end,
*ptr_ret;
int m,
if (len < 0)
len = 0;
- s1len = VARSIZE(string1) - VARHDRSZ;
+ s1len = VARSIZE_ANY_EXHDR(string1);
if (s1len < 0)
s1len = 0; /* shouldn't happen */
- s2len = VARSIZE(string2) - VARHDRSZ;
+ s2len = VARSIZE_ANY_EXHDR(string2);
if (s2len < 0)
s2len = 0; /* shouldn't happen */
- s1len = pg_mbstrlen_with_len(VARDATA(string1), s1len);
+ s1len = pg_mbstrlen_with_len(VARDATA_ANY(string1), s1len);
if (s1len > len)
s1len = len; /* truncate string1 to len chars */
m = len - s1len;
- ptr2 = VARDATA(string2);
+ ptr2 = ptr2start = VARDATA_ANY(string2);
ptr2end = ptr2 + s2len;
ptr_ret = VARDATA(ret);
ptr_ret += mlen;
ptr2 += mlen;
if (ptr2 == ptr2end) /* wrap around at end of s2 */
- ptr2 = VARDATA(string2);
+ ptr2 = ptr2start;
}
- ptr1 = VARDATA(string1);
+ ptr1 = VARDATA_ANY(string1);
while (s1len--)
{
Datum
rpad(PG_FUNCTION_ARGS)
{
- text *string1 = PG_GETARG_TEXT_P(0);
+ text *string1 = PG_GETARG_TEXT_PP(0);
int32 len = PG_GETARG_INT32(1);
- text *string2 = PG_GETARG_TEXT_P(2);
+ text *string2 = PG_GETARG_TEXT_PP(2);
text *ret;
char *ptr1,
*ptr2,
+ *ptr2start,
*ptr2end,
*ptr_ret;
int m,
if (len < 0)
len = 0;
- s1len = VARSIZE(string1) - VARHDRSZ;
+ s1len = VARSIZE_ANY_EXHDR(string1);
if (s1len < 0)
s1len = 0; /* shouldn't happen */
- s2len = VARSIZE(string2) - VARHDRSZ;
+ s2len = VARSIZE_ANY_EXHDR(string2);
if (s2len < 0)
s2len = 0; /* shouldn't happen */
- s1len = pg_mbstrlen_with_len(VARDATA(string1), s1len);
+ s1len = pg_mbstrlen_with_len(VARDATA_ANY(string1), s1len);
if (s1len > len)
s1len = len; /* truncate string1 to len chars */
ret = (text *) palloc(VARHDRSZ + bytelen);
m = len - s1len;
- ptr1 = VARDATA(string1);
+ ptr1 = VARDATA_ANY(string1);
ptr_ret = VARDATA(ret);
while (s1len--)
ptr1 += mlen;
}
- ptr2 = VARDATA(string2);
+ ptr2 = ptr2start = VARDATA_ANY(string2);
ptr2end = ptr2 + s2len;
while (m--)
ptr_ret += mlen;
ptr2 += mlen;
if (ptr2 == ptr2end) /* wrap around at end of s2 */
- ptr2 = VARDATA(string2);
+ ptr2 = ptr2start;
}
SET_VARSIZE(ret, ptr_ret - (char *) ret);
Datum
btrim(PG_FUNCTION_ARGS)
{
- text *string = PG_GETARG_TEXT_P(0);
- text *set = PG_GETARG_TEXT_P(1);
+ text *string = PG_GETARG_TEXT_PP(0);
+ text *set = PG_GETARG_TEXT_PP(1);
text *ret;
- ret = dotrim(VARDATA(string), VARSIZE(string) - VARHDRSZ,
- VARDATA(set), VARSIZE(set) - VARHDRSZ,
+ ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
+ VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set),
true, true);
PG_RETURN_TEXT_P(ret);
Datum
btrim1(PG_FUNCTION_ARGS)
{
- text *string = PG_GETARG_TEXT_P(0);
+ text *string = PG_GETARG_TEXT_PP(0);
text *ret;
- ret = dotrim(VARDATA(string), VARSIZE(string) - VARHDRSZ,
+ ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
" ", 1,
true, true);
Datum
byteatrim(PG_FUNCTION_ARGS)
{
- bytea *string = PG_GETARG_BYTEA_P(0);
- bytea *set = PG_GETARG_BYTEA_P(1);
+ bytea *string = PG_GETARG_BYTEA_PP(0);
+ bytea *set = PG_GETARG_BYTEA_PP(1);
bytea *ret;
char *ptr,
*end,
*ptr2,
+ *ptr2start,
*end2;
- int m;
+ int m,
+ stringlen,
+ setlen;
- if ((m = VARSIZE(string) - VARHDRSZ) <= 0 ||
- (VARSIZE(set) - VARHDRSZ) <= 0)
+ stringlen = VARSIZE_ANY_EXHDR(string);
+ setlen = VARSIZE_ANY_EXHDR(set);
+
+ if (stringlen <= 0 || setlen <= 0)
PG_RETURN_BYTEA_P(string);
- ptr = VARDATA(string);
- end = VARDATA(string) + VARSIZE(string) - VARHDRSZ - 1;
- end2 = VARDATA(set) + VARSIZE(set) - VARHDRSZ - 1;
+ m = stringlen;
+ ptr = VARDATA_ANY(string);
+ end = ptr + stringlen - 1;
+ ptr2start = VARDATA_ANY(set);
+ end2 = ptr2start + setlen - 1;
while (m > 0)
{
- ptr2 = VARDATA(set);
+ ptr2 = ptr2start;
while (ptr2 <= end2)
{
if (*ptr == *ptr2)
while (m > 0)
{
- ptr2 = VARDATA(set);
+ ptr2 = ptr2start;
while (ptr2 <= end2)
{
if (*end == *ptr2)
Datum
ltrim(PG_FUNCTION_ARGS)
{
- text *string = PG_GETARG_TEXT_P(0);
- text *set = PG_GETARG_TEXT_P(1);
+ text *string = PG_GETARG_TEXT_PP(0);
+ text *set = PG_GETARG_TEXT_PP(1);
text *ret;
- ret = dotrim(VARDATA(string), VARSIZE(string) - VARHDRSZ,
- VARDATA(set), VARSIZE(set) - VARHDRSZ,
+ ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
+ VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set),
true, false);
PG_RETURN_TEXT_P(ret);
Datum
ltrim1(PG_FUNCTION_ARGS)
{
- text *string = PG_GETARG_TEXT_P(0);
+ text *string = PG_GETARG_TEXT_PP(0);
text *ret;
- ret = dotrim(VARDATA(string), VARSIZE(string) - VARHDRSZ,
+ ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
" ", 1,
true, false);
Datum
rtrim(PG_FUNCTION_ARGS)
{
- text *string = PG_GETARG_TEXT_P(0);
- text *set = PG_GETARG_TEXT_P(1);
+ text *string = PG_GETARG_TEXT_PP(0);
+ text *set = PG_GETARG_TEXT_PP(1);
text *ret;
- ret = dotrim(VARDATA(string), VARSIZE(string) - VARHDRSZ,
- VARDATA(set), VARSIZE(set) - VARHDRSZ,
+ ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
+ VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set),
false, true);
PG_RETURN_TEXT_P(ret);
Datum
rtrim1(PG_FUNCTION_ARGS)
{
- text *string = PG_GETARG_TEXT_P(0);
+ text *string = PG_GETARG_TEXT_PP(0);
text *ret;
- ret = dotrim(VARDATA(string), VARSIZE(string) - VARHDRSZ,
+ ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),
" ", 1,
false, true);
Datum
translate(PG_FUNCTION_ARGS)
{
- text *string = PG_GETARG_TEXT_P(0);
- text *from = PG_GETARG_TEXT_P(1);
- text *to = PG_GETARG_TEXT_P(2);
+ text *string = PG_GETARG_TEXT_PP(0);
+ text *from = PG_GETARG_TEXT_PP(1);
+ text *to = PG_GETARG_TEXT_PP(2);
text *result;
char *from_ptr,
*to_ptr;
int source_len;
int from_index;
- if ((m = VARSIZE(string) - VARHDRSZ) <= 0)
+ m = VARSIZE_ANY_EXHDR(string);
+
+ if (m <= 0)
PG_RETURN_TEXT_P(string);
- fromlen = VARSIZE(from) - VARHDRSZ;
- from_ptr = VARDATA(from);
- tolen = VARSIZE(to) - VARHDRSZ;
- to_ptr = VARDATA(to);
+ fromlen = VARSIZE_ANY_EXHDR(from);
+ from_ptr = VARDATA_ANY(from);
+ tolen = VARSIZE_ANY_EXHDR(to);
+ to_ptr = VARDATA_ANY(to);
+
+ str_len = VARSIZE_ANY_EXHDR(string);
+ source = VARDATA_ANY(string);
- str_len = VARSIZE(string);
estimate_len = (tolen * 1.0 / fromlen + 0.5) * str_len;
estimate_len = estimate_len > str_len ? estimate_len : str_len;
- result = (text *) palloc(estimate_len);
- source = VARDATA(string);
+ result = (text *) palloc(estimate_len + VARHDRSZ);
target = VARDATA(result);
retlen = 0;
Datum
ascii(PG_FUNCTION_ARGS)
{
- text *string = PG_GETARG_TEXT_P(0);
+ text *string = PG_GETARG_TEXT_PP(0);
int encoding = GetDatabaseEncoding();
unsigned char *data;
- if (VARSIZE(string) <= VARHDRSZ)
+ if (VARSIZE_ANY_EXHDR(string) <= 0)
PG_RETURN_INT32(0);
- data = (unsigned char *) VARDATA(string);
+ data = (unsigned char *) VARDATA_ANY(string);
if (encoding == PG_UTF8 && *data > 127)
{
Datum
repeat(PG_FUNCTION_ARGS)
{
- text *string = PG_GETARG_TEXT_P(0);
+ text *string = PG_GETARG_TEXT_PP(0);
int32 count = PG_GETARG_INT32(1);
text *result;
int slen,
tlen;
int i;
- char *cp;
+ char *cp,
+ *sp;
if (count < 0)
count = 0;
- slen = (VARSIZE(string) - VARHDRSZ);
- tlen = (VARHDRSZ + (count * slen));
+ slen = VARSIZE_ANY_EXHDR(string);
+ tlen = VARHDRSZ + (count * slen);
/* Check for integer overflow */
if (slen != 0 && count != 0)
SET_VARSIZE(result, tlen);
cp = VARDATA(result);
+ sp = VARDATA_ANY(string);
for (i = 0; i < count; i++)
{
- memcpy(cp, VARDATA(string), slen);
+ memcpy(cp, sp, slen);
cp += slen;
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/regexp.c,v 1.73 2007/08/11 19:16:41 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/regexp.c,v 1.74 2007/09/21 22:52:52 tgl Exp $
*
* Alistair Crooks added the code for the regex caching
* agc - cached the regular expressions used - there's a good chance
#include "utils/builtins.h"
#include "utils/guc.h"
-#define PG_GETARG_TEXT_P_IF_EXISTS(_n) \
- (PG_NARGS() > (_n) ? PG_GETARG_TEXT_P(_n) : NULL)
+#define PG_GETARG_TEXT_PP_IF_EXISTS(_n) \
+ (PG_NARGS() > (_n) ? PG_GETARG_TEXT_PP(_n) : NULL)
/* GUC-settable flavor parameter */
/* this structure describes one cached regular expression */
typedef struct cached_re_str
{
- text *cre_pat; /* original RE (untoasted TEXT form) */
+ char *cre_pat; /* original RE (not null terminated!) */
+ int cre_pat_len; /* length of original RE, in bytes */
int cre_flags; /* compile flags: extended,icase etc */
regex_t cre_re; /* the compiled regular expression */
} cached_re_str;
*
* Returns regex_t *
*
- * text_re --- the pattern, expressed as an *untoasted* TEXT object
+ * text_re --- the pattern, expressed as a TEXT object
* cflags --- compile options for the pattern
*
* Pattern is given in the database encoding. We internally convert to
static regex_t *
RE_compile_and_cache(text *text_re, int cflags)
{
- int text_re_len = VARSIZE(text_re);
+ int text_re_len = VARSIZE_ANY_EXHDR(text_re);
+ char *text_re_val = VARDATA_ANY(text_re);
pg_wchar *pattern;
int pattern_len;
int i;
*/
for (i = 0; i < num_res; i++)
{
- if (VARSIZE(re_array[i].cre_pat) == text_re_len &&
- memcmp(re_array[i].cre_pat, text_re, text_re_len) == 0 &&
- re_array[i].cre_flags == cflags)
+ if (re_array[i].cre_pat_len == text_re_len &&
+ re_array[i].cre_flags == cflags &&
+ memcmp(re_array[i].cre_pat, text_re_val, text_re_len) == 0)
{
/*
* Found a match; move it to front if not there already.
*/
/* Convert pattern string to wide characters */
- pattern = (pg_wchar *) palloc((text_re_len - VARHDRSZ + 1) * sizeof(pg_wchar));
- pattern_len = pg_mb2wchar_with_len(VARDATA(text_re),
+ pattern = (pg_wchar *) palloc((text_re_len + 1) * sizeof(pg_wchar));
+ pattern_len = pg_mb2wchar_with_len(text_re_val,
pattern,
- text_re_len - VARHDRSZ);
+ text_re_len);
regcomp_result = pg_regcomp(&re_temp.cre_re,
pattern,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
}
- memcpy(re_temp.cre_pat, text_re, text_re_len);
+ memcpy(re_temp.cre_pat, text_re_val, text_re_len);
+ re_temp.cre_pat_len = text_re_len;
re_temp.cre_flags = cflags;
/*
*
* Returns TRUE on match, FALSE on no match
*
- * text_re --- the pattern, expressed as an *untoasted* TEXT object
+ * text_re --- the pattern, expressed as a TEXT object
* dat --- the data to match against (need not be null-terminated)
* dat_len --- the length of the data string
* cflags --- compile options for the pattern
* parse_re_flags - parse the options argument of regexp_matches and friends
*
* flags --- output argument, filled with desired options
- * opts --- *untoasted* TEXT object, or NULL for defaults
+ * opts --- TEXT object, or NULL for defaults
*
* This accepts all the options allowed by any of the callers; callers that
* don't want some have to reject them after the fact.
if (opts)
{
- char *opt_p = VARDATA(opts);
- int opt_len = VARSIZE(opts) - VARHDRSZ;
+ char *opt_p = VARDATA_ANY(opts);
+ int opt_len = VARSIZE_ANY_EXHDR(opts);
int i;
for (i = 0; i < opt_len; i++)
nameregexeq(PG_FUNCTION_ARGS)
{
Name n = PG_GETARG_NAME(0);
- text *p = PG_GETARG_TEXT_P(1);
+ text *p = PG_GETARG_TEXT_PP(1);
PG_RETURN_BOOL(RE_compile_and_execute(p,
NameStr(*n),
nameregexne(PG_FUNCTION_ARGS)
{
Name n = PG_GETARG_NAME(0);
- text *p = PG_GETARG_TEXT_P(1);
+ text *p = PG_GETARG_TEXT_PP(1);
PG_RETURN_BOOL(!RE_compile_and_execute(p,
NameStr(*n),
Datum
textregexeq(PG_FUNCTION_ARGS)
{
- text *s = PG_GETARG_TEXT_P(0);
- text *p = PG_GETARG_TEXT_P(1);
+ text *s = PG_GETARG_TEXT_PP(0);
+ text *p = PG_GETARG_TEXT_PP(1);
PG_RETURN_BOOL(RE_compile_and_execute(p,
- VARDATA(s),
- VARSIZE(s) - VARHDRSZ,
+ VARDATA_ANY(s),
+ VARSIZE_ANY_EXHDR(s),
regex_flavor,
0, NULL));
}
Datum
textregexne(PG_FUNCTION_ARGS)
{
- text *s = PG_GETARG_TEXT_P(0);
- text *p = PG_GETARG_TEXT_P(1);
+ text *s = PG_GETARG_TEXT_PP(0);
+ text *p = PG_GETARG_TEXT_PP(1);
PG_RETURN_BOOL(!RE_compile_and_execute(p,
- VARDATA(s),
- VARSIZE(s) - VARHDRSZ,
+ VARDATA_ANY(s),
+ VARSIZE_ANY_EXHDR(s),
regex_flavor,
0, NULL));
}
nameicregexeq(PG_FUNCTION_ARGS)
{
Name n = PG_GETARG_NAME(0);
- text *p = PG_GETARG_TEXT_P(1);
+ text *p = PG_GETARG_TEXT_PP(1);
PG_RETURN_BOOL(RE_compile_and_execute(p,
NameStr(*n),
nameicregexne(PG_FUNCTION_ARGS)
{
Name n = PG_GETARG_NAME(0);
- text *p = PG_GETARG_TEXT_P(1);
+ text *p = PG_GETARG_TEXT_PP(1);
PG_RETURN_BOOL(!RE_compile_and_execute(p,
NameStr(*n),
Datum
texticregexeq(PG_FUNCTION_ARGS)
{
- text *s = PG_GETARG_TEXT_P(0);
- text *p = PG_GETARG_TEXT_P(1);
+ text *s = PG_GETARG_TEXT_PP(0);
+ text *p = PG_GETARG_TEXT_PP(1);
PG_RETURN_BOOL(RE_compile_and_execute(p,
- VARDATA(s),
- VARSIZE(s) - VARHDRSZ,
+ VARDATA_ANY(s),
+ VARSIZE_ANY_EXHDR(s),
regex_flavor | REG_ICASE,
0, NULL));
}
Datum
texticregexne(PG_FUNCTION_ARGS)
{
- text *s = PG_GETARG_TEXT_P(0);
- text *p = PG_GETARG_TEXT_P(1);
+ text *s = PG_GETARG_TEXT_PP(0);
+ text *p = PG_GETARG_TEXT_PP(1);
PG_RETURN_BOOL(!RE_compile_and_execute(p,
- VARDATA(s),
- VARSIZE(s) - VARHDRSZ,
+ VARDATA_ANY(s),
+ VARSIZE_ANY_EXHDR(s),
regex_flavor | REG_ICASE,
0, NULL));
}
Datum
textregexsubstr(PG_FUNCTION_ARGS)
{
- text *s = PG_GETARG_TEXT_P(0);
- text *p = PG_GETARG_TEXT_P(1);
+ text *s = PG_GETARG_TEXT_PP(0);
+ text *p = PG_GETARG_TEXT_PP(1);
bool match;
regmatch_t pmatch[2];
* return what the whole regexp matched.
*/
match = RE_compile_and_execute(p,
- VARDATA(s),
- VARSIZE(s) - VARHDRSZ,
+ VARDATA_ANY(s),
+ VARSIZE_ANY_EXHDR(s),
regex_flavor,
2, pmatch);
Datum
textregexreplace_noopt(PG_FUNCTION_ARGS)
{
- text *s = PG_GETARG_TEXT_P(0);
- text *p = PG_GETARG_TEXT_P(1);
- text *r = PG_GETARG_TEXT_P(2);
+ text *s = PG_GETARG_TEXT_PP(0);
+ text *p = PG_GETARG_TEXT_PP(1);
+ text *r = PG_GETARG_TEXT_PP(2);
regex_t *re;
re = RE_compile_and_cache(p, regex_flavor);
Datum
textregexreplace(PG_FUNCTION_ARGS)
{
- text *s = PG_GETARG_TEXT_P(0);
- text *p = PG_GETARG_TEXT_P(1);
- text *r = PG_GETARG_TEXT_P(2);
- text *opt = PG_GETARG_TEXT_P(3);
+ text *s = PG_GETARG_TEXT_PP(0);
+ text *p = PG_GETARG_TEXT_PP(1);
+ text *r = PG_GETARG_TEXT_PP(2);
+ text *opt = PG_GETARG_TEXT_PP(3);
regex_t *re;
pg_re_flags flags;
/* This function is not strict, so must test explicitly */
if (PG_ARGISNULL(0))
PG_RETURN_NULL();
- pat_text = PG_GETARG_TEXT_P(0);
- p = VARDATA(pat_text);
- plen = (VARSIZE(pat_text) - VARHDRSZ);
+ pat_text = PG_GETARG_TEXT_PP(0);
+ p = VARDATA_ANY(pat_text);
+ plen = VARSIZE_ANY_EXHDR(pat_text);
if (PG_ARGISNULL(1))
{
/* No ESCAPE clause provided; default to backslash as escape */
}
else
{
- esc_text = PG_GETARG_TEXT_P(1);
- e = VARDATA(esc_text);
- elen = (VARSIZE(esc_text) - VARHDRSZ);
+ esc_text = PG_GETARG_TEXT_PP(1);
+ e = VARDATA_ANY(esc_text);
+ elen = VARSIZE_ANY_EXHDR(esc_text);
if (elen == 0)
e = NULL; /* no escape character */
else if (elen != 1)
if (SRF_IS_FIRSTCALL())
{
- text *pattern = PG_GETARG_TEXT_P(1);
- text *flags = PG_GETARG_TEXT_P_IF_EXISTS(2);
+ text *pattern = PG_GETARG_TEXT_PP(1);
+ text *flags = PG_GETARG_TEXT_PP_IF_EXISTS(2);
MemoryContext oldcontext;
funcctx = SRF_FIRSTCALL_INIT();
matchctx->orig_str = orig_str;
/* convert string to pg_wchar form for matching */
- orig_len = VARSIZE(orig_str) - VARHDRSZ;
+ orig_len = VARSIZE_ANY_EXHDR(orig_str);
wide_str = (pg_wchar *) palloc(sizeof(pg_wchar) * (orig_len + 1));
- wide_len = pg_mb2wchar_with_len(VARDATA(orig_str), wide_str, orig_len);
+ wide_len = pg_mb2wchar_with_len(VARDATA_ANY(orig_str), wide_str, orig_len);
/* determine options */
parse_re_flags(&re_flags, flags);
if (SRF_IS_FIRSTCALL())
{
- text *pattern = PG_GETARG_TEXT_P(1);
- text *flags = PG_GETARG_TEXT_P_IF_EXISTS(2);
+ text *pattern = PG_GETARG_TEXT_PP(1);
+ text *flags = PG_GETARG_TEXT_PP_IF_EXISTS(2);
MemoryContext oldcontext;
funcctx = SRF_FIRSTCALL_INIT();
ArrayBuildState *astate = NULL;
regexp_matches_ctx *splitctx;
- splitctx = setup_regexp_matches(PG_GETARG_TEXT_P(0),
- PG_GETARG_TEXT_P(1),
- PG_GETARG_TEXT_P_IF_EXISTS(2),
+ splitctx = setup_regexp_matches(PG_GETARG_TEXT_PP(0),
+ PG_GETARG_TEXT_PP(1),
+ PG_GETARG_TEXT_PP_IF_EXISTS(2),
true, false, true);
while (splitctx->next_match <= splitctx->nmatches)
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* 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 $
*
*-------------------------------------------------------------------------
*/
#define PG_GETARG_RAW_VARLENA_P(n) ((struct varlena *) PG_GETARG_POINTER(n))
/* use this if you want the input datum de-toasted: */
#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: */
#define DatumGetByteaP(X) ((bytea *) PG_DETOAST_DATUM(X))
#define DatumGetByteaPP(X) ((bytea *) PG_DETOAST_DATUM_PACKED(X))