OSDN Git Service

Rename rule CURRENT to OLD in source tree. Add mapping for backward
[pg-rex/syncrep.git] / src / backend / commands / view.c
1 /*-------------------------------------------------------------------------
2  *
3  * view.c
4  *        use rewrite rules to construct views
5  *
6  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *      $Id: view.c,v 1.43 2000/06/12 19:40:40 momjian Exp $
10  *
11  *-------------------------------------------------------------------------
12  */
13
14 #include "postgres.h"
15
16 #include "access/xact.h"
17 #include "catalog/heap.h"
18 #include "commands/creatinh.h"
19 #include "commands/view.h"
20 #include "nodes/makefuncs.h"
21 #include "parser/parse_relation.h"
22 #include "parser/parse_type.h"
23 #include "rewrite/rewriteDefine.h"
24 #include "rewrite/rewriteManip.h"
25 #include "rewrite/rewriteRemove.h"
26
27 /*---------------------------------------------------------------------
28  * DefineVirtualRelation
29  *
30  * Create the "view" relation.
31  * `DefineRelation' does all the work, we just provide the correct
32  * arguments!
33  *
34  * If the relation already exists, then 'DefineRelation' will abort
35  * the xact...
36  *---------------------------------------------------------------------
37  */
38 static void
39 DefineVirtualRelation(char *relname, List *tlist)
40 {
41         CreateStmt      createStmt;
42         List       *attrList,
43                            *t;
44         TargetEntry *entry;
45         Resdom     *res;
46         char       *resname;
47         char       *restypename;
48
49         /*
50          * create a list with one entry per attribute of this relation. Each
51          * entry is a two element list. The first element is the name of the
52          * attribute (a string) and the second the name of the type (NOTE: a
53          * string, not a type id!).
54          */
55         attrList = NIL;
56         if (tlist != NIL)
57         {
58                 foreach(t, tlist)
59                 {
60                         ColumnDef  *def = makeNode(ColumnDef);
61                         TypeName   *typename;
62
63                         /*
64                          * find the names of the attribute & its type
65                          */
66                         entry = lfirst(t);
67                         res = entry->resdom;
68                         resname = res->resname;
69                         restypename = typeidTypeName(res->restype);
70
71                         typename = makeNode(TypeName);
72
73                         typename->name = pstrdup(restypename);
74                         typename->typmod = res->restypmod;
75
76                         def->colname = pstrdup(resname);
77
78                         def->typename = typename;
79
80                         def->is_not_null = false;
81                         def->raw_default = NULL;
82                         def->cooked_default = NULL;
83
84                         attrList = lappend(attrList, def);
85                 }
86         }
87         else
88                 elog(ERROR, "attempted to define virtual relation with no attrs");
89
90         /*
91          * now create the parametesr for keys/inheritance etc. All of them are
92          * nil...
93          */
94         createStmt.relname = relname;
95         createStmt.istemp = false;
96         createStmt.tableElts = attrList;
97 /*        createStmt.tableType = NULL;*/
98         createStmt.inhRelnames = NIL;
99         createStmt.constraints = NIL;
100
101         /*
102          * finally create the relation...
103          */
104         DefineRelation(&createStmt, RELKIND_RELATION);
105 }
106
107 /*------------------------------------------------------------------
108  * makeViewRetrieveRuleName
109  *
110  * Given a view name, returns the name for the 'on retrieve to "view"'
111  * rule.
112  * This routine is called when defining/removing a view.
113  *------------------------------------------------------------------
114  */
115 char *
116 MakeRetrieveViewRuleName(char *viewName)
117 {
118         char       *buf;
119
120         buf = palloc(strlen(viewName) + 5);
121         snprintf(buf, strlen(viewName) + 5, "_RET%s", viewName);
122
123         return buf;
124 }
125
126 static RuleStmt *
127 FormViewRetrieveRule(char *viewName, Query *viewParse)
128 {
129         RuleStmt   *rule;
130         char       *rname;
131         Attr       *attr;
132
133         /*
134          * Create a RuleStmt that corresponds to the suitable rewrite rule
135          * args for DefineQueryRewrite();
136          */
137         rule = makeNode(RuleStmt);
138         rname = MakeRetrieveViewRuleName(viewName);
139
140         attr = makeNode(Attr);
141         attr->relname = pstrdup(viewName);
142 /*        attr->refname = pstrdup(viewName);*/
143         rule->rulename = pstrdup(rname);
144         rule->whereClause = NULL;
145         rule->event = CMD_SELECT;
146         rule->object = attr;
147         rule->instead = true;
148         rule->actions = lcons(viewParse, NIL);
149
150         return rule;
151 }
152
153 static void
154 DefineViewRules(char *viewName, Query *viewParse)
155 {
156         RuleStmt   *retrieve_rule = NULL;
157
158 #ifdef NOTYET
159         RuleStmt   *replace_rule = NULL;
160         RuleStmt   *append_rule = NULL;
161         RuleStmt   *delete_rule = NULL;
162
163 #endif
164
165         retrieve_rule = FormViewRetrieveRule(viewName, viewParse);
166
167 #ifdef NOTYET
168
169         replace_rule = FormViewReplaceRule(viewName, viewParse);
170         append_rule = FormViewAppendRule(viewName, viewParse);
171         delete_rule = FormViewDeleteRule(viewName, viewParse);
172
173 #endif
174
175         DefineQueryRewrite(retrieve_rule);
176
177 #ifdef NOTYET
178         DefineQueryRewrite(replace_rule);
179         DefineQueryRewrite(append_rule);
180         DefineQueryRewrite(delete_rule);
181 #endif
182
183 }
184
185 /*---------------------------------------------------------------
186  * UpdateRangeTableOfViewParse
187  *
188  * Update the range table of the given parsetree.
189  * This update consists of adding two new entries IN THE BEGINNING
190  * of the range table (otherwise the rule system will die a slow,
191  * horrible and painful death, and we do not want that now, do we?)
192  * one for the OLD relation and one for the NEW one (both of
193  * them refer in fact to the "view" relation).
194  *
195  * Of course we must also increase the 'varnos' of all the Var nodes
196  * by 2...
197  *
198  * NOTE: these are destructive changes. It would be difficult to
199  * make a complete copy of the parse tree and make the changes
200  * in the copy.
201  *---------------------------------------------------------------
202  */
203 static void
204 UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
205 {
206         List       *old_rt;
207         List       *new_rt;
208         RangeTblEntry *rt_entry1,
209                            *rt_entry2;
210
211         /*
212          * first offset all var nodes by 2
213          */
214         OffsetVarNodes((Node *) viewParse->targetList, 2, 0);
215         OffsetVarNodes(viewParse->qual, 2, 0);
216
217         OffsetVarNodes(viewParse->havingQual, 2, 0);
218
219
220         /*
221          * find the old range table...
222          */
223         old_rt = viewParse->rtable;
224
225         /*
226          * create the 2 new range table entries and form the new range
227          * table... OLD first, then NEW....
228          */
229         rt_entry1 = addRangeTableEntry(NULL, (char *) viewName,
230                                                                    makeAttr("*OLD*", NULL),
231                                                                    FALSE, FALSE, FALSE);
232         rt_entry2 = addRangeTableEntry(NULL, (char *) viewName,
233                                                                    makeAttr("*NEW*", NULL),
234                                                                    FALSE, FALSE, FALSE);
235         new_rt = lcons(rt_entry2, old_rt);
236         new_rt = lcons(rt_entry1, new_rt);
237
238         /*
239          * Now the tricky part.... Update the range table in place... Be
240          * careful here, or hell breaks loooooooooooooOOOOOOOOOOOOOOOOOOSE!
241          */
242         viewParse->rtable = new_rt;
243 }
244
245 /*-------------------------------------------------------------------
246  * DefineView
247  *
248  *              - takes a "viewname", "parsetree" pair and then
249  *              1)              construct the "virtual" relation
250  *              2)              commit the command but NOT the transaction,
251  *                              so that the relation exists
252  *                              before the rules are defined.
253  *              2)              define the "n" rules specified in the PRS2 paper
254  *                              over the "virtual" relation
255  *-------------------------------------------------------------------
256  */
257 void
258 DefineView(char *viewName, Query *viewParse)
259 {
260         List       *viewTlist;
261
262         viewTlist = viewParse->targetList;
263
264         /*
265          * Create the "view" relation NOTE: if it already exists, the xaxt
266          * will be aborted.
267          */
268         DefineVirtualRelation(viewName, viewTlist);
269
270         /*
271          * The relation we have just created is not visible to any other
272          * commands running with the same transaction & command id. So,
273          * increment the command id counter (but do NOT pfree any memory!!!!)
274          */
275         CommandCounterIncrement();
276
277         /*
278          * The range table of 'viewParse' does not contain entries for the
279          * "OLD" and "NEW" relations. So... add them! NOTE: we make the
280          * update in place! After this call 'viewParse' will never be what it
281          * used to be...
282          */
283         UpdateRangeTableOfViewParse(viewName, viewParse);
284         DefineViewRules(viewName, viewParse);
285 }
286
287 /*------------------------------------------------------------------
288  * RemoveView
289  *
290  * Remove a view given its name
291  *------------------------------------------------------------------
292  */
293 void
294 RemoveView(char *viewName)
295 {
296         char       *rname;
297
298         /*
299          * first remove all the "view" rules... Currently we only have one!
300          */
301         rname = MakeRetrieveViewRuleName(viewName);
302         RemoveRewriteRule(rname);
303
304         /*
305          * we don't really need that, but just in case...
306          */
307         CommandCounterIncrement();
308
309         /*
310          * now remove the relation.
311          */
312         heap_drop_with_catalog(viewName);
313         pfree(rname);
314 }