3
3
*back to source text
4
4
*
5
5
* 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 $
7
7
*
8
8
* This software is copyrighted by Jan Wieck - Hamburg.
9
9
*
@@ -130,6 +130,7 @@ static bool find_alias_in_namespace(Node *nsnode, Node *expr,
130
130
static bool phony_equal (Node * expr1 ,Node * expr2 ,int levelsup );
131
131
static void get_rule_expr (Node * node ,deparse_context * context );
132
132
static void get_func_expr (Expr * expr ,deparse_context * context );
133
+ static Node * strip_type_coercion (Node * expr ,Oid resultType );
133
134
static void get_tle_expr (TargetEntry * tle ,deparse_context * context );
134
135
static void get_const_expr (Const * constval ,deparse_context * context );
135
136
static void get_sublink_expr (Node * node ,deparse_context * context );
@@ -2038,49 +2039,31 @@ get_func_expr(Expr *expr, deparse_context *context)
2038
2039
if (exprIsLengthCoercion ((Node * )expr ,& coercedTypmod ))
2039
2040
{
2040
2041
Node * arg = lfirst (expr -> args );
2042
+ char * typdesc ;
2041
2043
2042
2044
/*
2043
- * Strip off anyRelabelType on the input, so we don't print
2044
- * redundancies like x::bpchar::char (8).
2045
+ * Strip off anytype coercions on the input, so we don't print
2046
+ * redundancies like x::bpchar::character (8).
2045
2047
*
2046
2048
* XXX Are there any cases where this is a bad idea?
2047
2049
*/
2048
- if ( IsA ( arg ,RelabelType ))
2049
- arg = (( RelabelType * ) arg ) -> arg ;
2050
+ arg = strip_type_coercion ( arg ,procStruct -> prorettype );
2051
+
2050
2052
appendStringInfoChar (buf ,'(' );
2051
2053
get_rule_expr (arg ,context );
2052
- appendStringInfo (buf ,")::" );
2053
-
2054
2054
/*
2055
2055
* 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?
2058
2062
*/
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 );
2084
2067
2085
2068
ReleaseSysCache (proctup );
2086
2069
return ;
@@ -2103,6 +2086,79 @@ get_func_expr(Expr *expr, deparse_context *context)
2103
2086
}
2104
2087
2105
2088
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
+
2106
2162
/* ----------
2107
2163
* get_tle_expr
2108
2164
*