<entry>The table this rule is for</entry>
</row>
- <row>
- <entry><structfield>ev_attr</structfield></entry>
- <entry><type>int2</type></entry>
- <entry></entry>
- <entry>The column this rule is for (currently, always -1 to
- indicate the whole table)</entry>
- </row>
-
<row>
<entry><structfield>ev_type</structfield></entry>
<entry><type>char</type></entry>
InsertRule(char *rulname,
int evtype,
Oid eventrel_oid,
- AttrNumber evslot_index,
bool evinstead,
Node *event_qual,
List *action,
namestrcpy(&rname, rulname);
values[Anum_pg_rewrite_rulename - 1] = NameGetDatum(&rname);
values[Anum_pg_rewrite_ev_class - 1] = ObjectIdGetDatum(eventrel_oid);
- values[Anum_pg_rewrite_ev_attr - 1] = Int16GetDatum(evslot_index);
values[Anum_pg_rewrite_ev_type - 1] = CharGetDatum(evtype + '0');
values[Anum_pg_rewrite_ev_enabled - 1] = CharGetDatum(RULE_FIRES_ON_ORIGIN);
values[Anum_pg_rewrite_is_instead - 1] = BoolGetDatum(evinstead);
* When replacing, we don't need to replace every attribute
*/
MemSet(replaces, false, sizeof(replaces));
- replaces[Anum_pg_rewrite_ev_attr - 1] = true;
replaces[Anum_pg_rewrite_ev_type - 1] = true;
replaces[Anum_pg_rewrite_is_instead - 1] = true;
replaces[Anum_pg_rewrite_ev_qual - 1] = true;
List *action)
{
Relation event_relation;
- int event_attno;
ListCell *l;
Query *query;
bool RelisBecomingView = false;
/*
* This rule is allowed - prepare to install it.
*/
- event_attno = -1;
/* discard rule if it's null action and not INSTEAD; it's a no-op */
if (action != NIL || is_instead)
ruleId = InsertRule(rulename,
event_type,
event_relid,
- event_attno,
is_instead,
event_qual,
action,
if (oneLock->event == event)
{
if (parsetree->commandType != CMD_SELECT ||
- (oneLock->attrno == -1 ?
- rangeTableEntry_used((Node *) parsetree, varno, 0) :
- attribute_used((Node *) parsetree,
- varno, oneLock->attrno, 0)))
+ rangeTableEntry_used((Node *) parsetree, varno, 0))
matching_locks = lappend(matching_locks, oneLock);
}
}
ApplyRetrieveRule(Query *parsetree,
RewriteRule *rule,
int rt_index,
- bool relation_level,
Relation relation,
List *activeRIRs,
bool forUpdatePushedDown)
elog(ERROR, "expected just one rule action");
if (rule->qual != NULL)
elog(ERROR, "cannot handle qualified ON SELECT rule");
- if (!relation_level)
- elog(ERROR, "cannot handle per-attribute ON SELECT rule");
if (rt_index == parsetree->resultRelation)
{
if (rule->event != CMD_SELECT)
continue;
- if (rule->attrno > 0)
- {
- /* per-attr rule; do we need it? */
- if (!attribute_used((Node *) parsetree, rt_index,
- rule->attrno, 0))
- continue;
- }
-
locks = lappend(locks, rule);
}
parsetree = ApplyRetrieveRule(parsetree,
rule,
rt_index,
- rule->attrno == -1,
rel,
activeRIRs,
forUpdatePushedDown);
}
-/*
- * attribute_used -
- * Check if a specific attribute number of a RTE is used
- * somewhere in the query or expression.
- */
-
-typedef struct
-{
- int rt_index;
- int attno;
- int sublevels_up;
-} attribute_used_context;
-
-static bool
-attribute_used_walker(Node *node,
- attribute_used_context *context)
-{
- if (node == NULL)
- return false;
- if (IsA(node, Var))
- {
- Var *var = (Var *) node;
-
- if (var->varlevelsup == context->sublevels_up &&
- var->varno == context->rt_index &&
- var->varattno == context->attno)
- return true;
- return false;
- }
- if (IsA(node, Query))
- {
- /* Recurse into subselects */
- bool result;
-
- context->sublevels_up++;
- result = query_tree_walker((Query *) node, attribute_used_walker,
- (void *) context, 0);
- context->sublevels_up--;
- return result;
- }
- return expression_tree_walker(node, attribute_used_walker,
- (void *) context);
-}
-
-bool
-attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
-{
- attribute_used_context context;
-
- context.rt_index = rt_index;
- context.attno = attno;
- context.sublevels_up = sublevels_up;
-
- /*
- * Must be prepared to start with a Query or a bare expression tree; if
- * it's a Query, we don't want to increment sublevels_up.
- */
- return query_or_expression_tree_walker(node,
- attribute_used_walker,
- (void *) &context,
- 0);
-}
-
-
/*
* If the given Query is an INSERT ... SELECT construct, extract and
* return the sub-Query node that represents the SELECT part. Otherwise
char *rulename;
char ev_type;
Oid ev_class;
- int16 ev_attr;
bool is_instead;
char *ev_qual;
char *ev_action;
Assert(!isnull);
ev_class = DatumGetObjectId(dat);
- fno = SPI_fnumber(rulettc, "ev_attr");
- dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
- Assert(!isnull);
- ev_attr = DatumGetInt16(dat);
-
fno = SPI_fnumber(rulettc, "is_instead");
dat = SPI_getbinval(ruletup, rulettc, fno, &isnull);
Assert(!isnull);
/* The relation the rule is fired on */
appendStringInfo(buf, " TO %s", generate_relation_name(ev_class, NIL));
- if (ev_attr > 0)
- appendStringInfo(buf, ".%s",
- quote_identifier(get_relid_attribute_name(ev_class,
- ev_attr)));
/* If the rule has an event qualification, add it */
if (ev_qual == NULL)
Query *query;
char ev_type;
Oid ev_class;
- int16 ev_attr;
bool is_instead;
char *ev_qual;
char *ev_action;
fno = SPI_fnumber(rulettc, "ev_class");
ev_class = (Oid) SPI_getbinval(ruletup, rulettc, fno, &isnull);
- fno = SPI_fnumber(rulettc, "ev_attr");
- ev_attr = (int16) SPI_getbinval(ruletup, rulettc, fno, &isnull);
-
fno = SPI_fnumber(rulettc, "is_instead");
is_instead = (bool) SPI_getbinval(ruletup, rulettc, fno, &isnull);
query = (Query *) linitial(actions);
- if (ev_type != '1' || ev_attr >= 0 || !is_instead ||
+ if (ev_type != '1' || !is_instead ||
strcmp(ev_qual, "<>") != 0 || query->commandType != CMD_SELECT)
{
appendStringInfo(buf, "Not a view");
rule->ruleId = HeapTupleGetOid(rewrite_tuple);
rule->event = rewrite_form->ev_type - '0';
- rule->attrno = rewrite_form->ev_attr;
rule->enabled = rewrite_form->ev_enabled;
rule->isInstead = rewrite_form->is_instead;
return false;
if (rule1->event != rule2->event)
return false;
- if (rule1->attrno != rule2->attrno)
- return false;
if (rule1->enabled != rule2->enabled)
return false;
if (rule1->isInstead != rule2->isInstead)
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201309031
+#define CATALOG_VERSION_NO 201309051
#endif
{
NameData rulename;
Oid ev_class;
- int16 ev_attr;
char ev_type;
char ev_enabled;
bool is_instead;
* compiler constants for pg_rewrite
* ----------------
*/
-#define Natts_pg_rewrite 8
+#define Natts_pg_rewrite 7
#define Anum_pg_rewrite_rulename 1
#define Anum_pg_rewrite_ev_class 2
-#define Anum_pg_rewrite_ev_attr 3
-#define Anum_pg_rewrite_ev_type 4
-#define Anum_pg_rewrite_ev_enabled 5
-#define Anum_pg_rewrite_is_instead 6
-#define Anum_pg_rewrite_ev_qual 7
-#define Anum_pg_rewrite_ev_action 8
+#define Anum_pg_rewrite_ev_type 3
+#define Anum_pg_rewrite_ev_enabled 4
+#define Anum_pg_rewrite_is_instead 5
+#define Anum_pg_rewrite_ev_qual 6
+#define Anum_pg_rewrite_ev_action 7
#endif /* PG_REWRITE_H */
{
Oid ruleId;
CmdType event;
- AttrNumber attrno;
Node *qual;
List *actions;
char enabled;
extern bool rangeTableEntry_used(Node *node, int rt_index,
int sublevels_up);
-extern bool attribute_used(Node *node, int rt_index, int attno,
- int sublevels_up);
extern Query *getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr);
allocfunc
array_unnest_fctx
assign_collations_context
-attribute_used_context
autovac_table
av_relation
avl_dbase