Skip to content

Commit 1c7bef3

Browse files
committed
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.
1 parent b6a7948 commit 1c7bef3

File tree

3 files changed

+104
-38
lines changed

3 files changed

+104
-38
lines changed

src/backend/utils/adt/format_type.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.18 2001/10/04 17:52:24 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.19 2001/10/08 19:55:07 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -87,18 +87,27 @@ format_type(PG_FUNCTION_ARGS)
8787
PG_RETURN_DATUM(_textin(result));
8888
}
8989

90-
91-
9290
/*
9391
* This version is for use within the backend in error messages, etc.
9492
* One difference is that it will fail for an invalid type.
93+
*
94+
* The result is always a palloc'd string.
9595
*/
9696
char *
9797
format_type_be(Oid type_oid)
9898
{
9999
return format_type_internal(type_oid, -1, false);
100100
}
101101

102+
/*
103+
* This version allows a nondefault typemod to be specified.
104+
*/
105+
char *
106+
format_type_with_typemod(Oid type_oid, int32 typemod)
107+
{
108+
return format_type_internal(type_oid, typemod, false);
109+
}
110+
102111

103112

104113
static char *

src/backend/utils/adt/ruleutils.c

Lines changed: 90 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* back to source text
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.84 2001/10/04 22:00:10 tgl Exp $
6+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.85 2001/10/08 19:55:07 tgl Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -130,6 +130,7 @@ static bool find_alias_in_namespace(Node *nsnode, Node *expr,
130130
static bool phony_equal(Node *expr1, Node *expr2, int levelsup);
131131
static void get_rule_expr(Node *node, deparse_context *context);
132132
static void get_func_expr(Expr *expr, deparse_context *context);
133+
static Node *strip_type_coercion(Node *expr, Oid resultType);
133134
static void get_tle_expr(TargetEntry *tle, deparse_context *context);
134135
static void get_const_expr(Const *constval, deparse_context *context);
135136
static void get_sublink_expr(Node *node, deparse_context *context);
@@ -2038,49 +2039,31 @@ get_func_expr(Expr *expr, deparse_context *context)
20382039
if (exprIsLengthCoercion((Node *) expr, &coercedTypmod))
20392040
{
20402041
Node *arg = lfirst(expr->args);
2042+
char *typdesc;
20412043

20422044
/*
2043-
* Strip off any RelabelType on the input, so we don't print
2044-
* redundancies like x::bpchar::char(8).
2045+
* Strip off any type coercions on the input, so we don't print
2046+
* redundancies like x::bpchar::character(8).
20452047
*
20462048
* XXX Are there any cases where this is a bad idea?
20472049
*/
2048-
if (IsA(arg, RelabelType))
2049-
arg = ((RelabelType *) arg)->arg;
2050+
arg = strip_type_coercion(arg, procStruct->prorettype);
2051+
20502052
appendStringInfoChar(buf, '(');
20512053
get_rule_expr(arg, context);
2052-
appendStringInfo(buf, ")::");
2053-
20542054
/*
20552055
* Show typename with appropriate length decoration. Note that
2056-
* since exprIsLengthCoercion succeeded, the function name is the
2057-
* same as its output type name.
2056+
* since exprIsLengthCoercion succeeded, the function's output
2057+
* type is the right thing to use.
2058+
*
2059+
* XXX In general it is incorrect to quote the result of
2060+
* format_type_with_typemod, but are there any special cases
2061+
* where we should do so?
20582062
*/
2059-
if (strcmp(proname, "bpchar") == 0)
2060-
{
2061-
if (coercedTypmod > (int32) VARHDRSZ)
2062-
appendStringInfo(buf, "char(%d)", coercedTypmod - VARHDRSZ);
2063-
else
2064-
appendStringInfo(buf, "char");
2065-
}
2066-
else if (strcmp(proname, "varchar") == 0)
2067-
{
2068-
if (coercedTypmod > (int32) VARHDRSZ)
2069-
appendStringInfo(buf, "varchar(%d)", coercedTypmod - VARHDRSZ);
2070-
else
2071-
appendStringInfo(buf, "varchar");
2072-
}
2073-
else if (strcmp(proname, "numeric") == 0)
2074-
{
2075-
if (coercedTypmod >= (int32) VARHDRSZ)
2076-
appendStringInfo(buf, "numeric(%d,%d)",
2077-
((coercedTypmod - VARHDRSZ) >> 16) & 0xffff,
2078-
(coercedTypmod - VARHDRSZ) & 0xffff);
2079-
else
2080-
appendStringInfo(buf, "numeric");
2081-
}
2082-
else
2083-
appendStringInfo(buf, "%s", quote_identifier(proname));
2063+
typdesc = format_type_with_typemod(procStruct->prorettype,
2064+
coercedTypmod);
2065+
appendStringInfo(buf, ")::%s", typdesc);
2066+
pfree(typdesc);
20842067

20852068
ReleaseSysCache(proctup);
20862069
return;
@@ -2103,6 +2086,79 @@ get_func_expr(Expr *expr, deparse_context *context)
21032086
}
21042087

21052088

2089+
/*
2090+
* strip_type_coercion
2091+
* Strip any type coercions at the top of the given expression tree,
2092+
* as long as they are coercions to the given datatype.
2093+
*
2094+
* A RelabelType node is always a type coercion. A function call is also
2095+
* considered a type coercion if it has one argument and the function name
2096+
* is the same as the (internal) name of its result type.
2097+
*
2098+
* XXX It'd be better if the parsetree retained some explicit indication
2099+
* of the coercion, so we didn't need these heuristics.
2100+
*/
2101+
static Node *
2102+
strip_type_coercion(Node *expr, Oid resultType)
2103+
{
2104+
if (expr == NULL || exprType(expr) != resultType)
2105+
return expr;
2106+
2107+
if (IsA(expr, RelabelType))
2108+
return strip_type_coercion(((RelabelType *) expr)->arg, resultType);
2109+
2110+
if (IsA(expr, Expr) && ((Expr *) expr)->opType == FUNC_EXPR)
2111+
{
2112+
Func *func;
2113+
HeapTuple procTuple;
2114+
HeapTuple typeTuple;
2115+
Form_pg_proc procStruct;
2116+
Form_pg_type typeStruct;
2117+
2118+
func = (Func *) (((Expr *) expr)->oper);
2119+
Assert(IsA(func, Func));
2120+
if (length(((Expr *) expr)->args) != 1)
2121+
return expr;
2122+
/* Lookup the function in pg_proc */
2123+
procTuple = SearchSysCache(PROCOID,
2124+
ObjectIdGetDatum(func->funcid),
2125+
0, 0, 0);
2126+
if (!HeapTupleIsValid(procTuple))
2127+
elog(ERROR, "cache lookup for proc %u failed", func->funcid);
2128+
procStruct = (Form_pg_proc) GETSTRUCT(procTuple);
2129+
/* Double-check func has one arg and correct result type */
2130+
if (procStruct->pronargs != 1 ||
2131+
procStruct->prorettype != resultType)
2132+
{
2133+
ReleaseSysCache(procTuple);
2134+
return expr;
2135+
}
2136+
/* See if function has same name as its result type */
2137+
typeTuple = SearchSysCache(TYPEOID,
2138+
ObjectIdGetDatum(procStruct->prorettype),
2139+
0, 0, 0);
2140+
if (!HeapTupleIsValid(typeTuple))
2141+
elog(ERROR, "cache lookup for type %u failed",
2142+
procStruct->prorettype);
2143+
typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
2144+
if (strncmp(NameStr(procStruct->proname),
2145+
NameStr(typeStruct->typname),
2146+
NAMEDATALEN) != 0)
2147+
{
2148+
ReleaseSysCache(procTuple);
2149+
ReleaseSysCache(typeTuple);
2150+
return expr;
2151+
}
2152+
/* Okay, it is indeed a type-coercion function */
2153+
ReleaseSysCache(procTuple);
2154+
ReleaseSysCache(typeTuple);
2155+
return strip_type_coercion(lfirst(((Expr *) expr)->args), resultType);
2156+
}
2157+
2158+
return expr;
2159+
}
2160+
2161+
21062162
/* ----------
21072163
* get_tle_expr
21082164
*

src/include/utils/builtins.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: builtins.h,v 1.165 2001/09/28 08:09:14 thomas Exp $
10+
* $Id: builtins.h,v 1.166 2001/10/08 19:55:07 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -598,6 +598,7 @@ extern Datum pg_convert2(PG_FUNCTION_ARGS);
598598
/* format_type.c */
599599
extern Datum format_type(PG_FUNCTION_ARGS);
600600
extern char * format_type_be(Oid type_oid);
601+
extern char * format_type_with_typemod(Oid type_oid, int32 typemod);
601602
extern Datum oidvectortypes(PG_FUNCTION_ARGS);
602603
extern int32 type_maximum_size(Oid type_oid, int32 typemod);
603604

0 commit comments

Comments
 (0)