1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* varchar.c
|
2000-06-05 09:29:25 +02:00
|
|
|
* Functions for the built-in types char(n) and varchar(n).
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2004-12-31 23:04:05 +01:00
|
|
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2005-04-12 06:26:34 +02:00
|
|
|
* $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.109 2005/04/12 04:26:26 tgl Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
2000-06-05 09:29:25 +02:00
|
|
|
|
2000-06-19 05:55:01 +02:00
|
|
|
#include "access/hash.h"
|
1999-05-03 21:10:48 +02:00
|
|
|
#include "catalog/pg_type.h"
|
2001-02-10 03:31:31 +01:00
|
|
|
#include "miscadmin.h"
|
2001-06-10 01:21:55 +02:00
|
|
|
#include "utils/array.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "utils/builtins.h"
|
2000-05-29 23:02:32 +02:00
|
|
|
#include "utils/fmgroids.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1999-07-17 18:25:28 +02:00
|
|
|
#include "mb/pg_wchar.h"
|
|
|
|
|
2000-04-12 19:17:23 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
|
|
|
* CHAR() and VARCHAR() types are part of the ANSI SQL standard. CHAR()
|
|
|
|
* is for blank-padded string whose length is specified in CREATE TABLE.
|
|
|
|
* VARCHAR is for storing string whose length is at most the length specified
|
|
|
|
* at CREATE TABLE time.
|
|
|
|
*
|
2000-06-05 09:29:25 +02:00
|
|
|
* It's hard to implement these types because we cannot figure out
|
2001-10-03 07:29:27 +02:00
|
|
|
* the length of the type from the type itself. I changed (hopefully all) the
|
1996-07-09 08:22:35 +02:00
|
|
|
* fmgr calls that invoke input functions of a data type to supply the
|
|
|
|
* length also. (eg. in INSERTs, we have the tupleDescriptor which contains
|
|
|
|
* the length of the attributes and hence the exact length of the char() or
|
|
|
|
* varchar(). We pass this to bpcharin() or varcharin().) In the case where
|
|
|
|
* we cannot determine the length, we pass in -1 instead and the input string
|
|
|
|
* must be null-terminated.
|
|
|
|
*
|
|
|
|
* We actually implement this as a varlena so that we don't have to pass in
|
2000-06-05 09:29:25 +02:00
|
|
|
* the length for the comparison functions. (The difference between these
|
|
|
|
* types and "text" is that we truncate and possibly blank-pad the string
|
|
|
|
* at insertion time.)
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* - ay 6/95
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* bpchar - char() *
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
/*
|
2001-05-21 18:54:46 +02:00
|
|
|
* Convert a C string to CHARACTER internal representation. atttypmod
|
|
|
|
* is the declared length of the type plus VARHDRSZ.
|
|
|
|
*
|
|
|
|
* If the C string is too long, raise an error, unless the extra
|
|
|
|
* characters are spaces, in which case they're truncated. (per SQL)
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2000-06-13 09:35:40 +02:00
|
|
|
Datum
|
|
|
|
bpcharin(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-13 09:35:40 +02:00
|
|
|
char *s = PG_GETARG_CSTRING(0);
|
2001-10-25 07:50:21 +02:00
|
|
|
|
2000-06-13 09:35:40 +02:00
|
|
|
#ifdef NOT_USED
|
|
|
|
Oid typelem = PG_GETARG_OID(1);
|
|
|
|
#endif
|
|
|
|
int32 atttypmod = PG_GETARG_INT32(2);
|
|
|
|
BpChar *result;
|
|
|
|
char *r;
|
2001-10-25 07:50:21 +02:00
|
|
|
size_t len,
|
|
|
|
maxlen;
|
1997-09-08 04:41:22 +02:00
|
|
|
int i;
|
2001-10-25 07:50:21 +02:00
|
|
|
int charlen; /* number of charcters in the input string */
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2003-07-27 06:53:12 +02:00
|
|
|
/* verify encoding */
|
2001-05-21 18:54:46 +02:00
|
|
|
len = strlen(s);
|
2003-07-27 06:53:12 +02:00
|
|
|
pg_verifymbstr(s, len, false);
|
2001-09-11 07:18:59 +02:00
|
|
|
|
2001-07-15 13:07:37 +02:00
|
|
|
charlen = pg_mbstrlen(s);
|
2002-08-29 09:22:30 +02:00
|
|
|
|
2001-06-01 19:49:17 +02:00
|
|
|
/* If typmod is -1 (or invalid), use the actual string length */
|
|
|
|
if (atttypmod < (int32) VARHDRSZ)
|
2001-07-15 13:07:37 +02:00
|
|
|
maxlen = charlen;
|
2001-06-01 19:49:17 +02:00
|
|
|
else
|
|
|
|
maxlen = atttypmod - VARHDRSZ;
|
|
|
|
|
2001-07-15 13:07:37 +02:00
|
|
|
if (charlen > maxlen)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2001-06-01 19:49:17 +02:00
|
|
|
/* Verify that extra characters are spaces, and clip them off */
|
2001-10-25 07:50:21 +02:00
|
|
|
size_t mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
|
|
|
|
|
2001-07-15 13:07:37 +02:00
|
|
|
/*
|
2001-10-25 07:50:21 +02:00
|
|
|
* at this point, len is the actual BYTE length of the input
|
|
|
|
* string, maxlen is the max number of CHARACTERS allowed for this
|
|
|
|
* bpchar type.
|
2001-07-15 13:07:37 +02:00
|
|
|
*/
|
2001-05-21 18:54:46 +02:00
|
|
|
if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
|
|
|
|
len = mbmaxlen;
|
2001-06-01 19:49:17 +02:00
|
|
|
else
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
2004-08-02 18:51:10 +02:00
|
|
|
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
2003-07-27 06:53:12 +02:00
|
|
|
errmsg("value too long for type character(%d)",
|
2003-08-04 02:43:34 +02:00
|
|
|
(int) maxlen)));
|
2001-10-25 07:50:21 +02:00
|
|
|
|
2001-07-15 13:07:37 +02:00
|
|
|
/*
|
2001-10-25 07:50:21 +02:00
|
|
|
* XXX: at this point, maxlen is the necessary byte length, not
|
|
|
|
* the number of CHARACTERS!
|
2001-07-15 13:07:37 +02:00
|
|
|
*/
|
|
|
|
maxlen = len;
|
2001-05-21 18:54:46 +02:00
|
|
|
}
|
2001-07-15 13:07:37 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
2001-10-25 07:50:21 +02:00
|
|
|
* XXX: at this point, maxlen is the necessary byte length, not
|
|
|
|
* the number of CHARACTERS!
|
2001-07-15 13:07:37 +02:00
|
|
|
*/
|
|
|
|
maxlen = len + (maxlen - charlen);
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
result = palloc(maxlen + VARHDRSZ);
|
|
|
|
VARATT_SIZEP(result) = maxlen + VARHDRSZ;
|
1998-01-07 19:47:07 +01:00
|
|
|
r = VARDATA(result);
|
2001-06-01 19:49:17 +02:00
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
*r++ = *s++;
|
1998-02-24 16:27:04 +01:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/* blank pad the string if necessary */
|
2001-05-21 18:54:46 +02:00
|
|
|
for (; i < maxlen; i++)
|
1997-09-07 07:04:48 +02:00
|
|
|
*r++ = ' ';
|
2000-06-13 09:35:40 +02:00
|
|
|
|
|
|
|
PG_RETURN_BPCHAR_P(result);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert a CHARACTER value to a C string.
|
|
|
|
*/
|
2000-06-13 09:35:40 +02:00
|
|
|
Datum
|
|
|
|
bpcharout(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-13 09:35:40 +02:00
|
|
|
BpChar *s = PG_GETARG_BPCHAR_P(0);
|
1997-09-08 04:41:22 +02:00
|
|
|
char *result;
|
|
|
|
int len;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-07-07 23:12:53 +02:00
|
|
|
/* copy and add null term */
|
2000-06-13 09:35:40 +02:00
|
|
|
len = VARSIZE(s) - VARHDRSZ;
|
|
|
|
result = (char *) palloc(len + 1);
|
2000-07-07 23:12:53 +02:00
|
|
|
memcpy(result, VARDATA(s), len);
|
|
|
|
result[len] = '\0';
|
1998-02-24 16:27:04 +01:00
|
|
|
|
2000-06-13 09:35:40 +02:00
|
|
|
PG_RETURN_CSTRING(result);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2003-05-13 01:08:52 +02:00
|
|
|
/*
|
|
|
|
* bpcharrecv - converts external binary format to bpchar
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bpcharrecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as textrecv, so share code */
|
|
|
|
return textrecv(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* bpcharsend - converts bpchar to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bpcharsend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as textsend, so share code */
|
|
|
|
return textsend(fcinfo);
|
|
|
|
}
|
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
|
|
|
|
/*
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* Converts a CHARACTER type to the specified size.
|
|
|
|
*
|
|
|
|
* maxlen is the typmod, ie, declared length plus VARHDRSZ bytes.
|
|
|
|
* isExplicit is true if this is for an explicit cast to char(N).
|
|
|
|
*
|
|
|
|
* Truncation rules: for an explicit cast, silently truncate to the given
|
|
|
|
* length; for an implicit cast, raise error unless extra characters are
|
2003-08-04 02:43:34 +02:00
|
|
|
* all spaces. (This is sort-of per SQL: the spec would actually have us
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* raise a "completion condition" for the explicit cast case, but Postgres
|
|
|
|
* hasn't got such a concept.)
|
1998-05-10 00:45:14 +02:00
|
|
|
*/
|
2000-06-13 09:35:40 +02:00
|
|
|
Datum
|
|
|
|
bpchar(PG_FUNCTION_ARGS)
|
1998-05-10 00:45:14 +02:00
|
|
|
{
|
2001-05-21 18:54:46 +02:00
|
|
|
BpChar *source = PG_GETARG_BPCHAR_P(0);
|
|
|
|
int32 maxlen = PG_GETARG_INT32(1);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
bool isExplicit = PG_GETARG_BOOL(2);
|
2000-06-13 09:35:40 +02:00
|
|
|
BpChar *result;
|
2001-05-21 18:54:46 +02:00
|
|
|
int32 len;
|
|
|
|
char *r;
|
|
|
|
char *s;
|
1998-05-10 00:45:14 +02:00
|
|
|
int i;
|
2001-10-25 07:50:21 +02:00
|
|
|
int charlen; /* number of charcters in the input string
|
|
|
|
* + VARHDRSZ */
|
2002-09-04 22:31:48 +02:00
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
len = VARSIZE(source);
|
2002-08-29 09:22:30 +02:00
|
|
|
|
2001-07-15 13:07:37 +02:00
|
|
|
charlen = pg_mbstrlen_with_len(VARDATA(source), len - VARHDRSZ) + VARHDRSZ;
|
2002-08-29 09:22:30 +02:00
|
|
|
|
2000-03-13 02:54:07 +01:00
|
|
|
/* No work if typmod is invalid or supplied data matches it already */
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
if (maxlen < (int32) VARHDRSZ || charlen == maxlen)
|
2001-05-21 18:54:46 +02:00
|
|
|
PG_RETURN_BPCHAR_P(source);
|
2002-08-29 09:22:30 +02:00
|
|
|
|
2001-07-15 13:07:37 +02:00
|
|
|
if (charlen > maxlen)
|
2001-05-21 18:54:46 +02:00
|
|
|
{
|
2001-06-01 19:49:17 +02:00
|
|
|
/* Verify that extra characters are spaces, and clip them off */
|
2001-05-21 18:54:46 +02:00
|
|
|
size_t maxmblen;
|
1998-05-10 00:45:14 +02:00
|
|
|
|
2001-07-15 13:07:37 +02:00
|
|
|
maxmblen = pg_mbcharcliplen(VARDATA(source), len - VARHDRSZ,
|
2001-10-25 07:50:21 +02:00
|
|
|
maxlen - VARHDRSZ) + VARHDRSZ;
|
1999-05-25 18:15:34 +02:00
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
if (!isExplicit)
|
|
|
|
{
|
|
|
|
for (i = maxmblen - VARHDRSZ; i < len - VARHDRSZ; i++)
|
|
|
|
if (*(VARDATA(source) + i) != ' ')
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
2004-08-29 07:07:03 +02:00
|
|
|
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
|
|
|
errmsg("value too long for type character(%d)",
|
|
|
|
maxlen - VARHDRSZ)));
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
}
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
len = maxmblen;
|
2001-10-25 07:50:21 +02:00
|
|
|
|
2001-07-15 13:07:37 +02:00
|
|
|
/*
|
|
|
|
* XXX: at this point, maxlen is the necessary byte
|
|
|
|
* length+VARHDRSZ, not the number of CHARACTERS!
|
|
|
|
*/
|
|
|
|
maxlen = len;
|
1998-05-10 00:45:14 +02:00
|
|
|
}
|
2001-07-15 13:07:37 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* XXX: at this point, maxlen is the necessary byte
|
|
|
|
* length+VARHDRSZ, not the number of CHARACTERS!
|
|
|
|
*/
|
|
|
|
maxlen = len + (maxlen - charlen);
|
|
|
|
}
|
1998-05-10 00:45:14 +02:00
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
s = VARDATA(source);
|
|
|
|
|
|
|
|
result = palloc(maxlen);
|
|
|
|
VARATT_SIZEP(result) = maxlen;
|
|
|
|
r = VARDATA(result);
|
|
|
|
|
2001-06-01 19:49:17 +02:00
|
|
|
for (i = 0; i < len - VARHDRSZ; i++)
|
2001-05-21 18:54:46 +02:00
|
|
|
*r++ = *s++;
|
1998-05-10 00:45:14 +02:00
|
|
|
|
|
|
|
/* blank pad the string if necessary */
|
2001-05-21 18:54:46 +02:00
|
|
|
for (; i < maxlen - VARHDRSZ; i++)
|
1998-05-10 00:45:14 +02:00
|
|
|
*r++ = ' ';
|
|
|
|
|
2000-06-13 09:35:40 +02:00
|
|
|
PG_RETURN_BPCHAR_P(result);
|
|
|
|
}
|
1998-05-10 00:45:14 +02:00
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
|
1998-05-10 00:45:14 +02:00
|
|
|
/* char_bpchar()
|
|
|
|
* Convert char to bpchar(1).
|
|
|
|
*/
|
2000-06-05 09:29:25 +02:00
|
|
|
Datum
|
|
|
|
char_bpchar(PG_FUNCTION_ARGS)
|
1998-05-10 00:45:14 +02:00
|
|
|
{
|
2000-06-05 09:29:25 +02:00
|
|
|
char c = PG_GETARG_CHAR(0);
|
2000-06-13 09:35:40 +02:00
|
|
|
BpChar *result;
|
1998-05-10 00:45:14 +02:00
|
|
|
|
2000-06-13 09:35:40 +02:00
|
|
|
result = (BpChar *) palloc(VARHDRSZ + 1);
|
1998-05-10 00:45:14 +02:00
|
|
|
|
2000-07-04 01:10:14 +02:00
|
|
|
VARATT_SIZEP(result) = VARHDRSZ + 1;
|
2000-06-05 09:29:25 +02:00
|
|
|
*(VARDATA(result)) = c;
|
1998-05-10 00:45:14 +02:00
|
|
|
|
2000-06-05 09:29:25 +02:00
|
|
|
PG_RETURN_BPCHAR_P(result);
|
|
|
|
}
|
1998-05-10 00:45:14 +02:00
|
|
|
|
|
|
|
|
1998-05-29 15:33:58 +02:00
|
|
|
/* bpchar_name()
|
|
|
|
* Converts a bpchar() type to a NameData type.
|
|
|
|
*/
|
2000-07-29 05:26:51 +02:00
|
|
|
Datum
|
|
|
|
bpchar_name(PG_FUNCTION_ARGS)
|
1998-05-29 15:33:58 +02:00
|
|
|
{
|
2000-07-29 05:26:51 +02:00
|
|
|
BpChar *s = PG_GETARG_BPCHAR_P(0);
|
|
|
|
Name result;
|
1998-05-29 15:33:58 +02:00
|
|
|
int len;
|
|
|
|
|
|
|
|
len = VARSIZE(s) - VARHDRSZ;
|
2000-07-29 05:26:51 +02:00
|
|
|
|
|
|
|
/* Truncate to max length for a Name */
|
2000-07-07 23:12:53 +02:00
|
|
|
if (len >= NAMEDATALEN)
|
2001-03-22 05:01:46 +01:00
|
|
|
len = NAMEDATALEN - 1;
|
1998-05-29 15:33:58 +02:00
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
/* Remove trailing blanks */
|
1998-09-01 06:40:42 +02:00
|
|
|
while (len > 0)
|
|
|
|
{
|
|
|
|
if (*(VARDATA(s) + len - 1) != ' ')
|
|
|
|
break;
|
1998-05-29 15:33:58 +02:00
|
|
|
len--;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = (NameData *) palloc(NAMEDATALEN);
|
2000-07-07 23:12:53 +02:00
|
|
|
memcpy(NameStr(*result), VARDATA(s), len);
|
1998-05-29 15:33:58 +02:00
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
/* Now null pad to full length... */
|
1998-09-01 06:40:42 +02:00
|
|
|
while (len < NAMEDATALEN)
|
|
|
|
{
|
1999-11-08 00:08:36 +01:00
|
|
|
*(NameStr(*result) + len) = '\0';
|
1998-05-29 15:33:58 +02:00
|
|
|
len++;
|
|
|
|
}
|
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
PG_RETURN_NAME(result);
|
|
|
|
}
|
1998-05-29 15:33:58 +02:00
|
|
|
|
|
|
|
/* name_bpchar()
|
|
|
|
* Converts a NameData type to a bpchar type.
|
|
|
|
*/
|
2000-07-29 05:26:51 +02:00
|
|
|
Datum
|
|
|
|
name_bpchar(PG_FUNCTION_ARGS)
|
1998-05-29 15:33:58 +02:00
|
|
|
{
|
2000-07-29 05:26:51 +02:00
|
|
|
Name s = PG_GETARG_NAME(0);
|
|
|
|
BpChar *result;
|
1998-05-29 15:33:58 +02:00
|
|
|
int len;
|
|
|
|
|
1999-11-08 00:08:36 +01:00
|
|
|
len = strlen(NameStr(*s));
|
2000-07-29 05:26:51 +02:00
|
|
|
result = (BpChar *) palloc(VARHDRSZ + len);
|
2000-07-07 23:12:53 +02:00
|
|
|
memcpy(VARDATA(result), NameStr(*s), len);
|
2000-07-04 01:10:14 +02:00
|
|
|
VARATT_SIZEP(result) = len + VARHDRSZ;
|
1998-05-29 15:33:58 +02:00
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
PG_RETURN_BPCHAR_P(result);
|
|
|
|
}
|
1998-05-29 15:33:58 +02:00
|
|
|
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*****************************************************************************
|
2003-05-26 02:11:29 +02:00
|
|
|
* varchar - varchar(n)
|
|
|
|
*
|
|
|
|
* Note: varchar piggybacks on type text for most operations, and so has no
|
|
|
|
* C-coded functions except for I/O and typmod checking.
|
1996-07-09 08:22:35 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
/*
|
2001-05-21 18:54:46 +02:00
|
|
|
* Convert a C string to VARCHAR internal representation. atttypmod
|
|
|
|
* is the declared length of the type plus VARHDRSZ.
|
|
|
|
*
|
2002-09-03 23:45:44 +02:00
|
|
|
* Note that atttypmod is regarded as the number of characters, which
|
|
|
|
* is not necessarily the same as the number of bytes.
|
2001-07-15 13:07:37 +02:00
|
|
|
*
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* If the C string is too long, raise an error, unless the extra characters
|
|
|
|
* are spaces, in which case they're truncated. (per SQL)
|
|
|
|
*/
|
2000-06-13 09:35:40 +02:00
|
|
|
Datum
|
|
|
|
varcharin(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-13 09:35:40 +02:00
|
|
|
char *s = PG_GETARG_CSTRING(0);
|
2001-10-25 07:50:21 +02:00
|
|
|
|
2000-06-13 09:35:40 +02:00
|
|
|
#ifdef NOT_USED
|
|
|
|
Oid typelem = PG_GETARG_OID(1);
|
|
|
|
#endif
|
|
|
|
int32 atttypmod = PG_GETARG_INT32(2);
|
2001-03-22 05:01:46 +01:00
|
|
|
VarChar *result;
|
2001-10-25 07:50:21 +02:00
|
|
|
size_t len,
|
|
|
|
maxlen;
|
|
|
|
|
2003-07-27 06:53:12 +02:00
|
|
|
/* verify encoding */
|
2001-05-21 18:54:46 +02:00
|
|
|
len = strlen(s);
|
2003-07-27 06:53:12 +02:00
|
|
|
pg_verifymbstr(s, len, false);
|
2002-08-29 09:22:30 +02:00
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
maxlen = atttypmod - VARHDRSZ;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
if (atttypmod >= (int32) VARHDRSZ && len > maxlen)
|
|
|
|
{
|
2001-06-01 19:49:17 +02:00
|
|
|
/* Verify that extra characters are spaces, and clip them off */
|
2001-10-25 07:50:21 +02:00
|
|
|
size_t mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
|
2001-05-21 18:54:46 +02:00
|
|
|
|
|
|
|
if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
|
|
|
|
len = mbmaxlen;
|
|
|
|
else
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
2004-08-02 18:51:10 +02:00
|
|
|
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
2003-08-04 02:43:34 +02:00
|
|
|
errmsg("value too long for type character varying(%d)",
|
|
|
|
(int) maxlen)));
|
2001-05-21 18:54:46 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
result = palloc(len + VARHDRSZ);
|
|
|
|
VARATT_SIZEP(result) = len + VARHDRSZ;
|
|
|
|
memcpy(VARDATA(result), s, len);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-06-13 09:35:40 +02:00
|
|
|
PG_RETURN_VARCHAR_P(result);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert a VARCHAR value to a C string.
|
|
|
|
*/
|
2000-06-13 09:35:40 +02:00
|
|
|
Datum
|
|
|
|
varcharout(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
VarChar *s = PG_GETARG_VARCHAR_P(0);
|
1997-09-08 04:41:22 +02:00
|
|
|
char *result;
|
2001-05-21 18:54:46 +02:00
|
|
|
int32 len;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-07-07 23:12:53 +02:00
|
|
|
/* copy and add null term */
|
2000-06-13 09:35:40 +02:00
|
|
|
len = VARSIZE(s) - VARHDRSZ;
|
2001-05-21 18:54:46 +02:00
|
|
|
result = palloc(len + 1);
|
2000-07-07 23:12:53 +02:00
|
|
|
memcpy(result, VARDATA(s), len);
|
|
|
|
result[len] = '\0';
|
1998-02-24 16:27:04 +01:00
|
|
|
|
2000-06-13 09:35:40 +02:00
|
|
|
PG_RETURN_CSTRING(result);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2003-05-13 01:08:52 +02:00
|
|
|
/*
|
|
|
|
* varcharrecv - converts external binary format to varchar
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
varcharrecv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as textrecv, so share code */
|
|
|
|
return textrecv(fcinfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* varcharsend - converts varchar to binary format
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
varcharsend(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
/* Exactly the same as textsend, so share code */
|
|
|
|
return textsend(fcinfo);
|
|
|
|
}
|
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
|
|
|
|
/*
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* Converts a VARCHAR type to the specified size.
|
|
|
|
*
|
|
|
|
* maxlen is the typmod, ie, declared length plus VARHDRSZ bytes.
|
|
|
|
* isExplicit is true if this is for an explicit cast to varchar(N).
|
|
|
|
*
|
|
|
|
* Truncation rules: for an explicit cast, silently truncate to the given
|
|
|
|
* length; for an implicit cast, raise error unless extra characters are
|
2003-08-04 02:43:34 +02:00
|
|
|
* all spaces. (This is sort-of per SQL: the spec would actually have us
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
* raise a "completion condition" for the explicit cast case, but Postgres
|
|
|
|
* hasn't got such a concept.)
|
1998-05-10 00:45:14 +02:00
|
|
|
*/
|
2000-06-13 09:35:40 +02:00
|
|
|
Datum
|
|
|
|
varchar(PG_FUNCTION_ARGS)
|
1998-05-10 00:45:14 +02:00
|
|
|
{
|
2001-05-21 18:54:46 +02:00
|
|
|
VarChar *source = PG_GETARG_VARCHAR_P(0);
|
|
|
|
int32 maxlen = PG_GETARG_INT32(1);
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
bool isExplicit = PG_GETARG_BOOL(2);
|
2001-03-22 05:01:46 +01:00
|
|
|
VarChar *result;
|
2001-05-21 18:54:46 +02:00
|
|
|
int32 len;
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
size_t maxmblen;
|
2001-05-21 18:54:46 +02:00
|
|
|
int i;
|
1998-05-10 00:45:14 +02:00
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
len = VARSIZE(source);
|
2001-06-01 19:49:17 +02:00
|
|
|
/* No work if typmod is invalid or supplied data fits it already */
|
2001-05-21 18:54:46 +02:00
|
|
|
if (maxlen < (int32) VARHDRSZ || len <= maxlen)
|
|
|
|
PG_RETURN_VARCHAR_P(source);
|
1998-05-10 00:45:14 +02:00
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
/* only reach here if string is too long... */
|
1998-05-10 00:45:14 +02:00
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
/* truncate multibyte string preserving multibyte boundary */
|
|
|
|
maxmblen = pg_mbcharcliplen(VARDATA(source), len - VARHDRSZ,
|
|
|
|
maxlen - VARHDRSZ);
|
2001-05-21 18:54:46 +02:00
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
if (!isExplicit)
|
|
|
|
{
|
|
|
|
for (i = maxmblen; i < len - VARHDRSZ; i++)
|
2001-05-21 18:54:46 +02:00
|
|
|
if (*(VARDATA(source) + i) != ' ')
|
2003-07-27 06:53:12 +02:00
|
|
|
ereport(ERROR,
|
2004-08-02 18:51:10 +02:00
|
|
|
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
2003-08-04 02:43:34 +02:00
|
|
|
errmsg("value too long for type character varying(%d)",
|
|
|
|
maxlen - VARHDRSZ)));
|
2001-05-21 18:54:46 +02:00
|
|
|
}
|
1998-05-10 00:45:14 +02:00
|
|
|
|
Extend pg_cast castimplicit column to a three-way value; this allows us
to be flexible about assignment casts without introducing ambiguity in
operator/function resolution. Introduce a well-defined promotion hierarchy
for numeric datatypes (int2->int4->int8->numeric->float4->float8).
Change make_const to initially label numeric literals as int4, int8, or
numeric (never float8 anymore).
Explicitly mark Func and RelabelType nodes to indicate whether they came
from a function call, explicit cast, or implicit cast; use this to do
reverse-listing more accurately and without so many heuristics.
Explicit casts to char, varchar, bit, varbit will truncate or pad without
raising an error (the pre-7.2 behavior), while assigning to a column without
any explicit cast will still raise an error for wrong-length data like 7.3.
This more nearly follows the SQL spec than 7.2 behavior (we should be
reporting a 'completion condition' in the explicit-cast cases, but we have
no mechanism for that, so just do silent truncation).
Fix some problems with enforcement of typmod for array elements;
it didn't work at all in 'UPDATE ... SET array[n] = foo', for example.
Provide a generalized array_length_coerce() function to replace the
specialized per-array-type functions that used to be needed (and were
missing for NUMERIC as well as all the datetime types).
Add missing conversions int8<->float4, text<->numeric, oid<->int8.
initdb forced.
2002-09-18 23:35:25 +02:00
|
|
|
len = maxmblen + VARHDRSZ;
|
2001-05-21 18:54:46 +02:00
|
|
|
result = palloc(len);
|
|
|
|
VARATT_SIZEP(result) = len;
|
|
|
|
memcpy(VARDATA(result), VARDATA(source), len - VARHDRSZ);
|
1998-05-10 00:45:14 +02:00
|
|
|
|
2000-06-13 09:35:40 +02:00
|
|
|
PG_RETURN_VARCHAR_P(result);
|
|
|
|
}
|
1998-05-10 00:45:14 +02:00
|
|
|
|
2001-05-21 18:54:46 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Exported functions
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
/* "True" length (not counting trailing blanks) of a BpChar */
|
1996-07-09 08:22:35 +02:00
|
|
|
static int
|
2000-07-29 05:26:51 +02:00
|
|
|
bcTruelen(BpChar *arg)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-01-07 19:47:07 +01:00
|
|
|
char *s = VARDATA(arg);
|
1997-09-08 04:41:22 +02:00
|
|
|
int i;
|
|
|
|
int len;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-01-07 19:47:07 +01:00
|
|
|
len = VARSIZE(arg) - VARHDRSZ;
|
1997-09-07 07:04:48 +02:00
|
|
|
for (i = len - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
if (s[i] != ' ')
|
|
|
|
break;
|
|
|
|
}
|
1998-09-01 05:29:17 +02:00
|
|
|
return i + 1;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
Datum
|
|
|
|
bpcharlen(PG_FUNCTION_ARGS)
|
1998-04-27 19:10:50 +02:00
|
|
|
{
|
2000-07-29 05:26:51 +02:00
|
|
|
BpChar *arg = PG_GETARG_BPCHAR_P(0);
|
2004-02-01 07:27:48 +01:00
|
|
|
int len;
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2004-02-01 07:27:48 +01:00
|
|
|
/* get number of bytes, ignoring trailing spaces */
|
|
|
|
len = bcTruelen(arg);
|
2004-08-29 07:07:03 +02:00
|
|
|
|
2004-02-01 07:27:48 +01:00
|
|
|
/* in multibyte encoding, convert to number of characters */
|
|
|
|
if (pg_database_encoding_max_length() != 1)
|
|
|
|
len = pg_mbstrlen_with_len(VARDATA(arg), len);
|
2001-11-18 13:07:07 +01:00
|
|
|
|
2004-02-01 07:27:48 +01:00
|
|
|
PG_RETURN_INT32(len);
|
1998-04-27 19:10:50 +02:00
|
|
|
}
|
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
Datum
|
|
|
|
bpcharoctetlen(PG_FUNCTION_ARGS)
|
1997-12-16 16:59:11 +01:00
|
|
|
{
|
2000-07-29 05:26:51 +02:00
|
|
|
BpChar *arg = PG_GETARG_BPCHAR_P(0);
|
1997-12-16 16:59:11 +01:00
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
PG_RETURN_INT32(VARSIZE(arg) - VARHDRSZ);
|
1998-01-08 04:05:01 +01:00
|
|
|
}
|
1997-12-16 16:59:11 +01:00
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* Comparison Functions used for bpchar
|
|
|
|
*
|
|
|
|
* Note: btree indexes need these routines not to leak memory; therefore,
|
|
|
|
* be careful to free working copies of toasted datums. Most places don't
|
|
|
|
* need to be so careful.
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bpchareq(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-07-29 05:26:51 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_P(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_P(1);
|
1997-09-08 04:41:22 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
2000-07-29 05:26:51 +02:00
|
|
|
bool result;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2001-05-03 21:00:37 +02:00
|
|
|
/* fast path for different-length inputs */
|
1997-09-07 07:04:48 +02:00
|
|
|
if (len1 != len2)
|
2000-07-29 05:26:51 +02:00
|
|
|
result = false;
|
|
|
|
else
|
2001-05-03 21:00:37 +02:00
|
|
|
result = (varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2) == 0);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(result);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
Datum
|
|
|
|
bpcharne(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-07-29 05:26:51 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_P(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_P(1);
|
1997-09-08 04:41:22 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
2000-07-29 05:26:51 +02:00
|
|
|
bool result;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2001-05-03 21:00:37 +02:00
|
|
|
/* fast path for different-length inputs */
|
1997-09-07 07:04:48 +02:00
|
|
|
if (len1 != len2)
|
2000-07-29 05:26:51 +02:00
|
|
|
result = true;
|
|
|
|
else
|
2001-05-03 21:00:37 +02:00
|
|
|
result = (varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2) != 0);
|
2000-07-29 05:26:51 +02:00
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
PG_RETURN_BOOL(result);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
Datum
|
|
|
|
bpcharlt(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-07-29 05:26:51 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_P(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_P(1);
|
1997-09-08 04:41:22 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
|
|
|
int cmp;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
|
|
|
|
1998-06-16 08:42:02 +02:00
|
|
|
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
|
2000-07-29 05:26:51 +02:00
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(cmp < 0);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
Datum
|
|
|
|
bpcharle(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-07-29 05:26:51 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_P(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_P(1);
|
1997-09-08 04:41:22 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
|
|
|
int cmp;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
|
|
|
|
1998-06-16 08:42:02 +02:00
|
|
|
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
|
2000-07-29 05:26:51 +02:00
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(cmp <= 0);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
Datum
|
|
|
|
bpchargt(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-07-29 05:26:51 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_P(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_P(1);
|
1997-09-08 04:41:22 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
|
|
|
int cmp;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
|
|
|
|
1998-06-16 08:42:02 +02:00
|
|
|
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
|
2000-07-29 05:26:51 +02:00
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(cmp > 0);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
Datum
|
|
|
|
bpcharge(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-07-29 05:26:51 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_P(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_P(1);
|
1997-09-08 04:41:22 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
|
|
|
int cmp;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
|
|
|
|
1998-06-16 08:42:02 +02:00
|
|
|
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
|
2000-07-29 05:26:51 +02:00
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(cmp >= 0);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
Datum
|
|
|
|
bpcharcmp(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-07-29 05:26:51 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_P(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_P(1);
|
1997-09-08 04:41:22 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
|
|
|
int cmp;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
|
|
|
|
1998-06-16 08:42:02 +02:00
|
|
|
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
|
2000-07-29 05:26:51 +02:00
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(cmp);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
2005-04-12 06:26:34 +02:00
|
|
|
Datum
|
|
|
|
bpchar_larger(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_P(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_P(1);
|
|
|
|
int len1,
|
|
|
|
len2;
|
|
|
|
int cmp;
|
|
|
|
|
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
|
|
|
|
|
|
|
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
|
|
|
|
|
|
|
|
PG_RETURN_BPCHAR_P((cmp >= 0) ? arg1 : arg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bpchar_smaller(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_P(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_P(1);
|
|
|
|
int len1,
|
|
|
|
len2;
|
|
|
|
int cmp;
|
|
|
|
|
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
|
|
|
|
|
|
|
cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);
|
|
|
|
|
|
|
|
PG_RETURN_BPCHAR_P((cmp <= 0) ? arg1 : arg2);
|
|
|
|
}
|
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* bpchar needs a specialized hash function because we want to ignore
|
2003-05-26 02:11:29 +02:00
|
|
|
* trailing blanks in comparisons.
|
2003-06-23 00:04:55 +02:00
|
|
|
*
|
|
|
|
* XXX is there any need for locale-specific behavior here?
|
2000-07-29 05:26:51 +02:00
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
hashbpchar(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
BpChar *key = PG_GETARG_BPCHAR_P(0);
|
|
|
|
char *keydata;
|
|
|
|
int keylen;
|
2000-12-09 00:57:03 +01:00
|
|
|
Datum result;
|
2000-07-29 05:26:51 +02:00
|
|
|
|
|
|
|
keydata = VARDATA(key);
|
|
|
|
keylen = bcTruelen(key);
|
|
|
|
|
2002-03-09 18:35:37 +01:00
|
|
|
result = hash_any((unsigned char *) keydata, keylen);
|
2000-12-09 00:57:03 +01:00
|
|
|
|
|
|
|
/* Avoid leaking memory for toasted inputs */
|
|
|
|
PG_FREE_IF_COPY(key, 0);
|
|
|
|
|
|
|
|
return result;
|
2000-07-29 05:26:51 +02:00
|
|
|
}
|