1 /*-------------------------------------------------------------------------
4 * This file contains all the rules that govern all version semantics.
6 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * The version stuff has not been tested under postgres95 and probably
10 * doesn't work! - jolly 8/19/95
13 * $Id: version.c,v 1.25 2001/01/24 19:42:53 momjian Exp $
16 * At the point the version is defined, 2 physical relations are created
17 * <vname>_added and <vname>_deleted.
19 * In addition, 4 rules are defined which govern the semantics of
20 * versions w.r.t retrieves, appends, replaces and deletes.
22 *-------------------------------------------------------------------------
28 #define MAX_QUERY_LEN 1024
30 char rule_buf[MAX_QUERY_LEN];
33 * problem: the version system assumes that the rules it declares will
34 * be fired in the order of declaration, it also assumes
35 * goh's silly instead semantics. Unfortunately, it is a pain
36 * to make the version system work with the new semantics.
37 * However the whole problem can be solved, and some nice
38 * functionality can be achieved if we get multiple action rules
39 * to work. So thats what I did -- glass
41 * Well, at least they've been working for about 20 minutes.
43 * So any comments in this code about 1 rule per transction are false...:)
48 * This is needed because the rule system only allows
49 * *1* rule to be defined per transaction.
51 * NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
52 * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
53 * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
54 * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
55 * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
56 * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
57 * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
58 * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
59 * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
60 * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
61 * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
62 * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
63 * OOOOOOOOOOOOOOOOOOO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
65 * DONT DO THAT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
67 * If you commit the current Xact all the palloced memory GOES AWAY
68 * and could be re-palloced in the new Xact and the whole hell breaks
69 * loose and poor people like me spend 2 hours of their live chassing
70 * a strange memory bug instead of watching the "Get Smart" marathon
72 * DO NOT COMMIT THE XACT, just increase the Cid counter!
77 eval_as_new_xact(char *query)
81 * WARNING! do not uncomment the following lines WARNING!
82 * CommitTransactionCommand(); StartTransactionCommand();
84 CommandCounterIncrement();
94 DefineVersion(char *name, char *fromRelname, char *date)
97 static char saved_basename[512];
98 static char saved_snapshot[512];
104 strcpy(saved_basename, (char *) bname);
105 *saved_snapshot = (char) NULL;
109 /* version is a snapshot */
111 strcpy(saved_basename, (char *) bname);
112 sprintf(saved_snapshot, "['%s']", date);
117 * Calls the routine ``GetAttrList'' get the list of attributes from
118 * the base relation. Code is put here so that we only need to look up
119 * the attribute once for both appends and replaces.
123 VersionCreate(name, saved_basename);
124 VersionAppend(name, saved_basename);
125 VersionDelete(name, saved_basename, saved_snapshot);
126 VersionReplace(name, saved_basename, saved_snapshot);
127 VersionRetrieve(name, saved_basename, saved_snapshot);
133 * Creates the deltas.
137 VersionCreate(char *vname, char *bname)
139 static char query_buf[MAX_QUERY_LEN];
142 * Creating the dummy version relation for triggering rules.
144 sprintf(query_buf, "SELECT * INTO TABLE %s from %s where 1 =2",
147 pg_exec_query(query_buf);
150 * Creating the ``v_added'' relation
152 sprintf(query_buf, "SELECT * INTO TABLE %s_added from %s where 1 = 2",
154 eval_as_new_xact(query_buf);
157 * Creating the ``v_deleted'' relation.
159 sprintf(query_buf, "CREATE TABLE %s_del (DOID oid)", vname);
160 eval_as_new_xact(query_buf);
167 * Given the relation name, does a catalog lookup for that relation and
168 * sets the global variable 'attr_list' with the list of attributes (names)
173 setAttrList(char *bname)
182 rel = heap_openr(bname);
185 elog(ERROR, "Unable to expand all -- amopenr failed ");
188 maxattrs = RelationGetNumberOfAttributes(rel);
192 for (i = maxattrs - 1; i > -1; --i)
194 attrname = NameStr(rel->rd_att->attrs[i]->attname);
197 sprintf(temp_buf, ", %s = new.%s", attrname, attrname);
200 sprintf(temp_buf, "%s = new.%s", attrname, attrname);
203 strcat(attr_list, temp_buf);
214 * This routine defines the rule governing the append semantics of
215 * versions. All tuples appended to a version gets appended to the
216 * <vname>_added relation.
220 VersionAppend(char *vname, char *bname)
223 "define rewrite rule %s_append is on INSERT to %s do instead append %s_added(%s)",
224 vname, vname, vname, attr_list);
226 eval_as_new_xact(rule_buf);
232 * This routine defines the rule governing the retrieval semantics of
233 * versions. To retrieve tuples from a version , we need to:
235 * 1. Retrieve all tuples in the <vname>_added relation.
236 * 2. Retrieve all tuples in the base relation which are not in
237 * the <vname>_del relation.
241 VersionRetrieve(char *vname, char *bname, char *snapshot)
245 "define rewrite rule %s_retrieve is on SELECT to %s do instead\n\
246 SELECT %s_1.oid, %s_1.* from _%s in %s%s, %s_1 in (%s_added | _%s) \
247 where _%s.oid !!= '%s_del.DOID'",
248 vname, vname, vname, vname, bname,
250 vname, vname, bname, bname, vname);
252 eval_as_new_xact(rule_buf);
254 /* printf("%s\n",rule_buf); */
261 * This routine defines the rules that govern the delete semantics of
262 * versions. Two things happens when we delete a tuple from a version:
264 * 1. If the tuple to be deleted was added to the version *after*
265 * the version was created, then we simply delete the tuple
266 * from the <vname>_added relation.
267 * 2. If the tuple to be deleted is actually in the base relation,
268 * then we have to mark that tuple as being deleted by adding
269 * it to the <vname>_del relation.
273 VersionDelete(char *vname, char *bname, char *snapshot)
277 "define rewrite rule %s_delete1 is on delete to %s do instead\n \
278 [delete %s_added where current.oid = %s_added.oid\n \
279 append %s_del(DOID = current.oid) from _%s in %s%s \
280 where current.oid = _%s.oid] \n",
281 vname, vname, vname, vname, vname,
282 bname, bname, snapshot, bname);
284 eval_as_new_xact(rule_buf);
287 "define rewrite rule %s_delete2 is on delete to %s do instead \n \
288 append %s_del(DOID = current.oid) from _%s in %s%s \
289 where current.oid = _%s.oid \n",
290 vname, vname, vname, bname, bname, snapshot, bname);
292 eval_as_new_xact(rule_buf);
293 #endif /* OLD_REWRITE */
299 * This routine defines the rules that govern the update semantics
300 * of versions. To update a tuple in a version:
302 * 1. If the tuple is in <vname>_added, we simply ``replace''
303 * the tuple (as per postgres style).
304 * 2. if the tuple is in the base relation, then two things have to
306 * 2.1 The tuple is marked ``deleted'' from the base relation by
307 * adding the tuple to the <vname>_del relation.
308 * 2.2 A copy of the tuple is appended to the <vname>_added relation
312 VersionReplace(char *vname, char *bname, char *snapshot)
315 "define rewrite rule %s_replace1 is on replace to %s do instead \n\
316 [replace %s_added(%s) where current.oid = %s_added.oid \n\
317 append %s_del(DOID = current.oid) from _%s in %s%s \
318 where current.oid = _%s.oid\n\
319 append %s_added(%s) from _%s in %s%s \
320 where current.oid !!= '%s_added.oid' and current.oid = _%s.oid]\n",
321 vname, vname, vname, attr_list, vname,
322 vname, bname, bname, snapshot, bname,
323 vname, attr_list, bname, bname, snapshot, vname, bname);
325 eval_as_new_xact(rule_buf);
327 /* printf("%s\n",rule_buf); */
330 "define rewrite rule %s_replace2 is on replace to %s do \n\
331 append %s_del(DOID = current.oid) from _%s in %s%s \
332 where current.oid = _%s.oid\n",
333 vname, vname, vname, bname, bname, snapshot, bname);
335 eval_as_new_xact(rule_buf);
338 "define rewrite rule %s_replace3 is on replace to %s do instead\n\
339 append %s_added(%s) from _%s in %s%s \
340 where current.oid !!= '%s_added.oid' and current.oid = \
342 vname, vname, vname, attr_list, bname, bname, snapshot, vname, bname);
344 eval_as_new_xact(rule_buf);
345 #endif /* OLD_REWRITE */
346 /* printf("%s\n",rule_buf); */