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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy