* postgresBeginForeignInsert * Begin an insert operation on a foreign table */
| 2132 | * Begin an insert operation on a foreign table |
| 2133 | */ |
| 2134 | static void |
| 2135 | postgresBeginForeignInsert(ModifyTableState *mtstate, |
| 2136 | ResultRelInfo *resultRelInfo) |
| 2137 | { |
| 2138 | PgFdwModifyState *fmstate; |
| 2139 | ModifyTable *plan = castNode(ModifyTable, mtstate->ps.plan); |
| 2140 | EState *estate = mtstate->ps.state; |
| 2141 | Index resultRelation; |
| 2142 | Relation rel = resultRelInfo->ri_RelationDesc; |
| 2143 | RangeTblEntry *rte; |
| 2144 | TupleDesc tupdesc = RelationGetDescr(rel); |
| 2145 | int attnum; |
| 2146 | int values_end_len; |
| 2147 | StringInfoData sql; |
| 2148 | List *targetAttrs = NIL; |
| 2149 | List *retrieved_attrs = NIL; |
| 2150 | bool doNothing = false; |
| 2151 | |
| 2152 | /* |
| 2153 | * If the foreign table we are about to insert routed rows into is also an |
| 2154 | * UPDATE subplan result rel that will be updated later, proceeding with |
| 2155 | * the INSERT will result in the later UPDATE incorrectly modifying those |
| 2156 | * routed rows, so prevent the INSERT --- it would be nice if we could |
| 2157 | * handle this case; but for now, throw an error for safety. |
| 2158 | */ |
| 2159 | if (plan && plan->operation == CMD_UPDATE && |
| 2160 | (resultRelInfo->ri_usesFdwDirectModify || |
| 2161 | resultRelInfo->ri_FdwState)) |
| 2162 | ereport(ERROR, |
| 2163 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 2164 | errmsg("cannot route tuples into foreign table to be updated \"%s\"", |
| 2165 | RelationGetRelationName(rel)))); |
| 2166 | |
| 2167 | initStringInfo(&sql); |
| 2168 | |
| 2169 | /* We transmit all columns that are defined in the foreign table. */ |
| 2170 | for (attnum = 1; attnum <= tupdesc->natts; attnum++) |
| 2171 | { |
| 2172 | Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1); |
| 2173 | |
| 2174 | if (!attr->attisdropped) |
| 2175 | targetAttrs = lappend_int(targetAttrs, attnum); |
| 2176 | } |
| 2177 | |
| 2178 | /* Check if we add the ON CONFLICT clause to the remote query. */ |
| 2179 | if (plan) |
| 2180 | { |
| 2181 | OnConflictAction onConflictAction = plan->onConflictAction; |
| 2182 | |
| 2183 | /* We only support DO NOTHING without an inference specification. */ |
| 2184 | if (onConflictAction == ONCONFLICT_NOTHING) |
| 2185 | doNothing = true; |
| 2186 | else if (onConflictAction != ONCONFLICT_NONE) |
| 2187 | elog(ERROR, "unexpected ON CONFLICT specification: %d", |
| 2188 | (int) onConflictAction); |
| 2189 | } |
| 2190 | |
| 2191 | /* |
nothing calls this directly
no test coverage detected