home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / rewrite / RewriteDefin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  9.4 KB  |  338 lines

  1. /* 
  2.  * $Header: /private/postgres/src/rewrite/RCS/RewriteDefine.c,v 2.18 1992/06/28 03:47:58 mao Exp $
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include "tmp/postgres.h"
  7.  
  8. /* #include "rules/prs2locks.h"        /* temporarily */
  9. #include "utils/rel.h"            /* for Relation stuff */
  10. #include "access/heapam.h"        /* access methods like amopenr */
  11. #include "utils/log.h"            /* for elog */
  12. #include "nodes/pg_lisp.h"        /* for Lisp support */
  13. #include "parser/parse.h"        /* lisp atom database */
  14. #include "parser/parsetree.h"        /* for parsetree manip defines */
  15. #include "./locks.h"            
  16. ObjectId LastOidProcessed = InvalidObjectId;
  17. bool prs2AttributeIsOfBasicType();
  18.  
  19. /*
  20.  * This is too small for many rule plans, but it'll have to do for now.
  21.  * Rule plans, etc will eventually have to be large objects.
  22.  * 
  23.  * should this be smaller?
  24.  */
  25.  
  26. #define RULE_PLAN_SIZE 8192 
  27.  
  28. #define ShowParseTL(ptree)    lispDisplay(parse_targetlist(ptree))
  29. #define ShowParseQual(ptree)    lispDisplay(parse_qualification(ptree))
  30. #define ShowParseCmd(ptree)    lispDisplay(root_command_type \
  31.                         parse_root(ptree))
  32. #define ShowParseQual(ptree)    lispDisplay(parse_qualification(ptree))
  33.  
  34. /*
  35.  *    InsertRule
  36.  *    DESC :  takes the arguments and inserts them
  37.  *        as attributes into the system relation "pg_prs2rule"
  38.  *
  39.  *    MODS :    changes the value of LastOidProcessed as a side
  40.  *        effect of inserting the rule tuple
  41.  *
  42.  *    ARGS :    rulname        -    name of the rule
  43.  *        evtype        -    one of RETRIEVE,REPLACE,DELETE,APPEND
  44.  *        evobj        -    name of relation
  45.  *        evslot        -    comma delimited list of slots
  46.  *                    if null => multi-attr rule
  47.  *        evinstead    -    is an instead rule
  48.  *        actiontree    -    parsetree(s) of rule action
  49.  */
  50.  
  51. static char *foo = "reality is for dead birds" ;
  52.  
  53. void strcpyq(dest, source)
  54.     char *dest, *source;
  55. {
  56.     char *current=source,*destp= dest;    
  57.  
  58.     for(current=source; *current; current++) {
  59.         if (*current == '\"')  {
  60.             *destp = '\\';
  61.             destp++;
  62.         }
  63.         *destp = *current;
  64.         destp++;
  65.     }
  66.     *destp = '\0';
  67. }
  68.  
  69. OID
  70. InsertRule ( rulname , evtype , evobj , evslot , evqual, evinstead ,
  71.          actiontree )
  72.      Name     rulname;
  73.      int     evtype;
  74.      Name     evobj;
  75.      Name     evslot;
  76.      char    *evqual;
  77.      bool    evinstead;
  78.      char    *actiontree;
  79.  
  80. {
  81.     static char    rulebuf[RULE_PLAN_SIZE];
  82.     static char actionbuf[RULE_PLAN_SIZE];
  83.     static char qualbuf[RULE_PLAN_SIZE];
  84.     ObjectId eventrel_oid = InvalidObjectId;
  85.     AttributeNumber evslot_index = InvalidAttributeNumber;
  86.     Relation eventrel = NULL;
  87.     char *is_instead = "f";
  88.     extern void eval_as_new_xact();
  89.  
  90.     eventrel = amopenr( evobj );
  91.     if ( eventrel == NULL ) {
  92.     elog ( WARN, "rules cannot be defined on relations not in schema");
  93.     }
  94.     eventrel_oid = RelationGetRelationId(eventrel);
  95.  
  96.     /*
  97.      * if the slotname is null, we know that this is a multi-attr
  98.      * rule
  99.      */
  100.     if ( evslot == NULL )
  101.       evslot_index = -1;
  102.     else
  103.       evslot_index = varattno ( eventrel,evslot );
  104.     if ( evinstead )
  105.     is_instead = "t";
  106.     if ( evqual == NULL )
  107.       evqual = "nil";
  108.     amclose(eventrel);
  109.     if (IsDefinedRewriteRule(rulname)) 
  110.     elog(WARN, "Attempt to insert rule '%s' failed: already exists",
  111.          rulname);
  112.     strcpyq(actionbuf,actiontree);    
  113.     strcpyq(qualbuf, evqual);
  114.     sprintf(rulebuf,
  115.         "append pg_rewrite (rulename=\"%s\",ev_type=\"%d2\"::char,\
  116.         ev_class=%d::oid,ev_attr= %d::int2,\
  117.         action= \"%s\"::text , ev_qual= \"%s\"::text, \
  118.             fril_lb= %f , fril_ub= %f , is_instead=\"%s\"::bool )",
  119.         rulname,
  120.         AtomValueGetString(evtype),
  121.         eventrel_oid,
  122.         evslot_index,
  123.         actionbuf,
  124.         qualbuf,
  125.         0.0, 0.0,        /* deprecated */
  126.         is_instead );
  127.  
  128.     /* fprintf(stdout,"rule is \n%s\n", rulebuf ); */
  129.  
  130.     pg_eval(rulebuf, (char *) NULL, (ObjectId *) NULL, 0);
  131.  
  132.     /* elog(NOTICE,"RuleOID is : %d\n", LastOidProcessed ); */
  133.  
  134.     return ( LastOidProcessed );
  135. }
  136.  
  137. void
  138. ModifyActionToReplaceCurrent ( retrieve_parsetree )
  139.     List retrieve_parsetree;
  140. {
  141.     List root = parse_root ( retrieve_parsetree );
  142.  
  143.     CADR(root) = lispAtom("replace");
  144.     CADDR(root) = lispInteger(1); /* CURRENT */
  145. }    
  146. /*
  147.  *    for now, event_object must be a single attribute
  148.  */
  149.  
  150. void ValidateRule(event_type, eobj_string, eslot_string, event_qual,
  151.           action, is_instead,event_attype)
  152.      char *eobj_string, *eslot_string;
  153.      int is_instead,event_type;
  154.      List *action,event_qual;
  155.     ObjectId event_attype;
  156. {
  157.     int count;
  158.     char *template = "(((0 retrieve nil nil 0 nil nil nil )((#S(resdom \
  159. :resno 1 :restype %d :reslen %d :resname \"%s\" :reskey 0 :reskeyop 0 \
  160. :resjunk 0)#S(const :consttype %d :constlen 0 :constisnull true \
  161. :constvalue NIL :constbyval nil))) nil))";
  162.     count = length(*action);
  163.     if (((event_type == APPEND) || (event_type == DELETE)) && eslot_string)
  164.     elog(WARN, "'to class.attribute' rules not allowed for this event");
  165.     if (event_qual && !*action && is_instead)
  166.     elog(WARN,
  167.          "event_quals on 'instead nothing' rules not currently supported");
  168. /*    if (event_type == RETRIEVE && is_instead && count > 1)
  169.     elog(WARN,
  170.          "multiple rule actions not supported on 'retrieve instead' rules");*/
  171.     /* on retrieve to class.attribute do instead nothing is converted
  172.      * to 'on retrieve to class.attribute do instead
  173.      *        retrieve (attribute = NULL)'
  174.      * --- this is also a terrible hack that works well -- glass*/
  175.     if (is_instead && !*action && eslot_string && event_type == RETRIEVE) {
  176.     char *temp_buffer = (char *) palloc(strlen(template)+80);
  177.     sprintf(temp_buffer, template, event_attype,
  178.         get_typlen(event_attype), eslot_string,
  179.         event_attype);
  180.     *action = (List) StringToPlan(temp_buffer);
  181.     pfree(temp_buffer);
  182.     }
  183. }
  184.      
  185.  
  186. DefineQueryRewrite ( args ) 
  187.      List args;
  188. {
  189.     List i            = NULL;
  190.     Name rulename         = (Name)CString ( nth ( 0,args )) ;
  191.     LispValue event_type    = nth ( 1 , args );
  192.     List event_obj        = nth ( 2 , args );
  193.     List event_qual            = nth ( 3 , args );
  194.     bool is_instead            = (bool)CInteger ( nth ( 4 , args ));
  195.     List action        = nth ( 5 , args );
  196.     Relation event_relation     = NULL ;
  197.     ObjectId ruleId;
  198.     ObjectId ev_relid        = 0;
  199.     char locktype;
  200.     char *eobj_string        = NULL;
  201.     char *eslot_string        = NULL;
  202.     int event_attno         = 0;
  203.     int j            = 0;        /* save index */
  204.     int k            = 0;        /* actual lock placement */
  205.     ObjectId event_attype    = 0;
  206.     char *actionP, *event_qualP;
  207.     
  208.     extern ObjectId att_typeid();
  209.  
  210.     extern    char        *PlanToString();
  211.  
  212.     eobj_string = CString ( CAR ( event_obj));
  213.     
  214.     if ( CDR (event_obj) != LispNil )
  215.       eslot_string = CString ( CADR ( event_obj));
  216.     else
  217.       eslot_string = NULL;
  218.     
  219.     event_relation = amopenr ( eobj_string );
  220.     if ( event_relation == NULL ) {
  221.     elog(WARN, "virtual relations not supported yet");
  222.     }
  223.     ev_relid = RelationGetRelationId (event_relation);
  224.     
  225.     if ( eslot_string == NULL ) {
  226.       event_attno = -1;
  227.       event_attype = -1; /* XXX - don't care */
  228.     } else {
  229.     event_attno = varattno ( event_relation, eslot_string );
  230.     event_attype = att_typeid(event_relation,event_attno);
  231.     }
  232.     amclose(event_relation);
  233.     /* fix bug about instead nothing */
  234.     ValidateRule(CAtom(event_type), eobj_string,
  235.          eslot_string, event_qual, &action,
  236.          is_instead,event_attype);
  237.     if (action == LispNil) {
  238.     if (!is_instead) return;    /* doesn't do anything */
  239.  
  240.     actionP = PlanToString(event_qual);
  241.  
  242.     if (strlen(actionP) > RULE_PLAN_SIZE)
  243.         elog(WARN, "DefineQueryRewrite: rule action too long.");
  244.  
  245.     ruleId = InsertRule ( rulename, 
  246.                 CAtom(event_type),
  247.                 (Name)eobj_string,
  248.                 (Name)eslot_string,
  249.                 actionP,
  250.                 1,
  251.                 "nil ");
  252.     locktype = PutRelationLocks ( ruleId,
  253.                     ev_relid,
  254.                     event_attno,
  255.                     CAtom(event_type),
  256.                     1);
  257.     prs2AddRelationLevelLock(ruleId,locktype,
  258.                  ev_relid,event_attno);
  259.     } else {
  260.  
  261.     printf("# number of actions = %d\n", length(action));
  262.     /*
  263.      * I don't use the some of the more interesting LockTypes...so
  264.      * PutRelationLocks() has suddenly got much dumber -- glass
  265.      */
  266.  
  267.     event_qualP = PlanToString(event_qual);
  268.     actionP = PlanToString(action);
  269.  
  270.     if (strlen(event_qualP) > RULE_PLAN_SIZE)
  271.         elog(WARN, "DefineQueryRewrite: event qual plan string too big.");
  272.  
  273.     if (strlen(actionP) > RULE_PLAN_SIZE)
  274.         elog(WARN, "DefineQueryRewrite: action plan string too big.");
  275.  
  276.     ruleId = InsertRule ( rulename, 
  277.                 CAtom(event_type),
  278.                 (Name)eobj_string,
  279.                 (Name)eslot_string,
  280.                 event_qualP,
  281.                 is_instead,
  282.                 actionP);
  283.  
  284.     locktype = PutRelationLocks ( ruleId,
  285.                     ev_relid,
  286.                     event_attno,
  287.                     CAtom(event_type),
  288.                     is_instead);
  289.     /* what is the max size of type text? XXX -- glass */
  290.     j = length(action);
  291.     if ( j > 15 )
  292.         elog(WARN,"max # of actions exceeded"); 
  293.     prs2AddRelationLevelLock(ruleId,locktype,
  294.                  ev_relid,event_attno);
  295.     }
  296. }
  297.  
  298. ShowRuleAction(ruleaction)
  299.      LispValue ruleaction;
  300. {
  301.     if ( ! lispNullp (ruleaction) ) {
  302.     if ( atom(CAR(ruleaction)) ) {
  303.         printf("Utility Actions are not supported yet");
  304.     } else {
  305.         switch ( root_command_type (parse_root ( ruleaction ) )) {
  306.           case RETRIEVE:
  307.         printf("\nAction Type: retrieve\n");
  308.         printf("Available attributes :\n");
  309.         break;
  310.           case REPLACE: 
  311.         printf("\nAction Type: retrieve\n");
  312.         printf("\nAction Targetlist :\n");
  313.           case DELETE: 
  314.         printf("\nAction Type: delete\n");
  315.         printf("\nAction Targetlist :\n");
  316.           case APPEND: 
  317.         printf("\nAction Type: append\n");
  318.         printf("\nAction Targetlist :\n");
  319.           case EXECUTE:
  320.         printf("\nAction Type: execute\n");
  321.         printf("\nAction Targetlist :\n");
  322.           default:
  323.         printf("unknown action type\n");
  324.         }
  325.         ShowParseTL(ruleaction);
  326.         printf("\nAdditional Qualifications :\n");
  327.         ShowParseQual(ruleaction);
  328.     }
  329.     } else {
  330.     printf (" NULL command ");
  331.     }
  332. }
  333.  
  334.  
  335.  
  336.  
  337.  
  338.