350 lines
9.5 KiB
C
350 lines
9.5 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* 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
|
|
*
|
|
*
|
|
* $Id: version.c,v 1.22 1999/07/17 20:16:55 momjian Exp $
|
|
*
|
|
* NOTES
|
|
* 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.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
#define MAX_QUERY_LEN 1024
|
|
|
|
char rule_buf[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.
|
|
*/
|
|
#ifdef NOT_USED
|
|
static void
|
|
eval_as_new_xact(char *query)
|
|
{
|
|
|
|
/*
|
|
* WARNING! do not uncomment the following lines WARNING!
|
|
* CommitTransactionCommand(); StartTransactionCommand();
|
|
*/
|
|
CommandCounterIncrement();
|
|
pg_exec_query(query);
|
|
}
|
|
|
|
#endif
|
|
/*
|
|
* Define a version.
|
|
*/
|
|
#ifdef NOT_USED
|
|
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;
|
|
strcpy(saved_basename, (char *) bname);
|
|
*saved_snapshot = (char) NULL;
|
|
}
|
|
else
|
|
{
|
|
/* version is a snapshot */
|
|
bname = fromRelname;
|
|
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);
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Creates the deltas.
|
|
*/
|
|
#ifdef NOT_USED
|
|
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_exec_query(query_buf);
|
|
|
|
/*
|
|
* 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);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
#ifdef NOT_USED
|
|
static void
|
|
setAttrList(char *bname)
|
|
{
|
|
Relation rel;
|
|
int i = 0;
|
|
int maxattrs = 0;
|
|
char *attrname;
|
|
char temp_buf[512];
|
|
int notfirst = 0;
|
|
|
|
rel = heap_openr(bname);
|
|
if (rel == NULL)
|
|
{
|
|
elog(ERROR, "Unable to expand all -- amopenr failed ");
|
|
return;
|
|
}
|
|
maxattrs = RelationGetNumberOfAttributes(rel);
|
|
|
|
attr_list[0] = '\0';
|
|
|
|
for (i = maxattrs - 1; i > -1; --i)
|
|
{
|
|
attrname = (rel->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(rel);
|
|
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
* This routine defines the rule governing the append semantics of
|
|
* versions. All tuples appended to a version gets appended to the
|
|
* <vname>_added relation.
|
|
*/
|
|
#ifdef NOT_USED
|
|
static 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);
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
#ifdef NOT_USED
|
|
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); */
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
#ifdef NOT_USED
|
|
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 */
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
#ifdef NOT_USED
|
|
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); */
|
|
|
|
}
|
|
|
|
#endif
|