1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-09 17:03:00 +03:00

> Here's a revised patch. Changes:

>
> 1. Now outputs '\\' instead of '\134' when using encode(bytea, 'escape')
> Note that I ended up leaving \0 as \000 so that there are no ambiguities
> when decoding something like, for example, \0123.
>
> 2. Fixed bug in byteain which allowed input values which were not valid
> octals (e.g. \789), to be parsed as if they were octals.
>
> Joe
>

Here's rev 2 of the bytea string support patch. Changes:

1. Added missing declaration for MatchBytea function
2. Added PQescapeBytea to fe-exec.c
3. Applies cleanly on cvs tip from this afternoon

I'm hoping that someone can review/approve/apply this before beta starts, so
I guess I'd vote (not that it counts for much) to delay beta a few days :-)

Joe Conway
This commit is contained in:
Bruce Momjian
2001-09-14 17:46:40 +00:00
parent e8d5b8d290
commit c1fbf06654
11 changed files with 799 additions and 38 deletions

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.72 2001/09/11 05:18:59 ishii Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.73 2001/09/14 17:46:40 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,14 +53,28 @@ byteain(PG_FUNCTION_ARGS)
for (byte = 0, tp = inputText; *tp != '\0'; byte++)
{
if (*tp++ == '\\')
if (tp[0] != '\\')
{
if (*tp == '\\')
tp++;
else if (!isdigit((unsigned char) *tp++) ||
!isdigit((unsigned char) *tp++) ||
!isdigit((unsigned char) *tp++))
elog(ERROR, "Bad input string for type bytea");
tp++;
}
else if ( (tp[0] == '\\') &&
(tp[1] >= '0' && tp[1] <= '3') &&
(tp[2] >= '0' && tp[2] <= '7') &&
(tp[3] >= '0' && tp[3] <= '7') )
{
tp += 4;
}
else if ( (tp[0] == '\\') &&
(tp[1] == '\\') )
{
tp += 2;
}
else
{
/*
* one backslash, not followed by 0 or ### valid octal
*/
elog(ERROR, "Bad input string for type bytea");
}
}
@@ -72,15 +86,35 @@ byteain(PG_FUNCTION_ARGS)
rp = result->vl_dat;
while (*tp != '\0')
{
if (*tp != '\\' || *++tp == '\\')
if (tp[0] != '\\')
{
*rp++ = *tp++;
}
else if ( (tp[0] == '\\') &&
(tp[1] >= '0' && tp[1] <= '3') &&
(tp[2] >= '0' && tp[2] <= '7') &&
(tp[3] >= '0' && tp[3] <= '7') )
{
byte = VAL(tp[1]);
byte <<= 3;
byte += VAL(tp[2]);
byte <<= 3;
*rp++ = byte + VAL(tp[3]);
tp += 4;
}
else if ( (tp[0] == '\\') &&
(tp[1] == '\\') )
{
*rp++ = '\\';
tp += 2;
}
else
{
byte = VAL(*tp++);
byte <<= 3;
byte += VAL(*tp++);
byte <<= 3;
*rp++ = byte + VAL(*tp++);
/*
* We should never get here. The first pass should
* not allow it.
*/
elog(ERROR, "Bad input string for type bytea");
}
}
@@ -671,6 +705,147 @@ byteaoctetlen(PG_FUNCTION_ARGS)
PG_RETURN_INT32(VARSIZE(v) - VARHDRSZ);
}
/*
* byteacat -
* takes two bytea* and returns a bytea* that is the concatenation of
* the two.
*
* Cloned from textcat and modified as required.
*/
Datum
byteacat(PG_FUNCTION_ARGS)
{
bytea *t1 = PG_GETARG_BYTEA_P(0);
bytea *t2 = PG_GETARG_BYTEA_P(1);
int len1,
len2,
len;
bytea *result;
char *ptr;
len1 = (VARSIZE(t1) - VARHDRSZ);
if (len1 < 0)
len1 = 0;
len2 = (VARSIZE(t2) - VARHDRSZ);
if (len2 < 0)
len2 = 0;
len = len1 + len2 + VARHDRSZ;
result = (bytea *) palloc(len);
/* Set size of result string... */
VARATT_SIZEP(result) = len;
/* Fill data field of result string... */
ptr = VARDATA(result);
if (len1 > 0)
memcpy(ptr, VARDATA(t1), len1);
if (len2 > 0)
memcpy(ptr + len1, VARDATA(t2), len2);
PG_RETURN_BYTEA_P(result);
}
/*
* bytea_substr()
* Return a substring starting at the specified position.
* Cloned from text_substr and modified as required.
*
* Input:
* - string
* - starting position (is one-based)
* - string length
*
* If the starting position is zero or less, then return from the start of the string
* adjusting the length to be consistant with the "negative start" per SQL92.
* If the length is less than zero, return the remaining string.
*
*/
Datum
bytea_substr(PG_FUNCTION_ARGS)
{
bytea *string = PG_GETARG_BYTEA_P(0);
int32 m = PG_GETARG_INT32(1);
int32 n = PG_GETARG_INT32(2);
bytea *ret;
int len;
len = VARSIZE(string) - VARHDRSZ;
/* starting position after the end of the string? */
if (m > len)
{
m = 1;
n = 0;
}
/*
* starting position before the start of the string? then offset into
* the string per SQL92 spec...
*/
else if (m < 1)
{
n += (m - 1);
m = 1;
}
/* m will now become a zero-based starting position */
m--;
if (((m + n) > len) || (n < 0))
n = (len - m);
ret = (bytea *) palloc(VARHDRSZ + n);
VARATT_SIZEP(ret) = VARHDRSZ + n;
memcpy(VARDATA(ret), VARDATA(string) + m, n);
PG_RETURN_BYTEA_P(ret);
}
/*
* byteapos -
* Return the position of the specified substring.
* Implements the SQL92 POSITION() function.
* Cloned from textpos and modified as required.
*/
Datum
byteapos(PG_FUNCTION_ARGS)
{
bytea *t1 = PG_GETARG_BYTEA_P(0);
bytea *t2 = PG_GETARG_BYTEA_P(1);
int pos;
int px,
p;
int len1,
len2;
char *p1,
*p2;
if (VARSIZE(t2) <= VARHDRSZ)
PG_RETURN_INT32(1); /* result for empty pattern */
len1 = (VARSIZE(t1) - VARHDRSZ);
len2 = (VARSIZE(t2) - VARHDRSZ);
p1 = VARDATA(t1);
p2 = VARDATA(t2);
pos = 0;
px = (len1 - len2);
for (p = 0; p <= px; p++)
{
if ((*p2 == *p1) && (memcmp(p1, p2, len2) == 0))
{
pos = p + 1;
break;
};
p1++;
};
PG_RETURN_INT32(pos);
}
/*-------------------------------------------------------------
* byteaGetByte
*