Commit 1c7bef32 authored by Tom Lane's avatar Tom Lane

Fix ruleutils to depend on format_type, rather than having a private

copy of code that knows about displaying types with typmod info.
Needed so that it does the right thing with timestamp datatypes now.
parent b6a79482
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.18 2001/10/04 17:52:24 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.19 2001/10/08 19:55:07 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -87,11 +87,11 @@ format_type(PG_FUNCTION_ARGS) ...@@ -87,11 +87,11 @@ format_type(PG_FUNCTION_ARGS)
PG_RETURN_DATUM(_textin(result)); PG_RETURN_DATUM(_textin(result));
} }
/* /*
* This version is for use within the backend in error messages, etc. * This version is for use within the backend in error messages, etc.
* One difference is that it will fail for an invalid type. * One difference is that it will fail for an invalid type.
*
* The result is always a palloc'd string.
*/ */
char * char *
format_type_be(Oid type_oid) format_type_be(Oid type_oid)
...@@ -99,6 +99,15 @@ format_type_be(Oid type_oid) ...@@ -99,6 +99,15 @@ format_type_be(Oid type_oid)
return format_type_internal(type_oid, -1, false); return format_type_internal(type_oid, -1, false);
} }
/*
* This version allows a nondefault typemod to be specified.
*/
char *
format_type_with_typemod(Oid type_oid, int32 typemod)
{
return format_type_internal(type_oid, typemod, false);
}
static char * static char *
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* back to source text * back to source text
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.84 2001/10/04 22:00:10 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.85 2001/10/08 19:55:07 tgl Exp $
* *
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
...@@ -130,6 +130,7 @@ static bool find_alias_in_namespace(Node *nsnode, Node *expr, ...@@ -130,6 +130,7 @@ static bool find_alias_in_namespace(Node *nsnode, Node *expr,
static bool phony_equal(Node *expr1, Node *expr2, int levelsup); static bool phony_equal(Node *expr1, Node *expr2, int levelsup);
static void get_rule_expr(Node *node, deparse_context *context); static void get_rule_expr(Node *node, deparse_context *context);
static void get_func_expr(Expr *expr, deparse_context *context); static void get_func_expr(Expr *expr, 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_tle_expr(TargetEntry *tle, deparse_context *context);
static void get_const_expr(Const *constval, 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_sublink_expr(Node *node, deparse_context *context);
...@@ -2038,49 +2039,31 @@ get_func_expr(Expr *expr, deparse_context *context) ...@@ -2038,49 +2039,31 @@ get_func_expr(Expr *expr, deparse_context *context)
if (exprIsLengthCoercion((Node *) expr, &coercedTypmod)) if (exprIsLengthCoercion((Node *) expr, &coercedTypmod))
{ {
Node *arg = lfirst(expr->args); Node *arg = lfirst(expr->args);
char *typdesc;
/* /*
* Strip off any RelabelType on the input, so we don't print * Strip off any type coercions on the input, so we don't print
* redundancies like x::bpchar::char(8). * redundancies like x::bpchar::character(8).
* *
* XXX Are there any cases where this is a bad idea? * XXX Are there any cases where this is a bad idea?
*/ */
if (IsA(arg, RelabelType)) arg = strip_type_coercion(arg, procStruct->prorettype);
arg = ((RelabelType *) arg)->arg;
appendStringInfoChar(buf, '('); appendStringInfoChar(buf, '(');
get_rule_expr(arg, context); get_rule_expr(arg, context);
appendStringInfo(buf, ")::");
/* /*
* Show typename with appropriate length decoration. Note that * Show typename with appropriate length decoration. Note that
* since exprIsLengthCoercion succeeded, the function name is the * since exprIsLengthCoercion succeeded, the function's output
* same as its output type name. * type is the right thing to use.
*
* XXX In general it is incorrect to quote the result of
* format_type_with_typemod, but are there any special cases
* where we should do so?
*/ */
if (strcmp(proname, "bpchar") == 0) typdesc = format_type_with_typemod(procStruct->prorettype,
{ coercedTypmod);
if (coercedTypmod > (int32) VARHDRSZ) appendStringInfo(buf, ")::%s", typdesc);
appendStringInfo(buf, "char(%d)", coercedTypmod - VARHDRSZ); pfree(typdesc);
else
appendStringInfo(buf, "char");
}
else if (strcmp(proname, "varchar") == 0)
{
if (coercedTypmod > (int32) VARHDRSZ)
appendStringInfo(buf, "varchar(%d)", coercedTypmod - VARHDRSZ);
else
appendStringInfo(buf, "varchar");
}
else if (strcmp(proname, "numeric") == 0)
{
if (coercedTypmod >= (int32) VARHDRSZ)
appendStringInfo(buf, "numeric(%d,%d)",
((coercedTypmod - VARHDRSZ) >> 16) & 0xffff,
(coercedTypmod - VARHDRSZ) & 0xffff);
else
appendStringInfo(buf, "numeric");
}
else
appendStringInfo(buf, "%s", quote_identifier(proname));
ReleaseSysCache(proctup); ReleaseSysCache(proctup);
return; return;
...@@ -2103,6 +2086,79 @@ get_func_expr(Expr *expr, deparse_context *context) ...@@ -2103,6 +2086,79 @@ get_func_expr(Expr *expr, 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.
*
* A RelabelType node is always a type coercion. A function call is also
* considered a type coercion if it has one argument and the function name
* is the same as the (internal) name of its result type.
*
* XXX It'd be better if the parsetree retained some explicit indication
* of the coercion, so we didn't need these heuristics.
*/
static Node *
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, Expr) && ((Expr *) expr)->opType == FUNC_EXPR)
{
Func *func;
HeapTuple procTuple;
HeapTuple typeTuple;
Form_pg_proc procStruct;
Form_pg_type typeStruct;
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 same name as its result type */
typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(procStruct->prorettype),
0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(ERROR, "cache lookup for type %u failed",
procStruct->prorettype);
typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
if (strncmp(NameStr(procStruct->proname),
NameStr(typeStruct->typname),
NAMEDATALEN) != 0)
{
ReleaseSysCache(procTuple);
ReleaseSysCache(typeTuple);
return expr;
}
/* Okay, it is indeed a type-coercion function */
ReleaseSysCache(procTuple);
ReleaseSysCache(typeTuple);
return strip_type_coercion(lfirst(((Expr *) expr)->args), resultType);
}
return expr;
}
/* ---------- /* ----------
* get_tle_expr * get_tle_expr
* *
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: builtins.h,v 1.165 2001/09/28 08:09:14 thomas Exp $ * $Id: builtins.h,v 1.166 2001/10/08 19:55:07 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -598,6 +598,7 @@ extern Datum pg_convert2(PG_FUNCTION_ARGS); ...@@ -598,6 +598,7 @@ extern Datum pg_convert2(PG_FUNCTION_ARGS);
/* format_type.c */ /* format_type.c */
extern Datum format_type(PG_FUNCTION_ARGS); extern Datum format_type(PG_FUNCTION_ARGS);
extern char * format_type_be(Oid type_oid); extern char * format_type_be(Oid type_oid);
extern char * format_type_with_typemod(Oid type_oid, int32 typemod);
extern Datum oidvectortypes(PG_FUNCTION_ARGS); extern Datum oidvectortypes(PG_FUNCTION_ARGS);
extern int32 type_maximum_size(Oid type_oid, int32 typemod); extern int32 type_maximum_size(Oid type_oid, int32 typemod);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment