/*------------------------------------------------------------------------- * * version.c-- * This file contains all the rules that govern all version semantics. * * Copyright (c) 1994, Regents of the University of California * * The version stuff has not been tested under postgres95 and probably doesn't * work! - jolly 8/19/95 * * * IDENTIFICATION * $Header: /cvsroot/pgsql/src/backend/commands/_deadcode/Attic/version.c,v 1.1.1.1 1996/07/09 06:21:23 scrappy Exp $ * * NOTES * At the point the version is defined, 2 physical relations are created * _added and _deleted. * * In addition, 4 rules are defined which govern the semantics of versions * w.r.t retrieves, appends, replaces and deletes. * *------------------------------------------------------------------------- */ #include #include "postgres.h" #include "utils/rel.h" #include "access/heapam.h" #include "utils/builtins.h" #include "utils/elog.h" #include "nodes/pg_list.h" #include "commands/version.h" #include "access/xact.h" /* for GetCurrentXactStartTime */ #include "tcop/tcopprot.h" #define MAX_QUERY_LEN 1024 char rule_buf[MAX_QUERY_LEN]; static char attr_list[MAX_QUERY_LEN]; static void setAttrList(char *bname); /* * 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. */ static void eval_as_new_xact(char *query) { /* WARNING! do not uncomment the following lines WARNING! * CommitTransactionCommand(); * StartTransactionCommand(); */ CommandCounterIncrement(); pg_eval(query, (char **) NULL, (Oid *) NULL, 0); } /* * Define a version. */ void DefineVersion(char *name, char *fromRelname, char *date) { char *bname; static char saved_basename[512]; static char saved_snapshot[512]; if (date == NULL) { /* no time ranges */ bname = fromRelname; (void) strcpy(saved_basename, (char *) bname); *saved_snapshot = (char)NULL; } else { /* version is a snapshot */ bname = fromRelname; (void) strcpy(saved_basename, (char *) bname); sprintf(saved_snapshot, "['%s']", date); } /* * 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. */ setAttrList(bname); VersionCreate (name, saved_basename); VersionAppend (name, saved_basename); VersionDelete (name, saved_basename,saved_snapshot); VersionReplace (name, saved_basename,saved_snapshot); VersionRetrieve (name, saved_basename, saved_snapshot); } /* * Creates the deltas. */ void VersionCreate(char *vname, char *bname) { static char query_buf [MAX_QUERY_LEN]; /* * Creating the dummy version relation for triggering rules. */ sprintf(query_buf, "SELECT * INTO TABLE %s from %s where 1 =2", vname, bname); pg_eval (query_buf, (char **) NULL, (Oid *) NULL, 0); /* * Creating the ``v_added'' relation */ sprintf (query_buf, "SELECT * INTO TABLE %s_added from %s where 1 = 2", vname, bname); eval_as_new_xact (query_buf); /* * Creating the ``v_deleted'' relation. */ sprintf (query_buf, "CREATE TABLE %s_del (DOID oid)", vname); eval_as_new_xact (query_buf); } /* * Given the relation name, does a catalog lookup for that relation and * sets the global variable 'attr_list' with the list of attributes (names) * for that relation. */ static void setAttrList(char *bname) { Relation rdesc; int i = 0; int maxattrs = 0; char *attrname; char temp_buf[512]; int notfirst = 0; rdesc = heap_openr(bname); if (rdesc == NULL ) { elog(WARN,"Unable to expand all -- amopenr failed "); return; } maxattrs = RelationGetNumberOfAttributes(rdesc); attr_list[0] = '\0'; for ( i = maxattrs-1 ; i > -1 ; --i ) { attrname = (rdesc->rd_att->attrs[i]->attname).data; 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); } heap_close(rdesc); return; } /* * This routine defines the rule governing the append semantics of * versions. All tuples appended to a version gets appended to the * _added relation. */ void VersionAppend(char *vname, char *bname) { sprintf(rule_buf, "define rewrite rule %s_append is on INSERT to %s do instead append %s_added(%s)", vname, vname, vname, attr_list); eval_as_new_xact(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 _added relation. * 2. Retrieve all tuples in the base relation which are not in * the _del relation. */ void VersionRetrieve(char *vname, char *bname, char *snapshot) { sprintf(rule_buf, "define rewrite rule %s_retrieve is on SELECT to %s do instead\n\ SELECT %s_1.oid, %s_1.* 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 _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 _del relation. */ void VersionDelete(char *vname, char *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 _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 _del relation. * 2.2 A copy of the tuple is appended to the _added relation */ void VersionReplace(char *vname, char *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_del(DOID = current.oid) from _%s in %s%s \ where current.oid = _%s.oid\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,vname, vname,bname,bname,snapshot,bname, vname,attr_list,bname,bname,snapshot,vname,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); */ }