summaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
authorTom Lane2002-09-18 21:35:25 +0000
committerTom Lane2002-09-18 21:35:25 +0000
commitb26dfb95222fddd25322bdddf3a5a58d3392d8b1 (patch)
tree757cf0bafab985d38a5c84d3afebe5edd34c4f27 /src/backend/utils
parentcc70ba2e4daa78ba99619770e19beb06de3dfd1c (diff)
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.
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/adt/arrayfuncs.c69
-rw-r--r--src/backend/utils/adt/int8.c137
-rw-r--r--src/backend/utils/adt/numeric.c46
-rw-r--r--src/backend/utils/adt/regproc.c68
-rw-r--r--src/backend/utils/adt/ruleutils.c202
-rw-r--r--src/backend/utils/adt/varbit.c121
-rw-r--r--src/backend/utils/adt/varchar.c130
-rw-r--r--src/backend/utils/cache/lsyscache.c47
8 files changed, 422 insertions, 398 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 5d53eca999f..f8643388970 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.80 2002/09/04 20:31:27 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.81 2002/09/18 21:35:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -19,6 +19,7 @@
#include "access/tupmacs.h"
#include "catalog/catalog.h"
#include "catalog/pg_type.h"
+#include "parser/parse_coerce.h"
#include "utils/array.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
@@ -755,6 +756,72 @@ array_out(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(retval);
}
+/*-------------------------------------------------------------------------
+ * array_length_coerce :
+ * Apply the element type's length-coercion routine to each element
+ * of the given array.
+ *-------------------------------------------------------------------------
+ */
+Datum
+array_length_coerce(PG_FUNCTION_ARGS)
+{
+ ArrayType *v = PG_GETARG_ARRAYTYPE_P(0);
+ int32 len = PG_GETARG_INT32(1);
+ bool isExplicit = PG_GETARG_BOOL(2);
+ FmgrInfo *fmgr_info = fcinfo->flinfo;
+ FmgrInfo *element_finfo;
+ FunctionCallInfoData locfcinfo;
+
+ /* If no typmod is provided, shortcircuit the whole thing */
+ if (len < 0)
+ PG_RETURN_ARRAYTYPE_P(v);
+
+ /*
+ * We arrange to look up the element type's coercion function only
+ * once per series of calls.
+ */
+ if (fmgr_info->fn_extra == NULL)
+ {
+ Oid funcId;
+ int nargs;
+
+ fmgr_info->fn_extra = MemoryContextAlloc(fmgr_info->fn_mcxt,
+ sizeof(FmgrInfo));
+ element_finfo = (FmgrInfo *) fmgr_info->fn_extra;
+
+ funcId = find_typmod_coercion_function(ARR_ELEMTYPE(v), &nargs);
+
+ if (OidIsValid(funcId))
+ fmgr_info_cxt(funcId, element_finfo, fmgr_info->fn_mcxt);
+ else
+ element_finfo->fn_oid = InvalidOid;
+ }
+ else
+ element_finfo = (FmgrInfo *) fmgr_info->fn_extra;
+
+ /*
+ * If we didn't find a coercion function, return the array unmodified
+ * (this should not happen in the normal course of things, but might
+ * happen if this function is called manually).
+ */
+ if (element_finfo->fn_oid == InvalidOid)
+ PG_RETURN_ARRAYTYPE_P(v);
+
+ /*
+ * Use array_map to apply the function to each array element.
+ *
+ * Note: we pass isExplicit whether or not the function wants it ...
+ */
+ MemSet(&locfcinfo, 0, sizeof(locfcinfo));
+ locfcinfo.flinfo = element_finfo;
+ locfcinfo.nargs = 3;
+ locfcinfo.arg[0] = PointerGetDatum(v);
+ locfcinfo.arg[1] = Int32GetDatum(len);
+ locfcinfo.arg[2] = BoolGetDatum(isExplicit);
+
+ return array_map(&locfcinfo, ARR_ELEMTYPE(v), ARR_ELEMTYPE(v));
+}
+
/*-----------------------------------------------------------------------------
* array_dims :
* returns the dimensions of the array pointed to by "v", as a "text"
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index 267ad821037..8a346cd8b83 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.41 2002/09/04 20:31:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.42 2002/09/18 21:35:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -48,14 +48,16 @@
* Formatting and conversion routines.
*---------------------------------------------------------*/
-/* int8in()
+/*
+ * scanint8 --- try to parse a string into an int8.
+ *
+ * If errorOK is false, elog a useful error message if the string is bad.
+ * If errorOK is true, just return "false" for bad input.
*/
-Datum
-int8in(PG_FUNCTION_ARGS)
+bool
+scanint8(const char *str, bool errorOK, int64 *result)
{
- char *str = PG_GETARG_CSTRING(0);
- int64 result;
- char *ptr = str;
+ const char *ptr = str;
int64 tmp = 0;
int sign = 1;
@@ -63,8 +65,11 @@ int8in(PG_FUNCTION_ARGS)
* Do our own scan, rather than relying on sscanf which might be
* broken for long long.
*/
- while (*ptr && isspace((unsigned char) *ptr)) /* skip leading spaces */
+
+ /* skip leading spaces */
+ while (*ptr && isspace((unsigned char) *ptr))
ptr++;
+
/* handle sign */
if (*ptr == '-')
{
@@ -79,28 +84,61 @@ int8in(PG_FUNCTION_ARGS)
#ifndef INT64_IS_BUSTED
if (strcmp(ptr, "9223372036854775808") == 0)
{
- result = -INT64CONST(0x7fffffffffffffff) - 1;
- PG_RETURN_INT64(result);
+ *result = -INT64CONST(0x7fffffffffffffff) - 1;
+ return true;
}
#endif
}
else if (*ptr == '+')
ptr++;
- if (!isdigit((unsigned char) *ptr)) /* require at least one digit */
- elog(ERROR, "Bad int8 external representation \"%s\"", str);
- while (*ptr && isdigit((unsigned char) *ptr)) /* process digits */
+
+ /* require at least one digit */
+ if (!isdigit((unsigned char) *ptr))
+ {
+ if (errorOK)
+ return false;
+ else
+ elog(ERROR, "Bad int8 external representation \"%s\"", str);
+ }
+
+ /* process digits */
+ while (*ptr && isdigit((unsigned char) *ptr))
{
int64 newtmp = tmp * 10 + (*ptr++ - '0');
if ((newtmp / 10) != tmp) /* overflow? */
- elog(ERROR, "int8 value out of range: \"%s\"", str);
+ {
+ if (errorOK)
+ return false;
+ else
+ elog(ERROR, "int8 value out of range: \"%s\"", str);
+ }
tmp = newtmp;
}
- if (*ptr) /* trailing junk? */
- elog(ERROR, "Bad int8 external representation \"%s\"", str);
- result = (sign < 0) ? -tmp : tmp;
+ /* trailing junk? */
+ if (*ptr)
+ {
+ if (errorOK)
+ return false;
+ else
+ elog(ERROR, "Bad int8 external representation \"%s\"", str);
+ }
+ *result = (sign < 0) ? -tmp : tmp;
+
+ return true;
+}
+
+/* int8in()
+ */
+Datum
+int8in(PG_FUNCTION_ARGS)
+{
+ char *str = PG_GETARG_CSTRING(0);
+ int64 result;
+
+ (void) scanint8(str, false, &result);
PG_RETURN_INT64(result);
}
@@ -747,7 +785,7 @@ i8tod(PG_FUNCTION_ARGS)
}
/* dtoi8()
- * Convert double float to 8-byte integer.
+ * Convert float8 to 8-byte integer.
*/
Datum
dtoi8(PG_FUNCTION_ARGS)
@@ -771,9 +809,67 @@ dtoi8(PG_FUNCTION_ARGS)
PG_RETURN_INT64(result);
}
-/* text_int8()
+Datum
+i8tof(PG_FUNCTION_ARGS)
+{
+ int64 val = PG_GETARG_INT64(0);
+ float4 result;
+
+ result = val;
+
+ PG_RETURN_FLOAT4(result);
+}
+
+/* ftoi8()
+ * Convert float4 to 8-byte integer.
*/
Datum
+ftoi8(PG_FUNCTION_ARGS)
+{
+ float4 val = PG_GETARG_FLOAT4(0);
+ int64 result;
+ float8 dval;
+
+ /* Round val to nearest integer (but it's still in float form) */
+ dval = rint(val);
+
+ /*
+ * Does it fit in an int64? Avoid assuming that we have handy
+ * constants defined for the range boundaries, instead test for
+ * overflow by reverse-conversion.
+ */
+ result = (int64) dval;
+
+ if ((float8) result != dval)
+ elog(ERROR, "Floating point conversion to int8 is out of range");
+
+ PG_RETURN_INT64(result);
+}
+
+Datum
+i8tooid(PG_FUNCTION_ARGS)
+{
+ int64 val = PG_GETARG_INT64(0);
+ Oid result;
+
+ result = (Oid) val;
+
+ /* Test for overflow by reverse-conversion. */
+ if ((int64) result != val)
+ elog(ERROR, "int8 conversion to OID is out of range");
+
+ PG_RETURN_OID(result);
+}
+
+Datum
+oidtoi8(PG_FUNCTION_ARGS)
+{
+ Oid val = PG_GETARG_OID(0);
+
+ PG_RETURN_INT64((int64) val);
+}
+
+Datum
text_int8(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
@@ -793,9 +889,6 @@ text_int8(PG_FUNCTION_ARGS)
return result;
}
-
-/* int8_text()
- */
Datum
int8_text(PG_FUNCTION_ARGS)
{
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 228c43c6c46..4ea0fec1c1a 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -5,7 +5,7 @@
*
* 1998 Jan Wieck
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.53 2002/09/04 20:31:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.54 2002/09/18 21:35:22 tgl Exp $
*
* ----------
*/
@@ -1709,6 +1709,50 @@ 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);
+
+ VARATT_SIZEP(result) = len + VARHDRSZ;
+ memcpy(VARDATA(result), s, len);
+
+ pfree(s);
+
+ PG_RETURN_TEXT_P(result);
+}
+
+
/* ----------------------------------------------------------------------
*
* Aggregate functions
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index 22c93c431a0..638f5293ed2 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.75 2002/09/04 20:31:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.76 2002/09/18 21:35:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -49,7 +49,7 @@ static void parseNameAndArgTypes(const char *string, const char *caller,
/*
* regprocin - converts "proname" to proc OID
*
- * We also accept a numeric OID, mostly for historical reasons.
+ * We also accept a numeric OID, for symmetry with the output routine.
*
* '-' signifies unknown (OID 0). In all other cases, the input must
* match an existing pg_proc entry.
@@ -71,15 +71,8 @@ regprocin(PG_FUNCTION_ARGS)
pro_name_or_oid[0] <= '9' &&
strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
{
- Oid searchOid;
-
- searchOid = DatumGetObjectId(DirectFunctionCall1(oidin,
+ result = DatumGetObjectId(DirectFunctionCall1(oidin,
CStringGetDatum(pro_name_or_oid)));
- result = (RegProcedure) GetSysCacheOid(PROCOID,
- ObjectIdGetDatum(searchOid),
- 0, 0, 0);
- if (!RegProcedureIsValid(result))
- elog(ERROR, "No procedure with oid %s", pro_name_or_oid);
PG_RETURN_OID(result);
}
@@ -211,7 +204,7 @@ regprocout(PG_FUNCTION_ARGS)
/*
* regprocedurein - converts "proname(args)" to proc OID
*
- * We also accept a numeric OID, mostly for historical reasons.
+ * We also accept a numeric OID, for symmetry with the output routine.
*
* '-' signifies unknown (OID 0). In all other cases, the input must
* match an existing pg_proc entry.
@@ -235,15 +228,8 @@ regprocedurein(PG_FUNCTION_ARGS)
pro_name_or_oid[0] <= '9' &&
strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
{
- Oid searchOid;
-
- searchOid = DatumGetObjectId(DirectFunctionCall1(oidin,
+ result = DatumGetObjectId(DirectFunctionCall1(oidin,
CStringGetDatum(pro_name_or_oid)));
- result = (RegProcedure) GetSysCacheOid(PROCOID,
- ObjectIdGetDatum(searchOid),
- 0, 0, 0);
- if (!RegProcedureIsValid(result))
- elog(ERROR, "No procedure with oid %s", pro_name_or_oid);
PG_RETURN_OID(result);
}
@@ -361,7 +347,7 @@ regprocedureout(PG_FUNCTION_ARGS)
/*
* regoperin - converts "oprname" to operator OID
*
- * We also accept a numeric OID, mostly for historical reasons.
+ * We also accept a numeric OID, for symmetry with the output routine.
*
* '0' signifies unknown (OID 0). In all other cases, the input must
* match an existing pg_operator entry.
@@ -383,15 +369,8 @@ regoperin(PG_FUNCTION_ARGS)
opr_name_or_oid[0] <= '9' &&
strspn(opr_name_or_oid, "0123456789") == strlen(opr_name_or_oid))
{
- Oid searchOid;
-
- searchOid = DatumGetObjectId(DirectFunctionCall1(oidin,
+ result = DatumGetObjectId(DirectFunctionCall1(oidin,
CStringGetDatum(opr_name_or_oid)));
- result = GetSysCacheOid(OPEROID,
- ObjectIdGetDatum(searchOid),
- 0, 0, 0);
- if (!OidIsValid(result))
- elog(ERROR, "No operator with oid %s", opr_name_or_oid);
PG_RETURN_OID(result);
}
@@ -531,7 +510,7 @@ regoperout(PG_FUNCTION_ARGS)
/*
* regoperatorin - converts "oprname(args)" to operator OID
*
- * We also accept a numeric OID, mostly for historical reasons.
+ * We also accept a numeric OID, for symmetry with the output routine.
*
* '0' signifies unknown (OID 0). In all other cases, the input must
* match an existing pg_operator entry.
@@ -556,15 +535,8 @@ regoperatorin(PG_FUNCTION_ARGS)
opr_name_or_oid[0] <= '9' &&
strspn(opr_name_or_oid, "0123456789") == strlen(opr_name_or_oid))
{
- Oid searchOid;
-
- searchOid = DatumGetObjectId(DirectFunctionCall1(oidin,
+ result = DatumGetObjectId(DirectFunctionCall1(oidin,
CStringGetDatum(opr_name_or_oid)));
- result = GetSysCacheOid(OPEROID,
- ObjectIdGetDatum(searchOid),
- 0, 0, 0);
- if (!OidIsValid(result))
- elog(ERROR, "No operator with oid %s", opr_name_or_oid);
PG_RETURN_OID(result);
}
@@ -698,7 +670,7 @@ regoperatorout(PG_FUNCTION_ARGS)
/*
* regclassin - converts "classname" to class OID
*
- * We also accept a numeric OID, mostly for historical reasons.
+ * We also accept a numeric OID, for symmetry with the output routine.
*
* '-' signifies unknown (OID 0). In all other cases, the input must
* match an existing pg_class entry.
@@ -719,15 +691,8 @@ regclassin(PG_FUNCTION_ARGS)
class_name_or_oid[0] <= '9' &&
strspn(class_name_or_oid, "0123456789") == strlen(class_name_or_oid))
{
- Oid searchOid;
-
- searchOid = DatumGetObjectId(DirectFunctionCall1(oidin,
+ result = DatumGetObjectId(DirectFunctionCall1(oidin,
CStringGetDatum(class_name_or_oid)));
- result = GetSysCacheOid(RELOID,
- ObjectIdGetDatum(searchOid),
- 0, 0, 0);
- if (!OidIsValid(result))
- elog(ERROR, "No class with oid %s", class_name_or_oid);
PG_RETURN_OID(result);
}
@@ -843,7 +808,7 @@ regclassout(PG_FUNCTION_ARGS)
/*
* regtypein - converts "typename" to type OID
*
- * We also accept a numeric OID, mostly for historical reasons.
+ * We also accept a numeric OID, for symmetry with the output routine.
*
* '-' signifies unknown (OID 0). In all other cases, the input must
* match an existing pg_type entry.
@@ -870,15 +835,8 @@ regtypein(PG_FUNCTION_ARGS)
typ_name_or_oid[0] <= '9' &&
strspn(typ_name_or_oid, "0123456789") == strlen(typ_name_or_oid))
{
- Oid searchOid;
-
- searchOid = DatumGetObjectId(DirectFunctionCall1(oidin,
+ result = DatumGetObjectId(DirectFunctionCall1(oidin,
CStringGetDatum(typ_name_or_oid)));
- result = GetSysCacheOid(TYPEOID,
- ObjectIdGetDatum(searchOid),
- 0, 0, 0);
- if (!OidIsValid(result))
- elog(ERROR, "No type with oid %s", typ_name_or_oid);
PG_RETURN_OID(result);
}
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 740dde36dd4..9f21a609f3d 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.121 2002/09/04 20:31:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.122 2002/09/18 21:35:23 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -152,7 +152,6 @@ static void get_oper_expr(Expr *expr, deparse_context *context);
static void get_func_expr(Expr *expr, deparse_context *context);
static void get_agg_expr(Aggref *aggref, deparse_context *context);
static Node *strip_type_coercion(Node *expr, Oid resultType);
-static void get_tle_expr(TargetEntry *tle, deparse_context *context);
static void get_const_expr(Const *constval, deparse_context *context);
static void get_sublink_expr(Node *node, deparse_context *context);
static void get_from_clause(Query *query, deparse_context *context);
@@ -1430,7 +1429,6 @@ get_basic_select_query(Query *query, deparse_context *context,
sep = ", ";
colno++;
- /* Do NOT use get_tle_expr here; see its comments! */
get_rule_expr(tle->expr, context);
/*
@@ -1644,7 +1642,7 @@ get_insert_query_def(Query *query, deparse_context *context)
appendStringInfo(buf, sep);
sep = ", ";
- get_tle_expr(tle, context);
+ get_rule_expr(tle->expr, context);
}
appendStringInfoChar(buf, ')');
}
@@ -1694,7 +1692,7 @@ get_update_query_def(Query *query, deparse_context *context)
if (!tleIsArrayAssign(tle))
appendStringInfo(buf, "%s = ",
quote_identifier(tle->resdom->resname));
- get_tle_expr(tle, context);
+ get_rule_expr(tle->expr, context);
}
/* Add the FROM clause if needed */
@@ -2106,12 +2104,29 @@ get_rule_expr(Node *node, deparse_context *context)
case T_RelabelType:
{
RelabelType *relabel = (RelabelType *) node;
+ Node *arg = relabel->arg;
- appendStringInfoChar(buf, '(');
- get_rule_expr(relabel->arg, context);
- appendStringInfo(buf, ")::%s",
+ if (relabel->relabelformat == COERCE_IMPLICIT_CAST)
+ {
+ /* don't show an implicit cast */
+ get_rule_expr(arg, context);
+ }
+ else
+ {
+ /*
+ * Strip off any type coercions on the input, so we don't
+ * print redundancies like x::bpchar::character(8).
+ *
+ * XXX Are there any cases where this is a bad idea?
+ */
+ arg = strip_type_coercion(arg, relabel->resulttype);
+
+ appendStringInfoChar(buf, '(');
+ get_rule_expr(arg, context);
+ appendStringInfo(buf, ")::%s",
format_type_with_typemod(relabel->resulttype,
- relabel->resulttypmod));
+ relabel->resulttypmod));
+ }
}
break;
@@ -2305,21 +2320,33 @@ get_func_expr(Expr *expr, deparse_context *context)
StringInfo buf = context->buf;
Func *func = (Func *) (expr->oper);
Oid funcoid = func->funcid;
- int32 coercedTypmod;
Oid argtypes[FUNC_MAX_ARGS];
int nargs;
List *l;
char *sep;
/*
- * Check to see if function is a length-coercion function for some
- * datatype. If so, display the operation as a type cast.
+ * If the function call came from an implicit coercion, then just show
+ * the first argument.
+ */
+ if (func->funcformat == COERCE_IMPLICIT_CAST)
+ {
+ get_rule_expr((Node *) lfirst(expr->args), context);
+ return;
+ }
+
+ /*
+ * If the function call came from an explicit cast, then show
+ * the first argument plus an explicit cast operation.
*/
- if (exprIsLengthCoercion((Node *) expr, &coercedTypmod))
+ if (func->funcformat == COERCE_EXPLICIT_CAST)
{
Node *arg = lfirst(expr->args);
- Oid rettype = get_func_rettype(funcoid);
- char *typdesc;
+ Oid rettype = expr->typeOid;
+ int32 coercedTypmod;
+
+ /* Get the typmod if this is a length-coercion function */
+ (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod);
/*
* Strip off any type coercions on the input, so we don't print
@@ -2331,17 +2358,8 @@ get_func_expr(Expr *expr, deparse_context *context)
appendStringInfoChar(buf, '(');
get_rule_expr(arg, context);
-
- /*
- * Show typename with appropriate length decoration. Note that
- * since exprIsLengthCoercion succeeded, the function's output
- * type is the right thing to report. Also note we don't need to
- * quote the result of format_type_with_typemod: it takes care of
- * double-quoting any identifier that needs it.
- */
- typdesc = format_type_with_typemod(rettype, coercedTypmod);
- appendStringInfo(buf, ")::%s", typdesc);
- pfree(typdesc);
+ appendStringInfo(buf, ")::%s",
+ format_type_with_typemod(rettype, coercedTypmod));
return;
}
@@ -2393,15 +2411,14 @@ get_agg_expr(Aggref *aggref, deparse_context *context)
/*
* strip_type_coercion
- * Strip any type coercions at the top of the given expression tree,
- * as long as they are coercions to the given datatype.
+ * Strip any type coercion at the top of the given expression tree,
+ * if it is a coercion to the given datatype.
*
- * A RelabelType node is always a type coercion. A function call is
- * also considered a type coercion if it has one argument and there is
- * a cast declared that uses it.
+ * We use this to avoid printing two levels of coercion in situations where
+ * the expression tree has a length-coercion node atop a type-coercion node.
*
- * XXX It'd be better if the parsetree retained some explicit indication
- * of the coercion, so we didn't need these heuristics.
+ * Note: avoid stripping a length-coercion node, since two successive
+ * coercions to different lengths aren't a no-op.
*/
static Node *
strip_type_coercion(Node *expr, Oid resultType)
@@ -2409,58 +2426,24 @@ strip_type_coercion(Node *expr, Oid resultType)
if (expr == NULL || exprType(expr) != resultType)
return expr;
- if (IsA(expr, RelabelType))
- return strip_type_coercion(((RelabelType *) expr)->arg, resultType);
+ if (IsA(expr, RelabelType) &&
+ ((RelabelType *) expr)->resulttypmod == -1)
+ return ((RelabelType *) expr)->arg;
if (IsA(expr, Expr) &&
((Expr *) expr)->opType == FUNC_EXPR)
{
- Func *func;
- HeapTuple procTuple;
- HeapTuple castTuple;
- Form_pg_proc procStruct;
- Form_pg_cast castStruct;
+ Func *func = (Func *) (((Expr *) expr)->oper);
- func = (Func *) (((Expr *) expr)->oper);
Assert(IsA(func, Func));
- if (length(((Expr *) expr)->args) != 1)
- return expr;
- /* Lookup the function in pg_proc */
- procTuple = SearchSysCache(PROCOID,
- ObjectIdGetDatum(func->funcid),
- 0, 0, 0);
- if (!HeapTupleIsValid(procTuple))
- elog(ERROR, "cache lookup for proc %u failed", func->funcid);
- procStruct = (Form_pg_proc) GETSTRUCT(procTuple);
- /* Double-check func has one arg and correct result type */
- if (procStruct->pronargs != 1 ||
- procStruct->prorettype != resultType)
- {
- ReleaseSysCache(procTuple);
- return expr;
- }
- /* See if function has is actually declared as a cast */
- castTuple = SearchSysCache(CASTSOURCETARGET,
- ObjectIdGetDatum(procStruct->proargtypes[0]),
- ObjectIdGetDatum(procStruct->prorettype),
- 0, 0);
- if (!HeapTupleIsValid(castTuple))
- {
- ReleaseSysCache(procTuple);
- return expr;
- }
- /* It must also be an implicit cast. */
- castStruct = (Form_pg_cast) GETSTRUCT(castTuple);
- if (!castStruct->castimplicit)
- {
- ReleaseSysCache(procTuple);
- ReleaseSysCache(castTuple);
+ if (func->funcformat != COERCE_EXPLICIT_CAST &&
+ func->funcformat != COERCE_IMPLICIT_CAST)
+ return expr; /* don't absorb into upper coercion */
+
+ if (exprIsLengthCoercion(expr, NULL))
return expr;
- }
- /* Okay, it is indeed a type-coercion function */
- ReleaseSysCache(procTuple);
- ReleaseSysCache(castTuple);
- return strip_type_coercion(lfirst(((Expr *) expr)->args), resultType);
+
+ return (Node *) lfirst(((Expr *) expr)->args);
}
return expr;
@@ -2468,43 +2451,6 @@ strip_type_coercion(Node *expr, Oid resultType)
/* ----------
- * get_tle_expr
- *
- * In an INSERT or UPDATE targetlist item, the parser may have inserted
- * a length-coercion function call to coerce the value to the right
- * length for the target column. We want to suppress the output of
- * that function call, otherwise dump/reload/dump... would blow up the
- * expression by adding more and more layers of length-coercion calls.
- *
- * As of 7.0, this hack is no longer absolutely essential, because the parser
- * is now smart enough not to add a redundant length coercion function call.
- * But we still suppress the function call just for neatness of displayed
- * rules.
- *
- * Note that this hack must NOT be applied to SELECT targetlist items;
- * any length coercion appearing there is something the user actually wrote.
- * ----------
- */
-static void
-get_tle_expr(TargetEntry *tle, deparse_context *context)
-{
- Expr *expr = (Expr *) (tle->expr);
- int32 coercedTypmod;
-
- /*
- * If top level is a length coercion to the correct length, suppress
- * it; else dump the expression normally.
- */
- if (tle->resdom->restypmod >= 0 &&
- exprIsLengthCoercion((Node *) expr, &coercedTypmod) &&
- coercedTypmod == tle->resdom->restypmod)
- get_rule_expr((Node *) lfirst(expr->args), context);
- else
- get_rule_expr(tle->expr, context);
-}
-
-
-/* ----------
* get_const_expr
*
* Make a string representation of a Const
@@ -2518,6 +2464,8 @@ get_const_expr(Const *constval, deparse_context *context)
Form_pg_type typeStruct;
char *extval;
char *valptr;
+ bool isfloat = false;
+ bool needlabel;
if (constval->constisnull)
{
@@ -2563,8 +2511,12 @@ get_const_expr(Const *constval, deparse_context *context)
* NaN, so we need not get too crazy about pattern
* matching here.
*/
- if (strspn(extval, "0123456789 +-eE.") == strlen(extval))
+ if (strspn(extval, "0123456789+-eE.") == strlen(extval))
+ {
appendStringInfo(buf, extval);
+ if (strcspn(extval, "eE.") != strlen(extval))
+ isfloat = true; /* it looks like a float */
+ }
else
appendStringInfo(buf, "'%s'", extval);
}
@@ -2609,20 +2561,30 @@ get_const_expr(Const *constval, deparse_context *context)
pfree(extval);
+ /*
+ * Append ::typename unless the constant will be implicitly typed as
+ * the right type when it is read in. XXX this code has to be kept
+ * in sync with the behavior of the parser, especially make_const.
+ */
switch (constval->consttype)
{
case BOOLOID:
case INT4OID:
- case FLOAT8OID:
case UNKNOWNOID:
/* These types can be left unlabeled */
+ needlabel = false;
+ break;
+ case NUMERICOID:
+ /* Float-looking constants will be typed as numeric */
+ needlabel = !isfloat;
break;
default:
- appendStringInfo(buf, "::%s",
- format_type_with_typemod(constval->consttype,
- -1));
+ needlabel = true;
break;
}
+ if (needlabel)
+ appendStringInfo(buf, "::%s",
+ format_type_with_typemod(constval->consttype, -1));
ReleaseSysCache(typetup);
}
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
index f0c31a3961b..715a99863fd 100644
--- a/src/backend/utils/adt/varbit.c
+++ b/src/backend/utils/adt/varbit.c
@@ -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;
-
- 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);
+ ipad = VARBITPAD(result);
+ if (ipad > 0)
+ {
+ mask = BITMASK << ipad;
+ *(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
+ }
- 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,37 +442,15 @@ varbit(PG_FUNCTION_ARGS)
memcpy(VARBITS(result), VARBITS(arg), VARBITBYTES(result));
- 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);
+ /* Make sure last byte is zero-padded if needed */
+ ipad = VARBITPAD(result);
+ if (ipad > 0)
+ {
+ mask = BITMASK << ipad;
+ *(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
+ }
- return array_map(&locfcinfo, VARBITOID, VARBITOID);
+ PG_RETURN_VARBIT_P(result);
}
@@ -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)
diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c
index 780daf75655..03579f437b6 100644
--- a/src/backend/utils/adt/varchar.c
+++ b/src/backend/utils/adt/varchar.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.94 2002/09/04 20:31:29 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.95 2002/09/18 21:35:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -165,21 +165,28 @@ bpcharout(PG_FUNCTION_ARGS)
/*
- * Converts a CHARACTER type to the specified size. maxlen is the new
- * declared length plus VARHDRSZ bytes. Truncation
- * rules see bpcharin() above.
+ * 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.)
*/
Datum
bpchar(PG_FUNCTION_ARGS)
{
BpChar *source = PG_GETARG_BPCHAR_P(0);
int32 maxlen = PG_GETARG_INT32(1);
+ bool isExplicit = PG_GETARG_BOOL(2);
BpChar *result;
int32 len;
char *r;
char *s;
int i;
-
int charlen; /* number of charcters in the input string
* + VARHDRSZ */
@@ -188,7 +195,7 @@ bpchar(PG_FUNCTION_ARGS)
charlen = pg_mbstrlen_with_len(VARDATA(source), len - VARHDRSZ) + VARHDRSZ;
/* No work if typmod is invalid or supplied data matches it already */
- if (maxlen < (int32) VARHDRSZ || len == maxlen)
+ if (maxlen < (int32) VARHDRSZ || charlen == maxlen)
PG_RETURN_BPCHAR_P(source);
if (charlen > maxlen)
@@ -199,10 +206,13 @@ bpchar(PG_FUNCTION_ARGS)
maxmblen = pg_mbcharcliplen(VARDATA(source), len - VARHDRSZ,
maxlen - VARHDRSZ) + VARHDRSZ;
- for (i = maxmblen - VARHDRSZ; i < len - VARHDRSZ; i++)
- if (*(VARDATA(source) + i) != ' ')
- elog(ERROR, "value too long for type character(%d)",
- maxlen - VARHDRSZ);
+ if (!isExplicit)
+ {
+ for (i = maxmblen - VARHDRSZ; i < len - VARHDRSZ; i++)
+ if (*(VARDATA(source) + i) != ' ')
+ elog(ERROR, "value too long for type character(%d)",
+ maxlen - VARHDRSZ);
+ }
len = maxmblen;
@@ -238,37 +248,6 @@ bpchar(PG_FUNCTION_ARGS)
}
-/* _bpchar()
- * Converts an array of char() elements to a specific internal length.
- * len is the length specified in () plus VARHDRSZ bytes.
- */
-Datum
-_bpchar(PG_FUNCTION_ARGS)
-{
- ArrayType *v = PG_GETARG_ARRAYTYPE_P(0);
- int32 len = PG_GETARG_INT32(1);
- FunctionCallInfoData locfcinfo;
-
- /*
- * Since bpchar() is a built-in function, we should only need to look
- * it up once per run.
- */
- static FmgrInfo bpchar_finfo;
-
- if (bpchar_finfo.fn_oid == InvalidOid)
- fmgr_info_cxt(F_BPCHAR, &bpchar_finfo, TopMemoryContext);
-
- MemSet(&locfcinfo, 0, sizeof(locfcinfo));
- locfcinfo.flinfo = &bpchar_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, BPCHAROID, BPCHAROID);
-}
-
-
/* char_bpchar()
* Convert char to bpchar(1).
*/
@@ -354,9 +333,9 @@ name_bpchar(PG_FUNCTION_ARGS)
* Note that atttypmod is regarded as the number of 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 C 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)
{
@@ -428,17 +407,26 @@ varcharout(PG_FUNCTION_ARGS)
/*
- * Converts a VARCHAR type to the specified size. maxlen is the new
- * declared length plus VARHDRSZ bytes. Truncation
- * rules see varcharin() above.
+ * 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.)
*/
Datum
varchar(PG_FUNCTION_ARGS)
{
VarChar *source = PG_GETARG_VARCHAR_P(0);
int32 maxlen = PG_GETARG_INT32(1);
+ bool isExplicit = PG_GETARG_BOOL(2);
VarChar *result;
int32 len;
+ size_t maxmblen;
int i;
len = VARSIZE(source);
@@ -448,21 +436,19 @@ varchar(PG_FUNCTION_ARGS)
/* only reach here if string is too long... */
- {
- size_t maxmblen;
-
- /* truncate multibyte string preserving multibyte boundary */
- maxmblen = pg_mbcharcliplen(VARDATA(source), len - VARHDRSZ,
- maxlen - VARHDRSZ) + VARHDRSZ;
+ /* truncate multibyte string preserving multibyte boundary */
+ maxmblen = pg_mbcharcliplen(VARDATA(source), len - VARHDRSZ,
+ maxlen - VARHDRSZ);
- for (i = maxmblen - VARHDRSZ; i < len - VARHDRSZ; i++)
+ if (!isExplicit)
+ {
+ for (i = maxmblen; i < len - VARHDRSZ; i++)
if (*(VARDATA(source) + i) != ' ')
elog(ERROR, "value too long for type character varying(%d)",
maxlen - VARHDRSZ);
-
- len = maxmblen;
}
+ len = maxmblen + VARHDRSZ;
result = palloc(len);
VARATT_SIZEP(result) = len;
memcpy(VARDATA(result), VARDATA(source), len - VARHDRSZ);
@@ -471,38 +457,6 @@ varchar(PG_FUNCTION_ARGS)
}
-/* _varchar()
- * Converts an array of varchar() elements to the specified size.
- * len is the length specified in () plus VARHDRSZ bytes.
- */
-Datum
-_varchar(PG_FUNCTION_ARGS)
-{
- ArrayType *v = PG_GETARG_ARRAYTYPE_P(0);
- int32 len = PG_GETARG_INT32(1);
- FunctionCallInfoData locfcinfo;
-
- /*
- * Since varchar() is a built-in function, we should only need to look
- * it up once per run.
- */
- static FmgrInfo varchar_finfo;
-
- if (varchar_finfo.fn_oid == InvalidOid)
- fmgr_info_cxt(F_VARCHAR, &varchar_finfo, TopMemoryContext);
-
- MemSet(&locfcinfo, 0, sizeof(locfcinfo));
- locfcinfo.flinfo = &varchar_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, VARCHAROID, VARCHAROID);
-}
-
-
-
/*****************************************************************************
* Exported functions
*****************************************************************************/
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 2672ed3aada..c8a038d8a7d 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.83 2002/09/04 20:31:30 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.84 2002/09/18 21:35:23 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -1074,51 +1074,6 @@ getBaseType(Oid typid)
}
/*
- * getBaseTypeMod
- * If the given type is a domain, return the typmod it applies to
- * its base type; otherwise return the specified original typmod.
- */
-int32
-getBaseTypeMod(Oid typid, int32 typmod)
-{
- /*
- * We loop to find the bottom base type in a stack of domains.
- */
- for (;;)
- {
- HeapTuple tup;
- Form_pg_type typTup;
-
- tup = SearchSysCache(TYPEOID,
- ObjectIdGetDatum(typid),
- 0, 0, 0);
- if (!HeapTupleIsValid(tup))
- elog(ERROR, "getBaseTypeMod: failed to lookup type %u", typid);
- typTup = (Form_pg_type) GETSTRUCT(tup);
- if (typTup->typtype != 'd')
- {
- /* Not a domain, so done */
- ReleaseSysCache(tup);
- break;
- }
-
- /*
- * The typmod applied to a domain should always be -1.
- *
- * We substitute the domain's typmod as we switch attention to the
- * base type.
- */
- Assert(typmod < 0);
-
- typid = typTup->typbasetype;
- typmod = typTup->typtypmod;
- ReleaseSysCache(tup);
- }
-
- return typmod;
-}
-
-/*
* get_typavgwidth
*
* Given a type OID and a typmod value (pass -1 if typmod is unknown),