OSDN Git Service

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