mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Change typreceive function API so that receive functions get the same
optional arguments as text input functions, ie, typioparam OID and atttypmod. Make all the datatypes that use typmod enforce it the same way in typreceive as they do in typinput. This fixes a problem with failure to enforce length restrictions during COPY FROM BINARY.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.246 2005/06/28 05:08:53 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.247 2005/07/10 21:13:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -144,7 +144,7 @@ static char *CopyReadAttributeCSV(const char *delim, const char *null_print,
|
||||
char *quote, char *escape,
|
||||
CopyReadResult *result, bool *isnull);
|
||||
static Datum CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo,
|
||||
Oid typioparam, bool *isnull);
|
||||
Oid typioparam, int32 typmod, bool *isnull);
|
||||
static void CopyAttributeOut(char *string, char *delim);
|
||||
static void CopyAttributeOutCSV(char *string, char *delim, char *quote,
|
||||
char *escape, bool force_quote);
|
||||
@@ -1843,8 +1843,9 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
copy_attname = "oid";
|
||||
loaded_oid =
|
||||
DatumGetObjectId(CopyReadBinaryAttribute(0,
|
||||
&oid_in_function,
|
||||
oid_typioparam,
|
||||
&oid_in_function,
|
||||
oid_typioparam,
|
||||
-1,
|
||||
&isnull));
|
||||
if (isnull || loaded_oid == InvalidOid)
|
||||
ereport(ERROR,
|
||||
@@ -1864,6 +1865,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
||||
values[m] = CopyReadBinaryAttribute(i,
|
||||
&in_functions[m],
|
||||
typioparams[m],
|
||||
attr[m]->atttypmod,
|
||||
&isnull);
|
||||
nulls[m] = isnull ? 'n' : ' ';
|
||||
copy_attname = NULL;
|
||||
@@ -2556,7 +2558,8 @@ CopyReadAttributeCSV(const char *delim, const char *null_print, char *quote,
|
||||
* Read a binary attribute
|
||||
*/
|
||||
static Datum
|
||||
CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo, Oid typioparam,
|
||||
CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo,
|
||||
Oid typioparam, int32 typmod,
|
||||
bool *isnull)
|
||||
{
|
||||
int32 fld_size;
|
||||
@@ -2594,9 +2597,10 @@ CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo, Oid typioparam,
|
||||
attribute_buf.data[fld_size] = '\0';
|
||||
|
||||
/* Call the column type's binary input converter */
|
||||
result = FunctionCall2(flinfo,
|
||||
result = FunctionCall3(flinfo,
|
||||
PointerGetDatum(&attribute_buf),
|
||||
ObjectIdGetDatum(typioparam));
|
||||
ObjectIdGetDatum(typioparam),
|
||||
Int32GetDatum(typmod));
|
||||
|
||||
/* Trouble if it didn't eat the whole buffer */
|
||||
if (attribute_buf.cursor != attribute_buf.len)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.74 2005/07/07 20:39:58 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.75 2005/07/10 21:13:58 tgl Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@@ -859,7 +859,7 @@ findTypeInputFunction(List *procname, Oid typeOid)
|
||||
|
||||
/*
|
||||
* Input functions can take a single argument of type CSTRING, or
|
||||
* three arguments (string, element OID, typmod).
|
||||
* three arguments (string, typioparam OID, typmod).
|
||||
*
|
||||
* For backwards compatibility we allow OPAQUE in place of CSTRING; if we
|
||||
* see this, we issue a warning and fix up the pg_proc entry.
|
||||
@@ -973,12 +973,12 @@ findTypeOutputFunction(List *procname, Oid typeOid)
|
||||
static Oid
|
||||
findTypeReceiveFunction(List *procname, Oid typeOid)
|
||||
{
|
||||
Oid argList[2];
|
||||
Oid argList[3];
|
||||
Oid procOid;
|
||||
|
||||
/*
|
||||
* Receive functions can take a single argument of type INTERNAL, or
|
||||
* two arguments (internal, oid).
|
||||
* three arguments (internal, typioparam OID, typmod).
|
||||
*/
|
||||
argList[0] = INTERNALOID;
|
||||
|
||||
@@ -987,8 +987,9 @@ findTypeReceiveFunction(List *procname, Oid typeOid)
|
||||
return procOid;
|
||||
|
||||
argList[1] = OIDOID;
|
||||
argList[2] = INT4OID;
|
||||
|
||||
procOid = LookupFuncName(procname, 2, argList, true);
|
||||
procOid = LookupFuncName(procname, 3, argList, true);
|
||||
if (OidIsValid(procOid))
|
||||
return procOid;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/tcop/fastpath.c,v 1.80 2005/05/01 18:56:18 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/tcop/fastpath.c,v 1.81 2005/07/10 21:13:58 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* This cruft is the server side of PQfn.
|
||||
@@ -493,9 +493,10 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info * fip,
|
||||
/* Call the argument type's binary input converter */
|
||||
getTypeBinaryInputInfo(fip->argtypes[i], &typreceive, &typioparam);
|
||||
|
||||
fcinfo->arg[i] = OidFunctionCall2(typreceive,
|
||||
fcinfo->arg[i] = OidFunctionCall3(typreceive,
|
||||
PointerGetDatum(&abuf),
|
||||
ObjectIdGetDatum(typioparam));
|
||||
ObjectIdGetDatum(typioparam),
|
||||
Int32GetDatum(-1));
|
||||
|
||||
/* Trouble if it didn't eat the whole buffer */
|
||||
if (abuf.cursor != abuf.len)
|
||||
@@ -579,9 +580,10 @@ parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info * fip,
|
||||
/* Call the argument type's binary input converter */
|
||||
getTypeBinaryInputInfo(fip->argtypes[i], &typreceive, &typioparam);
|
||||
|
||||
fcinfo->arg[i] = OidFunctionCall2(typreceive,
|
||||
fcinfo->arg[i] = OidFunctionCall3(typreceive,
|
||||
PointerGetDatum(&abuf),
|
||||
ObjectIdGetDatum(typioparam));
|
||||
ObjectIdGetDatum(typioparam),
|
||||
Int32GetDatum(-1));
|
||||
|
||||
/* Trouble if it didn't eat the whole buffer */
|
||||
if (abuf.cursor != abuf.len)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.452 2005/07/04 04:51:49 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.453 2005/07/10 21:13:58 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* this is the "main" module of the postgres backend and
|
||||
@@ -1571,9 +1571,10 @@ exec_bind_message(StringInfo input_message)
|
||||
getTypeBinaryInputInfo(ptype, &typreceive, &typioparam);
|
||||
|
||||
params[i].value =
|
||||
OidFunctionCall2(typreceive,
|
||||
OidFunctionCall3(typreceive,
|
||||
PointerGetDatum(&pbuf),
|
||||
ObjectIdGetDatum(typioparam));
|
||||
ObjectIdGetDatum(typioparam),
|
||||
Int32GetDatum(-1));
|
||||
|
||||
/* Trouble if it didn't eat the whole buffer */
|
||||
if (pbuf.cursor != pbuf.len)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.120 2005/05/01 18:56:18 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.121 2005/07/10 21:13:58 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -81,7 +81,7 @@ static Datum *ReadArrayStr(char *arrayStr, const char *origStr,
|
||||
int typlen, bool typbyval, char typalign,
|
||||
int *nbytes);
|
||||
static Datum *ReadArrayBinary(StringInfo buf, int nitems,
|
||||
FmgrInfo *receiveproc, Oid typioparam,
|
||||
FmgrInfo *receiveproc, Oid typioparam, int32 typmod,
|
||||
int typlen, bool typbyval, char typalign,
|
||||
int *nbytes);
|
||||
static void CopyArrayEls(char *p, Datum *values, int nitems,
|
||||
@@ -1121,6 +1121,8 @@ array_recv(PG_FUNCTION_ARGS)
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
Oid spec_element_type = PG_GETARG_OID(1); /* type of an array
|
||||
* element */
|
||||
int32 typmod = PG_GETARG_INT32(2); /* typmod for array
|
||||
* elements */
|
||||
Oid element_type;
|
||||
int typlen;
|
||||
bool typbyval;
|
||||
@@ -1215,7 +1217,8 @@ array_recv(PG_FUNCTION_ARGS)
|
||||
typalign = my_extra->typalign;
|
||||
typioparam = my_extra->typioparam;
|
||||
|
||||
dataPtr = ReadArrayBinary(buf, nitems, &my_extra->proc, typioparam,
|
||||
dataPtr = ReadArrayBinary(buf, nitems, &my_extra->proc,
|
||||
typioparam, typmod,
|
||||
typlen, typbyval, typalign,
|
||||
&nbytes);
|
||||
nbytes += ARR_OVERHEAD(ndim);
|
||||
@@ -1249,6 +1252,7 @@ ReadArrayBinary(StringInfo buf,
|
||||
int nitems,
|
||||
FmgrInfo *receiveproc,
|
||||
Oid typioparam,
|
||||
int32 typmod,
|
||||
int typlen,
|
||||
bool typbyval,
|
||||
char typalign,
|
||||
@@ -1289,9 +1293,10 @@ ReadArrayBinary(StringInfo buf,
|
||||
buf->data[buf->cursor] = '\0';
|
||||
|
||||
/* Now call the element's receiveproc */
|
||||
values[i] = FunctionCall2(receiveproc,
|
||||
values[i] = FunctionCall3(receiveproc,
|
||||
PointerGetDatum(&elem_buf),
|
||||
ObjectIdGetDatum(typioparam));
|
||||
ObjectIdGetDatum(typioparam),
|
||||
Int32GetDatum(typmod));
|
||||
|
||||
/* Trouble if it didn't eat the whole buffer */
|
||||
if (elem_buf.cursor != itemlen)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.110 2005/06/15 00:34:08 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.111 2005/07/10 21:13:59 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -982,12 +982,21 @@ Datum
|
||||
time_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
int32 typmod = PG_GETARG_INT32(2);
|
||||
TimeADT result;
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
PG_RETURN_TIMEADT((TimeADT) pq_getmsgint64(buf));
|
||||
result = pq_getmsgint64(buf);
|
||||
#else
|
||||
PG_RETURN_TIMEADT((TimeADT) pq_getmsgfloat8(buf));
|
||||
result = pq_getmsgfloat8(buf);
|
||||
#endif
|
||||
|
||||
AdjustTimeForTypmod(&result, typmod);
|
||||
|
||||
PG_RETURN_TIMEADT(result);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1774,18 +1783,24 @@ Datum
|
||||
timetz_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
TimeTzADT *time;
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
int32 typmod = PG_GETARG_INT32(2);
|
||||
TimeTzADT *result;
|
||||
|
||||
time = (TimeTzADT *) palloc(sizeof(TimeTzADT));
|
||||
result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
time->time = pq_getmsgint64(buf);
|
||||
result->time = pq_getmsgint64(buf);
|
||||
#else
|
||||
time->time = pq_getmsgfloat8(buf);
|
||||
result->time = pq_getmsgfloat8(buf);
|
||||
#endif
|
||||
time->zone = pq_getmsgint(buf, sizeof(time->zone));
|
||||
result->zone = pq_getmsgint(buf, sizeof(result->zone));
|
||||
|
||||
PG_RETURN_TIMETZADT_P(time);
|
||||
AdjustTimeForTypmod(&(result->time), typmod);
|
||||
|
||||
PG_RETURN_TIMETZADT_P(result);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* Copyright (c) 1998-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.84 2005/06/04 14:12:50 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.85 2005/07/10 21:13:59 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -383,6 +383,10 @@ Datum
|
||||
numeric_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
int32 typmod = PG_GETARG_INT32(2);
|
||||
NumericVar value;
|
||||
Numeric res;
|
||||
int len,
|
||||
@@ -419,6 +423,8 @@ numeric_recv(PG_FUNCTION_ARGS)
|
||||
value.digits[i] = d;
|
||||
}
|
||||
|
||||
apply_typmod(&value, typmod);
|
||||
|
||||
res = make_result(&value);
|
||||
free_var(&value);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.11 2005/05/01 18:56:18 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.12 2005/07/10 21:13:59 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -54,6 +54,9 @@ record_in(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *string = PG_GETARG_CSTRING(0);
|
||||
Oid tupType = PG_GETARG_OID(1);
|
||||
#ifdef NOT_USED
|
||||
int32 typmod = PG_GETARG_INT32(2);
|
||||
#endif
|
||||
HeapTupleHeader result;
|
||||
int32 tupTypmod;
|
||||
TupleDesc tupdesc;
|
||||
@@ -417,6 +420,9 @@ record_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
Oid tupType = PG_GETARG_OID(1);
|
||||
#ifdef NOT_USED
|
||||
int32 typmod = PG_GETARG_INT32(2);
|
||||
#endif
|
||||
HeapTupleHeader result;
|
||||
int32 tupTypmod;
|
||||
TupleDesc tupdesc;
|
||||
@@ -560,10 +566,10 @@ record_recv(PG_FUNCTION_ARGS)
|
||||
column_info->column_type = column_type;
|
||||
}
|
||||
|
||||
values[i] = FunctionCall2(&column_info->proc,
|
||||
values[i] = FunctionCall3(&column_info->proc,
|
||||
PointerGetDatum(&item_buf),
|
||||
ObjectIdGetDatum(column_info->typioparam));
|
||||
|
||||
ObjectIdGetDatum(column_info->typioparam),
|
||||
Int32GetDatum(tupdesc->attrs[i]->atttypmod));
|
||||
nulls[i] = ' ';
|
||||
|
||||
/* Trouble if it didn't eat the whole buffer */
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.129 2005/07/04 14:38:31 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.130 2005/07/10 21:13:59 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -170,6 +170,10 @@ Datum
|
||||
timestamp_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
int32 typmod = PG_GETARG_INT32(2);
|
||||
Timestamp timestamp;
|
||||
struct pg_tm tt,
|
||||
*tm = &tt;
|
||||
@@ -177,7 +181,6 @@ timestamp_recv(PG_FUNCTION_ARGS)
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
timestamp = (Timestamp) pq_getmsgint64(buf);
|
||||
|
||||
#else
|
||||
timestamp = (Timestamp) pq_getmsgfloat8(buf);
|
||||
#endif
|
||||
@@ -185,11 +188,13 @@ timestamp_recv(PG_FUNCTION_ARGS)
|
||||
/* rangecheck: see if timestamp_out would like it */
|
||||
if (TIMESTAMP_NOT_FINITE(timestamp))
|
||||
/* ok */ ;
|
||||
else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0)
|
||||
else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("timestamp out of range")));
|
||||
|
||||
AdjustTimestampForTypmod(×tamp, typmod);
|
||||
|
||||
PG_RETURN_TIMESTAMP(timestamp);
|
||||
}
|
||||
|
||||
@@ -409,6 +414,10 @@ Datum
|
||||
timestamptz_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
int32 typmod = PG_GETARG_INT32(2);
|
||||
TimestampTz timestamp;
|
||||
int tz;
|
||||
struct pg_tm tt,
|
||||
@@ -418,7 +427,6 @@ timestamptz_recv(PG_FUNCTION_ARGS)
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
timestamp = (TimestampTz) pq_getmsgint64(buf);
|
||||
|
||||
#else
|
||||
timestamp = (TimestampTz) pq_getmsgfloat8(buf);
|
||||
#endif
|
||||
@@ -431,6 +439,8 @@ timestamptz_recv(PG_FUNCTION_ARGS)
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("timestamp out of range")));
|
||||
|
||||
AdjustTimestampForTypmod(×tamp, typmod);
|
||||
|
||||
PG_RETURN_TIMESTAMPTZ(timestamp);
|
||||
}
|
||||
|
||||
@@ -526,7 +536,6 @@ interval_in(PG_FUNCTION_ARGS)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("interval out of range")));
|
||||
AdjustIntervalForTypmod(result, typmod);
|
||||
break;
|
||||
|
||||
case DTK_INVALID:
|
||||
@@ -540,6 +549,8 @@ interval_in(PG_FUNCTION_ARGS)
|
||||
dtype, str);
|
||||
}
|
||||
|
||||
AdjustIntervalForTypmod(result, typmod);
|
||||
|
||||
PG_RETURN_INTERVAL_P(result);
|
||||
}
|
||||
|
||||
@@ -573,18 +584,23 @@ Datum
|
||||
interval_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
int32 typmod = PG_GETARG_INT32(2);
|
||||
Interval *interval;
|
||||
|
||||
interval = (Interval *) palloc(sizeof(Interval));
|
||||
|
||||
#ifdef HAVE_INT64_TIMESTAMP
|
||||
interval->time = pq_getmsgint64(buf);
|
||||
|
||||
#else
|
||||
interval->time = pq_getmsgfloat8(buf);
|
||||
#endif
|
||||
interval->month = pq_getmsgint(buf, sizeof(interval->month));
|
||||
|
||||
AdjustIntervalForTypmod(interval, typmod);
|
||||
|
||||
PG_RETURN_INTERVAL_P(interval);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.44 2004/12/31 22:01:22 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.45 2005/07/10 21:13:59 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -221,8 +221,49 @@ bit_out(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
bit_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* Exactly the same as varbit_recv, so share code */
|
||||
return varbit_recv(fcinfo);
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
int32 atttypmod = PG_GETARG_INT32(2);
|
||||
VarBit *result;
|
||||
int len,
|
||||
bitlen;
|
||||
int ipad;
|
||||
bits8 mask;
|
||||
|
||||
bitlen = pq_getmsgint(buf, sizeof(int32));
|
||||
if (bitlen < 0)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
||||
errmsg("invalid length in external bit string")));
|
||||
|
||||
/*
|
||||
* Sometimes atttypmod is not supplied. If it is supplied we need to
|
||||
* make sure that the bitstring fits.
|
||||
*/
|
||||
if (atttypmod > 0 && bitlen != atttypmod)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
|
||||
errmsg("bit string length %d does not match type bit(%d)",
|
||||
bitlen, atttypmod)));
|
||||
|
||||
len = VARBITTOTALLEN(bitlen);
|
||||
result = (VarBit *) palloc(len);
|
||||
VARATT_SIZEP(result) = len;
|
||||
VARBITLEN(result) = bitlen;
|
||||
|
||||
pq_copymsgbytes(buf, (char *) VARBITS(result), 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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -459,6 +500,10 @@ Datum
|
||||
varbit_recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
int32 atttypmod = PG_GETARG_INT32(2);
|
||||
VarBit *result;
|
||||
int len,
|
||||
bitlen;
|
||||
@@ -471,6 +516,16 @@ varbit_recv(PG_FUNCTION_ARGS)
|
||||
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
||||
errmsg("invalid length in external bit string")));
|
||||
|
||||
/*
|
||||
* Sometimes atttypmod is not supplied. If it is supplied we need to
|
||||
* make sure that the bitstring fits.
|
||||
*/
|
||||
if (atttypmod > 0 && bitlen > atttypmod)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
||||
errmsg("bit string too long for type bit varying(%d)",
|
||||
atttypmod)));
|
||||
|
||||
len = VARBITTOTALLEN(bitlen);
|
||||
result = (VarBit *) palloc(len);
|
||||
VARATT_SIZEP(result) = len;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.110 2005/05/29 20:15:59 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.111 2005/07/10 21:13:59 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#include "access/hash.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "lib/stringinfo.h"
|
||||
#include "libpq/pqformat.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
@@ -53,28 +55,25 @@
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Convert a C string to CHARACTER internal representation. atttypmod
|
||||
* is the declared length of the type plus VARHDRSZ.
|
||||
* bpchar_input -- common guts of bpcharin and bpcharrecv
|
||||
*
|
||||
* If the C string is too long, raise an error, unless the extra
|
||||
* s is the input text of length len (may not be null-terminated)
|
||||
* atttypmod is the typmod value to apply
|
||||
*
|
||||
* 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
|
||||
* characters are spaces, in which case they're truncated. (per SQL)
|
||||
*/
|
||||
Datum
|
||||
bpcharin(PG_FUNCTION_ARGS)
|
||||
static BpChar *
|
||||
bpchar_input(const char *s, size_t len, int32 atttypmod)
|
||||
{
|
||||
char *s = PG_GETARG_CSTRING(0);
|
||||
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
int32 atttypmod = PG_GETARG_INT32(2);
|
||||
BpChar *result;
|
||||
char *r;
|
||||
size_t len,
|
||||
maxlen;
|
||||
size_t maxlen;
|
||||
|
||||
/* verify encoding */
|
||||
len = strlen(s);
|
||||
pg_verifymbstr(s, len, false);
|
||||
|
||||
/* If typmod is -1 (or invalid), use the actual string length */
|
||||
@@ -85,30 +84,32 @@ bpcharin(PG_FUNCTION_ARGS)
|
||||
size_t charlen; /* number of CHARACTERS in the input */
|
||||
|
||||
maxlen = atttypmod - VARHDRSZ;
|
||||
charlen = pg_mbstrlen(s);
|
||||
charlen = pg_mbstrlen_with_len(s, len);
|
||||
if (charlen > maxlen)
|
||||
{
|
||||
/* Verify that extra characters are spaces, and clip them off */
|
||||
size_t mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
|
||||
size_t j;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* bpchar type, mbmaxlen is the length in BYTES of those chars.
|
||||
*/
|
||||
if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
|
||||
len = mbmaxlen;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
||||
errmsg("value too long for type character(%d)",
|
||||
(int) maxlen)));
|
||||
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)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we set maxlen to the necessary byte length, not
|
||||
* the number of CHARACTERS!
|
||||
*/
|
||||
maxlen = len;
|
||||
maxlen = len = mbmaxlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -120,7 +121,7 @@ bpcharin(PG_FUNCTION_ARGS)
|
||||
}
|
||||
}
|
||||
|
||||
result = palloc(maxlen + VARHDRSZ);
|
||||
result = (BpChar *) palloc(maxlen + VARHDRSZ);
|
||||
VARATT_SIZEP(result) = maxlen + VARHDRSZ;
|
||||
r = VARDATA(result);
|
||||
memcpy(r, s, len);
|
||||
@@ -129,6 +130,24 @@ bpcharin(PG_FUNCTION_ARGS)
|
||||
if (maxlen > len)
|
||||
memset(r + len, ' ', maxlen - len);
|
||||
|
||||
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);
|
||||
#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);
|
||||
PG_RETURN_BPCHAR_P(result);
|
||||
}
|
||||
|
||||
@@ -158,8 +177,19 @@ bpcharout(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
bpcharrecv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* Exactly the same as textrecv, so share code */
|
||||
return textrecv(fcinfo);
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
#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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -344,30 +374,24 @@ name_bpchar(PG_FUNCTION_ARGS)
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Convert a C string to VARCHAR internal representation. atttypmod
|
||||
* is the declared length of the type plus VARHDRSZ.
|
||||
* varchar_input -- common guts of varcharin and varcharrecv
|
||||
*
|
||||
* Note that atttypmod is regarded as the number of characters, which
|
||||
* s is the input text of length len (may not be null-terminated)
|
||||
* atttypmod is the typmod value to apply
|
||||
*
|
||||
* Note that atttypmod is measured in characters, which
|
||||
* is not necessarily the same as the number of bytes.
|
||||
*
|
||||
* If the C string is too long, raise an error, unless the extra characters
|
||||
* are spaces, in which case they're truncated. (per SQL)
|
||||
* If the input string is too long, raise an error, unless the extra
|
||||
* characters are spaces, in which case they're truncated. (per SQL)
|
||||
*/
|
||||
Datum
|
||||
varcharin(PG_FUNCTION_ARGS)
|
||||
static VarChar *
|
||||
varchar_input(const char *s, size_t len, int32 atttypmod)
|
||||
{
|
||||
char *s = PG_GETARG_CSTRING(0);
|
||||
|
||||
#ifdef NOT_USED
|
||||
Oid typelem = PG_GETARG_OID(1);
|
||||
#endif
|
||||
int32 atttypmod = PG_GETARG_INT32(2);
|
||||
VarChar *result;
|
||||
size_t len,
|
||||
maxlen;
|
||||
size_t maxlen;
|
||||
|
||||
/* verify encoding */
|
||||
len = strlen(s);
|
||||
pg_verifymbstr(s, len, false);
|
||||
|
||||
maxlen = atttypmod - VARHDRSZ;
|
||||
@@ -376,20 +400,42 @@ varcharin(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* Verify that extra characters are spaces, and clip them off */
|
||||
size_t mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
|
||||
size_t j;
|
||||
|
||||
if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
|
||||
len = mbmaxlen;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
|
||||
errmsg("value too long for type character varying(%d)",
|
||||
(int) maxlen)));
|
||||
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;
|
||||
}
|
||||
|
||||
result = palloc(len + VARHDRSZ);
|
||||
result = (VarChar *) palloc(len + VARHDRSZ);
|
||||
VARATT_SIZEP(result) = len + VARHDRSZ;
|
||||
memcpy(VARDATA(result), s, len);
|
||||
|
||||
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);
|
||||
#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);
|
||||
PG_RETURN_VARCHAR_P(result);
|
||||
}
|
||||
|
||||
@@ -419,8 +465,19 @@ varcharout(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
varcharrecv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* Exactly the same as textrecv, so share code */
|
||||
return textrecv(fcinfo);
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
#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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.127 2005/07/10 04:54:30 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.128 2005/07/10 21:13:59 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -299,6 +299,10 @@ textrecv(PG_FUNCTION_ARGS)
|
||||
int nbytes;
|
||||
|
||||
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
|
||||
|
||||
/* verify encoding */
|
||||
pg_verifymbstr(str, nbytes, false);
|
||||
|
||||
result = (text *) palloc(nbytes + VARHDRSZ);
|
||||
VARATT_SIZEP(result) = nbytes + VARHDRSZ;
|
||||
memcpy(VARDATA(result), str, nbytes);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* (currently mule internal code (mic) is used)
|
||||
* Tatsuo Ishii
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/utils/mb/mbutils.c,v 1.49 2005/03/07 04:30:52 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/mb/mbutils.c,v 1.50 2005/07/10 21:13:59 tgl Exp $
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
@@ -489,16 +489,21 @@ pg_mbstrlen(const unsigned char *mbstr)
|
||||
}
|
||||
|
||||
/* returns the length (counted as a wchar) of a multibyte string
|
||||
(not necessarily NULL terminated) */
|
||||
* (not necessarily NULL terminated)
|
||||
*/
|
||||
int
|
||||
pg_mbstrlen_with_len(const unsigned char *mbstr, int limit)
|
||||
{
|
||||
int len = 0;
|
||||
int l;
|
||||
|
||||
/* optimization for single byte encoding */
|
||||
if (pg_database_encoding_max_length() == 1)
|
||||
return limit;
|
||||
|
||||
while (limit > 0 && *mbstr)
|
||||
{
|
||||
l = pg_mblen(mbstr);
|
||||
int l = pg_mblen(mbstr);
|
||||
|
||||
limit -= l;
|
||||
mbstr += l;
|
||||
len++;
|
||||
|
||||
Reference in New Issue
Block a user