diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index 5efda61bce47f6fe29cf3f81f223ac411862c0fd..f114f96cf7fc302e731ca14f3fd576cf000a3f94 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.123 2005/05/30 01:20:50 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.124 2005/07/04 18:56:44 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -48,16 +48,10 @@ typedef struct varlena unknown; text_length(PointerGetDatum(textp)) #define TEXTPOS(buf_text, from_sub_text) \ text_position(buf_text, from_sub_text, 1) -#define TEXTDUP(textp) \ - DatumGetTextPCopy(PointerGetDatum(textp)) #define LEFT(buf_text, from_sub_text) \ text_substring(PointerGetDatum(buf_text), \ 1, \ TEXTPOS(buf_text, from_sub_text) - 1, false) -#define RIGHT(buf_text, from_sub_text, from_sub_text_len) \ - text_substring(PointerGetDatum(buf_text), \ - TEXTPOS(buf_text, from_sub_text) + (from_sub_text_len), \ - -1, true) static int text_cmp(text *arg1, text *arg2); static int32 text_length(Datum str); @@ -67,6 +61,8 @@ static text *text_substring(Datum str, int32 length, bool length_not_specified); +static void appendStringInfoText(StringInfo str, const text *t); + /***************************************************************************** * USER I/O ROUTINES * @@ -1922,6 +1918,18 @@ byteacmp(PG_FUNCTION_ARGS) PG_RETURN_INT32(cmp); } +/* + * appendStringInfoText + * + * Append a text to str. + * Like appendStringInfoString(str, PG_TEXT_GET_STR(s)) but faster. + */ +static void +appendStringInfoText(StringInfo str, const text *t) +{ + appendBinaryStringInfo(str, VARDATA(t), VARSIZE(t) - VARHDRSZ); +} + /* * replace_text * replace all occurrences of 'old_sub_str' in 'orig_str' @@ -1938,36 +1946,45 @@ replace_text(PG_FUNCTION_ARGS) text *to_sub_text = PG_GETARG_TEXT_P(2); int src_text_len = TEXTLEN(src_text); int from_sub_text_len = TEXTLEN(from_sub_text); - char *to_sub_str = PG_TEXT_GET_STR(to_sub_text); text *left_text; text *right_text; text *buf_text; text *ret_text; int curr_posn; - StringInfo str = makeStringInfo(); + StringInfo str; if (src_text_len == 0 || from_sub_text_len == 0) PG_RETURN_TEXT_P(src_text); - buf_text = TEXTDUP(src_text); - curr_posn = TEXTPOS(buf_text, from_sub_text); + curr_posn = TEXTPOS(src_text, from_sub_text); + + /* When the from_sub_text is not found, there is nothing to do. */ + if (curr_posn == 0) + PG_RETURN_TEXT_P(src_text); + + str = makeStringInfo(); + buf_text = src_text; while (curr_posn > 0) { - left_text = LEFT(buf_text, from_sub_text); - right_text = RIGHT(buf_text, from_sub_text, from_sub_text_len); + left_text = text_substring(PointerGetDatum(buf_text), + 1, curr_posn - 1, false); + right_text = text_substring(PointerGetDatum(buf_text), + curr_posn + from_sub_text_len, -1, true); - appendStringInfoString(str, PG_TEXT_GET_STR(left_text)); - appendStringInfoString(str, to_sub_str); + appendStringInfoText(str, left_text); + appendStringInfoText(str, to_sub_text); - pfree(buf_text); + if (buf_text != src_text) + pfree(buf_text); pfree(left_text); buf_text = right_text; curr_posn = TEXTPOS(buf_text, from_sub_text); } - appendStringInfoString(str, PG_TEXT_GET_STR(buf_text)); - pfree(buf_text); + appendStringInfoText(str, buf_text); + if (buf_text != src_text) + pfree(buf_text); ret_text = PG_STR_GET_TEXT(str->data); pfree(str->data);