1 /*-------------------------------------------------------------------------
4 * use rewrite rules to construct views
6 * Copyright (c) 1994, Regents of the University of California
8 * $Id: view.c,v 1.38 1999/10/03 23:55:27 tgl Exp $
10 *-------------------------------------------------------------------------
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"
25 /*---------------------------------------------------------------------
26 * DefineVirtualRelation
28 * Create the "view" relation.
29 * `DefineRelation' does all the work, we just provide the correct
32 * If the relation already exists, then 'DefineRelation' will abort
34 *---------------------------------------------------------------------
37 DefineVirtualRelation(char *relname, List *tlist)
39 CreateStmt createStmt;
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!).
58 ColumnDef *def = makeNode(ColumnDef);
62 * find the names of the attribute & its type
66 resname = res->resname;
67 restypename = typeidTypeName(res->restype);
69 typename = makeNode(TypeName);
71 typename->name = pstrdup(restypename);
72 typename->typmod = res->restypmod;
74 def->colname = pstrdup(resname);
76 def->typename = typename;
78 def->is_not_null = false;
79 def->raw_default = NULL;
80 def->cooked_default = NULL;
82 attrList = lappend(attrList, def);
86 elog(ERROR, "attempted to define virtual relation with no attrs");
89 * now create the parametesr for keys/inheritance etc. All of them are
92 createStmt.relname = relname;
93 createStmt.istemp = false;
94 createStmt.tableElts = attrList;
95 /* createStmt.tableType = NULL;*/
96 createStmt.inhRelnames = NIL;
97 createStmt.constraints = NIL;
100 * finally create the relation...
102 DefineRelation(&createStmt, RELKIND_RELATION);
105 /*------------------------------------------------------------------
106 * makeViewRetrieveRuleName
108 * Given a view name, returns the name for the 'on retrieve to "view"'
110 * This routine is called when defining/removing a view.
111 *------------------------------------------------------------------
114 MakeRetrieveViewRuleName(char *viewName)
118 buf = palloc(strlen(viewName) + 5);
119 snprintf(buf, strlen(viewName) + 5, "_RET%s", viewName);
125 FormViewRetrieveRule(char *viewName, Query *viewParse)
132 * Create a RuleStmt that corresponds to the suitable rewrite rule
133 * args for DefineQueryRewrite();
135 rule = makeNode(RuleStmt);
136 rname = MakeRetrieveViewRuleName(viewName);
138 attr = makeNode(Attr);
139 attr->relname = pstrdup(viewName);
140 /* attr->refname = pstrdup(viewName);*/
141 rule->rulename = pstrdup(rname);
142 rule->whereClause = NULL;
143 rule->event = CMD_SELECT;
145 rule->instead = true;
146 rule->actions = lcons(viewParse, NIL);
152 DefineViewRules(char *viewName, Query *viewParse)
154 RuleStmt *retrieve_rule = NULL;
157 RuleStmt *replace_rule = NULL;
158 RuleStmt *append_rule = NULL;
159 RuleStmt *delete_rule = NULL;
163 retrieve_rule = FormViewRetrieveRule(viewName, viewParse);
167 replace_rule = FormViewReplaceRule(viewName, viewParse);
168 append_rule = FormViewAppendRule(viewName, viewParse);
169 delete_rule = FormViewDeleteRule(viewName, viewParse);
173 DefineQueryRewrite(retrieve_rule);
176 DefineQueryRewrite(replace_rule);
177 DefineQueryRewrite(append_rule);
178 DefineQueryRewrite(delete_rule);
183 /*---------------------------------------------------------------
184 * UpdateRangeTableOfViewParse
186 * Update the range table of the given parsetree.
187 * This update consists of adding two new entries IN THE BEGINNING
188 * of the range table (otherwise the rule system will die a slow,
189 * horrible and painful death, and we do not want that now, do we?)
190 * one for the CURRENT relation and one for the NEW one (both of
191 * them refer in fact to the "view" relation).
193 * Of course we must also increase the 'varnos' of all the Var nodes
196 * NOTE: these are destructive changes. It would be difficult to
197 * make a complete copy of the parse tree and make the changes
199 *---------------------------------------------------------------
202 UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
206 RangeTblEntry *rt_entry1,
210 * first offset all var nodes by 2
212 OffsetVarNodes((Node *) viewParse->targetList, 2, 0);
213 OffsetVarNodes(viewParse->qual, 2, 0);
215 OffsetVarNodes(viewParse->havingQual, 2, 0);
219 * find the old range table...
221 old_rt = viewParse->rtable;
224 * create the 2 new range table entries and form the new range
225 * table... CURRENT first, then NEW....
227 rt_entry1 = addRangeTableEntry(NULL, (char *) viewName, "*CURRENT*",
229 rt_entry2 = addRangeTableEntry(NULL, (char *) viewName, "*NEW*",
231 new_rt = lcons(rt_entry2, old_rt);
232 new_rt = lcons(rt_entry1, new_rt);
235 * Now the tricky part.... Update the range table in place... Be
236 * careful here, or hell breaks loooooooooooooOOOOOOOOOOOOOOOOOOSE!
238 viewParse->rtable = new_rt;
241 /*-------------------------------------------------------------------
244 * - takes a "viewname", "parsetree" pair and then
245 * 1) construct the "virtual" relation
246 * 2) commit the command but NOT the transaction,
247 * so that the relation exists
248 * before the rules are defined.
249 * 2) define the "n" rules specified in the PRS2 paper
250 * over the "virtual" relation
251 *-------------------------------------------------------------------
254 DefineView(char *viewName, Query *viewParse)
258 viewTlist = viewParse->targetList;
261 * Create the "view" relation NOTE: if it already exists, the xaxt
264 DefineVirtualRelation(viewName, viewTlist);
267 * The relation we have just created is not visible to any other
268 * commands running with the same transaction & command id. So,
269 * increment the command id counter (but do NOT pfree any memory!!!!)
271 CommandCounterIncrement();
274 * The range table of 'viewParse' does not contain entries for the
275 * "CURRENT" and "NEW" relations. So... add them! NOTE: we make the
276 * update in place! After this call 'viewParse' will never be what it
279 UpdateRangeTableOfViewParse(viewName, viewParse);
280 DefineViewRules(viewName, viewParse);
283 /*------------------------------------------------------------------
286 * Remove a view given its name
287 *------------------------------------------------------------------
290 RemoveView(char *viewName)
295 * first remove all the "view" rules... Currently we only have one!
297 rname = MakeRetrieveViewRuleName(viewName);
298 RemoveRewriteRule(rname);
301 * we don't really need that, but just in case...
303 CommandCounterIncrement();
306 * now remove the relation.
308 heap_destroy_with_catalog(viewName);