home *** CD-ROM | disk | FTP | other *** search
- /*
- * This file contains all the rules that govern all version semantics.
- *
- * At the point the version is defined, 2 physical relations are created
- * <vname>_added and <vname>_deleted.
- *
- * In addition, 4 rules are defined which govern the semantics of versions
- * w.r.t retrieves, appends, replaces and deletes.
- *
- * $Header: /private/postgres/src/commands/RCS/version.c,v 1.16 1992/06/28 03:46:38 mao Exp $
- */
-
- #include <stdio.h>
-
- #include "tmp/postgres.h"
-
- #include "utils/rel.h"
- #include "access/heapam.h"
- #include "utils/log.h"
- #include "nodes/pg_lisp.h"
- #include "commands/version.h"
- #include "access/xact.h" /* for GetCurrentXactStartTime */
-
- #define MAX_QUERY_LEN 1024
-
- char rule_buf[MAX_QUERY_LEN];
- static char attr_list[MAX_QUERY_LEN];
-
- /*
- * problem: the version system assumes that the rules it declares will
- * be fired in the order of declaration, it also assumes
- * goh's silly instead semantics. Unfortunately, it is a pain
- * to make the version system work with the new semantics.
- * However the whole problem can be solved, and some nice
- * functionality can be achieved if we get multiple action rules
- * to work. So thats what I did -- glass
- *
- * Well, at least they've been working for about 20 minutes.
- *
- * So any comments in this code about 1 rule per transction are false...:)
- *
- */
-
- /*
- * This is needed because the rule system only allows
- * *1* rule to be defined per transaction.
- *
- * NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- *
- * DONT DO THAT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- *
- * If you commit the current Xact all the palloced memory GOES AWAY
- * and could be re-palloced in the new Xact and the whole hell breaks
- * loose and poor people like me spend 2 hours of their live chassing
- * a strange memory bug instead of watching the "Get Smart" marathon
- * in NICK !
- * DO NOT COMMIT THE XACT, just increase the Cid counter!
- * _sp.
- */
-
- void
- eval_as_new_xact ( query )
- char *query;
- {
- /* WARNING! do not uncomment the following lines WARNING!
- * CommitTransactionCommand();
- * StartTransactionCommand();
- */
- CommandCounterIncrement();
- pg_eval(query, (char *) NULL, (ObjectId *) NULL, 0);
- }
-
- void
- CreateVersion (name, bnamestring)
- Name name;
- List bnamestring;
- {
- LispValue tmp_list = LispNil;
- int notfirst = 0;
- int length = 0;
- char *attrname;
- LispValue i, temp;
- Name bname;
- static char temp_buf[512];
- static char saved_basename[512];
- static char saved_vname[ sizeof(NameData)];
- static char saved_snapshot[512];
-
- if ( NodeType(bnamestring) == classTag(LispStr) ) {
- /* no time ranges */
- bname = (Name)CString(bnamestring);
- strcpy(saved_basename, bname);
- *saved_snapshot = (char)NULL;
- } else {
- /* version is a snapshot */
- bname = (Name)CString(CAR(bnamestring));
- strcpy(saved_basename, bname);
- sprintf(saved_snapshot, "[\"%s\"]",
- CString(CADR(bnamestring)) );
- }
-
- bcopy (name, saved_vname, sizeof(NameData));
-
- /*
- * Calls the routine ``GetAttrList'' get the list of attributes
- * from the base relation.
- * Code is put here so that we only need to look up the attribute once for
- * both appends and replaces.
- */
-
- tmp_list = GetAttrList(bname);
-
- attr_list[0] = '\0';
- foreach(i, tmp_list) {
- temp = CAR(i);
- attrname = CString(temp);
-
- if (notfirst == 1)
- sprintf(temp_buf, ", %s = new.%s", attrname, attrname);
- else {
- sprintf(temp_buf, "%s = new.%s", attrname, attrname);
- notfirst = 1;
- }
- strcat(attr_list, temp_buf);
- }
-
- length = strlen(attr_list) + 1;
- VersionCreate ((Name) saved_vname, (Name) saved_basename);
- VersionAppend ((Name) saved_vname, (Name) saved_basename);
- VersionDelete ((Name) saved_vname, (Name) saved_basename,saved_snapshot);
- VersionReplace ((Name) saved_vname, (Name) saved_basename,saved_snapshot);
- VersionRetrieve ((Name) saved_vname, (Name) saved_basename, saved_snapshot);
-
- }
-
-
- void
- VersionCreate (vname, bname)
- Name vname;
- Name bname;
-
- {
- static char query_buf [MAX_QUERY_LEN];
-
- /*
- * Creating the dummy version relation for triggering rules.
- */
- sprintf(query_buf, "retrieve into %s ( %s.all) where 1 =2", vname,bname);
-
- pg_eval (query_buf, (char *) NULL, (ObjectId *) NULL, 0);
-
- /*
- * Creating the ``v_added'' relation
- */
- sprintf (query_buf, "retrieve into %s_added (%s.all) where 1 = 2", vname, bname);
- eval_as_new_xact (query_buf);
-
- /* printf ("%s\n",query_buf); */
-
-
- /*
- * Creating the ``v_deleted'' relation.
- */
- sprintf (query_buf, "create %s_del(DOID = oid)", vname);
-
- eval_as_new_xact (query_buf);
- }
-
-
- /*
- * Given the relation name, GetAttrList does a catalog lookup for that
- * relation and returns the list of attributes (names) for that relation.
- */
-
- LispValue
- GetAttrList(bname)
- Name bname;
- {
- Relation rdesc;
- int i = 0;
- int maxattrs = 0;
- int type_id, type_len,vnum;
- LispValue attr_list = LispNil;
-
- rdesc = heap_openr(bname);
- if (rdesc == NULL ) {
- elog(WARN,"Unable to expand all -- amopenr failed ");
- return(NULL);
- }
- maxattrs = RelationGetNumberOfAttributes(rdesc);
-
- for ( i = maxattrs-1 ; i > -1 ; --i ) {
- attr_list = lispCons(lispString((char *)(&rdesc->rd_att.data[i]->attname)),
- attr_list);
- }
-
- heap_close(rdesc);
-
- return(attr_list);
- }
-
- /*
- * This routine defines the rule governing the append semantics of
- * versions. All tuples appended to a version gets appended to the
- * <vname>_added relation.
- */
-
- void
- VersionAppend (vname,bname)
- Name vname,bname;
- {
- sprintf(rule_buf,
- "define rewrite rule %s_append is on append to %s do instead append \
- %s_added(%s)",
- vname, vname, vname, attr_list);
-
- eval_as_new_xact(rule_buf);
- /* printf("%s\n",rule_buf); */
-
-
- }
-
-
- /*
- * This routine defines the rule governing the retrieval semantics of
- * versions. To retrieve tuples from a version , we need to:
- *
- * 1. Retrieve all tuples in the <vname>_added relation.
- * 2. Retrieve all tuples in the base relation which are not in
- * the <vname>_del relation.
- */
-
- void
- VersionRetrieve(vname,bname,snapshot)
- Name vname, bname;
- char *snapshot;
- {
-
- sprintf(rule_buf,
- "define rewrite rule %s_retrieve is on retrieve to %s do instead\n\
- retrieve (%s_1.oid,%s_1.all) from _%s in %s%s, %s_1 in (%s_added | _%s) \
- where _%s.oid !!= \"%s_del.DOID\"",
- vname, vname, vname, vname, bname, bname,snapshot,
- vname, vname, bname,bname,vname);
-
- eval_as_new_xact(rule_buf);
-
- /* printf("%s\n",rule_buf); */
-
- }
-
- /*
- * This routine defines the rules that govern the delete semantics of
- * versions. Two things happens when we delete a tuple from a version:
- *
- * 1. If the tuple to be deleted was added to the version *after*
- * the version was created, then we simply delete the tuple
- * from the <vname>_added relation.
- * 2. If the tuple to be deleted is actually in the base relation,
- * then we have to mark that tuple as being deleted by adding
- * it to the <vname>_del relation.
- */
-
- void
- VersionDelete(vname,bname,snapshot)
- Name vname,bname;
- char *snapshot;
- {
-
- sprintf(rule_buf,
- "define rewrite rule %s_delete1 is on delete to %s do instead\n \
- [delete %s_added where current.oid = %s_added.oid\n \
- append %s_del(DOID = current.oid) from _%s in %s%s \
- where current.oid = _%s.oid] \n",
- vname,vname,vname,vname,vname,bname,bname,snapshot,bname);
-
- eval_as_new_xact(rule_buf);
- #ifdef OLD_REWRITE
- sprintf(rule_buf,
- "define rewrite rule %s_delete2 is on delete to %s do instead \n \
- append %s_del(DOID = current.oid) from _%s in %s%s \
- where current.oid = _%s.oid \n",
- vname,vname,vname,bname,bname,snapshot,bname);
-
- eval_as_new_xact(rule_buf);
- #endif OLD_REWRITE
- }
-
- /*
- * This routine defines the rules that govern the update semantics
- * of versions. To update a tuple in a version:
- *
- * 1. If the tuple is in <vname>_added, we simply ``replace''
- * the tuple (as per postgres style).
- * 2. if the tuple is in the base relation, then two things have to
- * happen:
- * 2.1 The tuple is marked ``deleted'' from the base relation by
- * adding the tuple to the <vname>_del relation.
- * 2.2 A copy of the tuple is appended to the <vname>_added relation
- */
-
- void
- VersionReplace(vname, bname,snapshot)
- Name vname,bname;
- char *snapshot;
- {
- sprintf(rule_buf,
- "define rewrite rule %s_replace1 is on replace to %s do instead \n\
- [replace %s_added(%s) where current.oid = %s_added.oid \n\
- append %s_added(%s) from _%s in %s%s \
- where current.oid !!= \"%s_added.oid\" and current.oid = _%s.oid\n\
- append %s_del(DOID = current.oid) from _%s in %s%s \
- where current.oid = _%s.oid]\n",
- vname,vname,vname,attr_list,vname,
- vname,attr_list,bname,bname,snapshot,vname,bname,
- vname,bname,bname,snapshot,bname);
-
- eval_as_new_xact(rule_buf);
-
- /* printf("%s\n",rule_buf); */
- #ifdef OLD_REWRITE
- sprintf(rule_buf,
- "define rewrite rule %s_replace2 is on replace to %s do \n\
- append %s_del(DOID = current.oid) from _%s in %s%s \
- where current.oid = _%s.oid\n",
- vname,vname,vname,bname,bname,snapshot,bname);
-
- eval_as_new_xact(rule_buf);
-
- sprintf(rule_buf,
- "define rewrite rule %s_replace3 is on replace to %s do instead\n\
- append %s_added(%s) from _%s in %s%s \
- where current.oid !!= \"%s_added.oid\" and current.oid = \
- _%s.oid\n",
- vname,vname, vname,attr_list,bname,bname,snapshot,vname,bname);
-
- eval_as_new_xact(rule_buf);
- #endif OLD_REWRITE
- /* printf("%s\n",rule_buf); */
-
- }
-
- CreateBVersion(vname,bnamestring)
- Name vname;
- List bnamestring;
- {
- AbsoluteTime now = NULL;
- char *timestring = NULL;
- static char query_buf[MAX_QUERY_LEN];
- static char saved_vname[sizeof(NameData)];
- static char bname[sizeof(NameData)];
- #ifdef BOGUS
- Name bname;
- #endif
- now = GetCurrentTransactionStartTime();
- timestring = (char *)abstimeout(now);
-
-
- sprintf(bname,"%s", CString(bnamestring) );
- sprintf(saved_vname,"%s", vname);
-
-
- if (NodeType(bnamestring) != classTag(LispStr)) {
- elog(WARN,
- "Create Version: Backward deltas of snapshots not supported yet\n");
- }
-
- /*
- * Rename the base relation to the version name.
- */
-
- sprintf(query_buf, "rename %s to %s", bname,vname);
- eval_as_new_xact(query_buf);
-
- /*
- * Create a dummy base relation from which the
- * retrieve rule can be triggered.
- */
- sprintf(query_buf, "retrieve into %s(%s.all) where 1 = 2",
- bname, saved_vname);
- eval_as_new_xact(query_buf);
-
- /* Now to define the retrieve rule. */
-
- sprintf(query_buf,"define rewrite rule b%s_retrieve is \n\
- on retrieve to %s do instead retrieve (_%s.all) from _%s in %s[\"%s\"]\n",
- saved_vname, bname, saved_vname,saved_vname,
- saved_vname,timestring);
- eval_as_new_xact(query_buf);
-
- }
-
-
-
-