head 1.31; access; symbols release_4_2:1.31 aix_ok:1.29 Version_2_1:1.15; locks; strict; comment @ * @; 1.31 date 94.02.07.11.43.27; author aoki; state Exp; branches; next 1.30; 1.30 date 94.02.02.00.22.27; author marc; state Exp; branches; next 1.29; 1.29 date 93.09.26.00.05.56; author paxson; state Exp; branches; next 1.28; 1.28 date 93.01.16.03.14.59; author aoki; state Exp; branches; next 1.27; 1.27 date 92.12.19.01.38.45; author aoki; state Exp; branches; next 1.26; 1.26 date 92.07.08.20.51.28; author joey; state Exp; branches; next 1.25; 1.25 date 92.07.04.04.37.49; author mer; state Exp; branches; next 1.24; 1.24 date 92.05.05.01.01.08; author mer; state Exp; branches; next 1.23; 1.23 date 92.03.25.17.30.55; author hong; state Exp; branches; next 1.22; 1.22 date 91.11.18.22.21.22; author mer; state Exp; branches; next 1.21; 1.21 date 91.05.09.18.08.46; author sp; state Exp; branches; next 1.20; 1.20 date 91.05.03.16.20.05; author cimarron; state Exp; branches; next 1.19; 1.19 date 91.04.19.05.38.16; author kemnitz; state Exp; branches; next 1.18; 1.18 date 91.04.10.16.09.23; author sp; state Exp; branches; next 1.17; 1.17 date 91.04.08.18.14.21; author sp; state Exp; branches; next 1.16; 1.16 date 91.03.28.14.26.51; author sp; state Exp; branches; next 1.15; 1.15 date 91.02.25.16.54.02; author sp; state Exp; branches; next 1.14; 1.14 date 91.02.24.12.39.57; author sp; state Exp; branches; next 1.13; 1.13 date 91.01.09.19.07.12; author sp; state Exp; branches; next 1.12; 1.12 date 90.10.25.21.03.59; author goh; state Exp; branches; next 1.11; 1.11 date 90.10.20.14.29.51; author sp; state Exp; branches; next 1.10; 1.10 date 90.10.16.17.18.13; author sp; state Exp; branches; next 1.9; 1.9 date 90.10.10.18.58.00; author hong; state Exp; branches; next 1.8; 1.8 date 90.09.25.16.42.27; author kemnitz; state Exp; branches; next 1.7; 1.7 date 90.06.09.18.45.15; author kemnitz; state Exp; branches; next 1.6; 1.6 date 90.05.31.14.54.26; author sp; state Exp; branches; next 1.5; 1.5 date 90.05.14.20.29.12; author sp; state Exp; branches; next 1.4; 1.4 date 90.04.19.19.51.26; author sp; state Exp; branches; next 1.3; 1.3 date 90.04.03.17.11.43; author sp; state Exp; branches; next 1.2; 1.2 date 90.01.31.03.50.04; author sp; state Exp; branches; next 1.1; 1.1 date 90.01.11.14.42.49; author sp; state Exp; branches; next ; desc @rule definition/removal code @ 1.31 log @casting to shut up gcc name-safing @ text @/*----------------------------------------------------------------------- * FILE: * prs2define.c * * IDENTIFICATION: * $Header: /import/faerie/faerie/aoki/postgres/src/backend/rules/prs2/RCS/prs2define.c,v 1.30 1994/02/02 00:22:27 marc Exp aoki $ * * DESCRIPTION: * All the routines needed to define a (tuple level) PRS2 rule */ #include "tmp/postgres.h" #include "nodes/primnodes.h" #include "nodes/primnodes.a.h" #include "nodes/pg_lisp.h" #include "utils/log.h" #include "utils/relcache.h" /* RelationNameGetRelation() defined here...*/ #include "rules/prs2.h" #include "access/skey.h" /* 'ScanKeyEntryData' defined here... */ #include "access/tqual.h" /* 'NowTimeQual' defined here.. */ #include "access/heapam.h" /* heap AM calls defined here */ #include "utils/lsyscache.h" /* get_attnum() defined here...*/ #include "parse.h" /* RETRIEVE, APPEND etc defined here.. */ #include "parser/parsetree.h" #include "catalog/catname.h" /* names of various system relations */ #include "fmgr.h" /* for F_CHAR16EQ, F_CHAR16IN etc. */ #include "access/ftup.h" /* for FormHeapTuple() */ #include "utils/palloc.h" #include "catalog/pg_proc.h" #include "catalog/pg_prs2rule.h" #include "catalog/pg_prs2plans.h" #include "catalog/pg_relation.h" #include "catalog/syscache.h" extern LispValue planner(); extern LispValue lispCopy(); /*----------------------------------------------------------------------- * * prs2DefineTupleRule * * Define a tuple-level rule. This is the high-level interface. * *----------------------------------------------------------------------- */ void prs2DefineTupleRule(parseTree, ruleText) LispValue parseTree; char *ruleText; { Prs2RuleData ruleData; List hint; #ifdef PRS2_DEBUG printf("PRS2: ---prs2DefineTupleRule called, with argument ="); lispDisplay(parseTree); printf("\n"); printf("PRS2: ruletext = %s\n", ruleText); #endif PRS2_DEBUG /* * find the rule "hint", i.e. see if the user explicitly * stated what kind of lock he/she/it/ wnated to use. */ hint = GetRuleHintFromParse(parseTree); /* * extract some rule info form the parsetree... */ ruleData = prs2FindRuleData(parseTree, ruleText); /* * now put locks/stubs and update system catalogs... */ prs2AddTheNewRule(ruleData, hint); #ifdef PRS2_DEBUG printf("PRS2: --- DEFINE PRS2 RULE: Done.\n"); #endif PRS2_DEBUG } /*----------------------------------------------------------------------- * prs2GetRuleEventRel *----------------------------------------------------------------------- */ Name prs2GetRuleEventRel(rulename) char *rulename; { HeapTuple htp; ObjectId eventrel; htp = SearchSysCacheTuple(PRS2RULEID, rulename, NULL, NULL, NULL); if (!HeapTupleIsValid(htp)) elog(WARN, "prs2GetRuleEventRel: rule \"%s\" not found", rulename); eventrel = ((Form_pg_prs2rule) GETSTRUCT(htp))->prs2eventrel; htp = SearchSysCacheTuple(RELOID, eventrel, NULL, NULL, NULL); if (!HeapTupleIsValid(htp)) elog(WARN, "prs2GetRuleEventRel: class %d not found", eventrel); return(&((Form_pg_relation) GETSTRUCT(htp))->relname); } /*----------------------------------------------------------------------- * prs2RemoveTupleRule * * Remove a tuple-system rule given its name. * *----------------------------------------------------------------------- */ void prs2RemoveTupleRule(ruleName) Name ruleName; { ObjectId ruleId; /* * first find its oid & then remove it... */ ruleId = get_ruleid(ruleName); if (ruleId == InvalidObjectId) { elog(WARN, "Rule '%s' does not exist!", ruleName); } prs2DeleteTheOldRule(ruleId); } /*----------------------------------------------------------------------- * prs2FindRuleData * * create a 'Prs2RuleData' struct & fill it with all the information * about this rule we will ever need to know... * *----------------------------------------------------------------------- */ Prs2RuleData prs2FindRuleData(parseTree, ruleText) List parseTree; char *ruleText; { Prs2RuleData r; List eventTarget; Relation rel; bool newUsed, currentUsed; /* * create the structure where we hold all the rule * information we need to know... */ r = (Prs2RuleData) palloc(sizeof(Prs2RuleDataData)); if (r==NULL) { elog(WARN, "prs2FindRuleInfo: Out of memory"); } r->ruleName = (Name) palloc(sizeof(NameData)); if (r->ruleName == NULL) { elog(WARN, "prs2FindRuleInfo: Out of memory"); } r->eventRelationName = (Name) palloc(sizeof(NameData)); if (r->eventRelationName == NULL) { elog(WARN, "prs2FindRuleInfo: Out of memory"); } r->eventAttributeName = (Name) palloc(sizeof(NameData)); if (r->eventAttributeName == NULL) { elog(WARN, "prs2FindRuleInfo: Out of memory"); } /* * start filling it in... * NOTE: we do not know yet the rule oid... */ r->ruleId = InvalidObjectId; r->parseTree = parseTree; r->ruleText = ruleText; strncpy(r->ruleName->data, CString(GetRuleNameFromParse(parseTree)), NAMEDATALEN); if (CInteger(GetRuleInsteadFromParse(parseTree)) != 0) r->isInstead = true; else r->isInstead = false; r->eventType = prs2FindEventTypeFromParse(parseTree); /* * * Find the OID of the relation to be locked, and the * attribute number of the locked attribute. If no such * attribute has been specified, use 'InvalidAttributeNumber' * instead. * * NOTE: 'eventTarget' is a list of one or two items. * The first one is the name of the relation and the optional second * one is the attribute name * * XXX: this should change in the future! It would be better * that the parser will return a list with the relation OID * and the attibute number instead of their names! */ eventTarget = GetRuleEventTargetFromParse(parseTree); strncpy(r->eventRelationName->data, CString(CAR(eventTarget)), NAMEDATALEN); rel = RelationNameGetRelation(r->eventRelationName); r->eventRelationOid = rel->rd_id; if (null(CDR(eventTarget))) { /* * no attribute is specified */ r->eventAttributeNumber = InvalidAttributeNumber; r->eventAttributeName = NULL; } else { strncpy(r->eventAttributeName->data, CString(CADR(eventTarget)), NAMEDATALEN); r->eventAttributeNumber = get_attnum(r->eventRelationOid, r->eventAttributeName); if (r->eventAttributeNumber == InvalidAttributeNumber) { elog(WARN,"Illegal attribute in event target list"); } /* * XXX currently we only allow tuple-level rules to * be defined in attributes of basic types (i.e. not of type * relation etc....) */ if (!prs2AttributeIsOfBasicType(r->eventRelationOid, r->eventAttributeNumber)) { elog(WARN, "Can not define tuple rules in non-base type attributes"); } /* * "on delete" and "on append" rules must not have an attribute * specified in the event clause. */ if (r->eventType == EventTypeDelete) elog(WARN, "On Delete rules must not have an attribute in their event clause"); if (r->eventType == EventTypeAppend) elog(WARN, "On Append rules must not have an attribute in their event clause"); } /* * check if we use CURRENT on a 'on append' rule, or NEW * on a 'on retrieve' or 'on delete' rule. * If yes, then complain... */ r->ruleQual = GetRuleQualFromParse(parseTree); r->ruleAction = GetRuleActionFromParse(parseTree); IsPlanUsingNewOrCurrent(r->ruleQual, ¤tUsed, &newUsed); if (currentUsed && r->eventType == EventTypeAppend) { elog(WARN, "An `on append' rule, can not reference the 'current' tuple"); } if (newUsed && r->eventType == EventTypeRetrieve) { elog(WARN, "An `on retrieve' rule, can not reference the 'new' tuple"); } if (newUsed && r->eventType == EventTypeDelete) { elog(WARN, "An `on delete' rule, can not reference the 'new' tuple"); } IsPlanUsingNewOrCurrent(r->ruleAction, ¤tUsed, &newUsed); if (currentUsed && r->eventType == EventTypeAppend) { elog(WARN, "An `on append' rule, can not reference the 'current' tuple"); } if (newUsed && r->eventType == EventTypeRetrieve) { elog(WARN, "An `on retrieve' rule, can not reference the 'new' tuple"); } if (newUsed && r->eventType == EventTypeDelete) { elog(WARN, "An `on delete' rule, can not reference the 'new' tuple"); } /* * The parsetree generated by the parser has a NEW and/or CURRENT * entries in the range table. In order to find the rule qualification * and the action plans to be executed at rule activation time, * we have to change all the corresponding "Var" nodes to the * appropriate "Param" nodes. * Note however, that we must also keep the original rule qualification * (i.e. the one with the "Var" nodes) because it is needed to * calculate the appropriate stub records etc. * nodes to the equivalent */ r->paramParseTree = lispCopy(parseTree); SubstituteParamForNewOrCurrent(r->paramParseTree, r->eventRelationOid); r->paramRuleQual = GetRuleQualFromParse(r->paramParseTree); r->paramRuleAction = GetRuleActionFromParse(r->paramParseTree); /* * Now, find the type of action. (i.e. ActionTypeRetrieve, * ActionTypeReplaceCurrent or ActionTypeOther). * In the first 2 cases, `updatedAttributeNumber' is the number * of attribute beeing updated. */ r->actionType = prs2FindActionTypeFromParse(r->parseTree, r->eventAttributeNumber, &(r->updatedAttributeNumber), r->eventType); /* * Hm... for the time being we do NOT allow * ON RETRIEVE ... DO RETRIEVE .... * rules without an INSTEAD * unless this is a "view" rule (i.e. something * like "on retrieve to TOYEMP do retrieve...") * In this case the event target object must be a * relation and not a "relation.attribute" */ if (!(r->isInstead) && r->actionType == ActionTypeRetrieveValue && r->eventAttributeNumber != InvalidAttributeNumber ) { elog(WARN, "`on retrieve ... do retrieve' tuple rules must have an `instead'"); } #ifdef PRS2_DEBUG { printf("PRS2: ---DEFINE TUPLE RULE:\n"); printf("PRS2: RuleName = %.*s\n", NAMEDATALEN, r->ruleName->data); printf("PRS2: event type = %d ", r->eventType); switch (r->eventType) { case EventTypeRetrieve: printf("(retrieve)\n"); break; case EventTypeReplace: printf("(replace)\n"); break; case EventTypeAppend: printf("(append)\n"); break; case EventTypeDelete: printf("(delete)\n"); break; default: printf("(*** UNKNOWN ***)\n"); } printf("PRS2: event target:"); lispDisplay(eventTarget); printf("\n"); printf("PRS2: event target relation OID = %ld\n", r->eventRelationOid); printf("PRS2: event target attr no = %d\n", r->eventAttributeNumber); printf("PRS2: Instead flag = %d\n", r->isInstead); printf("PRS2: ruleAction:"); lispDisplay(r->paramRuleAction); printf("\n"); } #endif PRS2_DEBUG return(r); } /*----------------------------------------------------------------------- * * prs2InsertRuleInfoInCatalog * * Insert information about a rule in the rules system catalog. * As the rule names are unique, we have first to make sure * that no other rule with the same names exists. * *----------------------------------------------------------------------- */ ObjectId prs2InsertRuleInfoInCatalog(r) Prs2RuleData r; { register i; Relation prs2RuleRelation; HeapTuple heapTuple; char *values[Prs2RuleRelationNumberOfAttributes]; char nulls[Prs2RuleRelationNumberOfAttributes]; ObjectId objectId; HeapScanDesc heapScan; ScanKeyEntryData ruleNameKey[1]; /* * Open the system catalog relation * where we keep the rule info (pg_prs2rule) */ prs2RuleRelation = RelationNameOpenHeapRelation(Prs2RuleRelationName); if (!RelationIsValid(prs2RuleRelation)) { elog(WARN, "prs2InsertRuleInfoCatalog: could not open relation %s", Prs2RuleRelationName); } /* * First make sure that no other rule with the same name exists! */ ScanKeyEntryInitialize(&ruleNameKey[0], 0, Prs2RuleNameAttributeNumber, F_CHAR16EQ, NameGetDatum(r->ruleName)); heapScan = RelationBeginHeapScan(prs2RuleRelation, false, NowTimeQual, 1, (ScanKey) ruleNameKey); heapTuple = HeapScanGetNextTuple(heapScan, false, (Buffer *) NULL); if (HeapTupleIsValid(heapTuple)) { HeapScanEnd(heapScan); RelationCloseHeapRelation(prs2RuleRelation); elog(WARN, "Sorry, rule %s is already defined", r->ruleName); } HeapScanEnd(heapScan); /* * Now create a tuple with the new rule info */ for (i = 0; i < Prs2RuleRelationNumberOfAttributes; ++i) { values[i] = NULL; nulls[i] = 'n'; } values[Prs2RuleNameAttributeNumber-1] = fmgr(F_CHAR16IN,(char *)(r->ruleName)); nulls[Prs2RuleNameAttributeNumber-1] = ' '; values[Prs2RuleEventTypeAttributeNumber-1] = (char *) (long) r->eventType; nulls[Prs2RuleEventTypeAttributeNumber-1] = ' '; values[Prs2RuleEventTargetRelationAttributeNumber-1] = (char *) (long) r->eventRelationOid; nulls[Prs2RuleEventTargetRelationAttributeNumber-1] = ' '; values[Prs2RuleEventTargetAttributeAttributeNumber-1] = (char *) (long) r->eventAttributeNumber; nulls[Prs2RuleEventTargetAttributeAttributeNumber-1] = ' '; values[Prs2RuleTextAttributeNumber-1] = fmgr(F_TEXTIN, r->ruleText); nulls[Prs2RuleTextAttributeNumber-1] = ' '; heapTuple = FormHeapTuple(Prs2RuleRelationNumberOfAttributes, &prs2RuleRelation->rd_att, values, nulls); /* * Now insert the tuple in the system catalog * and return its OID (which form now on is the rule's id. */ (void) RelationInsertHeapTuple(prs2RuleRelation, heapTuple, (double *) NULL); objectId = heapTuple->t_oid; RelationCloseHeapRelation(prs2RuleRelation); return(objectId); } /*----------------------------------------------------------------------- * prs2DeleteRuleInfoFromCatalog * * remove all rule info stored in 'pg_prs2rule' about the given * rule. * *----------------------------------------------------------------------- */ void prs2DeleteRuleInfoFromCatalog(ruleId) ObjectId ruleId; { Relation prs2RuleRelation; HeapScanDesc scanDesc; ScanKeyData scanKey; HeapTuple tuple; Buffer buffer; /* * Open the pg_rule relation. */ prs2RuleRelation = RelationNameOpenHeapRelation(Prs2RuleRelationName); /* * Scan the RuleRelation ('pg_prs2rule') until we find a tuple */ ScanKeyEntryInitialize(&scanKey.data[0], 0, ObjectIdAttributeNumber, ObjectIdEqualRegProcedure, ObjectIdGetDatum(ruleId)); scanDesc = RelationBeginHeapScan(prs2RuleRelation, false, NowTimeQual, 1, &scanKey); tuple = HeapScanGetNextTuple(scanDesc, false, &buffer); /* * complain if no such rule existed */ if (!HeapTupleIsValid(tuple)) { RelationCloseHeapRelation(prs2RuleRelation); elog(WARN, "No rule with id = '%d' was found.\n", ruleId); } /* * Now delete the tuple... */ RelationDeleteHeapTuple(prs2RuleRelation, &(tuple->t_ctid)); RelationCloseHeapRelation(prs2RuleRelation); HeapScanEnd(scanDesc); } /*----------------------------------------------------------------------- * * prs2InsertRulePlanInCatalog * * Insert a rule plan into the appropriate system catalogs. * Arguments: * ruleId the OID of the rule (as returned by routine * 'prs2InsertRuleInfoInCatalog'). * planNumber the corresponding planNumber. * rulePlan the rule plan itself! * *----------------------------------------------------------------------- */ void prs2InsertRulePlanInCatalog(ruleId, planNumber, rulePlan) ObjectId ruleId; Prs2PlanNumber planNumber; List rulePlan; { register i; char *rulePlanString; Relation prs2PlansRelation; HeapTuple heapTuple; char *values[Prs2PlansRelationNumberOfAttributes]; char nulls[Prs2PlansRelationNumberOfAttributes]; /* * Open the system catalog relation */ prs2PlansRelation=RelationNameOpenHeapRelation(Prs2PlansRelationName); if (!RelationIsValid(prs2PlansRelation)) { elog(WARN, "prs2InsertRulePlanInCatalog: could not open relation %s", Prs2PlansRelationName); } /* * Create the appropriate tuple. * NOTE: 'rulePlan' is of type LispValue, so we have first * to transform it to a string using 'PlanToString()' */ rulePlanString = PlanToString(rulePlan); for (i = 0; i < Prs2PlansRelationNumberOfAttributes; ++i) { nulls[i] = ' '; } values[Prs2PlansRuleIdAttributeNumber-1] = (char *) (long) ruleId; values[Prs2PlansPlanNumberAttributeNumber-1] = (char *) (long) planNumber; values[Prs2PlansCodeAttributeNumber-1] = fmgr(F_TEXTIN,rulePlanString); heapTuple = FormHeapTuple(Prs2PlansRelationNumberOfAttributes, &prs2PlansRelation->rd_att, values, nulls); /* * Now insert the tuple to the system catalog. */ (void) RelationInsertHeapTuple(prs2PlansRelation, heapTuple, (double *) NULL); RelationCloseHeapRelation(prs2PlansRelation); pfree(rulePlanString); } /*-------------------------------------------------------------------------- * prs2DeleteRulePlanFromCatalog * * Delete all rule plans for the given rule from the "pg_prs2plans" * system catalog. *-------------------------------------------------------------------------- */ void prs2DeleteRulePlanFromCatalog(ruleId) ObjectId ruleId; { Relation prs2PlansRelation; HeapScanDesc scanDesc; ScanKeyData scanKey; HeapTuple tuple; Buffer buffer; /* * Delete all tuples of the Prs2Plans relation (pg_prs2plans) * corresponding to this rule... */ prs2PlansRelation = RelationNameOpenHeapRelation(Prs2PlansRelationName); ScanKeyEntryInitialize(&scanKey.data[0], 0, Prs2PlansRuleIdAttributeNumber, ObjectIdEqualRegProcedure, ObjectIdGetDatum(ruleId)); scanDesc = RelationBeginHeapScan(prs2PlansRelation, false, NowTimeQual, 1, &scanKey); while((tuple=HeapScanGetNextTuple(scanDesc,false,(Buffer *)NULL)) !=NULL) { /* * delete the prs2PlansRelation tuple... */ RelationDeleteHeapTuple(prs2PlansRelation, &(tuple->t_ctid)); } RelationCloseHeapRelation(prs2PlansRelation); HeapScanEnd(scanDesc); } /*---------------------------------------------------------------------- * * prs2GenerateActionPlans * * generate the plan+parse trees for the action part of the rule * *---------------------------------------------------------------------- */ LispValue prs2GenerateActionPlans(r) Prs2RuleData r; { LispValue result; LispValue action; LispValue oneParse; LispValue onePlan; LispValue oneEntry; LispValue qualQuery; LispValue ruleInfo; LispValue rangeTable; AttributeNumber currentAttributeNo; rangeTable = GetRuleRangeTableFromParse(r->parseTree); /* * the first entry in the result is some rule info * This consists of the following fields: * a) "instead" or "not-instead" * b) the attribute number of the attribute specified * in the ON EVENT TO REL.attribute clause * (or InvalidAttributeNumber) * c) either InvalidAttributeNumber, or in the case of a rule * of the form: * ON REPLACE TO REL.x WHERE .... * DO REPLACE CURRENT.attribute * the 'attribute' that is replced by the rule. */ if (r->isInstead) { ruleInfo = lispCons(lispString("instead"), LispNil); } else { ruleInfo = lispCons(lispString("not-instead"), LispNil); } ruleInfo = nappend1(ruleInfo, lispInteger(r->eventAttributeNumber)); ruleInfo = nappend1(ruleInfo, lispInteger(r->updatedAttributeNumber)); result = lispCons(ruleInfo, LispNil); /* * now append the qual entry (parse tree + plan) */ if (null(r->ruleQual)) { oneEntry = LispNil; } else { /* * the 'ruleQual' is just a qualification. * Transform it into a query of the form: * "retrieve (foo=1) where QUAL". * The rule manager will run this query and if there is * a tuple returned, then we know that the qual is true, * otherwise we know it is false */ LispValue MakeRoot(); LispValue root, targetList; Resdom resdom; Const constant; Name name; Datum value; /* * construct the target list */ name = (Name) palloc(sizeof(NameData)); if (name == NULL) { elog(WARN, "prs2GenerateActionPlans: Out of memory"); } strncpy(name->data, "foo", NAMEDATALEN); resdom = MakeResdom((AttributeNumber)1, (ObjectId) 23, false, (Size) 4, name, (Index) 0, (OperatorTupleForm) 0, 0); value = Int32GetDatum(1); constant = MakeConst((ObjectId) 23, /* type */ (Size) 4, /* size */ value, /* value */ false, /* isnull */ true, /* byval */ false); /* isset */ targetList = lispCons( lispCons((LispValue)resdom, lispCons((LispValue)constant, LispNil)), LispNil); /* * now the root * XXX NumLevels == 1 ??? IS THIS CORRECT ???? */ root = MakeRoot( 1, /* num levels */ lispAtom("retrieve"), /* command */ LispNil, /* result relation */ rangeTable, /* range table */ lispInteger(0), /* priority */ LispNil, /* rule info */ LispNil, /* unique flag */ LispNil, /* sort_clause */ targetList); /* targetList */ /* * Finally, construct the parse tree... */ qualQuery = lispCons(root, lispCons(targetList, lispCons(r->paramRuleQual, LispNil))); onePlan = planner(qualQuery); oneEntry = lispCons(onePlan, LispNil); oneEntry = lispCons(qualQuery, oneEntry); } result = nappend1(result, oneEntry); /* * Now for each action append the corresponding entry * (parse tree + plan) */ foreach (action, r->paramRuleAction) { oneParse = CAR(action); /* * XXX: THIS IS A HACK !!! * (but it works, so what the hell....) * * if this is a REPLACE CURRENT (X = ...) * change it to a RETRIEVE (X = ...) */ changeReplaceToRetrieve(oneParse); /* * call the planner to create a plan for this parse tree */ onePlan = planner(oneParse); oneEntry = lispCons(onePlan, LispNil); oneEntry = lispCons(oneParse, oneEntry); result = nappend1(result, oneEntry); } /* * finally insert itn the beginning of the list the * string Prs2RulePlanType_ACTION to show that this is * an action plan (as opposed to an import/export plan). */ result = lispCons(lispString(Prs2RulePlanType_ACTION), result); return(result); } /*------------------------------------------------------------------ * * prs2FindEventTypeFromParse * * Given a rule's parse tree find its event type. *------------------------------------------------------------------ */ EventType prs2FindEventTypeFromParse(parseTree) LispValue parseTree; { int eventTypeInt; EventType eventType; eventTypeInt = CInteger(GetRuleEventTypeFromParse(parseTree)); /* * Note that the event type as stored in the parse tree is one of * RETRIEVE, REPLACE, APPEND or DELETE. All these symbols are * defined in "parse.h". So, we have to change them * into the appropriate "EventType" type. */ switch (eventTypeInt) { case RETRIEVE: eventType = EventTypeRetrieve; break; case REPLACE: eventType = EventTypeReplace; break; case APPEND: eventType = EventTypeAppend; break; case DELETE: eventType = EventTypeDelete; break; default: eventType = EventTypeInvalid; elog(WARN, "prs2DefineTupleRule: Illegal event type (int) %d", eventTypeInt); } /* switch*/ return(eventType); } /*------------------------------------------------------------------ * * prs2FindActionTypeFromParse * * find the ActionType of a rule. * * if the action is in the form 'REPLACE CURRENT(x = ....)' * then (*updatedAttributeNumber) is the attribute number of the * updated field, otherwise it is InvalidAttributeNumber. *------------------------------------------------------------------ */ ActionType prs2FindActionTypeFromParse(parseTree, eventTargetAttributeNumber, updatedAttributeNumberP, eventType) LispValue parseTree; AttributeNumber eventTargetAttributeNumber; AttributeNumberPtr updatedAttributeNumberP; EventType eventType; { LispValue ruleActions; LispValue t, oneRuleAction; LispValue root; int commandType; LispValue resultRelation; LispValue rangeTable; ActionType actionType; Name relationName; NameData nameData; LispValue targetList; int resultRelationNo; LispValue resultRelationEntry; *updatedAttributeNumberP = InvalidAttributeNumber; ruleActions = GetRuleActionFromParse(parseTree); if (null(ruleActions)) { if (eventType != EventTypeRetrieve) { /* * then this is probably an `instead' rule with no action * specified, e.g. "ON delete to DEPT WHERE ... DO INSTEAD" */ return(ActionTypeOther); } else { /* * However, if we have something like: * ON RETRIEVE THEN DO INSTEAD NOTHING * we assume that this means do NOT retrieve a value, * i.e. return a null attribute. */ *updatedAttributeNumberP = eventTargetAttributeNumber; return(ActionTypeRetrieveValue); } } foreach(t, ruleActions) { oneRuleAction = CAR(t); /* * find the type of query (retrieve, delete etc...) */ root = parse_root(oneRuleAction); commandType = root_command_type(root); resultRelation = root_result_relation(root); rangeTable = root_rangetable(root); if (!null(resultRelation)) { if (commandType == RETRIEVE) { /* * This is a retrieve into, the result reln info * is a list of junk. */ strncpy(&(nameData.data[0]), CString(CADR(resultRelation)), NAMEDATALEN); } else { resultRelationNo = CInteger(resultRelation); resultRelationEntry = nth(resultRelationNo-1, rangeTable); strncpy(&(nameData.data[0]), CString(rt_relname(resultRelationEntry)), NAMEDATALEN); } relationName = &nameData; } else { relationName = InvalidName; } if (commandType == RETRIEVE && null(resultRelation)) { /* * this is a "retrieve" (NOT a "retrieve into...") * action. * It can be either something like: * ON retrieve to EMP.salary * WHERE .... * DO retrieve (salary = ....) where ..... * * In which case only one 'retrieve' command is allowed * in the action part of the rule, * or it can be a view type rule: * ON retrieve to TOYEMP * DO retrieve (EMP.all) where EMP.dept = "toy" */ actionType = ActionTypeRetrieveValue; break; /* exit 'foreach' loop */ } else if (commandType == REPLACE && /* * Dangerous cast - it just happens that NameIsEqual() * currently calls strncmp() */ NameIsEqual((Name)"*CURRENT*", relationName)) { /* * this is a replace CURRENT(...) */ actionType = ActionTypeReplaceCurrent; /* * find the updated attribute number... */ targetList = parse_targetlist(oneRuleAction); if (ExecTargetListLength(targetList) != 1) { elog(WARN, " a 'replace CURRENT(...)' must replace ONLY 1 attribute"); } *updatedAttributeNumberP = get_resno((Resdom)tl_resdom(CAR(targetList))); break; /* exit 'foreach' loop */ } else if (commandType == REPLACE && NameIsEqual((Name)"*NEW*", relationName)) { /* * this is a replace NEW(...) */ actionType = ActionTypeReplaceNew; /* * find the updated attribute number... */ targetList = parse_targetlist(oneRuleAction); if (ExecTargetListLength(targetList) != 1) { elog(WARN, " a 'replace NEW(...)' must replace ONLY 1 attribute"); } *updatedAttributeNumberP = get_resno((Resdom)tl_resdom(CAR(targetList))); break; /* exit 'foreach' loop */ } else { actionType = ActionTypeOther; } } /* foreach */ if (actionType == ActionTypeRetrieveValue) { /* * then this must be the ONLY statement in the rule actions! */ if (length(ruleActions) != 1) { elog(WARN, "a 'retrieve (..)' must be the only action of a PRS2 rule!"); } *updatedAttributeNumberP = eventTargetAttributeNumber; } if (actionType == ActionTypeReplaceCurrent) { /* * then this must be the ONLY statement in the rule actions! */ if (length(ruleActions) != 1) { elog(WARN, "a 'replace CURRENT(..)' must be the only action of a PRS2 rule!"); } } if (actionType == ActionTypeReplaceNew) { /* * then this must be the ONLY statement in the rule actions! */ if (length(ruleActions) != 1) { elog(WARN, "a 'replace NEW(..)' must be the only action of a PRS2 rule!"); } } return(actionType); } /*---------------------------------------------------------------- * * changeReplaceToRetrieve * * Ghange the parse tree of a 'REPLACE CURRENT(X = ...)' * or 'REPLACE NEW(X = ...)' command to a * 'RETRIEVE (X = ...)' *---------------------------------------------------------------- */ void changeReplaceToRetrieve(parseTree) LispValue parseTree; { LispValue root; LispValue targetList; int commandType; LispValue resultRelation; LispValue rangeTable; Name relationName; NameData nameData; int resultRelationNo; LispValue resultRelationEntry; root = parse_root(parseTree); commandType = root_command_type(root); resultRelation = root_result_relation(root); rangeTable = root_rangetable(root); if (!null(resultRelation)) { if (commandType == RETRIEVE) { /* * This is a retrieve into, the result reln info * is a list of junk. */ strncpy(&(nameData.data[0]), CString(CADR(resultRelation)), NAMEDATALEN); } else { resultRelationNo = CInteger(resultRelation); resultRelationEntry = nth(resultRelationNo-1, rangeTable); namecpy(&nameData, CString(rt_relname(resultRelationEntry))); } relationName = &nameData; } else { relationName = InvalidName; } /* * Is this a REPLACE CURRENT command? */ if (commandType!=REPLACE || (!NameIsEqual((Name)"*CURRENT*", relationName) && !NameIsEqual((Name)"*NEW*", relationName))) { /* * NO, this is not a REPLACE CURRENT or a REPLACE NEW command */ return; } /* * Yes it is! * * Now *DESTRUCTIVELY* change the parse tree... * * Change the command from 'replace' to 'retrieve' * and the result relation to 'nil' */ root = parse_root(parseTree); root_command_type_atom(root) = lispAtom("retrieve"); root_result_relation(root) = LispNil; /* * Now go to the target list (which must have exactly 1 Resdom * node, and change the 'resno' to 1 */ targetList = parse_targetlist(parseTree); set_resno((Resdom)tl_resdom(CAR(targetList)), (AttributeNumber)1); } /*----------------------------------------------------------------- * * prs2AttributeIsOfBasicType * * check if the given attribute is of a "basic" type. *----------------------------------------------------------------- */ bool prs2AttributeIsOfBasicType(relOid, attrNo) ObjectId relOid; AttributeNumber attrNo; { ObjectId typeId; char typtype; typeId = get_atttype(relOid, attrNo); typtype = get_typtype(typeId); if (typtype == '\0') { elog(WARN, "Cache lookup for type %ld failed...", typeId); } if (typtype == 'b') { return(true); } else { return(false); } } /*=============================== DEBUGGINF STUFF ================*/ LispValue prs2ReadRule(fname) char *fname; { FILE *fp; int c; int count, maxcount; char *s1, *s2; LispValue l; LispValue StringToPlan(); printf("--- prsReadRule.\n"); AllocateFile(); if (fname==NULL) { fp = stdin; printf(" reading rule from stdin.\n"); } else { AllocateFile(); fp = fopen(fname, "r"); if (fp==NULL){ printf(" Can not open rule file %s\n", fname); elog(WARN,"prs2ReadRule.... exiting...\n"); } else { printf("Reading rule from file %s\n", fname); } } maxcount = 100; s1 = palloc(maxcount); if (s1 == NULL) { elog(WARN,"prs2ReadRule : out of memory!"); } count = 0; while((c=getc(fp)) != EOF) { if (count >= maxcount) { maxcount = maxcount + 1000; s2 = palloc(maxcount); if (s2 == NULL) { elog(WARN,"prs2ReadRule : out of memory!"); } bcopy(s1, s2, count); pfree(s1); s1 = s2; } s1[count] = c; count++; } s1[count+1] = '\0'; l = StringToPlan(s1); printf(" list = \n"); lispDisplay(l); if (fp!=stdin) { fclose(fp); FreeFile(); } return(l); } @ 1.30 log @Fixes to make sure we don't expect NameData variables to be NULL terminated and that we don't write mroe than NAMEDATALEN chars into them @ text @d6 1 a6 1 * $Header: /usr/local/devel/postgres.test/src/backend/rules/prs2/RCS/prs2define.c,v 1.29 1993/09/26 00:05:56 paxson Exp marc $ d421 1 a421 1 values[Prs2RuleEventTypeAttributeNumber-1] = (char *) r->eventType; d425 1 a425 1 (char *) r->eventRelationOid; d429 1 a429 1 (char *) r->eventAttributeNumber; d548 2 a549 2 values[Prs2PlansRuleIdAttributeNumber-1] = (char *) ruleId; values[Prs2PlansPlanNumberAttributeNumber-1] = (char *) planNumber; d1031 1 a1031 3 strcpy(&(nameData.data[0]), CString(rt_relname(resultRelationEntry)), NAMEDATALEN); @ 1.29 log @added constisset param to MakeConst calls @ text @d6 1 a6 1 * $Header: /local/src/postgres/src/backend/rules/prs2/RCS/prs2define.c,v 1.28 1993/01/16 03:14:59 aoki Exp paxson $ d179 2 a180 1 strcpy(r->ruleName->data, CString(GetRuleNameFromParse(parseTree))); d204 2 a205 1 strcpy(r->eventRelationName->data, CString(CAR(eventTarget))); d215 2 a216 1 strcpy(r->eventAttributeName->data, CString(CADR(eventTarget))); d323 1 a323 1 printf("PRS2: RuleName = %s\n", r->ruleName->data); d686 1 a686 1 strcpy(name->data,"foo"); d884 1 a884 1 CString(CADR(resultRelation)), sizeof(NameData)); d888 3 a890 2 strcpy(&(nameData.data[0]), CString(rt_relname(resultRelationEntry))); d1027 1 a1027 1 CString(CADR(resultRelation)), sizeof(NameData)); d1032 2 a1033 1 CString(rt_relname(resultRelationEntry))); @ 1.28 log @removed references to utils/fmgr.h and parser/parse.h @ text @d6 1 a6 1 * $Header: /home2/aoki/postgres/src/backend/rules/prs2/RCS/prs2define.c,v 1.27 1992/12/19 01:38:45 aoki Exp aoki $ d23 1 a23 1 #include "parse.h" /* RETRIEVE, APPEND etc defined here.. */ d697 2 a698 1 true); /* byval */ @ 1.27 log @second checkin for acls and other stuff @ text @d6 1 a6 1 * $Header: /usr/local/dev/postgres/mastertree/newconf/RCS/prs2define.c,v 1.26 1992/07/08 20:51:28 joey Exp $ d23 1 a23 1 #include "parser/parse.h" /* RETRIEVE, APPEND etc defined here.. */ d26 1 a26 1 #include "utils/fmgr.h" /* for F_CHAR16EQ, F_CHAR16IN etc. */ @ 1.26 log @set up resdom->rescomplex correctly @ text @d6 1 a6 1 * $Header: /private/joey/pg/src/rules/prs2/RCS/prs2define.c,v 1.25 1992/07/04 04:37:49 mer Exp joey $ d33 2 d84 23 @ 1.25 log @compute target list correctly @ text @d6 1 a6 1 * $Header: /private/mer/pg/src/rules/prs2/RCS/prs2define.c,v 1.24 1992/05/05 01:01:08 mer Exp mer $ d661 1 @ 1.24 log @fix bug related to retrieve into rule actions @ text @d6 1 a6 1 * $Header: /users/mer/pg/src/rules/prs2/RCS/prs2define.c,v 1.23 1992/03/25 17:30:55 hong Exp mer $ d897 1 a897 1 if (length(targetList) != 1) { d914 1 a914 1 if (length(targetList) != 1) { @ 1.23 log @plugged buffer leaks @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.22 91/11/18 22:21:22 mer Exp $ d848 13 a860 4 resultRelationNo = CInteger(resultRelation); resultRelationEntry = nth(resultRelationNo-1, rangeTable); strcpy(&(nameData.data[0]), CString(rt_relname(resultRelationEntry))); d990 14 a1003 5 resultRelationNo = CInteger(resultRelation); resultRelationEntry = nth(resultRelationNo-1, rangeTable); strcpy(&(nameData.data[0]), CString(rt_relname(resultRelationEntry))); relationName = &nameData; @ 1.22 log @prototypes finale @ text @d6 1 a6 1 * $Header: /users/mer/postgres/src/rules/prs2/RCS/prs2define.c,v 1.21 1991/05/09 18:08:46 sp Exp mer $ d470 1 d576 1 @ 1.21 log @"On append" or "On delete" rules must not be defined on a specific attribute.... @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.20 91/05/03 16:20:05 cimarron Exp Locker: sp $ d58 1 a58 1 lispDisplay(parseTree, 0); d314 1 a314 1 lispDisplay(eventTarget, 0); d671 2 a672 1 lispCons(resdom, lispCons(constant, LispNil)), d873 5 a877 1 NameIsEqual("*CURRENT*", relationName)) { d890 2 a891 1 *updatedAttributeNumberP = get_resno(tl_resdom(CAR(targetList))); d894 1 a894 1 NameIsEqual("*NEW*", relationName)) { d907 2 a908 1 *updatedAttributeNumberP = get_resno(tl_resdom(CAR(targetList))); d992 2 a993 2 (!NameIsEqual("*CURRENT*", relationName) && !NameIsEqual("*NEW*", relationName))) { d1017 1 a1017 1 set_resno(tl_resdom(CAR(targetList)), (AttributeNumber)1); d1102 1 a1102 1 lispDisplay(l,0); @ 1.20 log @removed extern decl (now a macro) @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.19 91/04/19 05:38:16 kemnitz Exp Locker: cimarron $ d204 10 a214 1 @ 1.19 log @uses new scankey stuff @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.18 91/04/10 16:09:23 sp Exp Locker: kemnitz $ a33 1 extern HeapTuple palloctup(); @ 1.18 log @the format of the rule plans has slightly changed... @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.17 91/04/08 18:14:21 sp Exp $ d359 2 a360 4 ruleNameKey[0].flags = 0; ruleNameKey[0].attributeNumber= Prs2RuleNameAttributeNumber; ruleNameKey[0].procedure = F_CHAR16EQ; ruleNameKey[0].argument = NameGetDatum(r->ruleName); d440 4 a443 4 scanKey.data[0].flags = 0; scanKey.data[0].attributeNumber = ObjectIdAttributeNumber; scanKey.data[0].procedure = ObjectIdEqualRegProcedure; scanKey.data[0].argument = ObjectIdGetDatum(ruleId); d551 4 a554 4 scanKey.data[0].flags = 0; scanKey.data[0].attributeNumber = Prs2PlansRuleIdAttributeNumber; scanKey.data[0].procedure = ObjectIdEqualRegProcedure; scanKey.data[0].argument = ObjectIdGetDatum(ruleId); @ 1.17 log @misc changes to support locking more than one path in the rule qualification's tree... @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.16 91/03/28 14:26:51 sp Exp Locker: sp $ d715 7 @ 1.16 log @minor fix in a debuggin routine (never called under normal operations) @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.15 91/02/25 16:54:02 sp Exp $ d526 2 @ 1.15 log @Now the user can explicitly specify what kind of lock (tuple-level-lock or relation-level-lock) a tuple-system rule will use. @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.14 91/02/24 12:39:57 sp Exp $ d1069 1 a1069 1 free(s1); @ 1.14 log @Quite a few changes. Now tuple-level-locking is implemented plus some code cleanup... @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.13 91/01/09 19:07:12 sp Exp Locker: sp $ d55 1 d65 6 d78 1 a78 1 prs2AddTheNewRule(ruleData); @ 1.13 log @The routines that put relation level or tuple level locks have been moved to 'prs2putlocks.c', 'prs2rel.c' and 'prs2tup.c' @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.12 90/10/25 21:03:59 goh Exp $ d28 1 a37 2 void changeReplaceToRetrieve(); bool prs2AttributeIsOfBasicType(); a52 17 NameData ruleName; EventType eventType; ActionType actionType; LispValue eventTarget; NameData eventTargetRelationNameData; Relation eventTargetRelation; ObjectId eventTargetRelationOid; NameData eventTargetAttributeNameData; AttributeNumber eventTargetAttributeNumber; LispValue ruleQual; LispValue paramRuleQual; LispValue paramRuleAction; LispValue paramParseTree; int isRuleInstead; LispValue ruleActionPlans; ObjectId ruleId; /*the OID for the new rule*/ AttributeNumber updatedAttributeNumber; d54 1 a55 2 LispValue prs2ReadRule(); d57 1 a57 1 printf("---prs2DefineTupleRule called, with argument ="); d60 1 a60 1 printf(" ruletext = %s\n", ruleText); d62 5 d68 4 a71 4 strcpy(ruleName.data, CString(GetRuleNameFromParse(parseTree))); eventTarget = GetRuleEventTargetFromParse(parseTree); isRuleInstead = CInteger(GetRuleInsteadFromParse(parseTree)); eventType = prs2FindEventTypeFromParse(parseTree); d73 18 d92 65 d171 4 a174 3 strcpy(eventTargetRelationNameData.data, CString(CAR(eventTarget))); eventTargetRelation = RelationNameGetRelation(&eventTargetRelationNameData); eventTargetRelationOid = eventTargetRelation->rd_id; d179 2 a180 1 eventTargetAttributeNumber = InvalidAttributeNumber; d182 4 a185 4 strcpy(eventTargetAttributeNameData.data, CString(CADR(eventTarget))); eventTargetAttributeNumber = get_attnum(eventTargetRelationOid, &eventTargetAttributeNameData); if (eventTargetAttributeNumber == InvalidAttributeNumber) { d193 2 a194 2 if (!prs2AttributeIsOfBasicType(eventTargetRelationOid, eventTargetAttributeNumber)) { d200 1 d202 34 d246 4 a249 5 ruleQual = GetRuleQualFromParse(parseTree); paramParseTree = lispCopy(parseTree); SubstituteParamForNewOrCurrent(paramParseTree, eventTargetRelationOid); paramRuleQual = GetRuleQualFromParse(paramParseTree); paramRuleAction = GetRuleActionFromParse(paramParseTree); d257 4 a260 4 actionType = prs2FindActionTypeFromParse(parseTree, eventTargetAttributeNumber, &updatedAttributeNumber, eventType); d270 2 a271 2 if (!isRuleInstead && actionType == ActionTypeRetrieveValue && eventTargetAttributeNumber != InvalidAttributeNumber ) { a275 1 d278 5 a282 4 printf("---DEFINE TUPLE RULE:\n"); printf(" RuleName = %s\n", ruleName.data); printf(" event type = %d ", eventType); switch (eventType) { d298 1 a298 1 printf(" event target:"); d301 5 a305 5 printf(" event target relation OID = %ld\n", eventTargetRelationOid); printf(" event target attr no = %d\n", eventTargetAttributeNumber); printf(" Instead flag = %d\n", isRuleInstead); printf(" ruleAction:"); lispDisplay(paramRuleAction, 0); d307 1 a308 28 /* * Insert information about the rule in the catalogs. * The routine returns the rule's OID. * */ ruleId = prs2InsertRuleInfoInCatalog(&ruleName, eventType, eventTargetRelationOid, eventTargetAttributeNumber, ruleText); /* * Now generate the plans for the action part of the rule */ ruleActionPlans = prs2GenerateActionPlans(isRuleInstead, paramRuleQual,paramRuleAction, GetRuleRangeTableFromParse(parseTree), eventTargetAttributeNumber, updatedAttributeNumber); /* * Store the plans generated above in the system * catalogs. */ prs2InsertRulePlanInCatalog(ruleId, ActionPlanNumber, ruleActionPlans); d310 1 a310 13 /* * Now set the appropriate locks. */ prs2TupleSystemPutLocks(ruleId, eventTargetRelationOid, eventTargetAttributeNumber, updatedAttributeNumber, eventType, actionType, ruleQual); #ifdef PRS2_DEBUG printf("--- DEFINE PRS2 RULE: Done.\n"); #endif PRS2_DEBUG d322 1 a323 1 d325 2 a326 7 prs2InsertRuleInfoInCatalog(ruleName, eventType, eventRelationOid, eventAttributeNumber, ruleText) Name ruleName; EventType eventType; ObjectId eventRelationOid; AttributeNumber eventAttributeNumber; char * ruleText; d341 1 d355 1 a355 1 ruleNameKey[0].argument = NameGetDatum(ruleName); d357 1 a357 1 heapScan = RelationBeginHeapScan(prs2RuleRelation, 0, NowTimeQual, d359 1 a359 1 heapTuple = HeapScanGetNextTuple(heapScan, 0, (Buffer *) NULL); d363 2 a364 2 elog(WARN, "prs2InsertRuleInfoInCatalog: rule %s already defined", ruleName); d376 2 a377 1 values[Prs2RuleNameAttributeNumber-1] = fmgr(F_CHAR16IN,(char *)ruleName); d380 1 a380 1 values[Prs2RuleEventTypeAttributeNumber-1] = (char *) eventType; d384 1 a384 1 (char *) eventRelationOid; d388 1 a388 1 (char *) eventAttributeNumber; d392 1 a392 1 fmgr(F_TEXTIN, ruleText); d410 1 d412 49 d469 2 d474 3 a476 3 ObjectId ruleId; Prs2PlanNumber planNumber; LispValue rulePlan; d521 42 d568 2 d572 2 a573 10 prs2GenerateActionPlans(isRuleInstead, ruleQual,ruleAction, rangeTable, eventTargetAttributeNumber, updatedAttributeNumber) int isRuleInstead; LispValue ruleQual; LispValue ruleAction; LispValue rangeTable; AttributeNumber eventTargetAttributeNumber; AttributeNumber updatedAttributeNumber; d582 1 d586 2 d601 1 a601 1 if (isRuleInstead) { d607 2 a608 2 ruleInfo = nappend1(ruleInfo, lispInteger(eventTargetAttributeNumber)); ruleInfo = nappend1(ruleInfo, lispInteger(updatedAttributeNumber)); d616 1 a616 1 if (null(ruleQual)) { d677 1 a677 1 lispCons(ruleQual, LispNil))); d688 1 a688 1 foreach (action, ruleAction) { a707 1 a709 113 /* ---------------------------------------------------------------- * * prs2RemoveTupleRule * * Delete a rule given its rulename. * * There are three steps. * 1) Find the corresponding tuple in 'pg_prs2rule' relation. * Find the rule Id (i.e. the Oid of the tuple) and finally delete * the tuple. * 2) Given the rule Id find and delete all corresonding tuples from * 'pg_prs2plans' relation * 3) (Optional) Delete the locks from the 'pg_relation' relation. * * * ---------------------------------------------------------------- */ void prs2RemoveTupleRule(ruleName) Name ruleName; { Relation prs2RuleRelation; Relation prs2PlansRelation; HeapScanDesc scanDesc; ScanKeyData scanKey; HeapTuple tuple; ObjectId ruleId; ObjectId eventRelationOid; Datum eventRelationOidDatum; Buffer buffer; Boolean isNull; /* * Open the pg_rule relation. */ prs2RuleRelation = RelationNameOpenHeapRelation(Prs2RuleRelationName); /* * Scan the RuleRelation ('pg_prs2rule') until we find a tuple */ scanKey.data[0].flags = 0; scanKey.data[0].attributeNumber = Prs2RuleNameAttributeNumber; scanKey.data[0].procedure = Character16EqualRegProcedure; scanKey.data[0].argument = NameGetDatum(ruleName); scanDesc = RelationBeginHeapScan(prs2RuleRelation, 0, NowTimeQual, 1, &scanKey); tuple = HeapScanGetNextTuple(scanDesc, 0, &buffer); /* * complain if no rule with such name existed */ if (!HeapTupleIsValid(tuple)) { RelationCloseHeapRelation(prs2RuleRelation); elog(WARN, "No rule with name = '%s' was found.\n", ruleName); } /* * Store the OID of the rule (i.e. the tuple's OID) * and the event relation's OID */ ruleId = tuple->t_oid; eventRelationOidDatum = HeapTupleGetAttributeValue( tuple, buffer, Prs2RuleEventTargetRelationAttributeNumber, &(prs2RuleRelation->rd_att), &isNull); if (isNull) { /* XXX strange!!! */ elog(WARN, "prs2RemoveTupleRule: null event target relation!"); } eventRelationOid = DatumGetObjectId(eventRelationOidDatum); /* * Now delete the tuple... */ RelationDeleteHeapTuple(prs2RuleRelation, &(tuple->t_ctid)); RelationCloseHeapRelation(prs2RuleRelation); /* * Now delete all tuples of the Prs2Plans relation (pg_prs2plans) * corresponding to this rule... */ prs2PlansRelation = RelationNameOpenHeapRelation(Prs2PlansRelationName); scanKey.data[0].flags = 0; scanKey.data[0].attributeNumber = Prs2PlansRuleIdAttributeNumber; scanKey.data[0].procedure = ObjectIdEqualRegProcedure; scanKey.data[0].argument = ObjectIdGetDatum(ruleId); scanDesc = RelationBeginHeapScan(prs2PlansRelation, 0, NowTimeQual, 1, &scanKey); while((tuple=HeapScanGetNextTuple(scanDesc, 0, (Buffer *)NULL)) != NULL) { /* * delete the prs2PlansRelation tuple... */ RelationDeleteHeapTuple(prs2PlansRelation, &(tuple->t_ctid)); } RelationCloseHeapRelation(prs2PlansRelation); /* * Now delete the relation level locks from the updated relation */ prs2RemoveRelationLevelLocks(ruleId, eventRelationOid); elog(DEBUG, "---Rule '%s' deleted.\n", ruleName); } d715 1 d764 1 a919 64 /*=============================== DEBUGGINF STUFF ================*/ LispValue prs2ReadRule(fname) char *fname; { FILE *fp; int c; int count, maxcount; char *s1, *s2; LispValue l; LispValue StringToPlan(); printf("--- prsReadRule.\n"); AllocateFile(); if (fname==NULL) { fp = stdin; printf(" reading rule from stdin.\n"); } else { AllocateFile(); fp = fopen(fname, "r"); if (fp==NULL){ printf(" Can not open rule file %s\n", fname); elog(WARN,"prs2ReadRule.... exiting...\n"); } else { printf("Reading rule from file %s\n", fname); } } maxcount = 100; s1 = palloc(maxcount); if (s1 == NULL) { elog(WARN,"prs2ReadRule : out of memory!"); } count = 0; while((c=getc(fp)) != EOF) { if (count >= maxcount) { maxcount = maxcount + 1000; s2 = palloc(maxcount); if (s2 == NULL) { elog(WARN,"prs2ReadRule : out of memory!"); } bcopy(s1, s2, count); free(s1); s1 = s2; } s1[count] = c; count++; } s1[count+1] = '\0'; l = StringToPlan(s1); printf(" list = \n"); lispDisplay(l,0); if (fp!=stdin) { fclose(fp); FreeFile(); } return(l); } d927 1 d996 1 d1017 64 @ 1.12 log @spyro's earlier change to locks breaks procedures, not caught till mike's new demo used it because I didn't have latest files. - jeff @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.11 90/10/20 14:29:51 sp Exp Locker: goh $ d35 2 d44 3 d64 3 a66 1 LispValue ruleAction; a69 1 Prs2LockType lockType; a83 1 ruleQual = GetRuleQualFromParse(parseTree); d85 1 a85 1 ruleAction = GetRuleActionFromParse(parseTree); a86 1 eventType = prs2FindEventTypeFromParse(parseTree); d130 17 d200 1 a200 1 lispDisplay(ruleAction, 0); d219 1 a219 1 ruleQual,ruleAction, d235 1 a235 1 prs2PutTupleOrRewriteLocks(ruleId, eventTargetRelationOid, d238 2 a239 1 eventType, actionType, true); a246 7 /*----------------------------------------------------------------------- * prs2PutLocksInRelation * * Put the appropriate locks for the rule. For the time * being we just put a relation level lock in pg_relation. * All the tuples of the target relation are assumed to be locked */ a247 80 void prs2PutLocksInRelation(ruleId, lockType, eventRelationOid, eventAttributeNumber) ObjectId ruleId; Prs2LockType lockType; ObjectId eventRelationOid; AttributeNumber eventAttributeNumber; { Relation relationRelation; HeapScanDesc scanDesc; ScanKeyData scanKey; HeapTuple tuple; Buffer buffer; HeapTuple newTuple; RuleLock currentLock; /* * Lock a relation given its ObjectId. * Go to the RelationRelation (i.e. pg_relation), find the * appropriate tuple, and add the specified lock to it. */ relationRelation = RelationNameOpenHeapRelation(RelationRelationName); scanKey.data[0].flags = 0; scanKey.data[0].attributeNumber = ObjectIdAttributeNumber; scanKey.data[0].procedure = ObjectIdEqualRegProcedure; scanKey.data[0].argument = ObjectIdGetDatum(eventRelationOid); scanDesc = RelationBeginHeapScan(relationRelation, 0, NowTimeQual, 1, &scanKey); tuple = HeapScanGetNextTuple(scanDesc, 0, &buffer); if (!HeapTupleIsValid(tuple)) { elog(WARN, "Invalid rel OID %ld", eventRelationOid); } /* * We have found the appropriate tuple of the RelationRelation. * Now find its old locks, and add the new one */ currentLock = prs2GetLocksFromTuple(tuple, buffer, relationRelation->rd_att); #ifdef PRS2_DEBUG /*-- DEBUG --*/ printf("previous Lock:"); prs2PrintLocks(currentLock); printf("\n"); #endif /* PRS2_DEBUG */ currentLock = prs2AddLock(currentLock, ruleId, lockType, eventAttributeNumber, ActionPlanNumber); #ifdef PRS2_DEBUG /*-- DEBUG --*/ printf("new Lock:"); prs2PrintLocks(currentLock); printf("\n"); #endif /* PRS2_DEBUG */ /* * Create a new tuple (i.e. a copy of the old tuple * with its rule lock field changed and replace the old * tuple in the Relationrelation */ newTuple = prs2PutLocksInTuple(tuple, buffer, relationRelation, currentLock); RelationReplaceHeapTuple(relationRelation, &(tuple->t_ctid), newTuple, (double *)NULL); RelationCloseHeapRelation(relationRelation); } d664 1 a664 1 prs2RemoveLocks(ruleId, eventRelationOid); a669 86 /*-------------------------------------------------------------- * * RuleUnlockRelation * * Unlock a relation given its ObjectId ant the Objectid of the rule * Go to the RelationRelation (i.e. pg_relation), find the * appropriate tuple, and remove all locks of this rule from it. */ void prs2RemoveLocks(ruleId, eventRelationOid) ObjectId ruleId; ObjectId eventRelationOid; { Relation relationRelation; HeapScanDesc scanDesc; ScanKeyData scanKey; HeapTuple tuple; Buffer buffer; HeapTuple newTuple; HeapTuple newTuple2; RuleLock currentLocks; Boolean isNull; int i; int numberOfLocks; Prs2OneLock oneLock; relationRelation = RelationNameOpenHeapRelation(RelationRelationName); scanKey.data[0].flags = 0; scanKey.data[0].attributeNumber = ObjectIdAttributeNumber; scanKey.data[0].procedure = ObjectIdEqualRegProcedure; scanKey.data[0].argument = ObjectIdGetDatum(eventRelationOid); scanDesc = RelationBeginHeapScan(relationRelation, 0, NowTimeQual, 1, &scanKey); tuple = HeapScanGetNextTuple(scanDesc, 0, &buffer); if (!HeapTupleIsValid(tuple)) { elog(NOTICE, "Could not find relation with id %ld\n", eventRelationOid); } else { /* * "calculate" the new locks... */ currentLocks = prs2GetLocksFromTuple( tuple, buffer, &(relationRelation->rd_att)); #ifdef PRS2_DEBUG printf("previous Lock:"); prs2PrintLocks(currentLocks); printf("\n"); #endif PRS2_DEBUG /* * find all the locks with the given rule id and remove them */ currentLocks = prs2RemoveAllLocksOfRule(currentLocks, ruleId); #ifdef PRS2_DEBUG printf("new Lock:"); prs2PrintLocks(currentLocks); printf("\n"); #endif PRS2_DEBUG /* * Create a new tuple (i.e. a copy of the old tuple * with its rule lock field changed and replace the old * tuple in the RelationRelation */ newTuple = prs2PutLocksInTuple(tuple, buffer, relationRelation, currentLocks); RelationReplaceHeapTuple(relationRelation, &(tuple->t_ctid), newTuple, (double *)NULL); } /* * we are done, close the RelationRelation... */ RelationCloseHeapRelation(relationRelation); } a875 159 } /*------------------------------------------------------------------ * * prs2PutLocks * * (used by the query rewrite system) */ prs2PutLocks(ruleId, relationOid, eventAttributeNo, updatedAttributeNo, eventType, actionType) ObjectId ruleId; ObjectId relationOid; AttributeNumber eventAttributeNo; AttributeNumber updatedAttributeNo; EventType eventType; ActionType actionType; { prs2PutTupleOrRewriteLocks(ruleId, relationOid, eventAttributeNo, updatedAttributeNo, eventType, actionType, false); } /*------------------------------------------------------------------ * * prs2PutTupleOrRewriteLocks * * Put the appropriate rule locks. * NOTE: currently only relation level locking is implemented * NOTE: isTupleLevel is true if this routine is used by the tuple * level system, otherwise (if it is used by the query rewrite * system) it is false. */ prs2PutTupleOrRewriteLocks(ruleId, relationOid, eventAttributeNo, updatedAttributeNo, eventType, actionType, isTupleLevel) ObjectId ruleId; ObjectId relationOid; AttributeNumber eventAttributeNo; AttributeNumber updatedAttributeNo; EventType eventType; ActionType actionType; bool isTupleLevel; { Prs2LockType lockType; AttributeNumber attributeNo; /* * find the lock type */ lockType = LockTypeInvalid; if (actionType == ActionTypeRetrieveValue && eventAttributeNo == InvalidAttributeNumber) { /* * this is a "view" rule.... */ if (isTupleLevel) { lockType = LockTypeTupleRetrieveRelation; } else { lockType = LockTypeRetrieveRelation; } attributeNo = InvalidAttributeNumber; } else if (actionType == ActionTypeRetrieveValue || actionType == ActionTypeReplaceCurrent || actionType == ActionTypeReplaceNew) { /* * In this case the attribute to be locked is the updated * attribute... */ attributeNo = updatedAttributeNo; switch (eventType) { case EventTypeRetrieve: if (isTupleLevel) { lockType = LockTypeTupleRetrieveWrite; } else { if ( actionType == ActionTypeRetrieveValue ) { lockType = LockTypeRetrieveRelation; } else lockType = LockTypeRetrieveWrite; } break; case EventTypeReplace: if (isTupleLevel) { lockType = LockTypeTupleReplaceWrite; } else { lockType = LockTypeReplaceWrite; } if (actionType == ActionTypeReplaceCurrent) { elog(WARN, "ON REPLACE rules can not update CURRENT tuple"); } break; case EventTypeAppend: if (isTupleLevel) { lockType = LockTypeTupleAppendWrite; } else { lockType = LockTypeAppendWrite; } if (actionType == ActionTypeReplaceCurrent) { elog(WARN, "ON APPEND rules can not update CURRENT tuple"); } break; case EventTypeDelete: if (isTupleLevel) { lockType = LockTypeTupleDeleteWrite; } else { lockType = LockTypeDeleteWrite; } elog(WARN, "ON DELETE rules can not update CURRENT tuple"); break; default: elog(WARN, "prs2PutLocks: Illegal Event type: %c", eventType); } } else if (actionType == ActionTypeOther) { /* * In this case the attribute to be locked is the 'event' * attribute... */ attributeNo = eventAttributeNo; switch (eventType) { case EventTypeRetrieve: if (isTupleLevel) { lockType = LockTypeTupleRetrieveAction; } else { lockType = LockTypeRetrieveAction; } break; case EventTypeReplace: if (isTupleLevel) { lockType = LockTypeTupleReplaceAction; } else { lockType = LockTypeReplaceAction; } break; case EventTypeAppend: if (isTupleLevel) { lockType = LockTypeTupleAppendAction; } else { lockType = LockTypeAppendAction; } break; case EventTypeDelete: if (isTupleLevel) { lockType = LockTypeTupleDeleteAction; } else { lockType = LockTypeDeleteAction; } break; default: elog(WARN, "prs2PutLocks: Illegal Event type: %c", eventType); } } else { elog(WARN, "prs2PutLocks: Illegal Action type: %c", actionType); } #ifdef PRS2DEBUG printf("prs2PutLocks: (ACTION='%c', EVENT='%c', LOCK='%c'\n", actionType, eventType, lockType); #endif PRS2DEBUG prs2PutLocksInRelation(ruleId, lockType, relationOid, attributeNo); @ 1.11 log @Now "view" rules don't have to have an "instead" @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.10 90/10/16 17:18:13 sp Exp $ d1101 4 a1104 1 lockType = LockTypeRetrieveWrite; @ 1.10 log @bug fix: space allocated for a Name was local to a routine and it was blown away upon return... @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.9 90/10/10 18:58:00 hong Exp $ d139 4 d144 2 a145 1 if (!isRuleInstead && actionType == ActionTypeRetrieveValue) { @ 1.9 log @added a new field in Resdom node @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.8 90/09/25 16:42:27 kemnitz Exp Locker: hong $ d537 1 a537 1 NameData nameData; d543 5 a547 1 strcpy(nameData.data,"foo"); d551 1 a551 1 &(nameData.data[0]), @ 1.8 log @Updating from revision 1.7 to revision 1.18 @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.18 90/08/18 00:41:40 cimarron Exp $ d549 2 a550 1 (OperatorTupleForm) 0); @ 1.7 log @Got rid of datum indirection. @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.6 90/05/31 14:54:26 sp Exp $ d12 16 a27 19 #include "c.h" #include "primnodes.h" #include "primnodes.a.h" #include "datum.h" #include "pg_lisp.h" #include "log.h" #include "relcache.h" /* RelationNameGetRelation() defined here...*/ #include "prs2.h" #include "anum.h" /* RuleRelationNumberOfAttributes etc. defined here */ #include "skey.h" /* 'ScanKeyEntryData' defined here... */ #include "tqual.h" /* 'NowTimeQual' defined here.. */ #include "heapam.h" /* heap AM calls defined here */ #include "lsyscache.h" /* get_attnum() defined here...*/ #include "parse.h" /* RETRIEVE, APPEND etc defined here.. */ #include "parsetree.h" #include "catname.h" /* names of various system relations defined here */ #include "rproc.h" /* for ObjectIdEqualRegProcedure etc. */ #include "fmgr.h" /* for F_CHAR16EQ, F_CHAR16IN etc. */ #include "ftup.h" /* for FormHeapTuple() */ d29 4 d36 1 a68 5 /* #define NO_PARSER_SUPPORT */ #ifdef NO_PARSER_SUPPORT parseTree = prs2ReadRule("/users/spyros/postgres/O/support/RULE"); #endif d113 10 d133 11 a143 1 &updatedAttributeNumber); d193 4 a196 3 ruleQual,ruleAction, eventTargetAttributeNumber, updatedAttributeNumber); d209 1 a209 1 prs2PutLocks(ruleId, eventTargetRelationOid, d212 1 a212 1 eventType, actionType); d330 2 a331 2 char *values[RuleRelationNumberOfAttributes]; char nulls[RuleRelationNumberOfAttributes]; d474 1 d480 1 a524 1 #ifdef NOT_YET d533 1 d540 3 a542 5 root = lispCons(lispInteger(1), lispCons(lispAtom("retrieve"), lispCons(LispNil, lispCons(LispNil, lispCons(lispCons(0,LispNil),LispNil))))); d547 1 a547 1 &nameData, d559 17 a578 3 #else /* NOT_YET*/ qualQuery = ruleQual; #endif /* NOT_YET */ d765 9 a773 8 elog(WARN, "Invalid rel Oid %ld\n", eventRelationOid); } currentLocks = prs2GetLocksFromTuple( tuple, buffer, &(relationRelation->rd_att)); d775 3 a777 3 printf("previous Lock:"); prs2PrintLocks(currentLocks); printf("\n"); a778 5 /* * find all the locks with the given rule id and remove them */ currentLocks = prs2RemoveAllLocksOfRule(currentLocks, ruleId); d780 5 d786 3 a788 3 printf("new Lock:"); prs2PrintLocks(currentLocks); printf("\n"); d791 13 d805 1 a805 3 * Create a new tuple (i.e. a copy of the old tuple * with its rule lock field changed and replace the old * tuple in the RelationRelation a806 7 newTuple = prs2PutLocksInTuple(tuple, buffer, relationRelation, currentLocks); RelationReplaceHeapTuple(relationRelation, &(tuple->t_ctid), newTuple, (double *)NULL); d868 2 a869 1 updatedAttributeNumberP) d873 1 d886 2 d894 16 a909 5 /* * then this is probably an `instead' rule with no action * specified, e.g. "ON delete to DEPT WHERE ... DO INSTEAD" */ return(ActionTypeOther); d921 5 a925 2 if (!null(rangeTable)) { strcpy(&(nameData.data[0]), CString(rt_relname(CAR(rangeTable)))); d947 1 d949 1 a949 1 NameIsEqual("CURRENT", relationName)) { d964 16 d1006 10 d1023 19 d1044 3 d1048 3 a1050 2 prs2PutLocks(ruleId, relationOid, eventAttributeNo, updatedAttributeNo, eventType, actionType) d1057 1 d1072 5 a1076 1 lockType = LockTypeRetrieveRelation; d1079 2 a1080 1 actionType == ActionTypeReplaceCurrent) { d1088 5 a1092 1 lockType = LockTypeRetrieveWrite; d1095 8 a1102 1 lockType = LockTypeReplaceWrite; d1105 8 a1112 1 lockType = LockTypeAppendWrite; d1115 5 a1119 1 lockType = LockTypeDeleteWrite; d1133 5 a1137 1 lockType = LockTypeRetrieveAction; d1140 5 a1144 1 lockType = LockTypeReplaceAction; d1147 5 a1151 1 lockType = LockTypeAppendAction; d1154 5 a1158 1 lockType = LockTypeDeleteAction; d1243 2 a1244 1 * Ghange the parse tree of a 'REPLACE CURRENT(X = ...)' command to a d1259 2 d1267 5 a1271 2 if (!null(rangeTable)) { strcpy(&(nameData.data[0]), CString(rt_relname(CAR(rangeTable)))); d1280 3 a1282 1 if (commandType!=REPLACE || !NameIsEqual("CURRENT", relationName)) { d1284 1 a1284 1 * NO, this is not a REPLACE CURRENT command d1307 27 @ 1.6 log @MakeConst now takes a new argument ("byval") @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.5 90/05/14 20:29:12 sp Exp Locker: sp $ d236 1 a236 1 scanKey.data[0].argument.objectId.value = eventRelationOid; d335 1 a335 1 ruleNameKey[0].argument.name.value = ruleName; d624 1 a624 1 scanKey.data[0].argument.name.value = ruleName; d670 1 a670 1 scanKey.data[0].argument.objectId.value = ruleId; d726 1 a726 1 scanKey.data[0].argument.objectId.value = eventRelationOid; @ 1.5 log @now it uses the parse tree returned by the parser (instead of trying to read it from a file) , @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.4 90/04/19 19:51:26 sp Exp $ d533 5 a537 4 constant = MakeConst((ObjectId) 23, (Size) 4, value, false); @ 1.4 log @Now can handle 'view' rules... @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.3 90/04/03 17:11:43 sp Exp $ d67 1 a67 1 #define NO_PARSER_SUPPORT @ 1.3 log @rules with 'on ... do replace CURRENT' are defined correctly @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.2 90/01/31 03:50:04 sp Exp $ d9 1 a9 1 * All teh routines needed to define a (tuple) PRS2 rule d876 12 a887 1 * this is a retrieve (NOT a retrieve into...) d960 8 a967 1 if (actionType == ActionTypeRetrieveValue || @ 1.2 log @a little bit more clever when deciding what kind of locks to put! @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.1 90/01/11 14:42:49 sp Exp Locker: sp $ d13 3 d34 1 d62 1 d65 7 a85 2 actionType = prs2FindActionTypeFromParse(parseTree); d117 11 d176 3 a178 1 ruleQual,ruleAction); d192 3 a194 1 eventTargetAttributeNumber, eventType, actionType); d455 3 a457 1 prs2GenerateActionPlans(isRuleInstead, ruleQual,ruleAction) d461 2 d469 3 a472 1 result = LispNil; d476 10 d488 1 a488 1 oneEntry = lispCons(lispString("instead"), LispNil); d490 1 a490 1 oneEntry = lispCons(lispString("not-instead"), LispNil); d493 2 a494 1 result = nappend1(result, oneEntry); d496 1 d498 1 d505 42 a546 1 onePlan = planner(ruleQual); d548 1 a548 1 oneEntry = lispCons(ruleQual, oneEntry); d559 8 d822 4 d828 3 a830 1 prs2FindActionTypeFromParse(parseTree) d832 2 d844 2 d847 2 d851 8 d869 2 a870 1 strcpy(relationName,CString(rt_relname(CAR(rangeTable)))); d874 1 a874 1 if (commandType == RETRIEVE && !null(resultRelation)) { d886 9 d909 1 d932 2 a933 1 prs2PutLocks(ruleId, relationOid, attributeNo, eventType, actionType) d936 2 a937 1 AttributeNumber attributeNo; d942 1 d951 5 d974 5 d1005 126 @ 1.1 log @Initial revision @ text @d6 1 a6 1 * $Header: RCS/prs2define.c,v 1.2 90/01/11 00:22:47 sp Exp Locker: sp $ a17 1 #include "ruledef.h" /* PlanToString() defined here... */ d23 1 a43 1 int eventTypeInt; d45 1 a67 1 eventTypeInt = CInteger(GetRuleEventTypeFromParse(parseTree)); d73 2 a74 25 /* * Note that the event type as stored in the parse tree is one of * RETRIEVE, REPLACE, APPEND or DELETE. All these symbols are * defined in "parse.h". So, we have to change them * into the appropriate "EventType" type. */ switch (eventTypeInt) { case RETRIEVE: eventType = EventTypeRetrieve; break; case REPLACE: eventType = EventTypeReplace; break; case APPEND: eventType = EventTypeAppend; break; case DELETE: eventType = EventTypeDelete; break; default: eventType = EventTypeInvalid; elog(WARN, "prs2DefineTupleRule: Illegal event type (int) %d", eventTypeInt); } /* switch*/ a166 4 * * Try first to findthe appropriate type of lock. * Normally if the rule updates the current tuple * we must put a LockTypeWrite lock. d168 2 a170 6 /* XXX Thsi wil not work! */ lockType = LockTypeWrite; prs2PutLocks(ruleId, lockType, eventTargetRelationOid, eventTargetAttributeNumber); d178 1 a178 1 * prs2PutLocks d186 1 a186 1 prs2PutLocks(ruleId, lockType, eventRelationOid, eventAttributeNumber) d199 1 a199 1 Prs2Locks currentLock; d621 1 a621 1 Prs2Locks currentLocks; d678 190 @