home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / commands / version.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-02  |  11.6 KB  |  407 lines

  1. /*
  2.  *  This file contains all the rules that govern all version semantics.
  3.  *
  4.  *  At the point the version is defined, 2 physical relations are created
  5.  *  <vname>_added and <vname>_deleted.
  6.  *
  7.  *  In addition, 4 rules are defined which govern the semantics of versions 
  8.  *  w.r.t retrieves, appends, replaces and deletes.
  9.  *
  10.  *  $Header: /private/postgres/src/commands/RCS/version.c,v 1.16 1992/06/28 03:46:38 mao Exp $
  11.  */
  12.  
  13. #include <stdio.h>
  14.  
  15. #include "tmp/postgres.h"
  16.  
  17. #include "utils/rel.h"
  18. #include "access/heapam.h"
  19. #include "utils/log.h"
  20. #include "nodes/pg_lisp.h"
  21. #include "commands/version.h"
  22. #include "access/xact.h"        /* for GetCurrentXactStartTime */
  23.  
  24. #define MAX_QUERY_LEN 1024
  25.  
  26. char rule_buf[MAX_QUERY_LEN];
  27. static char attr_list[MAX_QUERY_LEN];
  28.  
  29. /*
  30.  * problem: the version system assumes that the rules it declares will
  31.  *          be fired in the order of declaration, it also assumes
  32.  *          goh's silly instead semantics.  Unfortunately, it is a pain
  33.  *          to make the version system work with the new semantics.
  34.  *          However the whole problem can be solved, and some nice
  35.  *          functionality can be achieved if we get multiple action rules
  36.  *          to work.  So thats what I did                       -- glass
  37.  *
  38.  * Well, at least they've been working for about 20 minutes.
  39.  * 
  40.  * So any comments in this code about 1 rule per transction are false...:)
  41.  *
  42.  */
  43.  
  44. /*
  45.  *  This is needed because the rule system only allows 
  46.  *  *1* rule to be defined per transaction.
  47.  *
  48.  * NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  49.  * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  50.  * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  51.  * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  52.  * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  53.  * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  54.  * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  55.  * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  56.  * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  57.  * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  58.  * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  59.  * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
  60.  * OOOOOOOOOOOOOOOOOOO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  61.  *
  62.  * DONT DO THAT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  63.  *
  64.  * If you commit the current Xact all the palloced memory GOES AWAY
  65.  * and could be re-palloced in the new Xact and the whole hell breaks
  66.  * loose and poor people like me spend 2 hours of their live chassing
  67.  * a strange memory bug instead of watching the "Get Smart" marathon
  68.  * in NICK !
  69.  * DO NOT COMMIT THE XACT, just increase the Cid counter!
  70.  *                            _sp.
  71.  */
  72.  
  73. void
  74. eval_as_new_xact ( query )
  75.      char *query;
  76. {
  77.   /* WARNING! do not uncomment the following lines WARNING!
  78.    *  CommitTransactionCommand();
  79.    * StartTransactionCommand();
  80.    */
  81.   CommandCounterIncrement();
  82.   pg_eval(query, (char *) NULL, (ObjectId *) NULL, 0);
  83. }
  84.  
  85. void
  86. CreateVersion (name, bnamestring)
  87.      Name     name;
  88.      List     bnamestring;
  89. {
  90.   LispValue tmp_list = LispNil;
  91.   int notfirst = 0;
  92.   int length = 0;
  93.   char *attrname;
  94.   LispValue i, temp;
  95.   Name bname;
  96.   static char temp_buf[512];
  97.   static char saved_basename[512];
  98.   static char saved_vname[ sizeof(NameData)];
  99.   static char saved_snapshot[512];
  100.  
  101.   if ( NodeType(bnamestring) == classTag(LispStr) ) {
  102.     /* no time ranges */
  103.     bname = (Name)CString(bnamestring);
  104.     strcpy(saved_basename, bname);
  105.     *saved_snapshot = (char)NULL;
  106.   } else {
  107.     /* version is a snapshot */
  108.     bname = (Name)CString(CAR(bnamestring));
  109.     strcpy(saved_basename, bname);
  110.     sprintf(saved_snapshot, "[\"%s\"]",
  111.         CString(CADR(bnamestring)) );
  112.   }
  113.  
  114.   bcopy (name, saved_vname, sizeof(NameData));
  115.   
  116.   /*
  117.    * Calls the routine ``GetAttrList'' get the list of attributes
  118.    * from the base relation. 
  119.    * Code is put here so that we only need to look up the attribute once for
  120.    * both appends and replaces.
  121.    */
  122.  
  123.   tmp_list = GetAttrList(bname);
  124.   
  125.   attr_list[0] = '\0';
  126.   foreach(i, tmp_list) {
  127.     temp = CAR(i);
  128.     attrname = CString(temp);
  129.  
  130.     if (notfirst == 1)
  131.       sprintf(temp_buf, ", %s = new.%s", attrname, attrname);
  132.     else {
  133.       sprintf(temp_buf, "%s = new.%s", attrname, attrname);
  134.       notfirst = 1;
  135.     }
  136.     strcat(attr_list, temp_buf);  
  137.   }
  138.  
  139.   length = strlen(attr_list) + 1;
  140.   VersionCreate ((Name) saved_vname, (Name) saved_basename);
  141.   VersionAppend ((Name) saved_vname, (Name) saved_basename);
  142.   VersionDelete ((Name) saved_vname, (Name) saved_basename,saved_snapshot);
  143.   VersionReplace ((Name) saved_vname, (Name) saved_basename,saved_snapshot);
  144.   VersionRetrieve ((Name) saved_vname, (Name) saved_basename, saved_snapshot);
  145.  
  146. }
  147.  
  148.  
  149. void
  150. VersionCreate (vname, bname)
  151.      Name vname;
  152.      Name bname;
  153.  
  154. {
  155.   static char query_buf [MAX_QUERY_LEN];
  156.  
  157.   /*
  158.    *  Creating the dummy version relation for triggering rules.
  159.    */
  160.   sprintf(query_buf, "retrieve into %s ( %s.all) where 1 =2", vname,bname);
  161.  
  162.   pg_eval (query_buf, (char *) NULL, (ObjectId *) NULL, 0);  
  163.  
  164.   /* 
  165.    * Creating the ``v_added'' relation 
  166.    */
  167.   sprintf (query_buf, "retrieve into %s_added (%s.all) where 1 = 2", vname, bname);
  168.   eval_as_new_xact (query_buf); 
  169.  
  170. /*  printf ("%s\n",query_buf); */
  171.  
  172.  
  173.   /* 
  174.    * Creating the ``v_deleted'' relation. 
  175.    */
  176.   sprintf (query_buf, "create %s_del(DOID = oid)", vname);
  177.  
  178.   eval_as_new_xact (query_buf); 
  179. }
  180.  
  181.  
  182. /*
  183.  * Given the relation name, GetAttrList does a catalog lookup for that
  184.  * relation and returns the list of attributes (names) for that relation.
  185.  */
  186.  
  187. LispValue
  188. GetAttrList(bname)
  189.     Name bname;
  190. {
  191.     Relation rdesc;
  192.     int i = 0;
  193.     int maxattrs = 0;
  194.     int type_id, type_len,vnum;
  195.     LispValue attr_list = LispNil;
  196.     
  197.     rdesc = heap_openr(bname);
  198.     if (rdesc == NULL ) {
  199.     elog(WARN,"Unable to expand all -- amopenr failed ");
  200.     return(NULL);
  201.     }
  202.     maxattrs = RelationGetNumberOfAttributes(rdesc);
  203.  
  204.     for ( i = maxattrs-1 ; i > -1 ; --i ) {
  205.     attr_list = lispCons(lispString((char *)(&rdesc->rd_att.data[i]->attname)),
  206.                  attr_list);
  207.     }
  208.  
  209.     heap_close(rdesc);
  210.  
  211.     return(attr_list);
  212. }
  213.  
  214. /*
  215.  * This routine defines the rule governing the append semantics of
  216.  * versions.  All tuples appended to a version gets appended to the 
  217.  * <vname>_added relation.
  218.  */
  219.  
  220. void
  221. VersionAppend (vname,bname)
  222.      Name vname,bname;
  223. {
  224.   sprintf(rule_buf,
  225.       "define rewrite rule %s_append is on append to %s do instead append \
  226. %s_added(%s)",
  227.       vname, vname, vname, attr_list);
  228.  
  229.   eval_as_new_xact(rule_buf); 
  230. /*  printf("%s\n",rule_buf);  */
  231.  
  232.  
  233. }
  234.  
  235.  
  236. /*
  237.  * This routine defines the rule governing the retrieval semantics of
  238.  * versions.  To retrieve tuples from a version , we need to:
  239.  *
  240.  *      1. Retrieve all tuples in the <vname>_added relation.
  241.  *      2. Retrieve all tuples in the base relation which are not in 
  242.  *         the <vname>_del relation.
  243.  */
  244.  
  245. void
  246. VersionRetrieve(vname,bname,snapshot)
  247.     Name vname, bname;
  248.      char *snapshot;
  249. {
  250.  
  251.   sprintf(rule_buf, 
  252.       "define rewrite rule %s_retrieve is on retrieve to %s do instead\n\
  253. retrieve (%s_1.oid,%s_1.all) from _%s in %s%s, %s_1 in (%s_added | _%s) \
  254. where _%s.oid !!= \"%s_del.DOID\"",
  255.       vname, vname, vname, vname, bname, bname,snapshot,
  256.       vname, vname, bname,bname,vname);
  257.  
  258.   eval_as_new_xact(rule_buf); 
  259.  
  260. /*  printf("%s\n",rule_buf); */
  261.  
  262. }
  263.  
  264. /*
  265.  * This routine defines the rules that govern the delete semantics of 
  266.  * versions. Two things happens when we delete a tuple from a version:
  267.  *
  268.  *     1. If the tuple to be deleted was added to the version *after*
  269.  *        the version was created, then we simply delete the tuple 
  270.  *        from the <vname>_added relation.
  271.  *     2. If the tuple to be deleted is actually in the base relation,
  272.  *        then we have to mark that tuple as being deleted by adding
  273.  *        it to the <vname>_del relation.
  274.  */
  275.  
  276. void
  277. VersionDelete(vname,bname,snapshot)
  278.      Name vname,bname;
  279.      char *snapshot;
  280. {
  281.  
  282.   sprintf(rule_buf,
  283.       "define rewrite rule %s_delete1 is on delete to %s do instead\n \
  284. [delete %s_added where current.oid = %s_added.oid\n \
  285.  append %s_del(DOID = current.oid) from _%s in %s%s \
  286.  where current.oid = _%s.oid] \n",
  287.       vname,vname,vname,vname,vname,bname,bname,snapshot,bname);
  288.  
  289.   eval_as_new_xact(rule_buf); 
  290. #ifdef OLD_REWRITE
  291.    sprintf(rule_buf,
  292.          "define rewrite rule %s_delete2 is on delete to %s do instead \n \
  293.  append %s_del(DOID = current.oid) from _%s in %s%s \
  294.  where current.oid = _%s.oid \n",
  295.          vname,vname,vname,bname,bname,snapshot,bname);
  296.  
  297.    eval_as_new_xact(rule_buf);
  298. #endif OLD_REWRITE
  299. }
  300.  
  301. /*
  302.  *  This routine defines the rules that govern the update semantics
  303.  *  of versions. To update a tuple in a version:
  304.  *
  305.  *      1. If the tuple is in <vname>_added, we simply ``replace''
  306.  *         the tuple (as per postgres style).
  307.  *      2. if the tuple is in the base relation, then two things have to
  308.  *         happen:
  309.  *         2.1  The tuple is marked ``deleted'' from the base relation by 
  310.  *              adding the tuple to the <vname>_del relation. 
  311.  *         2.2  A copy of the tuple is appended to the <vname>_added relation
  312.  */
  313.  
  314. void
  315. VersionReplace(vname, bname,snapshot)
  316.      Name vname,bname;
  317.      char *snapshot;
  318. {
  319.   sprintf(rule_buf,
  320.       "define rewrite rule %s_replace1 is on replace to %s do instead \n\
  321. [replace %s_added(%s) where current.oid = %s_added.oid \n\
  322.  append %s_added(%s) from _%s in %s%s \
  323.  where current.oid !!= \"%s_added.oid\" and current.oid = _%s.oid\n\
  324.  append %s_del(DOID = current.oid) from _%s in %s%s \
  325.  where current.oid = _%s.oid]\n",
  326.       vname,vname,vname,attr_list,vname,
  327. vname,attr_list,bname,bname,snapshot,vname,bname,
  328.           vname,bname,bname,snapshot,bname);
  329.  
  330.   eval_as_new_xact(rule_buf); 
  331.  
  332. /*  printf("%s\n",rule_buf); */
  333. #ifdef OLD_REWRITE
  334.   sprintf(rule_buf,
  335.       "define rewrite rule %s_replace2 is on replace to %s do \n\
  336. append %s_del(DOID = current.oid) from _%s in %s%s \
  337. where current.oid = _%s.oid\n",
  338.       vname,vname,vname,bname,bname,snapshot,bname);
  339.  
  340.   eval_as_new_xact(rule_buf); 
  341.  
  342.   sprintf(rule_buf,
  343.       "define rewrite rule %s_replace3 is on replace to %s do instead\n\
  344. append %s_added(%s) from _%s in %s%s \
  345. where current.oid !!= \"%s_added.oid\" and current.oid = \
  346. _%s.oid\n",
  347.       vname,vname, vname,attr_list,bname,bname,snapshot,vname,bname);
  348.  
  349.   eval_as_new_xact(rule_buf); 
  350. #endif OLD_REWRITE
  351. /*  printf("%s\n",rule_buf); */
  352.  
  353. }
  354.  
  355. CreateBVersion(vname,bnamestring)
  356.      Name vname;
  357.      List bnamestring;
  358. {
  359.     AbsoluteTime now    = NULL;
  360.     char *timestring     = NULL;
  361.     static char query_buf[MAX_QUERY_LEN];
  362.     static char saved_vname[sizeof(NameData)];
  363.     static char bname[sizeof(NameData)];
  364. #ifdef BOGUS
  365.     Name bname;
  366. #endif
  367.     now = GetCurrentTransactionStartTime();
  368.     timestring = (char *)abstimeout(now);
  369.  
  370.  
  371.     sprintf(bname,"%s", CString(bnamestring) );
  372.     sprintf(saved_vname,"%s", vname);
  373.  
  374.  
  375.     if (NodeType(bnamestring) != classTag(LispStr)) {
  376.       elog(WARN,
  377.        "Create Version:  Backward deltas of snapshots not supported yet\n");
  378.     }
  379.  
  380.     /*
  381.      *  Rename the base relation to the version name.
  382.      */
  383.  
  384.     sprintf(query_buf, "rename %s to %s", bname,vname);
  385.     eval_as_new_xact(query_buf); 
  386.  
  387.     /*
  388.      *  Create a dummy base relation from which the 
  389.      *  retrieve rule can be triggered.
  390.      */
  391.     sprintf(query_buf, "retrieve into %s(%s.all) where 1 = 2",
  392.         bname, saved_vname);
  393.     eval_as_new_xact(query_buf);  
  394.  
  395.     /* Now to define the retrieve rule. */
  396.  
  397.     sprintf(query_buf,"define rewrite rule b%s_retrieve is \n\
  398. on retrieve to %s do instead retrieve (_%s.all) from _%s in %s[\"%s\"]\n",
  399.         saved_vname, bname, saved_vname,saved_vname,
  400.         saved_vname,timestring);
  401.     eval_as_new_xact(query_buf); 
  402.  
  403. }
  404.  
  405.  
  406.  
  407.