* transformRuleStmt - * transform a CREATE RULE Statement. The action is a list of parse * trees which is transformed into a list of query trees, and we also * transform the WHERE clause if any. * * actions and whereClause are output parameters that receive the * transformed results. */
| 4112 | * transformed results. |
| 4113 | */ |
| 4114 | void |
| 4115 | transformRuleStmt(RuleStmt *stmt, const char *queryString, |
| 4116 | List **actions, Node **whereClause) |
| 4117 | { |
| 4118 | Relation rel; |
| 4119 | ParseState *pstate; |
| 4120 | ParseNamespaceItem *oldnsitem; |
| 4121 | ParseNamespaceItem *newnsitem; |
| 4122 | |
| 4123 | /* |
| 4124 | * To avoid deadlock, make sure the first thing we do is grab |
| 4125 | * AccessExclusiveLock on the target relation. This will be needed by |
| 4126 | * DefineQueryRewrite(), and we don't want to grab a lesser lock |
| 4127 | * beforehand. |
| 4128 | */ |
| 4129 | rel = table_openrv(stmt->relation, AccessExclusiveLock); |
| 4130 | |
| 4131 | if (rel->rd_rel->relkind == RELKIND_MATVIEW) |
| 4132 | ereport(ERROR, |
| 4133 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 4134 | errmsg("rules on materialized views are not supported"))); |
| 4135 | |
| 4136 | /* Set up pstate */ |
| 4137 | pstate = make_parsestate(NULL); |
| 4138 | pstate->p_sourcetext = queryString; |
| 4139 | |
| 4140 | /* |
| 4141 | * NOTE: 'OLD' must always have a varno equal to 1 and 'NEW' equal to 2. |
| 4142 | * Set up their ParseNamespaceItems in the main pstate for use in parsing |
| 4143 | * the rule qualification. |
| 4144 | */ |
| 4145 | oldnsitem = addRangeTableEntryForRelation(pstate, rel, |
| 4146 | AccessShareLock, |
| 4147 | makeAlias("old", NIL), |
| 4148 | false, false); |
| 4149 | newnsitem = addRangeTableEntryForRelation(pstate, rel, |
| 4150 | AccessShareLock, |
| 4151 | makeAlias("new", NIL), |
| 4152 | false, false); |
| 4153 | /* Must override addRangeTableEntry's default access-check flags */ |
| 4154 | oldnsitem->p_rte->requiredPerms = 0; |
| 4155 | newnsitem->p_rte->requiredPerms = 0; |
| 4156 | |
| 4157 | /* |
| 4158 | * They must be in the namespace too for lookup purposes, but only add the |
| 4159 | * one(s) that are relevant for the current kind of rule. In an UPDATE |
| 4160 | * rule, quals must refer to OLD.field or NEW.field to be unambiguous, but |
| 4161 | * there's no need to be so picky for INSERT & DELETE. We do not add them |
| 4162 | * to the joinlist. |
| 4163 | */ |
| 4164 | switch (stmt->event) |
| 4165 | { |
| 4166 | case CMD_SELECT: |
| 4167 | addNSItemToQuery(pstate, oldnsitem, false, true, true); |
| 4168 | break; |
| 4169 | case CMD_UPDATE: |
| 4170 | addNSItemToQuery(pstate, oldnsitem, false, true, true); |
| 4171 | addNSItemToQuery(pstate, newnsitem, false, true, true); |
no test coverage detected