diff options
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/adt/varlena.c | 87 | ||||
-rw-r--r-- | src/backend/utils/fmgr/fmgr.c | 9 |
2 files changed, 53 insertions, 43 deletions
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c index 7e55bfa4ba1..b10ec7d6855 100644 --- a/src/backend/utils/adt/varlena.c +++ b/src/backend/utils/adt/varlena.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.78 2001/11/19 19:15:07 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.79 2002/03/05 05:33:19 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -332,49 +332,71 @@ textcat(PG_FUNCTION_ARGS) * Changed behavior if starting position is less than one to conform to SQL92 behavior. * Formerly returned the entire string; now returns a portion. * - Thomas Lockhart 1998-12-10 + * Now uses faster TOAST-slicing interface + * - John Gray 2002-02-22 */ Datum text_substr(PG_FUNCTION_ARGS) { - text *string = PG_GETARG_TEXT_P(0); + text *string; int32 m = PG_GETARG_INT32(1); int32 n = PG_GETARG_INT32(2); - text *ret; - int len; - + int32 sm; + int32 sn; + int eml = 1; #ifdef MULTIBYTE int i; + int len; + text *ret; char *p; -#endif - - len = VARSIZE(string) - VARHDRSZ; -#ifdef MULTIBYTE - len = pg_mbstrlen_with_len(VARDATA(string), len); -#endif - - /* starting position after the end of the string? */ - if (m > len) - { - m = 1; - n = 0; - } +#endif /* * starting position before the start of the string? then offset into * the string per SQL92 spec... */ - else if (m < 1) + if (m < 1) { n += (m - 1); m = 1; } + /* Check for m > octet length is made in TOAST access routine */ /* m will now become a zero-based starting position */ + sm = m - 1; + sn = n; + +#ifdef MULTIBYTE + eml = pg_database_encoding_max_length (); + + if (eml > 1) + { + sm = 0; + sn = (m + n) * eml + 3; /* +3 to avoid mb characters overhanging slice end */ + } +#endif + + string = PG_GETARG_TEXT_P_SLICE (0, sm, sn); + + if (eml == 1) + { + PG_RETURN_TEXT_P (string); + } +#ifndef MULTIBYTE + PG_RETURN_NULL(); /* notreached: suppress compiler warning */ +#endif +#ifdef MULTIBYTE + len = pg_mbstrlen_with_len (VARDATA (string), sn - 3); + + if (m > len) + { + m = 1; + n = 0; + } m--; if (((m + n) > len) || (n < 0)) n = (len - m); -#ifdef MULTIBYTE p = VARDATA(string); for (i = 0; i < m; i++) p += pg_mblen(p); @@ -382,7 +404,6 @@ text_substr(PG_FUNCTION_ARGS) for (i = 0; i < n; i++) p += pg_mblen(p); n = p - (VARDATA(string) + m); -#endif ret = (text *) palloc(VARHDRSZ + n); VARATT_SIZEP(ret) = VARHDRSZ + n; @@ -390,6 +411,7 @@ text_substr(PG_FUNCTION_ARGS) memcpy(VARDATA(ret), VARDATA(string) + m, n); PG_RETURN_TEXT_P(ret); +#endif } /* @@ -740,26 +762,14 @@ byteacat(PG_FUNCTION_ARGS) 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) + if (m < 1) { n += (m - 1); m = 1; @@ -767,15 +777,8 @@ bytea_substr(PG_FUNCTION_ARGS) /* 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); + PG_RETURN_BYTEA_P(PG_GETARG_BYTEA_P_SLICE (0, m, n)); } /* diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index 6fffd7bab8b..64988a2077b 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.57 2001/11/05 17:46:30 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.58 2002/03/05 05:33:20 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1520,3 +1520,10 @@ pg_detoast_datum_copy(struct varlena * datum) return result; } } + +struct varlena * +pg_detoast_datum_slice(struct varlena * datum, int32 first, int32 count) +{ + /* Only get the specified portion from the toast rel */ + return (struct varlena *) heap_tuple_untoast_attr_slice((varattrib *) datum, first, count); +} |