1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-29 23:43:17 +03:00

Downgrade implicit casts to text to be assignment-only, except for the ones

from the other string-category types; this eliminates a lot of surprising
interpretations that the parser could formerly make when there was no directly
applicable operator.

Create a general mechanism that supports casts to and from the standard string
types (text,varchar,bpchar) for *every* datatype, by invoking the datatype's
I/O functions.  These new casts are assignment-only in the to-string direction,
explicit-only in the other, and therefore should create no surprising behavior.
Remove a bunch of thereby-obsoleted datatype-specific casting functions.

The "general mechanism" is a new expression node type CoerceViaIO that can
actually convert between *any* two datatypes if their external text
representations are compatible.  This is more general than needed for the
immediate feature, but might be useful in plpgsql or other places in future.

This commit does nothing about the issue that applying the concatenation
operator || to non-text types will now fail, often with strange error messages
due to misinterpreting the operator as array concatenation.  Since it often
(not always) worked before, we should either make it succeed or at least give
a more user-friendly error; but details are still under debate.

Peter Eisentraut and Tom Lane
This commit is contained in:
Tom Lane
2007-06-05 21:31:09 +00:00
parent 1120b99445
commit 31edbadf4a
60 changed files with 850 additions and 1612 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/bool.c,v 1.39 2007/06/01 23:40:18 neilc Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/bool.c,v 1.40 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -142,22 +142,11 @@ boolsend(PG_FUNCTION_ARGS)
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
/*
* textbool - cast function for text => bool
*/
Datum
textbool(PG_FUNCTION_ARGS)
{
Datum in_text = PG_GETARG_DATUM(0);
char *str;
str = DatumGetCString(DirectFunctionCall1(textout, in_text));
PG_RETURN_DATUM(DirectFunctionCall1(boolin, CStringGetDatum(str)));
}
/*
* booltext - cast function for bool => text
*
* We need this because it's different from the behavior of boolout();
* this function follows the SQL-spec result (except for producing lower case)
*/
Datum
booltext(PG_FUNCTION_ARGS)

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.131 2007/06/02 16:41:09 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.132 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -873,65 +873,6 @@ abstime_date(PG_FUNCTION_ARGS)
}
/* date_text()
* Convert date to text data type.
*/
Datum
date_text(PG_FUNCTION_ARGS)
{
/* Input is a Date, but may as well leave it in Datum form */
Datum date = PG_GETARG_DATUM(0);
text *result;
char *str;
int len;
str = DatumGetCString(DirectFunctionCall1(date_out, date));
len = strlen(str) + VARHDRSZ;
result = palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, (len - VARHDRSZ));
pfree(str);
PG_RETURN_TEXT_P(result);
}
/* text_date()
* Convert text string to date.
* Text type is not null terminated, so use temporary string
* then call the standard input routine.
*/
Datum
text_date(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
int i;
char *sp,
*dp,
dstr[MAXDATELEN + 1];
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid input syntax for type date: \"%s\"",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(str))))));
sp = VARDATA(str);
dp = dstr;
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
*dp++ = *sp++;
*dp = '\0';
return DirectFunctionCall1(date_in,
CStringGetDatum(dstr));
}
/*****************************************************************************
* Time ADT
*****************************************************************************/
@@ -1617,62 +1558,6 @@ time_mi_interval(PG_FUNCTION_ARGS)
}
/* time_text()
* Convert time to text data type.
*/
Datum
time_text(PG_FUNCTION_ARGS)
{
/* Input is a Time, but may as well leave it in Datum form */
Datum time = PG_GETARG_DATUM(0);
text *result;
char *str;
int len;
str = DatumGetCString(DirectFunctionCall1(time_out, time));
len = strlen(str) + VARHDRSZ;
result = palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, len - VARHDRSZ);
pfree(str);
PG_RETURN_TEXT_P(result);
}
/* text_time()
* Convert text string to time.
* Text type is not null terminated, so use temporary string
* then call the standard input routine.
*/
Datum
text_time(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
char dstr[MAXDATELEN + 1];
size_t len;
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid input syntax for type time: \"%s\"",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(str))))));
len = VARSIZE(str) - VARHDRSZ;
memcpy(dstr, VARDATA(str), len);
dstr[len] = '\0';
return DirectFunctionCall3(time_in,
CStringGetDatum(dstr),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
}
/* time_part()
* Extract specified field from time type.
*/
@@ -2400,66 +2285,6 @@ datetimetz_timestamptz(PG_FUNCTION_ARGS)
}
/* timetz_text()
* Convert timetz to text data type.
*/
Datum
timetz_text(PG_FUNCTION_ARGS)
{
/* Input is a Timetz, but may as well leave it in Datum form */
Datum timetz = PG_GETARG_DATUM(0);
text *result;
char *str;
int len;
str = DatumGetCString(DirectFunctionCall1(timetz_out, timetz));
len = strlen(str) + VARHDRSZ;
result = palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, (len - VARHDRSZ));
pfree(str);
PG_RETURN_TEXT_P(result);
}
/* text_timetz()
* Convert text string to timetz.
* Text type is not null terminated, so use temporary string
* then call the standard input routine.
*/
Datum
text_timetz(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
int i;
char *sp,
*dp,
dstr[MAXDATELEN + 1];
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid input syntax for type time with time zone: \"%s\"",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(str))))));
sp = VARDATA(str);
dp = dstr;
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
*dp++ = *sp++;
*dp = '\0';
return DirectFunctionCall3(timetz_in,
CStringGetDatum(dstr),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
}
/* timetz_part()
* Extract specified field from time type.
*/

View File

@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/enum.c,v 1.2 2007/04/02 22:14:17 adunstan Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/enum.c,v 1.3 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,8 +21,6 @@
#include "utils/syscache.h"
static Oid cstring_enum(char *name, Oid enumtypoid);
static char *enum_cstring(Oid enumval);
static ArrayType *enum_range_internal(Oid enumtypoid, Oid lower, Oid upper);
static int enum_elem_cmp(const void *left, const void *right);
@@ -32,75 +30,60 @@ static int enum_elem_cmp(const void *left, const void *right);
Datum
enum_in(PG_FUNCTION_ARGS)
{
char *name = PG_GETARG_CSTRING(0);
Oid enumtypoid = PG_GETARG_OID(1);
PG_RETURN_OID(cstring_enum(name, enumtypoid));
}
/* guts of enum_in and text-to-enum */
static Oid
cstring_enum(char *name, Oid enumtypoid)
{
HeapTuple tup;
char *name = PG_GETARG_CSTRING(0);
Oid enumtypoid = PG_GETARG_OID(1);
Oid enumoid;
HeapTuple tup;
/* must check length to prevent Assert failure within SearchSysCache */
if (strlen(name) >= NAMEDATALEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input value for enum %s: \"%s\"",
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input value for enum %s: \"%s\"",
format_type_be(enumtypoid),
name)));
name)));
tup = SearchSysCache(ENUMTYPOIDNAME,
ObjectIdGetDatum(enumtypoid),
CStringGetDatum(name),
0, 0);
if (tup == NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input value for enum %s: \"%s\"",
if (!HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input value for enum %s: \"%s\"",
format_type_be(enumtypoid),
name)));
name)));
enumoid = HeapTupleGetOid(tup);
ReleaseSysCache(tup);
return enumoid;
PG_RETURN_OID(enumoid);
}
Datum
enum_out(PG_FUNCTION_ARGS)
{
Oid enumoid = PG_GETARG_OID(0);
PG_RETURN_CSTRING(enum_cstring(enumoid));
}
/* guts of enum_out and enum-to-text */
static char *
enum_cstring(Oid enumval)
{
Oid enumval = PG_GETARG_OID(0);
char *result;
HeapTuple tup;
Form_pg_enum en;
char *label;
tup = SearchSysCache(ENUMOID,
ObjectIdGetDatum(enumval),
0, 0, 0);
if (tup == NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
errmsg("invalid internal value for enum: %u",
enumval)));
if (!HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
errmsg("invalid internal value for enum: %u",
enumval)));
en = (Form_pg_enum) GETSTRUCT(tup);
label = pstrdup(NameStr(en->enumlabel));
result = pstrdup(NameStr(en->enumlabel));
ReleaseSysCache(tup);
return label;
PG_RETURN_CSTRING(result);
}
/* Comparison functions and related */
@@ -191,47 +174,6 @@ enum_cmp(PG_FUNCTION_ARGS)
PG_RETURN_INT32(-1);
}
/* Casts between text and enum */
Datum
enum_text(PG_FUNCTION_ARGS)
{
Oid enumval = PG_GETARG_OID(0);
text *result;
char *cstr;
int len;
cstr = enum_cstring(enumval);
len = strlen(cstr);
result = (text *) palloc(VARHDRSZ + len);
SET_VARSIZE(result, VARHDRSZ + len);
memcpy(VARDATA(result), cstr, len);
pfree(cstr);
PG_RETURN_TEXT_P(result);
}
Datum
text_enum(PG_FUNCTION_ARGS)
{
text *textval = PG_GETARG_TEXT_P(0);
Oid enumtypoid;
char *str;
/*
* We rely on being able to get the specific enum type from the calling
* expression tree.
*/
enumtypoid = get_fn_expr_rettype(fcinfo->flinfo);
if (enumtypoid == InvalidOid)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("could not determine actual enum type")));
str = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(textval)));
PG_RETURN_OID(cstring_enum(str, enumtypoid));
}
/* Enum programming support functions */
Datum
@@ -266,7 +208,7 @@ enum_first(PG_FUNCTION_ARGS)
ReleaseCatCacheList(list);
if (!OidIsValid(min)) /* should not happen */
if (!OidIsValid(min)) /* should not happen */
elog(ERROR, "no values found for enum %s",
format_type_be(enumtypoid));
@@ -276,10 +218,10 @@ enum_first(PG_FUNCTION_ARGS)
Datum
enum_last(PG_FUNCTION_ARGS)
{
Oid enumtypoid;
Oid max = InvalidOid;
CatCList *list;
int num, i;
Oid enumtypoid;
Oid max = InvalidOid;
CatCList *list;
int num, i;
/*
* We rely on being able to get the specific enum type from the calling
@@ -292,24 +234,24 @@ enum_last(PG_FUNCTION_ARGS)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("could not determine actual enum type")));
list = SearchSysCacheList(ENUMTYPOIDNAME, 1,
ObjectIdGetDatum(enumtypoid),
list = SearchSysCacheList(ENUMTYPOIDNAME, 1,
ObjectIdGetDatum(enumtypoid),
0, 0, 0);
num = list->n_members;
for (i = 0; i < num; i++)
{
num = list->n_members;
for (i = 0; i < num; i++)
{
Oid valoid = HeapTupleHeaderGetOid(list->members[i]->tuple.t_data);
if(!OidIsValid(max) || valoid > max)
max = valoid;
}
if (!OidIsValid(max) || valoid > max)
max = valoid;
}
ReleaseCatCacheList(list);
if (!OidIsValid(max)) /* should not happen */
if (!OidIsValid(max)) /* should not happen */
elog(ERROR, "no values found for enum %s",
format_type_be(enumtypoid));
PG_RETURN_OID(max);
PG_RETURN_OID(max);
}
/* 2-argument variant of enum_range */
@@ -368,26 +310,26 @@ static ArrayType *
enum_range_internal(Oid enumtypoid, Oid lower, Oid upper)
{
ArrayType *result;
CatCList *list;
int total, i, j;
Datum *elems;
CatCList *list;
int total, i, j;
Datum *elems;
list = SearchSysCacheList(ENUMTYPOIDNAME, 1,
ObjectIdGetDatum(enumtypoid),
ObjectIdGetDatum(enumtypoid),
0, 0, 0);
total = list->n_members;
elems = (Datum *) palloc(total * sizeof(Datum));
j = 0;
for (i = 0; i < total; i++)
{
for (i = 0; i < total; i++)
{
Oid val = HeapTupleGetOid(&(list->members[i]->tuple));
if ((!OidIsValid(lower) || lower <= val) &&
(!OidIsValid(upper) || val <= upper))
elems[j++] = ObjectIdGetDatum(val);
}
elems[j++] = ObjectIdGetDatum(val);
}
/* shouldn't need the cache anymore */
ReleaseCatCacheList(list);

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.149 2007/02/27 23:48:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.150 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1196,108 +1196,6 @@ i2tof(PG_FUNCTION_ARGS)
}
/*
* float8_text - converts a float8 number to a text string
*/
Datum
float8_text(PG_FUNCTION_ARGS)
{
float8 num = PG_GETARG_FLOAT8(0);
text *result;
int len;
char *str;
str = DatumGetCString(DirectFunctionCall1(float8out,
Float8GetDatum(num)));
len = strlen(str) + VARHDRSZ;
result = (text *) palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, (len - VARHDRSZ));
pfree(str);
PG_RETURN_TEXT_P(result);
}
/*
* text_float8 - converts a text string to a float8 number
*/
Datum
text_float8(PG_FUNCTION_ARGS)
{
text *string = PG_GETARG_TEXT_P(0);
Datum result;
int len;
char *str;
len = (VARSIZE(string) - VARHDRSZ);
str = palloc(len + 1);
memcpy(str, VARDATA(string), len);
*(str + len) = '\0';
result = DirectFunctionCall1(float8in, CStringGetDatum(str));
pfree(str);
PG_RETURN_DATUM(result);
}
/*
* float4_text - converts a float4 number to a text string
*/
Datum
float4_text(PG_FUNCTION_ARGS)
{
float4 num = PG_GETARG_FLOAT4(0);
text *result;
int len;
char *str;
str = DatumGetCString(DirectFunctionCall1(float4out,
Float4GetDatum(num)));
len = strlen(str) + VARHDRSZ;
result = (text *) palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, (len - VARHDRSZ));
pfree(str);
PG_RETURN_TEXT_P(result);
}
/*
* text_float4 - converts a text string to a float4 number
*/
Datum
text_float4(PG_FUNCTION_ARGS)
{
text *string = PG_GETARG_TEXT_P(0);
Datum result;
int len;
char *str;
len = (VARSIZE(string) - VARHDRSZ);
str = palloc(len + 1);
memcpy(str, VARDATA(string), len);
*(str + len) = '\0';
result = DirectFunctionCall1(float4in, CStringGetDatum(str));
pfree(str);
PG_RETURN_DATUM(result);
}
/*
* =======================
* RANDOM FLOAT8 OPERATORS

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.79 2007/02/27 23:48:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.80 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,8 +18,6 @@
* int2in, int2out, int2recv, int2send
* int4in, int4out, int4recv, int4send
* int2vectorin, int2vectorout, int2vectorrecv, int2vectorsend
* Conversion routines:
* itoi, int2_text, int4_text
* Boolean operators:
* inteq, intne, intlt, intle, intgt, intge
* Arithmetic operators:
@@ -343,68 +341,6 @@ i4toi2(PG_FUNCTION_ARGS)
PG_RETURN_INT16((int16) arg1);
}
Datum
int2_text(PG_FUNCTION_ARGS)
{
int16 arg1 = PG_GETARG_INT16(0);
text *result = (text *) palloc(7 + VARHDRSZ); /* sign,5 digits, '\0' */
pg_itoa(arg1, VARDATA(result));
SET_VARSIZE(result, strlen(VARDATA(result)) + VARHDRSZ);
PG_RETURN_TEXT_P(result);
}
Datum
text_int2(PG_FUNCTION_ARGS)
{
text *string = PG_GETARG_TEXT_P(0);
Datum result;
int len;
char *str;
len = VARSIZE(string) - VARHDRSZ;
str = palloc(len + 1);
memcpy(str, VARDATA(string), len);
*(str + len) = '\0';
result = DirectFunctionCall1(int2in, CStringGetDatum(str));
pfree(str);
return result;
}
Datum
int4_text(PG_FUNCTION_ARGS)
{
int32 arg1 = PG_GETARG_INT32(0);
text *result = (text *) palloc(12 + VARHDRSZ); /* sign,10 digits,'\0' */
pg_ltoa(arg1, VARDATA(result));
SET_VARSIZE(result, strlen(VARDATA(result)) + VARHDRSZ);
PG_RETURN_TEXT_P(result);
}
Datum
text_int4(PG_FUNCTION_ARGS)
{
text *string = PG_GETARG_TEXT_P(0);
Datum result;
int len;
char *str;
len = VARSIZE(string) - VARHDRSZ;
str = palloc(len + 1);
memcpy(str, VARDATA(string), len);
*(str + len) = '\0';
result = DirectFunctionCall1(int4in, CStringGetDatum(str));
pfree(str);
return result;
}
/* Cast int4 -> bool */
Datum
int4_bool(PG_FUNCTION_ARGS)

View File

@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.65 2007/02/27 23:48:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.66 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1137,48 +1137,6 @@ oidtoi8(PG_FUNCTION_ARGS)
PG_RETURN_INT64((int64) arg);
}
Datum
text_int8(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
int len;
char *s;
Datum result;
len = (VARSIZE(str) - VARHDRSZ);
s = palloc(len + 1);
memcpy(s, VARDATA(str), len);
*(s + len) = '\0';
result = DirectFunctionCall1(int8in, CStringGetDatum(s));
pfree(s);
return result;
}
Datum
int8_text(PG_FUNCTION_ARGS)
{
/* arg is int64, but easier to leave it as Datum */
Datum arg = PG_GETARG_DATUM(0);
char *s;
int len;
text *result;
s = DatumGetCString(DirectFunctionCall1(int8out, arg));
len = strlen(s);
result = (text *) palloc(VARHDRSZ + len);
SET_VARSIZE(result, VARHDRSZ + len);
memcpy(VARDATA(result), s, len);
pfree(s);
PG_RETURN_TEXT_P(result);
}
/*
* non-persistent numeric series generator
*/

View File

@@ -1,7 +1,7 @@
/*
* PostgreSQL type definitions for MAC addresses.
*
* $PostgreSQL: pgsql/src/backend/utils/adt/mac.c,v 1.37 2007/02/27 23:48:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/mac.c,v 1.38 2007/06/05 21:31:06 tgl Exp $
*/
#include "postgres.h"
@@ -144,59 +144,6 @@ macaddr_send(PG_FUNCTION_ARGS)
}
/*
* Convert macaddr to text data type.
*/
Datum
macaddr_text(PG_FUNCTION_ARGS)
{
/* Input is a macaddr, but may as well leave it in Datum form */
Datum addr = PG_GETARG_DATUM(0);
text *result;
char *str;
int len;
str = DatumGetCString(DirectFunctionCall1(macaddr_out, addr));
len = (strlen(str) + VARHDRSZ);
result = palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, (len - VARHDRSZ));
pfree(str);
PG_RETURN_TEXT_P(result);
}
/*
* Convert text to macaddr data type.
*/
Datum
text_macaddr(PG_FUNCTION_ARGS)
{
text *addr = PG_GETARG_TEXT_P(0);
Datum result;
char str[100];
int len;
len = (VARSIZE(addr) - VARHDRSZ);
if (len >= sizeof(str))
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("text too long to convert to MAC address")));
memcpy(str, VARDATA(addr), len);
*(str + len) = '\0';
result = DirectFunctionCall1(macaddr_in, CStringGetDatum(str));
return result;
}
/*
* Comparison function for sorting:
*/

View File

@@ -1,7 +1,7 @@
/*
* PostgreSQL type definitions for the INET and CIDR types.
*
* $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.70 2007/05/17 23:31:49 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.71 2007/06/05 21:31:06 tgl Exp $
*
* Jon Postel RIP 16 Oct 1998
*/
@@ -22,7 +22,6 @@
#include "utils/inet.h"
static inet *text_network(text *src, bool is_cidr);
static int32 network_cmp_internal(inet *a1, inet *a2);
static int bitncmp(void *l, void *r, int n);
static bool addressOK(unsigned char *a, int bits, int family);
@@ -314,35 +313,6 @@ cidr_send(PG_FUNCTION_ARGS)
}
static inet *
text_network(text *src, bool is_cidr)
{
int len = VARSIZE(src) - VARHDRSZ;
char *str = palloc(len + 1);
memcpy(str, VARDATA(src), len);
str[len] = '\0';
return network_in(str, is_cidr);
}
Datum
text_inet(PG_FUNCTION_ARGS)
{
text *src = PG_GETARG_TEXT_P(0);
PG_RETURN_INET_P(text_network(src, false));
}
Datum
text_cidr(PG_FUNCTION_ARGS)
{
text *src = PG_GETARG_TEXT_P(0);
PG_RETURN_INET_P(text_network(src, true));
}
Datum
inet_to_cidr(PG_FUNCTION_ARGS)
{
@@ -655,6 +625,11 @@ network_host(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(ret);
}
/*
* network_show implements the inet and cidr casts to text. This is not
* quite the same behavior as network_out, hence we can't drop it in favor
* of CoerceViaIO.
*/
Datum
network_show(PG_FUNCTION_ARGS)
{

View File

@@ -14,7 +14,7 @@
* Copyright (c) 1998-2007, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.102 2007/05/08 18:56:47 neilc Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.103 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2146,50 +2146,6 @@ numeric_float4(PG_FUNCTION_ARGS)
}
Datum
text_numeric(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
int len;
char *s;
Datum result;
len = (VARSIZE(str) - VARHDRSZ);
s = palloc(len + 1);
memcpy(s, VARDATA(str), len);
*(s + len) = '\0';
result = DirectFunctionCall3(numeric_in, CStringGetDatum(s),
ObjectIdGetDatum(0), Int32GetDatum(-1));
pfree(s);
return result;
}
Datum
numeric_text(PG_FUNCTION_ARGS)
{
/* val is numeric, but easier to leave it as Datum */
Datum val = PG_GETARG_DATUM(0);
char *s;
int len;
text *result;
s = DatumGetCString(DirectFunctionCall1(numeric_out, val));
len = strlen(s);
result = (text *) palloc(VARHDRSZ + len);
SET_VARSIZE(result, VARHDRSZ + len);
memcpy(VARDATA(result), s, len);
pfree(s);
PG_RETURN_TEXT_P(result);
}
/* ----------------------------------------------------------------------
*
* Aggregate functions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.71 2007/02/27 23:48:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.72 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -31,7 +31,7 @@
*****************************************************************************/
static Oid
oidin_subr(const char *funcname, const char *s, char **endloc)
oidin_subr(const char *s, char **endloc)
{
unsigned long cvt;
char *endptr;
@@ -116,7 +116,7 @@ oidin(PG_FUNCTION_ARGS)
char *s = PG_GETARG_CSTRING(0);
Oid result;
result = oidin_subr("oidin", s, NULL);
result = oidin_subr(s, NULL);
PG_RETURN_OID(result);
}
@@ -202,7 +202,7 @@ oidvectorin(PG_FUNCTION_ARGS)
oidString++;
if (*oidString == '\0')
break;
result->values[n] = oidin_subr("oidvectorin", oidString, &oidString);
result->values[n] = oidin_subr(oidString, &oidString);
}
while (*oidString && isspace((unsigned char) *oidString))
oidString++;
@@ -419,45 +419,3 @@ oidvectorgt(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(cmp > 0);
}
Datum
oid_text(PG_FUNCTION_ARGS)
{
Oid oid = PG_GETARG_OID(0);
text *result;
int len;
char *str;
str = DatumGetCString(DirectFunctionCall1(oidout,
ObjectIdGetDatum(oid)));
len = strlen(str) + VARHDRSZ;
result = (text *) palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, (len - VARHDRSZ));
pfree(str);
PG_RETURN_TEXT_P(result);
}
Datum
text_oid(PG_FUNCTION_ARGS)
{
text *string = PG_GETARG_TEXT_P(0);
Oid result;
int len;
char *str;
len = (VARSIZE(string) - VARHDRSZ);
str = palloc(len + 1);
memcpy(str, VARDATA(string), len);
*(str + len) = '\0';
result = oidin_subr("text_oid", str, NULL);
pfree(str);
PG_RETURN_OID(result);
}

View File

@@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.100 2007/01/05 22:19:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.101 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1070,6 +1070,10 @@ regtypesend(PG_FUNCTION_ARGS)
/*
* text_regclass: convert text to regclass
*
* This could be replaced by CoerceViaIO, except that we need to treat
* text-to-regclass as an implicit cast to support legacy forms of nextval()
* and related functions.
*/
Datum
text_regclass(PG_FUNCTION_ARGS)

View File

@@ -15,7 +15,7 @@
*
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.94 2007/03/27 23:21:10 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.95 2007/06/05 21:31:06 tgl Exp $
*
* ----------
*/
@@ -3871,7 +3871,7 @@ ri_HashCompareOp(Oid eq_opr, Oid typeid)
Oid lefttype,
righttype,
castfunc;
bool arrayCoerce;
CoercionPathType pathtype;
/* We always need to know how to call the equality operator */
fmgr_info_cxt(get_opcode(eq_opr), &entry->eq_opr_finfo,
@@ -3885,20 +3885,28 @@ ri_HashCompareOp(Oid eq_opr, Oid typeid)
* here and in ri_AttributesEqual(). At the moment there is no
* point because cases involving nonidentical array types will
* be rejected at constraint creation time.
*
* XXX perhaps also consider supporting CoerceViaIO? No need at the
* moment since that will never be generated for implicit coercions.
*/
op_input_types(eq_opr, &lefttype, &righttype);
Assert(lefttype == righttype);
if (typeid == lefttype)
castfunc = InvalidOid; /* simplest case */
else if (!find_coercion_pathway(lefttype, typeid, COERCION_IMPLICIT,
&castfunc, &arrayCoerce)
|| arrayCoerce) /* XXX fixme */
else
{
/* If target is ANYARRAY, assume it's OK, else punt. */
if (lefttype != ANYARRAYOID)
elog(ERROR, "no conversion function from %s to %s",
format_type_be(typeid),
format_type_be(lefttype));
pathtype = find_coercion_pathway(lefttype, typeid,
COERCION_IMPLICIT,
&castfunc);
if (pathtype != COERCION_PATH_FUNC &&
pathtype != COERCION_PATH_RELABELTYPE)
{
/* If target is ANYARRAY, assume it's OK, else punt. */
if (lefttype != ANYARRAYOID)
elog(ERROR, "no conversion function from %s to %s",
format_type_be(typeid),
format_type_be(lefttype));
}
}
if (OidIsValid(castfunc))
fmgr_info_cxt(castfunc, &entry->cast_func_finfo,

View File

@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.258 2007/05/24 18:58:42 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.259 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -3127,6 +3127,9 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_RelabelType:
return isSimpleNode((Node *) ((RelabelType *) node)->arg,
node, prettyFlags);
case T_CoerceViaIO:
return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
node, prettyFlags);
case T_ArrayCoerceExpr:
return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
node, prettyFlags);
@@ -3595,6 +3598,27 @@ get_rule_expr(Node *node, deparse_context *context,
}
break;
case T_CoerceViaIO:
{
CoerceViaIO *iocoerce = (CoerceViaIO *) node;
Node *arg = (Node *) iocoerce->arg;
if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
!showimplicit)
{
/* don't show the implicit cast */
get_rule_expr_paren(arg, context, false, node);
}
else
{
get_coercion_expr(arg, context,
iocoerce->resulttype,
-1,
node);
}
}
break;
case T_ArrayCoerceExpr:
{
ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.176 2007/04/30 21:01:52 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.177 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -3229,187 +3229,6 @@ timestamptz_age(PG_FUNCTION_ARGS)
*---------------------------------------------------------*/
/* timestamp_text()
* Convert timestamp to text data type.
*/
Datum
timestamp_text(PG_FUNCTION_ARGS)
{
/* Input is a Timestamp, but may as well leave it in Datum form */
Datum timestamp = PG_GETARG_DATUM(0);
text *result;
char *str;
int len;
str = DatumGetCString(DirectFunctionCall1(timestamp_out, timestamp));
len = (strlen(str) + VARHDRSZ);
result = palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, len - VARHDRSZ);
pfree(str);
PG_RETURN_TEXT_P(result);
}
/* text_timestamp()
* Convert text string to timestamp.
* Text type is not null terminated, so use temporary string
* then call the standard input routine.
*/
Datum
text_timestamp(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
int i;
char *sp,
*dp,
dstr[MAXDATELEN + 1];
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid input syntax for type timestamp: \"%s\"",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(str))))));
sp = VARDATA(str);
dp = dstr;
for (i = 0; i < VARSIZE(str) - VARHDRSZ; i++)
*dp++ = *sp++;
*dp = '\0';
return DirectFunctionCall3(timestamp_in,
CStringGetDatum(dstr),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
}
/* timestamptz_text()
* Convert timestamp with time zone to text data type.
*/
Datum
timestamptz_text(PG_FUNCTION_ARGS)
{
/* Input is a Timestamp, but may as well leave it in Datum form */
Datum timestamp = PG_GETARG_DATUM(0);
text *result;
char *str;
int len;
str = DatumGetCString(DirectFunctionCall1(timestamptz_out, timestamp));
len = strlen(str) + VARHDRSZ;
result = palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, len - VARHDRSZ);
pfree(str);
PG_RETURN_TEXT_P(result);
}
/* text_timestamptz()
* Convert text string to timestamp with time zone.
* Text type is not null terminated, so use temporary string
* then call the standard input routine.
*/
Datum
text_timestamptz(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
int i;
char *sp,
*dp,
dstr[MAXDATELEN + 1];
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid input syntax for type timestamp with time zone: \"%s\"",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(str))))));
sp = VARDATA(str);
dp = dstr;
for (i = 0; i < VARSIZE(str) - VARHDRSZ; i++)
*dp++ = *sp++;
*dp = '\0';
return DirectFunctionCall3(timestamptz_in,
CStringGetDatum(dstr),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
}
/* interval_text()
* Convert interval to text data type.
*/
Datum
interval_text(PG_FUNCTION_ARGS)
{
Interval *interval = PG_GETARG_INTERVAL_P(0);
text *result;
char *str;
int len;
str = DatumGetCString(DirectFunctionCall1(interval_out,
IntervalPGetDatum(interval)));
len = strlen(str) + VARHDRSZ;
result = palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, len - VARHDRSZ);
pfree(str);
PG_RETURN_TEXT_P(result);
}
/* text_interval()
* Convert text string to interval.
* Text type may not be null terminated, so copy to temporary string
* then call the standard input routine.
*/
Datum
text_interval(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
int i;
char *sp,
*dp,
dstr[MAXDATELEN + 1];
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid input syntax for type interval: \"%s\"",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(str))))));
sp = VARDATA(str);
dp = dstr;
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
*dp++ = *sp++;
*dp = '\0';
return DirectFunctionCall3(interval_in,
CStringGetDatum(dstr),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
}
/* timestamp_trunc()
* Truncate timestamp to specified units.
*/

View File

@@ -6,7 +6,7 @@
* Copyright (c) 2007, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/uuid.c,v 1.3 2007/01/31 19:33:54 neilc Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/uuid.c,v 1.4 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -238,32 +238,3 @@ uuid_hash(PG_FUNCTION_ARGS)
pg_uuid_t *key = PG_GETARG_UUID_P(0);
return hash_any(key->data, UUID_LEN);
}
/* cast text to uuid */
Datum
text_uuid(PG_FUNCTION_ARGS)
{
text *input = PG_GETARG_TEXT_P(0);
int length;
char *str;
Datum result;
length = VARSIZE(input) - VARHDRSZ;
str = palloc(length + 1);
memcpy(str, VARDATA(input), length);
*(str + length) = '\0';
result = DirectFunctionCall1(uuid_in, CStringGetDatum(str));
pfree(str);
PG_RETURN_DATUM(result);
}
/* cast uuid to text */
Datum
uuid_text(PG_FUNCTION_ARGS)
{
pg_uuid_t *uuid = PG_GETARG_UUID_P(0);
Datum uuid_str = DirectFunctionCall1(uuid_out, UUIDPGetDatum(uuid));
PG_RETURN_DATUM(DirectFunctionCall1(textin, uuid_str));
}