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
|
|
|
*
|
2022-01-08 01:04:57 +01:00
|
|
|
* Portions Copyright (c) 1996-2022, 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
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/utils/adt/varchar.c
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
2000-06-05 09:29:25 +02:00
|
|
|
|
2019-07-08 17:58:05 +02:00
|
|
|
#include "access/detoast.h"
|
2016-02-03 20:17:35 +01:00
|
|
|
#include "catalog/pg_collation.h"
|
Make type "name" collation-aware.
The "name" comparison operators now all support collations, making them
functionally equivalent to "text" comparisons, except for the different
physical representation of the datatype. They do, in fact, mostly share
the varstr_cmp and varstr_sortsupport infrastructure, which has been
slightly enlarged to handle the case.
To avoid changes in the default behavior of the datatype, set name's
typcollation to C_COLLATION_OID not DEFAULT_COLLATION_OID, so that
by default comparisons to a name value will continue to use strcmp
semantics. (This would have been the case for system catalog columns
anyway, because of commit 6b0faf723, but doing this makes it true for
user-created name columns as well. In particular, this avoids
locale-dependent changes in our regression test results.)
In consequence, tweak a couple of places that made assumptions about
collatable base types always having typcollation DEFAULT_COLLATION_OID.
I have not, however, attempted to relax the restriction that user-
defined collatable types must have that. Hence, "name" doesn't
behave quite like a user-defined type; it acts more like a domain
with COLLATE "C". (Conceivably, if we ever get rid of the need for
catalog name columns to be fixed-length, "name" could actually become
such a domain over text. But that'd be a pretty massive undertaking,
and I'm not volunteering.)
Discussion: https://postgr.es/m/15938.1544377821@sss.pgh.pa.us
2018-12-19 23:35:12 +01:00
|
|
|
#include "catalog/pg_type.h"
|
2020-02-27 04:55:41 +01:00
|
|
|
#include "common/hashfn.h"
|
2005-07-10 23:14:00 +02:00
|
|
|
#include "libpq/pqformat.h"
|
2019-11-12 04:00:16 +01:00
|
|
|
#include "mb/pg_wchar.h"
|
2011-06-22 04:15:24 +02:00
|
|
|
#include "nodes/nodeFuncs.h"
|
2019-02-10 00:08:48 +01:00
|
|
|
#include "nodes/supportnodes.h"
|
2006-12-30 22:21:56 +01:00
|
|
|
#include "utils/array.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "utils/builtins.h"
|
2019-03-22 12:09:32 +01:00
|
|
|
#include "utils/lsyscache.h"
|
|
|
|
#include "utils/pg_locale.h"
|
2017-01-21 02:29:53 +01:00
|
|
|
#include "utils/varlena.h"
|
2000-04-12 19:17:23 +02:00
|
|
|
|
2006-12-30 22:21:56 +01:00
|
|
|
/* common code for bpchartypmodin and varchartypmodin */
|
|
|
|
static int32
|
|
|
|
anychar_typmodin(ArrayType *ta, const char *typename)
|
|
|
|
{
|
|
|
|
int32 typmod;
|
|
|
|
int32 *tl;
|
|
|
|
int n;
|
|
|
|
|
2007-06-15 22:56:52 +02:00
|
|
|
tl = ArrayGetIntegerTypmods(ta, &n);
|
2006-12-30 22:21:56 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* we're not too tense about good error message here because grammar
|
|
|
|
* shouldn't allow wrong number of modifiers for CHAR
|
|
|
|
*/
|
|
|
|
if (n != 1)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("invalid type modifier")));
|
|
|
|
|
|
|
|
if (*tl < 1)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("length for type %s must be at least 1", typename)));
|
|
|
|
if (*tl > MaxAttrSize)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("length for type %s cannot exceed %d",
|
|
|
|
typename, MaxAttrSize)));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For largely historical reasons, the typmod is VARHDRSZ plus the number
|
|
|
|
* of characters; there is enough client-side code that knows about that
|
|
|
|
* that we'd better not change it.
|
|
|
|
*/
|
|
|
|
typmod = VARHDRSZ + *tl;
|
|
|
|
|
|
|
|
return typmod;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* common code for bpchartypmodout and varchartypmodout */
|
|
|
|
static char *
|
|
|
|
anychar_typmodout(int32 typmod)
|
|
|
|
{
|
|
|
|
char *res = (char *) palloc(64);
|
|
|
|
|
|
|
|
if (typmod > VARHDRSZ)
|
|
|
|
snprintf(res, 64, "(%d)", (int) (typmod - VARHDRSZ));
|
|
|
|
else
|
|
|
|
*res = '\0';
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
2009-07-11 23:15:32 +02:00
|
|
|
* CHAR() and VARCHAR() types are part of the SQL standard. CHAR()
|
1996-07-09 08:22:35 +02:00
|
|
|
* 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
|
2005-05-29 22:15:59 +02:00
|
|
|
* we cannot determine the length, we pass in -1 instead and the input
|
|
|
|
* converter does not enforce any length check.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* 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
|
|
|
*
|
|
|
|
* - ay 6/95
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* bpchar - char() *
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
/*
|
2005-07-10 23:14:00 +02:00
|
|
|
* bpchar_input -- common guts of bpcharin and bpcharrecv
|
|
|
|
*
|
|
|
|
* s is the input text of length len (may not be null-terminated)
|
|
|
|
* atttypmod is the typmod value to apply
|
2001-05-21 18:54:46 +02:00
|
|
|
*
|
2005-07-10 23:14:00 +02:00
|
|
|
* Note that atttypmod is measured in characters, which
|
|
|
|
* is not necessarily the same as the number of bytes.
|
|
|
|
*
|
|
|
|
* If the input string is too long, raise an error, unless the extra
|
2001-05-21 18:54:46 +02:00
|
|
|
* characters are spaces, in which case they're truncated. (per SQL)
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2005-07-10 23:14:00 +02:00
|
|
|
static BpChar *
|
|
|
|
bpchar_input(const char *s, size_t len, int32 atttypmod)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-13 09:35:40 +02:00
|
|
|
BpChar *result;
|
|
|
|
char *r;
|
2005-07-10 23:14:00 +02:00
|
|
|
size_t maxlen;
|
1997-09-07 07:04:48 +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)
|
2005-05-29 22:15:59 +02:00
|
|
|
maxlen = len;
|
2001-06-01 19:49:17 +02:00
|
|
|
else
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2005-05-29 22:15:59 +02:00
|
|
|
size_t charlen; /* number of CHARACTERS in the input */
|
2001-10-25 07:50:21 +02:00
|
|
|
|
2005-05-29 22:15:59 +02:00
|
|
|
maxlen = atttypmod - VARHDRSZ;
|
2005-07-10 23:14:00 +02:00
|
|
|
charlen = pg_mbstrlen_with_len(s, len);
|
2005-05-29 22:15:59 +02:00
|
|
|
if (charlen > maxlen)
|
|
|
|
{
|
|
|
|
/* Verify that extra characters are spaces, and clip them off */
|
|
|
|
size_t mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
|
2005-07-10 23:14:00 +02:00
|
|
|
size_t j;
|
2005-05-29 22:15:59 +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
|
2005-07-10 23:14:00 +02:00
|
|
|
* bpchar type, mbmaxlen is the length in BYTES of those chars.
|
2005-05-29 22:15:59 +02:00
|
|
|
*/
|
2005-07-10 23:14:00 +02:00
|
|
|
for (j = mbmaxlen; j < len; j++)
|
|
|
|
{
|
|
|
|
if (s[j] != ' ')
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
|
|
|
errmsg("value too long for type character(%d)",
|
|
|
|
(int) maxlen)));
|
|
|
|
}
|
2005-05-29 22:15:59 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Now we set maxlen to the necessary byte length, not the number
|
|
|
|
* of CHARACTERS!
|
|
|
|
*/
|
2005-07-10 23:14:00 +02:00
|
|
|
maxlen = len = mbmaxlen;
|
2005-05-29 22:15:59 +02:00
|
|
|
}
|
2001-06-01 19:49:17 +02:00
|
|
|
else
|
2005-05-29 22:15:59 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Now we set maxlen to the necessary byte length, not the number
|
|
|
|
* of CHARACTERS!
|
|
|
|
*/
|
|
|
|
maxlen = len + (maxlen - charlen);
|
|
|
|
}
|
2001-07-15 13:07:37 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2005-07-10 23:14:00 +02:00
|
|
|
result = (BpChar *) palloc(maxlen + VARHDRSZ);
|
2007-02-28 00:48:10 +01:00
|
|
|
SET_VARSIZE(result, maxlen + VARHDRSZ);
|
1998-01-07 19:47:07 +01:00
|
|
|
r = VARDATA(result);
|
2005-05-29 22:15:59 +02:00
|
|
|
memcpy(r, s, len);
|
1998-02-24 16:27:04 +01:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* blank pad the string if necessary */
|
2005-05-29 22:15:59 +02:00
|
|
|
if (maxlen > len)
|
|
|
|
memset(r + len, ' ', maxlen - len);
|
2000-06-13 09:35:40 +02:00
|
|
|
|
2005-07-10 23:14:00 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert a C string to CHARACTER internal representation. atttypmod
|
|
|
|
* is the declared length of the type plus VARHDRSZ.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
bpcharin(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *s = PG_GETARG_CSTRING(0);
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2005-07-10 23:14:00 +02:00
|
|
|
#ifdef NOT_USED
|
|
|
|
Oid typelem = PG_GETARG_OID(1);
|
|
|
|
#endif
|
|
|
|
int32 atttypmod = PG_GETARG_INT32(2);
|
|
|
|
BpChar *result;
|
|
|
|
|
|
|
|
result = bpchar_input(s, strlen(s), atttypmod);
|
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.
|
2008-03-25 23:42:46 +01:00
|
|
|
*
|
|
|
|
* Uses the text conversion functions, which is only appropriate if BpChar
|
|
|
|
* and text are equivalent types.
|
2001-05-21 18:54:46 +02:00
|
|
|
*/
|
2000-06-13 09:35:40 +02:00
|
|
|
Datum
|
|
|
|
bpcharout(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2008-03-25 23:42:46 +01:00
|
|
|
Datum txt = PG_GETARG_DATUM(0);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2008-03-25 23:42:46 +01:00
|
|
|
PG_RETURN_CSTRING(TextDatumGetCString(txt));
|
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)
|
|
|
|
{
|
2005-07-10 23:14:00 +02:00
|
|
|
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2005-07-10 23:14:00 +02:00
|
|
|
#ifdef NOT_USED
|
|
|
|
Oid typelem = PG_GETARG_OID(1);
|
|
|
|
#endif
|
|
|
|
int32 atttypmod = PG_GETARG_INT32(2);
|
|
|
|
BpChar *result;
|
|
|
|
char *str;
|
|
|
|
int nbytes;
|
|
|
|
|
|
|
|
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
|
|
|
|
result = bpchar_input(str, nbytes, atttypmod);
|
|
|
|
pfree(str);
|
|
|
|
PG_RETURN_BPCHAR_P(result);
|
2003-05-13 01:08:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
* all spaces. (This is sort-of per SQL: the spec would actually have us
|
|
|
|
* 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
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
BpChar *source = PG_GETARG_BPCHAR_PP(0);
|
2001-05-21 18:54:46 +02:00
|
|
|
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;
|
2005-07-29 14:59:15 +02:00
|
|
|
int charlen; /* number of characters in the input string +
|
2001-07-15 13:07:37 +02:00
|
|
|
* VARHDRSZ */
|
2002-09-04 22:31:48 +02:00
|
|
|
|
2005-05-29 22:15:59 +02:00
|
|
|
/* No work if typmod is invalid */
|
|
|
|
if (maxlen < (int32) VARHDRSZ)
|
|
|
|
PG_RETURN_BPCHAR_P(source);
|
|
|
|
|
2007-04-06 06:21:44 +02:00
|
|
|
maxlen -= VARHDRSZ;
|
2002-08-29 09:22:30 +02:00
|
|
|
|
2007-04-06 06:21:44 +02:00
|
|
|
len = VARSIZE_ANY_EXHDR(source);
|
|
|
|
s = VARDATA_ANY(source);
|
|
|
|
|
|
|
|
charlen = pg_mbstrlen_with_len(s, len);
|
2002-08-29 09:22:30 +02:00
|
|
|
|
2005-05-29 22:15:59 +02:00
|
|
|
/* No work if supplied data matches typmod already */
|
|
|
|
if (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
|
|
|
|
2007-04-06 06:21:44 +02:00
|
|
|
maxmblen = pg_mbcharcliplen(s, len, maxlen);
|
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)
|
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
for (i = maxmblen; i < len; i++)
|
|
|
|
if (s[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-07-27 06:53:12 +02:00
|
|
|
errmsg("value too long for type character(%d)",
|
2007-04-06 06:21:44 +02:00
|
|
|
maxlen)));
|
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
|
|
|
/*
|
2007-04-06 06:21:44 +02:00
|
|
|
* At this point, maxlen is the necessary byte length, not the number
|
2001-07-15 13:07:37 +02:00
|
|
|
* of CHARACTERS!
|
|
|
|
*/
|
|
|
|
maxlen = len;
|
1998-05-10 00:45:14 +02:00
|
|
|
}
|
2001-07-15 13:07:37 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
2007-04-06 06:21:44 +02:00
|
|
|
* At this point, maxlen is the necessary byte length, not the number
|
2001-07-15 13:07:37 +02:00
|
|
|
* of CHARACTERS!
|
|
|
|
*/
|
|
|
|
maxlen = len + (maxlen - charlen);
|
|
|
|
}
|
1998-05-10 00:45:14 +02:00
|
|
|
|
2007-04-06 06:21:44 +02:00
|
|
|
Assert(maxlen >= len);
|
2001-05-21 18:54:46 +02:00
|
|
|
|
2007-04-06 06:21:44 +02:00
|
|
|
result = palloc(maxlen + VARHDRSZ);
|
|
|
|
SET_VARSIZE(result, maxlen + VARHDRSZ);
|
2001-05-21 18:54:46 +02:00
|
|
|
r = VARDATA(result);
|
|
|
|
|
2007-04-06 06:21:44 +02:00
|
|
|
memcpy(r, s, len);
|
1998-05-10 00:45:14 +02:00
|
|
|
|
|
|
|
/* blank pad the string if necessary */
|
2005-05-29 22:15:59 +02:00
|
|
|
if (maxlen > len)
|
2007-04-06 06:21:44 +02:00
|
|
|
memset(r + len, ' ', maxlen - len);
|
1998-05-10 00:45:14 +02:00
|
|
|
|
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
|
|
|
|
2007-02-28 00:48:10 +01:00
|
|
|
SET_VARSIZE(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
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
BpChar *s = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
char *s_data;
|
2000-07-29 05:26:51 +02:00
|
|
|
Name result;
|
1998-05-29 15:33:58 +02:00
|
|
|
int len;
|
|
|
|
|
2007-04-06 06:21:44 +02:00
|
|
|
len = VARSIZE_ANY_EXHDR(s);
|
|
|
|
s_data = VARDATA_ANY(s);
|
2000-07-29 05:26:51 +02:00
|
|
|
|
2012-05-25 23:34:51 +02:00
|
|
|
/* Truncate oversize input */
|
2000-07-07 23:12:53 +02:00
|
|
|
if (len >= NAMEDATALEN)
|
2012-05-25 23:34:51 +02:00
|
|
|
len = pg_mbcliplen(s_data, len, NAMEDATALEN - 1);
|
1998-05-29 15:33:58 +02:00
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
/* Remove trailing blanks */
|
1998-05-29 15:33:58 +02:00
|
|
|
while (len > 0)
|
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
if (s_data[len - 1] != ' ')
|
1998-05-29 15:33:58 +02:00
|
|
|
break;
|
|
|
|
len--;
|
|
|
|
}
|
|
|
|
|
2012-05-25 23:34:51 +02:00
|
|
|
/* We use palloc0 here to ensure result is zero-padded */
|
|
|
|
result = (Name) palloc0(NAMEDATALEN);
|
2007-04-06 06:21:44 +02:00
|
|
|
memcpy(NameStr(*result), s_data, len);
|
1998-05-29 15:33:58 +02:00
|
|
|
|
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.
|
2008-03-25 23:42:46 +01:00
|
|
|
*
|
|
|
|
* Uses the text conversion functions, which is only appropriate if BpChar
|
|
|
|
* and text are equivalent types.
|
1998-05-29 15:33:58 +02:00
|
|
|
*/
|
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
|
|
|
|
2008-03-25 23:42:46 +01:00
|
|
|
result = (BpChar *) cstring_to_text(NameStr(*s));
|
2000-07-29 05:26:51 +02:00
|
|
|
PG_RETURN_BPCHAR_P(result);
|
|
|
|
}
|
1998-05-29 15:33:58 +02:00
|
|
|
|
2006-12-30 22:21:56 +01:00
|
|
|
Datum
|
|
|
|
bpchartypmodin(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(anychar_typmodin(ta, "char"));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bpchartypmodout(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int32 typmod = PG_GETARG_INT32(0);
|
|
|
|
|
|
|
|
PG_RETURN_CSTRING(anychar_typmodout(typmod));
|
|
|
|
}
|
|
|
|
|
1998-05-29 15:33:58 +02:00
|
|
|
|
1996-07-09 08:22:35 +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
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
/*
|
2005-07-10 23:14:00 +02:00
|
|
|
* varchar_input -- common guts of varcharin and varcharrecv
|
|
|
|
*
|
|
|
|
* s is the input text of length len (may not be null-terminated)
|
|
|
|
* atttypmod is the typmod value to apply
|
2001-05-21 18:54:46 +02:00
|
|
|
*
|
2005-07-10 23:14:00 +02:00
|
|
|
* Note that atttypmod is measured in characters, which
|
2002-09-03 23:45:44 +02:00
|
|
|
* is not necessarily the same as the number of bytes.
|
2001-07-15 13:07:37 +02:00
|
|
|
*
|
2005-07-10 23:14:00 +02:00
|
|
|
* If the input string is too long, raise an error, unless the extra
|
|
|
|
* characters are spaces, in which case they're truncated. (per SQL)
|
2008-03-25 23:42:46 +01:00
|
|
|
*
|
|
|
|
* Uses the C string to text conversion function, which is only appropriate
|
|
|
|
* if VarChar and text are equivalent types.
|
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
|
|
|
*/
|
2005-07-10 23:14:00 +02:00
|
|
|
static VarChar *
|
|
|
|
varchar_input(const char *s, size_t len, int32 atttypmod)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2000-06-13 09:35:40 +02:00
|
|
|
VarChar *result;
|
2005-07-10 23:14:00 +02:00
|
|
|
size_t maxlen;
|
2001-10-25 07:50:21 +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-07-15 13:07:37 +02:00
|
|
|
size_t mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
|
2005-07-10 23:14:00 +02:00
|
|
|
size_t j;
|
2001-05-21 18:54:46 +02:00
|
|
|
|
2005-07-10 23:14:00 +02:00
|
|
|
for (j = mbmaxlen; j < len; j++)
|
|
|
|
{
|
|
|
|
if (s[j] != ' ')
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
|
|
|
errmsg("value too long for type character varying(%d)",
|
|
|
|
(int) maxlen)));
|
|
|
|
}
|
|
|
|
|
|
|
|
len = mbmaxlen;
|
2001-05-21 18:54:46 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2008-03-25 23:42:46 +01:00
|
|
|
result = (VarChar *) cstring_to_text_with_len(s, len);
|
2005-07-10 23:14:00 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert a C string to VARCHAR internal representation. atttypmod
|
|
|
|
* is the declared length of the type plus VARHDRSZ.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
varcharin(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *s = PG_GETARG_CSTRING(0);
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2005-07-10 23:14:00 +02:00
|
|
|
#ifdef NOT_USED
|
|
|
|
Oid typelem = PG_GETARG_OID(1);
|
|
|
|
#endif
|
|
|
|
int32 atttypmod = PG_GETARG_INT32(2);
|
|
|
|
VarChar *result;
|
|
|
|
|
|
|
|
result = varchar_input(s, strlen(s), atttypmod);
|
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.
|
2008-03-25 23:42:46 +01:00
|
|
|
*
|
|
|
|
* Uses the text to C string conversion function, which is only appropriate
|
|
|
|
* if VarChar and text are equivalent types.
|
2001-05-21 18:54:46 +02:00
|
|
|
*/
|
2000-06-13 09:35:40 +02:00
|
|
|
Datum
|
|
|
|
varcharout(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2008-03-25 23:42:46 +01:00
|
|
|
Datum txt = PG_GETARG_DATUM(0);
|
1998-02-24 16:27:04 +01:00
|
|
|
|
2008-03-25 23:42:46 +01:00
|
|
|
PG_RETURN_CSTRING(TextDatumGetCString(txt));
|
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)
|
|
|
|
{
|
2005-07-10 23:14:00 +02:00
|
|
|
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
2005-10-15 04:49:52 +02:00
|
|
|
|
2005-07-10 23:14:00 +02:00
|
|
|
#ifdef NOT_USED
|
|
|
|
Oid typelem = PG_GETARG_OID(1);
|
|
|
|
#endif
|
|
|
|
int32 atttypmod = PG_GETARG_INT32(2);
|
|
|
|
VarChar *result;
|
|
|
|
char *str;
|
|
|
|
int nbytes;
|
|
|
|
|
|
|
|
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
|
|
|
|
result = varchar_input(str, nbytes, atttypmod);
|
|
|
|
pfree(str);
|
|
|
|
PG_RETURN_VARCHAR_P(result);
|
2003-05-13 01:08:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
2011-06-22 04:15:24 +02:00
|
|
|
/*
|
2019-02-10 00:08:48 +01:00
|
|
|
* varchar_support()
|
|
|
|
*
|
|
|
|
* Planner support function for the varchar() length coercion function.
|
|
|
|
*
|
|
|
|
* Currently, the only interesting thing we can do is flatten calls that set
|
|
|
|
* the new maximum length >= the previous maximum length. We can ignore the
|
|
|
|
* isExplicit argument, since that only affects truncation cases.
|
2011-06-22 04:15:24 +02:00
|
|
|
*/
|
|
|
|
Datum
|
2019-02-10 00:08:48 +01:00
|
|
|
varchar_support(PG_FUNCTION_ARGS)
|
2011-06-22 04:15:24 +02:00
|
|
|
{
|
2019-02-10 00:08:48 +01:00
|
|
|
Node *rawreq = (Node *) PG_GETARG_POINTER(0);
|
2011-06-22 04:15:24 +02:00
|
|
|
Node *ret = NULL;
|
|
|
|
|
2019-02-10 00:08:48 +01:00
|
|
|
if (IsA(rawreq, SupportRequestSimplify))
|
|
|
|
{
|
|
|
|
SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq;
|
|
|
|
FuncExpr *expr = req->fcall;
|
|
|
|
Node *typmod;
|
2011-06-22 04:15:24 +02:00
|
|
|
|
2019-02-10 00:08:48 +01:00
|
|
|
Assert(list_length(expr->args) >= 2);
|
2011-06-22 04:15:24 +02:00
|
|
|
|
2019-02-10 00:08:48 +01:00
|
|
|
typmod = (Node *) lsecond(expr->args);
|
|
|
|
|
|
|
|
if (IsA(typmod, Const) && !((Const *) typmod)->constisnull)
|
|
|
|
{
|
|
|
|
Node *source = (Node *) linitial(expr->args);
|
|
|
|
int32 old_typmod = exprTypmod(source);
|
|
|
|
int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
|
|
|
|
int32 old_max = old_typmod - VARHDRSZ;
|
|
|
|
int32 new_max = new_typmod - VARHDRSZ;
|
|
|
|
|
|
|
|
if (new_typmod < 0 || (old_typmod >= 0 && old_max <= new_max))
|
|
|
|
ret = relabel_to_typmod(source, new_typmod);
|
|
|
|
}
|
2011-06-22 04:15:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
PG_RETURN_POINTER(ret);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
* all spaces. (This is sort-of per SQL: the spec would actually have us
|
|
|
|
* 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
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
VarChar *source = PG_GETARG_VARCHAR_PP(0);
|
|
|
|
int32 typmod = 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);
|
2007-04-06 06:21:44 +02:00
|
|
|
int32 len,
|
|
|
|
maxlen;
|
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;
|
2007-04-06 06:21:44 +02:00
|
|
|
char *s_data;
|
|
|
|
|
|
|
|
len = VARSIZE_ANY_EXHDR(source);
|
|
|
|
s_data = VARDATA_ANY(source);
|
|
|
|
maxlen = typmod - VARHDRSZ;
|
1998-05-10 00:45:14 +02:00
|
|
|
|
2001-06-01 19:49:17 +02:00
|
|
|
/* No work if typmod is invalid or supplied data fits it already */
|
2007-04-06 06:21:44 +02:00
|
|
|
if (maxlen < 0 || len <= maxlen)
|
2001-05-21 18:54:46 +02:00
|
|
|
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 */
|
2007-04-06 06:21:44 +02:00
|
|
|
maxmblen = pg_mbcharcliplen(s_data, len, maxlen);
|
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)
|
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
for (i = maxmblen; i < len; i++)
|
|
|
|
if (s_data[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),
|
2007-04-06 06:21:44 +02:00
|
|
|
errmsg("value too long for type character varying(%d)",
|
|
|
|
maxlen)));
|
2001-05-21 18:54:46 +02:00
|
|
|
}
|
1998-05-10 00:45:14 +02:00
|
|
|
|
2008-05-04 18:42:41 +02:00
|
|
|
PG_RETURN_VARCHAR_P((VarChar *) cstring_to_text_with_len(s_data,
|
|
|
|
maxmblen));
|
2000-06-13 09:35:40 +02:00
|
|
|
}
|
1998-05-10 00:45:14 +02:00
|
|
|
|
2006-12-30 22:21:56 +01:00
|
|
|
Datum
|
|
|
|
varchartypmodin(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(anychar_typmodin(ta, "varchar"));
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
varchartypmodout(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
int32 typmod = PG_GETARG_INT32(0);
|
|
|
|
|
|
|
|
PG_RETURN_CSTRING(anychar_typmodout(typmod));
|
|
|
|
}
|
|
|
|
|
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 */
|
2016-02-03 20:17:35 +01:00
|
|
|
static inline int
|
2000-07-29 05:26:51 +02:00
|
|
|
bcTruelen(BpChar *arg)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2016-02-03 20:17:35 +01:00
|
|
|
return bpchartruelen(VARDATA_ANY(arg), VARSIZE_ANY_EXHDR(arg));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
bpchartruelen(char *s, int len)
|
|
|
|
{
|
1996-07-09 08:22:35 +02:00
|
|
|
int i;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2016-02-03 20:17:35 +01:00
|
|
|
/*
|
|
|
|
* Note that we rely on the assumption that ' ' is a singleton unit on
|
|
|
|
* every supported multibyte server encoding.
|
|
|
|
*/
|
1996-07-09 08:22:35 +02:00
|
|
|
for (i = len - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
if (s[i] != ' ')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
Datum
|
|
|
|
bpcharlen(PG_FUNCTION_ARGS)
|
1998-04-27 19:10:50 +02:00
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
BpChar *arg = PG_GETARG_BPCHAR_PP(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)
|
2007-04-06 06:21:44 +02:00
|
|
|
len = pg_mbstrlen_with_len(VARDATA_ANY(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
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
Datum arg = PG_GETARG_DATUM(0);
|
1997-12-16 16:59:11 +01:00
|
|
|
|
2007-04-06 06:21:44 +02:00
|
|
|
/* We need not detoast the input at all */
|
|
|
|
PG_RETURN_INT32(toast_raw_datum_size(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.
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2019-03-22 12:09:32 +01:00
|
|
|
static void
|
|
|
|
check_collation_set(Oid collid)
|
|
|
|
{
|
|
|
|
if (!OidIsValid(collid))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This typically means that the parser could not resolve a conflict
|
|
|
|
* of implicit collations, so report it that way.
|
|
|
|
*/
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
|
|
|
errmsg("could not determine which collation to use for string comparison"),
|
|
|
|
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-07-29 05:26:51 +02:00
|
|
|
Datum
|
|
|
|
bpchareq(PG_FUNCTION_ARGS)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1);
|
1996-07-09 08:22:35 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
2000-07-29 05:26:51 +02:00
|
|
|
bool result;
|
2019-03-22 12:09:32 +01:00
|
|
|
Oid collid = PG_GET_COLLATION();
|
2022-01-20 09:38:05 +01:00
|
|
|
bool locale_is_c = false;
|
|
|
|
pg_locale_t mylocale = 0;
|
2019-03-22 12:09:32 +01:00
|
|
|
|
|
|
|
check_collation_set(collid);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
|
|
|
|
2022-01-20 09:38:05 +01:00
|
|
|
if (lc_collate_is_c(collid))
|
|
|
|
locale_is_c = true;
|
|
|
|
else
|
|
|
|
mylocale = pg_newlocale_from_collation(collid);
|
|
|
|
|
|
|
|
if (locale_is_c || !mylocale || mylocale->deterministic)
|
2019-03-22 12:09:32 +01:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Since we only care about equality or not-equality, we can avoid all
|
|
|
|
* the expense of strcoll() here, and just do bitwise comparison.
|
|
|
|
*/
|
|
|
|
if (len1 != len2)
|
|
|
|
result = false;
|
|
|
|
else
|
|
|
|
result = (memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), len1) == 0);
|
|
|
|
}
|
2000-07-29 05:26:51 +02:00
|
|
|
else
|
2019-03-22 12:09:32 +01:00
|
|
|
{
|
|
|
|
result = (varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2,
|
|
|
|
collid) == 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
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1);
|
1996-07-09 08:22:35 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
2000-07-29 05:26:51 +02:00
|
|
|
bool result;
|
2019-03-22 12:09:32 +01:00
|
|
|
Oid collid = PG_GET_COLLATION();
|
2022-01-20 09:38:05 +01:00
|
|
|
bool locale_is_c = false;
|
|
|
|
pg_locale_t mylocale = 0;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2019-11-13 21:53:53 +01:00
|
|
|
check_collation_set(collid);
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
|
|
|
|
2022-01-20 09:38:05 +01:00
|
|
|
if (lc_collate_is_c(collid))
|
|
|
|
locale_is_c = true;
|
|
|
|
else
|
|
|
|
mylocale = pg_newlocale_from_collation(collid);
|
|
|
|
|
|
|
|
if (locale_is_c || !mylocale || mylocale->deterministic)
|
2019-03-22 12:09:32 +01:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Since we only care about equality or not-equality, we can avoid all
|
|
|
|
* the expense of strcoll() here, and just do bitwise comparison.
|
|
|
|
*/
|
|
|
|
if (len1 != len2)
|
|
|
|
result = true;
|
|
|
|
else
|
|
|
|
result = (memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), len1) != 0);
|
|
|
|
}
|
2000-07-29 05:26:51 +02:00
|
|
|
else
|
2019-03-22 12:09:32 +01:00
|
|
|
{
|
|
|
|
result = (varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2,
|
|
|
|
collid) != 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
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1);
|
1996-07-09 08:22:35 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
|
|
|
int cmp;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2011-02-08 22:04:18 +01:00
|
|
|
cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2,
|
|
|
|
PG_GET_COLLATION());
|
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
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1);
|
1996-07-09 08:22:35 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
1996-08-26 22:38:52 +02:00
|
|
|
int cmp;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2011-02-08 22:04:18 +01:00
|
|
|
cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2,
|
|
|
|
PG_GET_COLLATION());
|
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
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1);
|
1996-07-09 08:22:35 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
|
|
|
int cmp;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2011-02-08 22:04:18 +01:00
|
|
|
cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2,
|
|
|
|
PG_GET_COLLATION());
|
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
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1);
|
1996-07-09 08:22:35 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
1996-08-26 22:38:52 +02:00
|
|
|
int cmp;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2011-02-08 22:04:18 +01:00
|
|
|
cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2,
|
|
|
|
PG_GET_COLLATION());
|
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
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1);
|
1996-07-09 08:22:35 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
1996-08-26 22:38:52 +02:00
|
|
|
int cmp;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2011-02-08 22:04:18 +01:00
|
|
|
cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2,
|
|
|
|
PG_GET_COLLATION());
|
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
|
|
|
}
|
|
|
|
|
2016-02-03 20:17:35 +01:00
|
|
|
Datum
|
|
|
|
bpchar_sortsupport(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
|
|
|
|
Oid collid = ssup->ssup_collation;
|
|
|
|
MemoryContext oldcontext;
|
|
|
|
|
|
|
|
oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
|
|
|
|
|
|
|
|
/* Use generic string SortSupport */
|
Make type "name" collation-aware.
The "name" comparison operators now all support collations, making them
functionally equivalent to "text" comparisons, except for the different
physical representation of the datatype. They do, in fact, mostly share
the varstr_cmp and varstr_sortsupport infrastructure, which has been
slightly enlarged to handle the case.
To avoid changes in the default behavior of the datatype, set name's
typcollation to C_COLLATION_OID not DEFAULT_COLLATION_OID, so that
by default comparisons to a name value will continue to use strcmp
semantics. (This would have been the case for system catalog columns
anyway, because of commit 6b0faf723, but doing this makes it true for
user-created name columns as well. In particular, this avoids
locale-dependent changes in our regression test results.)
In consequence, tweak a couple of places that made assumptions about
collatable base types always having typcollation DEFAULT_COLLATION_OID.
I have not, however, attempted to relax the restriction that user-
defined collatable types must have that. Hence, "name" doesn't
behave quite like a user-defined type; it acts more like a domain
with COLLATE "C". (Conceivably, if we ever get rid of the need for
catalog name columns to be fixed-length, "name" could actually become
such a domain over text. But that'd be a pretty massive undertaking,
and I'm not volunteering.)
Discussion: https://postgr.es/m/15938.1544377821@sss.pgh.pa.us
2018-12-19 23:35:12 +01:00
|
|
|
varstr_sortsupport(ssup, BPCHAROID, collid);
|
2016-02-03 20:17:35 +01:00
|
|
|
|
|
|
|
MemoryContextSwitchTo(oldcontext);
|
|
|
|
|
|
|
|
PG_RETURN_VOID();
|
|
|
|
}
|
|
|
|
|
2005-04-12 06:26:34 +02:00
|
|
|
Datum
|
|
|
|
bpchar_larger(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1);
|
2005-04-12 06:26:34 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
|
|
|
int cmp;
|
|
|
|
|
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
|
|
|
|
2011-02-08 22:04:18 +01:00
|
|
|
cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2,
|
|
|
|
PG_GET_COLLATION());
|
2005-04-12 06:26:34 +02:00
|
|
|
|
|
|
|
PG_RETURN_BPCHAR_P((cmp >= 0) ? arg1 : arg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bpchar_smaller(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1);
|
2005-04-12 06:26:34 +02:00
|
|
|
int len1,
|
|
|
|
len2;
|
|
|
|
int cmp;
|
|
|
|
|
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
|
|
|
|
2011-02-08 22:04:18 +01:00
|
|
|
cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2,
|
|
|
|
PG_GET_COLLATION());
|
2005-04-12 06:26:34 +02:00
|
|
|
|
|
|
|
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.
|
2000-07-29 05:26:51 +02:00
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
hashbpchar(PG_FUNCTION_ARGS)
|
|
|
|
{
|
2007-04-06 06:21:44 +02:00
|
|
|
BpChar *key = PG_GETARG_BPCHAR_PP(0);
|
2019-03-22 12:09:32 +01:00
|
|
|
Oid collid = PG_GET_COLLATION();
|
2000-07-29 05:26:51 +02:00
|
|
|
char *keydata;
|
|
|
|
int keylen;
|
2019-03-22 12:09:32 +01:00
|
|
|
pg_locale_t mylocale = 0;
|
2000-12-09 00:57:03 +01:00
|
|
|
Datum result;
|
2000-07-29 05:26:51 +02:00
|
|
|
|
2019-03-22 12:09:32 +01:00
|
|
|
if (!collid)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
|
|
|
errmsg("could not determine which collation to use for string hashing"),
|
|
|
|
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
|
|
|
|
2007-04-06 06:21:44 +02:00
|
|
|
keydata = VARDATA_ANY(key);
|
2000-07-29 05:26:51 +02:00
|
|
|
keylen = bcTruelen(key);
|
|
|
|
|
2022-01-20 09:38:05 +01:00
|
|
|
if (!lc_collate_is_c(collid))
|
2019-03-22 12:09:32 +01:00
|
|
|
mylocale = pg_newlocale_from_collation(collid);
|
|
|
|
|
|
|
|
if (!mylocale || mylocale->deterministic)
|
|
|
|
{
|
|
|
|
result = hash_any((unsigned char *) keydata, keylen);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#ifdef USE_ICU
|
|
|
|
if (mylocale->provider == COLLPROVIDER_ICU)
|
|
|
|
{
|
|
|
|
int32_t ulen = -1;
|
|
|
|
UChar *uchar = NULL;
|
|
|
|
Size bsize;
|
|
|
|
uint8_t *buf;
|
|
|
|
|
|
|
|
ulen = icu_to_uchar(&uchar, keydata, keylen);
|
|
|
|
|
|
|
|
bsize = ucol_getSortKey(mylocale->info.icu.ucol,
|
|
|
|
uchar, ulen, NULL, 0);
|
|
|
|
buf = palloc(bsize);
|
|
|
|
ucol_getSortKey(mylocale->info.icu.ucol,
|
|
|
|
uchar, ulen, buf, bsize);
|
|
|
|
|
|
|
|
result = hash_any(buf, bsize);
|
|
|
|
|
|
|
|
pfree(buf);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
/* shouldn't happen */
|
|
|
|
elog(ERROR, "unsupported collprovider: %c", mylocale->provider);
|
|
|
|
}
|
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
|
|
|
}
|
2008-05-27 02:13:09 +02:00
|
|
|
|
2017-09-01 04:21:21 +02:00
|
|
|
Datum
|
|
|
|
hashbpcharextended(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
BpChar *key = PG_GETARG_BPCHAR_PP(0);
|
2019-03-22 12:09:32 +01:00
|
|
|
Oid collid = PG_GET_COLLATION();
|
2017-09-01 04:21:21 +02:00
|
|
|
char *keydata;
|
|
|
|
int keylen;
|
2019-03-22 12:09:32 +01:00
|
|
|
pg_locale_t mylocale = 0;
|
2017-09-01 04:21:21 +02:00
|
|
|
Datum result;
|
|
|
|
|
2019-03-22 12:09:32 +01:00
|
|
|
if (!collid)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INDETERMINATE_COLLATION),
|
|
|
|
errmsg("could not determine which collation to use for string hashing"),
|
|
|
|
errhint("Use the COLLATE clause to set the collation explicitly.")));
|
|
|
|
|
2017-09-01 04:21:21 +02:00
|
|
|
keydata = VARDATA_ANY(key);
|
|
|
|
keylen = bcTruelen(key);
|
|
|
|
|
2022-01-20 09:38:05 +01:00
|
|
|
if (!lc_collate_is_c(collid))
|
2019-03-22 12:09:32 +01:00
|
|
|
mylocale = pg_newlocale_from_collation(collid);
|
|
|
|
|
|
|
|
if (!mylocale || mylocale->deterministic)
|
|
|
|
{
|
|
|
|
result = hash_any_extended((unsigned char *) keydata, keylen,
|
|
|
|
PG_GETARG_INT64(1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#ifdef USE_ICU
|
|
|
|
if (mylocale->provider == COLLPROVIDER_ICU)
|
|
|
|
{
|
|
|
|
int32_t ulen = -1;
|
|
|
|
UChar *uchar = NULL;
|
|
|
|
Size bsize;
|
|
|
|
uint8_t *buf;
|
|
|
|
|
|
|
|
ulen = icu_to_uchar(&uchar, VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key));
|
|
|
|
|
|
|
|
bsize = ucol_getSortKey(mylocale->info.icu.ucol,
|
|
|
|
uchar, ulen, NULL, 0);
|
|
|
|
buf = palloc(bsize);
|
|
|
|
ucol_getSortKey(mylocale->info.icu.ucol,
|
|
|
|
uchar, ulen, buf, bsize);
|
|
|
|
|
|
|
|
result = hash_any_extended(buf, bsize, PG_GETARG_INT64(1));
|
|
|
|
|
|
|
|
pfree(buf);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
/* shouldn't happen */
|
|
|
|
elog(ERROR, "unsupported collprovider: %c", mylocale->provider);
|
|
|
|
}
|
2017-09-01 04:21:21 +02:00
|
|
|
|
|
|
|
PG_FREE_IF_COPY(key, 0);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2008-05-27 02:13:09 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The following operators support character-by-character comparison
|
|
|
|
* of bpchar datums, to allow building indexes suitable for LIKE clauses.
|
2016-02-03 20:17:35 +01:00
|
|
|
* Note that the regular bpchareq/bpcharne comparison operators, and
|
|
|
|
* regular support functions 1 and 2 with "C" collation are assumed to be
|
|
|
|
* compatible with these!
|
2008-05-27 02:13:09 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
static int
|
Fix up handling of nondeterministic collations with pattern_ops opclasses.
text_pattern_ops and its siblings can't be used with nondeterministic
collations, because they use the text_eq operator which will not behave
as bitwise equality if applied with a nondeterministic collation. The
initial implementation of that restriction was to insert a run-time test
in the related comparison functions, but that is inefficient, may throw
misleading errors, and will throw errors in some cases that would work.
It seems sufficient to just prevent the combination during CREATE INDEX,
so do that instead.
Lacking any better way to identify the opclasses involved, we need to
hard-wire tests for them, which requires hand-assigned values for their
OIDs, which forces a catversion bump because they previously had OIDs
that would be assigned automatically. That's slightly annoying in the
v12 branch, but fortunately we're not at rc1 yet, so just do it.
Back-patch to v12 where nondeterministic collations were added.
In passing, run make reformat-dat-files, which found some unrelated
whitespace issues (slightly different ones in HEAD and v12).
Peter Eisentraut, with small corrections by me
Discussion: https://postgr.es/m/22566.1568675619@sss.pgh.pa.us
2019-09-21 22:29:17 +02:00
|
|
|
internal_bpchar_pattern_compare(BpChar *arg1, BpChar *arg2)
|
2008-05-27 02:13:09 +02:00
|
|
|
{
|
|
|
|
int result;
|
|
|
|
int len1,
|
|
|
|
len2;
|
|
|
|
|
|
|
|
len1 = bcTruelen(arg1);
|
|
|
|
len2 = bcTruelen(arg2);
|
|
|
|
|
2010-12-22 04:11:40 +01:00
|
|
|
result = memcmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), Min(len1, len2));
|
2008-05-27 02:13:09 +02:00
|
|
|
if (result != 0)
|
|
|
|
return result;
|
|
|
|
else if (len1 < len2)
|
|
|
|
return -1;
|
|
|
|
else if (len1 > len2)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bpchar_pattern_lt(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1);
|
|
|
|
int result;
|
|
|
|
|
Fix up handling of nondeterministic collations with pattern_ops opclasses.
text_pattern_ops and its siblings can't be used with nondeterministic
collations, because they use the text_eq operator which will not behave
as bitwise equality if applied with a nondeterministic collation. The
initial implementation of that restriction was to insert a run-time test
in the related comparison functions, but that is inefficient, may throw
misleading errors, and will throw errors in some cases that would work.
It seems sufficient to just prevent the combination during CREATE INDEX,
so do that instead.
Lacking any better way to identify the opclasses involved, we need to
hard-wire tests for them, which requires hand-assigned values for their
OIDs, which forces a catversion bump because they previously had OIDs
that would be assigned automatically. That's slightly annoying in the
v12 branch, but fortunately we're not at rc1 yet, so just do it.
Back-patch to v12 where nondeterministic collations were added.
In passing, run make reformat-dat-files, which found some unrelated
whitespace issues (slightly different ones in HEAD and v12).
Peter Eisentraut, with small corrections by me
Discussion: https://postgr.es/m/22566.1568675619@sss.pgh.pa.us
2019-09-21 22:29:17 +02:00
|
|
|
result = internal_bpchar_pattern_compare(arg1, arg2);
|
2008-05-27 02:13:09 +02:00
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(result < 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bpchar_pattern_le(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1);
|
|
|
|
int result;
|
|
|
|
|
Fix up handling of nondeterministic collations with pattern_ops opclasses.
text_pattern_ops and its siblings can't be used with nondeterministic
collations, because they use the text_eq operator which will not behave
as bitwise equality if applied with a nondeterministic collation. The
initial implementation of that restriction was to insert a run-time test
in the related comparison functions, but that is inefficient, may throw
misleading errors, and will throw errors in some cases that would work.
It seems sufficient to just prevent the combination during CREATE INDEX,
so do that instead.
Lacking any better way to identify the opclasses involved, we need to
hard-wire tests for them, which requires hand-assigned values for their
OIDs, which forces a catversion bump because they previously had OIDs
that would be assigned automatically. That's slightly annoying in the
v12 branch, but fortunately we're not at rc1 yet, so just do it.
Back-patch to v12 where nondeterministic collations were added.
In passing, run make reformat-dat-files, which found some unrelated
whitespace issues (slightly different ones in HEAD and v12).
Peter Eisentraut, with small corrections by me
Discussion: https://postgr.es/m/22566.1568675619@sss.pgh.pa.us
2019-09-21 22:29:17 +02:00
|
|
|
result = internal_bpchar_pattern_compare(arg1, arg2);
|
2008-05-27 02:13:09 +02:00
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(result <= 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bpchar_pattern_ge(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1);
|
|
|
|
int result;
|
|
|
|
|
Fix up handling of nondeterministic collations with pattern_ops opclasses.
text_pattern_ops and its siblings can't be used with nondeterministic
collations, because they use the text_eq operator which will not behave
as bitwise equality if applied with a nondeterministic collation. The
initial implementation of that restriction was to insert a run-time test
in the related comparison functions, but that is inefficient, may throw
misleading errors, and will throw errors in some cases that would work.
It seems sufficient to just prevent the combination during CREATE INDEX,
so do that instead.
Lacking any better way to identify the opclasses involved, we need to
hard-wire tests for them, which requires hand-assigned values for their
OIDs, which forces a catversion bump because they previously had OIDs
that would be assigned automatically. That's slightly annoying in the
v12 branch, but fortunately we're not at rc1 yet, so just do it.
Back-patch to v12 where nondeterministic collations were added.
In passing, run make reformat-dat-files, which found some unrelated
whitespace issues (slightly different ones in HEAD and v12).
Peter Eisentraut, with small corrections by me
Discussion: https://postgr.es/m/22566.1568675619@sss.pgh.pa.us
2019-09-21 22:29:17 +02:00
|
|
|
result = internal_bpchar_pattern_compare(arg1, arg2);
|
2008-05-27 02:13:09 +02:00
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(result >= 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Datum
|
|
|
|
bpchar_pattern_gt(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1);
|
|
|
|
int result;
|
|
|
|
|
Fix up handling of nondeterministic collations with pattern_ops opclasses.
text_pattern_ops and its siblings can't be used with nondeterministic
collations, because they use the text_eq operator which will not behave
as bitwise equality if applied with a nondeterministic collation. The
initial implementation of that restriction was to insert a run-time test
in the related comparison functions, but that is inefficient, may throw
misleading errors, and will throw errors in some cases that would work.
It seems sufficient to just prevent the combination during CREATE INDEX,
so do that instead.
Lacking any better way to identify the opclasses involved, we need to
hard-wire tests for them, which requires hand-assigned values for their
OIDs, which forces a catversion bump because they previously had OIDs
that would be assigned automatically. That's slightly annoying in the
v12 branch, but fortunately we're not at rc1 yet, so just do it.
Back-patch to v12 where nondeterministic collations were added.
In passing, run make reformat-dat-files, which found some unrelated
whitespace issues (slightly different ones in HEAD and v12).
Peter Eisentraut, with small corrections by me
Discussion: https://postgr.es/m/22566.1568675619@sss.pgh.pa.us
2019-09-21 22:29:17 +02:00
|
|
|
result = internal_bpchar_pattern_compare(arg1, arg2);
|
2008-05-27 02:13:09 +02:00
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_BOOL(result > 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Datum
|
|
|
|
btbpchar_pattern_cmp(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
BpChar *arg1 = PG_GETARG_BPCHAR_PP(0);
|
|
|
|
BpChar *arg2 = PG_GETARG_BPCHAR_PP(1);
|
|
|
|
int result;
|
|
|
|
|
Fix up handling of nondeterministic collations with pattern_ops opclasses.
text_pattern_ops and its siblings can't be used with nondeterministic
collations, because they use the text_eq operator which will not behave
as bitwise equality if applied with a nondeterministic collation. The
initial implementation of that restriction was to insert a run-time test
in the related comparison functions, but that is inefficient, may throw
misleading errors, and will throw errors in some cases that would work.
It seems sufficient to just prevent the combination during CREATE INDEX,
so do that instead.
Lacking any better way to identify the opclasses involved, we need to
hard-wire tests for them, which requires hand-assigned values for their
OIDs, which forces a catversion bump because they previously had OIDs
that would be assigned automatically. That's slightly annoying in the
v12 branch, but fortunately we're not at rc1 yet, so just do it.
Back-patch to v12 where nondeterministic collations were added.
In passing, run make reformat-dat-files, which found some unrelated
whitespace issues (slightly different ones in HEAD and v12).
Peter Eisentraut, with small corrections by me
Discussion: https://postgr.es/m/22566.1568675619@sss.pgh.pa.us
2019-09-21 22:29:17 +02:00
|
|
|
result = internal_bpchar_pattern_compare(arg1, arg2);
|
2008-05-27 02:13:09 +02:00
|
|
|
|
|
|
|
PG_FREE_IF_COPY(arg1, 0);
|
|
|
|
PG_FREE_IF_COPY(arg2, 1);
|
|
|
|
|
|
|
|
PG_RETURN_INT32(result);
|
|
|
|
}
|
2016-02-03 20:17:35 +01:00
|
|
|
|
|
|
|
|
|
|
|
Datum
|
|
|
|
btbpchar_pattern_sortsupport(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
|
|
|
|
MemoryContext oldcontext;
|
|
|
|
|
|
|
|
oldcontext = MemoryContextSwitchTo(ssup->ssup_cxt);
|
|
|
|
|
|
|
|
/* Use generic string SortSupport, forcing "C" collation */
|
Make type "name" collation-aware.
The "name" comparison operators now all support collations, making them
functionally equivalent to "text" comparisons, except for the different
physical representation of the datatype. They do, in fact, mostly share
the varstr_cmp and varstr_sortsupport infrastructure, which has been
slightly enlarged to handle the case.
To avoid changes in the default behavior of the datatype, set name's
typcollation to C_COLLATION_OID not DEFAULT_COLLATION_OID, so that
by default comparisons to a name value will continue to use strcmp
semantics. (This would have been the case for system catalog columns
anyway, because of commit 6b0faf723, but doing this makes it true for
user-created name columns as well. In particular, this avoids
locale-dependent changes in our regression test results.)
In consequence, tweak a couple of places that made assumptions about
collatable base types always having typcollation DEFAULT_COLLATION_OID.
I have not, however, attempted to relax the restriction that user-
defined collatable types must have that. Hence, "name" doesn't
behave quite like a user-defined type; it acts more like a domain
with COLLATE "C". (Conceivably, if we ever get rid of the need for
catalog name columns to be fixed-length, "name" could actually become
such a domain over text. But that'd be a pretty massive undertaking,
and I'm not volunteering.)
Discussion: https://postgr.es/m/15938.1544377821@sss.pgh.pa.us
2018-12-19 23:35:12 +01:00
|
|
|
varstr_sortsupport(ssup, BPCHAROID, C_COLLATION_OID);
|
2016-02-03 20:17:35 +01:00
|
|
|
|
|
|
|
MemoryContextSwitchTo(oldcontext);
|
|
|
|
|
|
|
|
PG_RETURN_VOID();
|
|
|
|
}
|