mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03: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.
This commit is contained in:
@ -9,7 +9,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.25 2002/09/04 20:31:29 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.26 2002/09/18 21:35:23 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -35,6 +35,11 @@
|
||||
* data section -- private data section for the bits data structures
|
||||
* bitlength -- length of the bit string in bits
|
||||
* bitdata -- bit string, most significant byte first
|
||||
*
|
||||
* The length of the bitdata vector should always be exactly as many
|
||||
* bytes as are needed for the given bitlength. If the bitlength is
|
||||
* not a multiple of 8, the extra low-order padding bits of the last
|
||||
* byte must be zeroes.
|
||||
*----------
|
||||
*/
|
||||
|
||||
@ -104,7 +109,7 @@ bit_in(PG_FUNCTION_ARGS)
|
||||
len = VARBITTOTALLEN(atttypmod);
|
||||
result = (VarBit *) palloc(len);
|
||||
/* set to 0 so that *r is always initialised and string is zero-padded */
|
||||
memset(result, 0, len);
|
||||
MemSet(result, 0, len);
|
||||
VARATT_SIZEP(result) = len;
|
||||
VARBITLEN(result) = atttypmod;
|
||||
|
||||
@ -203,50 +208,52 @@ bit_out(PG_FUNCTION_ARGS)
|
||||
/* bit()
|
||||
* Converts a bit() type to a specific internal length.
|
||||
* len is the bitlength specified in the column definition.
|
||||
*
|
||||
* If doing implicit cast, raise error when source data is wrong length.
|
||||
* If doing explicit cast, silently truncate or zero-pad to specified length.
|
||||
*/
|
||||
Datum
|
||||
bit(PG_FUNCTION_ARGS)
|
||||
{
|
||||
VarBit *arg = PG_GETARG_VARBIT_P(0);
|
||||
int32 len = PG_GETARG_INT32(1);
|
||||
bool isExplicit = PG_GETARG_BOOL(2);
|
||||
VarBit *result;
|
||||
int rlen;
|
||||
int ipad;
|
||||
bits8 mask;
|
||||
|
||||
/* No work if typmod is invalid or supplied data matches it already */
|
||||
if (len <= 0 || len == VARBITLEN(arg))
|
||||
PG_RETURN_VARBIT_P(arg);
|
||||
else
|
||||
|
||||
if (!isExplicit)
|
||||
elog(ERROR, "Bit string length %d does not match type BIT(%d)",
|
||||
VARBITLEN(arg), len);
|
||||
return 0; /* quiet compiler */
|
||||
}
|
||||
|
||||
/* _bit()
|
||||
* Converts an array of bit() elements to a specific internal length.
|
||||
* len is the bitlength specified in the column definition.
|
||||
*/
|
||||
Datum
|
||||
_bit(PG_FUNCTION_ARGS)
|
||||
{
|
||||
ArrayType *v = PG_GETARG_ARRAYTYPE_P(0);
|
||||
int32 len = PG_GETARG_INT32(1);
|
||||
FunctionCallInfoData locfcinfo;
|
||||
rlen = VARBITTOTALLEN(len);
|
||||
result = (VarBit *) palloc(rlen);
|
||||
/* set to 0 so that string is zero-padded */
|
||||
MemSet(result, 0, rlen);
|
||||
VARATT_SIZEP(result) = rlen;
|
||||
VARBITLEN(result) = len;
|
||||
|
||||
memcpy(VARBITS(result), VARBITS(arg),
|
||||
Min(VARBITBYTES(result), VARBITBYTES(arg)));
|
||||
|
||||
/*
|
||||
* Since bit() is a built-in function, we should only need to look it
|
||||
* up once per run.
|
||||
* Make sure last byte is zero-padded if needed. This is useless but
|
||||
* safe if source data was shorter than target length (we assume the
|
||||
* last byte of the source data was itself correctly zero-padded).
|
||||
*/
|
||||
static FmgrInfo bit_finfo;
|
||||
ipad = VARBITPAD(result);
|
||||
if (ipad > 0)
|
||||
{
|
||||
mask = BITMASK << ipad;
|
||||
*(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
|
||||
}
|
||||
|
||||
if (bit_finfo.fn_oid == InvalidOid)
|
||||
fmgr_info_cxt(F_BIT, &bit_finfo, TopMemoryContext);
|
||||
|
||||
MemSet(&locfcinfo, 0, sizeof(locfcinfo));
|
||||
locfcinfo.flinfo = &bit_finfo;
|
||||
locfcinfo.nargs = 2;
|
||||
/* We assume we are "strict" and need not worry about null inputs */
|
||||
locfcinfo.arg[0] = PointerGetDatum(v);
|
||||
locfcinfo.arg[1] = Int32GetDatum(len);
|
||||
|
||||
return array_map(&locfcinfo, BITOID, BITOID);
|
||||
PG_RETURN_VARBIT_P(result);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -311,7 +318,7 @@ varbit_in(PG_FUNCTION_ARGS)
|
||||
len = VARBITTOTALLEN(bitlen);
|
||||
result = (VarBit *) palloc(len);
|
||||
/* set to 0 so that *r is always initialised and string is zero-padded */
|
||||
memset(result, 0, len);
|
||||
MemSet(result, 0, len);
|
||||
VARATT_SIZEP(result) = len;
|
||||
VARBITLEN(result) = Min(bitlen, atttypmod);
|
||||
|
||||
@ -406,20 +413,26 @@ varbit_out(PG_FUNCTION_ARGS)
|
||||
/* varbit()
|
||||
* Converts a varbit() type to a specific internal length.
|
||||
* len is the maximum bitlength specified in the column definition.
|
||||
*
|
||||
* If doing implicit cast, raise error when source data is too long.
|
||||
* If doing explicit cast, silently truncate to max length.
|
||||
*/
|
||||
Datum
|
||||
varbit(PG_FUNCTION_ARGS)
|
||||
{
|
||||
VarBit *arg = PG_GETARG_VARBIT_P(0);
|
||||
int32 len = PG_GETARG_INT32(1);
|
||||
bool isExplicit = PG_GETARG_BOOL(2);
|
||||
VarBit *result;
|
||||
int rlen;
|
||||
int ipad;
|
||||
bits8 mask;
|
||||
|
||||
/* No work if typmod is invalid or supplied data matches it already */
|
||||
if (len <= 0 || len >= VARBITLEN(arg))
|
||||
PG_RETURN_VARBIT_P(arg);
|
||||
|
||||
if (len < VARBITLEN(arg))
|
||||
if (!isExplicit)
|
||||
elog(ERROR, "Bit string too long for type BIT VARYING(%d)", len);
|
||||
|
||||
rlen = VARBITTOTALLEN(len);
|
||||
@ -429,39 +442,17 @@ varbit(PG_FUNCTION_ARGS)
|
||||
|
||||
memcpy(VARBITS(result), VARBITS(arg), VARBITBYTES(result));
|
||||
|
||||
/* Make sure last byte is zero-padded if needed */
|
||||
ipad = VARBITPAD(result);
|
||||
if (ipad > 0)
|
||||
{
|
||||
mask = BITMASK << ipad;
|
||||
*(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
|
||||
}
|
||||
|
||||
PG_RETURN_VARBIT_P(result);
|
||||
}
|
||||
|
||||
/* _varbit()
|
||||
* Converts an array of bit() elements to a specific internal length.
|
||||
* len is the maximum bitlength specified in the column definition.
|
||||
*/
|
||||
Datum
|
||||
_varbit(PG_FUNCTION_ARGS)
|
||||
{
|
||||
ArrayType *v = PG_GETARG_ARRAYTYPE_P(0);
|
||||
int32 len = PG_GETARG_INT32(1);
|
||||
FunctionCallInfoData locfcinfo;
|
||||
|
||||
/*
|
||||
* Since varbit() is a built-in function, we should only need to look
|
||||
* it up once per run.
|
||||
*/
|
||||
static FmgrInfo varbit_finfo;
|
||||
|
||||
if (varbit_finfo.fn_oid == InvalidOid)
|
||||
fmgr_info_cxt(F_VARBIT, &varbit_finfo, TopMemoryContext);
|
||||
|
||||
MemSet(&locfcinfo, 0, sizeof(locfcinfo));
|
||||
locfcinfo.flinfo = &varbit_finfo;
|
||||
locfcinfo.nargs = 2;
|
||||
/* We assume we are "strict" and need not worry about null inputs */
|
||||
locfcinfo.arg[0] = PointerGetDatum(v);
|
||||
locfcinfo.arg[1] = Int32GetDatum(len);
|
||||
|
||||
return array_map(&locfcinfo, VARBITOID, VARBITOID);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Comparison operators
|
||||
@ -978,7 +969,7 @@ bitshiftleft(PG_FUNCTION_ARGS)
|
||||
/* If we shifted all the bits out, return an all-zero string */
|
||||
if (shft >= VARBITLEN(arg))
|
||||
{
|
||||
memset(r, 0, VARBITBYTES(arg));
|
||||
MemSet(r, 0, VARBITBYTES(arg));
|
||||
PG_RETURN_VARBIT_P(result);
|
||||
}
|
||||
|
||||
@ -991,7 +982,7 @@ bitshiftleft(PG_FUNCTION_ARGS)
|
||||
/* Special case: we can do a memcpy */
|
||||
len = VARBITBYTES(arg) - byte_shift;
|
||||
memcpy(r, p, len);
|
||||
memset(r + len, 0, byte_shift);
|
||||
MemSet(r + len, 0, byte_shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1037,7 +1028,7 @@ bitshiftright(PG_FUNCTION_ARGS)
|
||||
/* If we shifted all the bits out, return an all-zero string */
|
||||
if (shft >= VARBITLEN(arg))
|
||||
{
|
||||
memset(r, 0, VARBITBYTES(arg));
|
||||
MemSet(r, 0, VARBITBYTES(arg));
|
||||
PG_RETURN_VARBIT_P(result);
|
||||
}
|
||||
|
||||
@ -1046,7 +1037,7 @@ bitshiftright(PG_FUNCTION_ARGS)
|
||||
p = VARBITS(arg);
|
||||
|
||||
/* Set the first part of the result to 0 */
|
||||
memset(r, 0, byte_shift);
|
||||
MemSet(r, 0, byte_shift);
|
||||
r += byte_shift;
|
||||
|
||||
if (ishift == 0)
|
||||
|
Reference in New Issue
Block a user