33 *back to source text
44 *
55 * IDENTIFICATION
6- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.113 2002/08/0801:44:31 tgl Exp $
6+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.114 2002/08/0817:00:19 tgl Exp $
77 *
88 * This software is copyrighted by Jan Wieck - Hamburg.
99 *
@@ -118,15 +118,19 @@ static char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_c
118118static text * pg_do_getviewdef (Oid viewoid );
119119static void make_ruledef (StringInfo buf ,HeapTuple ruletup ,TupleDesc rulettc );
120120static void make_viewdef (StringInfo buf ,HeapTuple ruletup ,TupleDesc rulettc );
121- static void get_query_def (Query * query ,StringInfo buf ,List * parentnamespace );
122- static void get_select_query_def (Query * query ,deparse_context * context );
121+ static void get_query_def (Query * query ,StringInfo buf ,List * parentnamespace ,
122+ TupleDesc resultDesc );
123+ static void get_select_query_def (Query * query ,deparse_context * context ,
124+ TupleDesc resultDesc );
123125static void get_insert_query_def (Query * query ,deparse_context * context );
124126static void get_update_query_def (Query * query ,deparse_context * context );
125127static void get_delete_query_def (Query * query ,deparse_context * context );
126128static void get_utility_query_def (Query * query ,deparse_context * context );
127- static void get_basic_select_query (Query * query ,deparse_context * context );
129+ static void get_basic_select_query (Query * query ,deparse_context * context ,
130+ TupleDesc resultDesc );
128131static void get_setop_query (Node * setOp ,Query * query ,
129- deparse_context * context );
132+ deparse_context * context ,
133+ TupleDesc resultDesc );
130134static Node * get_rule_sortgroupclause (SortClause * srt ,List * tlist ,
131135bool force_colno ,
132136deparse_context * context );
@@ -936,25 +940,22 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
936940foreach (action ,actions )
937941{
938942query = (Query * )lfirst (action );
939- get_query_def (query ,buf ,NIL );
943+ get_query_def (query ,buf ,NIL , NULL );
940944appendStringInfo (buf ,"; " );
941945}
942946appendStringInfo (buf ,");" );
943947}
948+ else if (length (actions )== 0 )
949+ {
950+ appendStringInfo (buf ,"NOTHING;" );
951+ }
944952else
945953{
946- if (length (actions )== 0 )
947- {
948- appendStringInfo (buf ,"NOTHING;" );
949- }
950- else
951- {
952- Query * query ;
954+ Query * query ;
953955
954- query = (Query * )lfirst (actions );
955- get_query_def (query ,buf ,NIL );
956- appendStringInfo (buf ,";" );
957- }
956+ query = (Query * )lfirst (actions );
957+ get_query_def (query ,buf ,NIL ,NULL );
958+ appendStringInfo (buf ,";" );
958959}
959960}
960961
@@ -975,6 +976,7 @@ make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
975976char * ev_qual ;
976977char * ev_action ;
977978List * actions = NIL ;
979+ Relation ev_relation ;
978980int fno ;
979981bool isnull ;
980982
@@ -1010,25 +1012,31 @@ make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
10101012query = (Query * )lfirst (actions );
10111013
10121014if (ev_type != '1' || ev_attr >=0 || !is_instead ||
1013- strcmp (ev_qual ,"<>" )!= 0 )
1015+ strcmp (ev_qual ,"<>" )!= 0 || query -> commandType != CMD_SELECT )
10141016{
10151017appendStringInfo (buf ,"Not a view" );
10161018return ;
10171019}
10181020
1019- get_query_def (query ,buf ,NIL );
1021+ ev_relation = heap_open (ev_class ,AccessShareLock );
1022+
1023+ get_query_def (query ,buf ,NIL ,RelationGetDescr (ev_relation ));
10201024appendStringInfo (buf ,";" );
1025+
1026+ heap_close (ev_relation ,AccessShareLock );
10211027}
10221028
10231029
10241030/* ----------
1025- * get_query_def- Parse back one action from
1026- * the parsetree in the actions
1027- * list
1031+ * get_query_def- Parse back one query parsetree
1032+ *
1033+ * If resultDesc is not NULL, then it is the output tuple descriptor for
1034+ * the view represented by a SELECT query.
10281035 * ----------
10291036 */
10301037static void
1031- get_query_def (Query * query ,StringInfo buf ,List * parentnamespace )
1038+ get_query_def (Query * query ,StringInfo buf ,List * parentnamespace ,
1039+ TupleDesc resultDesc )
10321040{
10331041deparse_context context ;
10341042deparse_namespace dpns ;
@@ -1044,7 +1052,7 @@ get_query_def(Query *query, StringInfo buf, List *parentnamespace)
10441052switch (query -> commandType )
10451053{
10461054case CMD_SELECT :
1047- get_select_query_def (query ,& context );
1055+ get_select_query_def (query ,& context , resultDesc );
10481056break ;
10491057
10501058case CMD_UPDATE :
@@ -1080,7 +1088,8 @@ get_query_def(Query *query, StringInfo buf, List *parentnamespace)
10801088 * ----------
10811089 */
10821090static void
1083- get_select_query_def (Query * query ,deparse_context * context )
1091+ get_select_query_def (Query * query ,deparse_context * context ,
1092+ TupleDesc resultDesc )
10841093{
10851094StringInfo buf = context -> buf ;
10861095bool force_colno ;
@@ -1094,13 +1103,13 @@ get_select_query_def(Query *query, deparse_context *context)
10941103 */
10951104if (query -> setOperations )
10961105{
1097- get_setop_query (query -> setOperations ,query ,context );
1106+ get_setop_query (query -> setOperations ,query ,context , resultDesc );
10981107/* ORDER BY clauses must be simple in this case */
10991108force_colno = true;
11001109}
11011110else
11021111{
1103- get_basic_select_query (query ,context );
1112+ get_basic_select_query (query ,context , resultDesc );
11041113force_colno = false;
11051114}
11061115
@@ -1151,11 +1160,13 @@ get_select_query_def(Query *query, deparse_context *context)
11511160}
11521161
11531162static void
1154- get_basic_select_query (Query * query ,deparse_context * context )
1163+ get_basic_select_query (Query * query ,deparse_context * context ,
1164+ TupleDesc resultDesc )
11551165{
11561166StringInfo buf = context -> buf ;
11571167char * sep ;
11581168List * l ;
1169+ int colno ;
11591170
11601171/*
11611172 * Build up the query string - first we say SELECT
@@ -1186,23 +1197,37 @@ get_basic_select_query(Query *query, deparse_context *context)
11861197
11871198/* Then we tell what to select (the targetlist) */
11881199sep = " " ;
1200+ colno = 0 ;
11891201foreach (l ,query -> targetList )
11901202{
11911203TargetEntry * tle = (TargetEntry * )lfirst (l );
11921204bool tell_as = false;
1205+ char * colname ;
11931206
11941207if (tle -> resdom -> resjunk )
11951208continue ;/* ignore junk entries */
11961209
11971210appendStringInfo (buf ,sep );
11981211sep = ", " ;
1212+ colno ++ ;
11991213
12001214/* Do NOT use get_tle_expr here; see its comments! */
12011215get_rule_expr (tle -> expr ,context );
12021216
1217+ /*
1218+ * Figure out what the result column should be called. In the
1219+ * context of a view, use the view's tuple descriptor (so as to
1220+ * pick up the effects of any column RENAME that's been done on the
1221+ * view). Otherwise, just use what we can find in the TLE.
1222+ */
1223+ if (resultDesc && colno <=resultDesc -> natts )
1224+ colname = NameStr (resultDesc -> attrs [colno - 1 ]-> attname );
1225+ else
1226+ colname = tle -> resdom -> resname ;
1227+
12031228/* Check if we must say AS ... */
12041229if (!IsA (tle -> expr ,Var ))
1205- tell_as = (strcmp (tle -> resdom -> resname ,"?column?" )!= 0 );
1230+ tell_as = (strcmp (colname ,"?column?" )!= 0 );
12061231else
12071232{
12081233Var * var = (Var * ) (tle -> expr );
@@ -1212,13 +1237,12 @@ get_basic_select_query(Query *query, deparse_context *context)
12121237
12131238get_names_for_var (var ,context ,& schemaname ,& refname ,& attname );
12141239tell_as = (attname == NULL ||
1215- strcmp (attname ,tle -> resdom -> resname )!= 0 );
1240+ strcmp (attname ,colname )!= 0 );
12161241}
12171242
12181243/* and do if so */
12191244if (tell_as )
1220- appendStringInfo (buf ," AS %s" ,
1221- quote_identifier (tle -> resdom -> resname ));
1245+ appendStringInfo (buf ," AS %s" ,quote_identifier (colname ));
12221246}
12231247
12241248/* Add the FROM clause if needed */
@@ -1256,7 +1280,8 @@ get_basic_select_query(Query *query, deparse_context *context)
12561280}
12571281
12581282static void
1259- get_setop_query (Node * setOp ,Query * query ,deparse_context * context )
1283+ get_setop_query (Node * setOp ,Query * query ,deparse_context * context ,
1284+ TupleDesc resultDesc )
12601285{
12611286StringInfo buf = context -> buf ;
12621287
@@ -1267,14 +1292,14 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context)
12671292Query * subquery = rte -> subquery ;
12681293
12691294Assert (subquery != NULL );
1270- get_query_def (subquery ,buf ,context -> namespaces );
1295+ get_query_def (subquery ,buf ,context -> namespaces , resultDesc );
12711296}
12721297else if (IsA (setOp ,SetOperationStmt ))
12731298{
12741299SetOperationStmt * op = (SetOperationStmt * )setOp ;
12751300
12761301appendStringInfo (buf ,"((" );
1277- get_setop_query (op -> larg ,query ,context );
1302+ get_setop_query (op -> larg ,query ,context , resultDesc );
12781303switch (op -> op )
12791304{
12801305case SETOP_UNION :
@@ -1294,7 +1319,7 @@ get_setop_query(Node *setOp, Query *query, deparse_context *context)
12941319appendStringInfo (buf ,"ALL (" );
12951320else
12961321appendStringInfo (buf ,"(" );
1297- get_setop_query (op -> rarg ,query ,context );
1322+ get_setop_query (op -> rarg ,query ,context , resultDesc );
12981323appendStringInfo (buf ,"))" );
12991324}
13001325else
@@ -1405,7 +1430,7 @@ get_insert_query_def(Query *query, deparse_context *context)
14051430appendStringInfoChar (buf ,')' );
14061431}
14071432else
1408- get_query_def (select_rte -> subquery ,buf ,NIL );
1433+ get_query_def (select_rte -> subquery ,buf ,NIL , NULL );
14091434}
14101435
14111436
@@ -2418,7 +2443,7 @@ get_sublink_expr(Node *node, deparse_context *context)
24182443if (need_paren )
24192444appendStringInfoChar (buf ,'(' );
24202445
2421- get_query_def (query ,buf ,context -> namespaces );
2446+ get_query_def (query ,buf ,context -> namespaces , NULL );
24222447
24232448if (need_paren )
24242449appendStringInfo (buf ,"))" );
@@ -2491,7 +2516,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
24912516case RTE_SUBQUERY :
24922517/* Subquery RTE */
24932518appendStringInfoChar (buf ,'(' );
2494- get_query_def (rte -> subquery ,buf ,context -> namespaces );
2519+ get_query_def (rte -> subquery ,buf ,context -> namespaces , NULL );
24952520appendStringInfoChar (buf ,')' );
24962521break ;
24972522case RTE_FUNCTION :
@@ -2521,6 +2546,18 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
25212546appendStringInfoChar (buf ,')' );
25222547}
25232548}
2549+ else if (rte -> rtekind == RTE_RELATION &&
2550+ strcmp (rte -> eref -> aliasname ,get_rel_name (rte -> relid ))!= 0 )
2551+ {
2552+ /*
2553+ * Apparently the rel has been renamed since the rule was made.
2554+ * Emit a fake alias clause so that variable references will
2555+ * still work. This is not a 100% solution but should work in
2556+ * most reasonable situations.
2557+ */
2558+ appendStringInfo (buf ," %s" ,
2559+ quote_identifier (rte -> eref -> aliasname ));
2560+ }
25242561}
25252562else if (IsA (jtnode ,JoinExpr ))
25262563{