@@ -391,6 +391,11 @@ static PgFdwModifyState *create_foreign_modify(EState *estate,
391391 List * target_attrs ,
392392 bool has_returning ,
393393 List * retrieved_attrs );
394+ static TupleTableSlot * execute_foreign_modify (EState * estate ,
395+ ResultRelInfo * resultRelInfo ,
396+ CmdType operation ,
397+ TupleTableSlot * slot ,
398+ TupleTableSlot * planSlot );
394399static void prepare_foreign_modify (PgFdwModifyState * fmstate );
395400static const char * * convert_prep_stmt_params (PgFdwModifyState * fmstate ,
396401 ItemPointer tupleid ,
@@ -1776,58 +1781,8 @@ postgresExecForeignInsert(EState *estate,
17761781 TupleTableSlot * slot ,
17771782 TupleTableSlot * planSlot )
17781783{
1779- PgFdwModifyState * fmstate = (PgFdwModifyState * ) resultRelInfo -> ri_FdwState ;
1780- const char * * p_values ;
1781- PGresult * res ;
1782- int n_rows ;
1783-
1784- /* Set up the prepared statement on the remote server, if we didn't yet */
1785- if (!fmstate -> p_name )
1786- prepare_foreign_modify (fmstate );
1787-
1788- /* Convert parameters needed by prepared statement to text form */
1789- p_values = convert_prep_stmt_params (fmstate , NULL , slot );
1790-
1791- /*
1792- * Execute the prepared statement.
1793- */
1794- if (!PQsendQueryPrepared (fmstate -> conn ,
1795- fmstate -> p_name ,
1796- fmstate -> p_nums ,
1797- p_values ,
1798- NULL ,
1799- NULL ,
1800- 0 ))
1801- pgfdw_report_error (ERROR , NULL , fmstate -> conn , false, fmstate -> query );
1802-
1803- /*
1804- * Get the result, and check for success.
1805- *
1806- * We don't use a PG_TRY block here, so be careful not to throw error
1807- * without releasing the PGresult.
1808- */
1809- res = pgfdw_get_result (fmstate -> conn , fmstate -> query );
1810- if (PQresultStatus (res ) !=
1811- (fmstate -> has_returning ? PGRES_TUPLES_OK : PGRES_COMMAND_OK ))
1812- pgfdw_report_error (ERROR , res , fmstate -> conn , true, fmstate -> query );
1813-
1814- /* Check number of rows affected, and fetch RETURNING tuple if any */
1815- if (fmstate -> has_returning )
1816- {
1817- n_rows = PQntuples (res );
1818- if (n_rows > 0 )
1819- store_returning_result (fmstate , slot , res );
1820- }
1821- else
1822- n_rows = atoi (PQcmdTuples (res ));
1823-
1824- /* And clean up */
1825- PQclear (res );
1826-
1827- MemoryContextReset (fmstate -> temp_cxt );
1828-
1829- /* Return NULL if nothing was inserted on the remote end */
1830- return (n_rows > 0 ) ? slot : NULL ;
1784+ return execute_foreign_modify (estate , resultRelInfo , CMD_INSERT ,
1785+ slot , planSlot );
18311786}
18321787
18331788/*
@@ -1840,70 +1795,8 @@ postgresExecForeignUpdate(EState *estate,
18401795 TupleTableSlot * slot ,
18411796 TupleTableSlot * planSlot )
18421797{
1843- PgFdwModifyState * fmstate = (PgFdwModifyState * ) resultRelInfo -> ri_FdwState ;
1844- Datum datum ;
1845- bool isNull ;
1846- const char * * p_values ;
1847- PGresult * res ;
1848- int n_rows ;
1849-
1850- /* Set up the prepared statement on the remote server, if we didn't yet */
1851- if (!fmstate -> p_name )
1852- prepare_foreign_modify (fmstate );
1853-
1854- /* Get the ctid that was passed up as a resjunk column */
1855- datum = ExecGetJunkAttribute (planSlot ,
1856- fmstate -> ctidAttno ,
1857- & isNull );
1858- /* shouldn't ever get a null result... */
1859- if (isNull )
1860- elog (ERROR , "ctid is NULL" );
1861-
1862- /* Convert parameters needed by prepared statement to text form */
1863- p_values = convert_prep_stmt_params (fmstate ,
1864- (ItemPointer ) DatumGetPointer (datum ),
1865- slot );
1866-
1867- /*
1868- * Execute the prepared statement.
1869- */
1870- if (!PQsendQueryPrepared (fmstate -> conn ,
1871- fmstate -> p_name ,
1872- fmstate -> p_nums ,
1873- p_values ,
1874- NULL ,
1875- NULL ,
1876- 0 ))
1877- pgfdw_report_error (ERROR , NULL , fmstate -> conn , false, fmstate -> query );
1878-
1879- /*
1880- * Get the result, and check for success.
1881- *
1882- * We don't use a PG_TRY block here, so be careful not to throw error
1883- * without releasing the PGresult.
1884- */
1885- res = pgfdw_get_result (fmstate -> conn , fmstate -> query );
1886- if (PQresultStatus (res ) !=
1887- (fmstate -> has_returning ? PGRES_TUPLES_OK : PGRES_COMMAND_OK ))
1888- pgfdw_report_error (ERROR , res , fmstate -> conn , true, fmstate -> query );
1889-
1890- /* Check number of rows affected, and fetch RETURNING tuple if any */
1891- if (fmstate -> has_returning )
1892- {
1893- n_rows = PQntuples (res );
1894- if (n_rows > 0 )
1895- store_returning_result (fmstate , slot , res );
1896- }
1897- else
1898- n_rows = atoi (PQcmdTuples (res ));
1899-
1900- /* And clean up */
1901- PQclear (res );
1902-
1903- MemoryContextReset (fmstate -> temp_cxt );
1904-
1905- /* Return NULL if nothing was updated on the remote end */
1906- return (n_rows > 0 ) ? slot : NULL ;
1798+ return execute_foreign_modify (estate , resultRelInfo , CMD_UPDATE ,
1799+ slot , planSlot );
19071800}
19081801
19091802/*
@@ -1916,70 +1809,8 @@ postgresExecForeignDelete(EState *estate,
19161809 TupleTableSlot * slot ,
19171810 TupleTableSlot * planSlot )
19181811{
1919- PgFdwModifyState * fmstate = (PgFdwModifyState * ) resultRelInfo -> ri_FdwState ;
1920- Datum datum ;
1921- bool isNull ;
1922- const char * * p_values ;
1923- PGresult * res ;
1924- int n_rows ;
1925-
1926- /* Set up the prepared statement on the remote server, if we didn't yet */
1927- if (!fmstate -> p_name )
1928- prepare_foreign_modify (fmstate );
1929-
1930- /* Get the ctid that was passed up as a resjunk column */
1931- datum = ExecGetJunkAttribute (planSlot ,
1932- fmstate -> ctidAttno ,
1933- & isNull );
1934- /* shouldn't ever get a null result... */
1935- if (isNull )
1936- elog (ERROR , "ctid is NULL" );
1937-
1938- /* Convert parameters needed by prepared statement to text form */
1939- p_values = convert_prep_stmt_params (fmstate ,
1940- (ItemPointer ) DatumGetPointer (datum ),
1941- NULL );
1942-
1943- /*
1944- * Execute the prepared statement.
1945- */
1946- if (!PQsendQueryPrepared (fmstate -> conn ,
1947- fmstate -> p_name ,
1948- fmstate -> p_nums ,
1949- p_values ,
1950- NULL ,
1951- NULL ,
1952- 0 ))
1953- pgfdw_report_error (ERROR , NULL , fmstate -> conn , false, fmstate -> query );
1954-
1955- /*
1956- * Get the result, and check for success.
1957- *
1958- * We don't use a PG_TRY block here, so be careful not to throw error
1959- * without releasing the PGresult.
1960- */
1961- res = pgfdw_get_result (fmstate -> conn , fmstate -> query );
1962- if (PQresultStatus (res ) !=
1963- (fmstate -> has_returning ? PGRES_TUPLES_OK : PGRES_COMMAND_OK ))
1964- pgfdw_report_error (ERROR , res , fmstate -> conn , true, fmstate -> query );
1965-
1966- /* Check number of rows affected, and fetch RETURNING tuple if any */
1967- if (fmstate -> has_returning )
1968- {
1969- n_rows = PQntuples (res );
1970- if (n_rows > 0 )
1971- store_returning_result (fmstate , slot , res );
1972- }
1973- else
1974- n_rows = atoi (PQcmdTuples (res ));
1975-
1976- /* And clean up */
1977- PQclear (res );
1978-
1979- MemoryContextReset (fmstate -> temp_cxt );
1980-
1981- /* Return NULL if nothing was deleted on the remote end */
1982- return (n_rows > 0 ) ? slot : NULL ;
1812+ return execute_foreign_modify (estate , resultRelInfo , CMD_DELETE ,
1813+ slot , planSlot );
19831814}
19841815
19851816/*
@@ -3425,6 +3256,98 @@ create_foreign_modify(EState *estate,
34253256 return fmstate ;
34263257}
34273258
3259+ /*
3260+ * execute_foreign_modify
3261+ * Perform foreign-table modification as required, and fetch RETURNING
3262+ * result if any. (This is the shared guts of postgresExecForeignInsert,
3263+ * postgresExecForeignUpdate, and postgresExecForeignDelete.)
3264+ */
3265+ static TupleTableSlot *
3266+ execute_foreign_modify (EState * estate ,
3267+ ResultRelInfo * resultRelInfo ,
3268+ CmdType operation ,
3269+ TupleTableSlot * slot ,
3270+ TupleTableSlot * planSlot )
3271+ {
3272+ PgFdwModifyState * fmstate = (PgFdwModifyState * ) resultRelInfo -> ri_FdwState ;
3273+ ItemPointer ctid = NULL ;
3274+ const char * * p_values ;
3275+ PGresult * res ;
3276+ int n_rows ;
3277+
3278+ /* The operation should be INSERT, UPDATE, or DELETE */
3279+ Assert (operation == CMD_INSERT ||
3280+ operation == CMD_UPDATE ||
3281+ operation == CMD_DELETE );
3282+
3283+ /* Set up the prepared statement on the remote server, if we didn't yet */
3284+ if (!fmstate -> p_name )
3285+ prepare_foreign_modify (fmstate );
3286+
3287+ /*
3288+ * For UPDATE/DELETE, get the ctid that was passed up as a resjunk column
3289+ */
3290+ if (operation == CMD_UPDATE || operation == CMD_DELETE )
3291+ {
3292+ Datum datum ;
3293+ bool isNull ;
3294+
3295+ datum = ExecGetJunkAttribute (planSlot ,
3296+ fmstate -> ctidAttno ,
3297+ & isNull );
3298+ /* shouldn't ever get a null result... */
3299+ if (isNull )
3300+ elog (ERROR , "ctid is NULL" );
3301+ ctid = (ItemPointer ) DatumGetPointer (datum );
3302+ }
3303+
3304+ /* Convert parameters needed by prepared statement to text form */
3305+ p_values = convert_prep_stmt_params (fmstate , ctid , slot );
3306+
3307+ /*
3308+ * Execute the prepared statement.
3309+ */
3310+ if (!PQsendQueryPrepared (fmstate -> conn ,
3311+ fmstate -> p_name ,
3312+ fmstate -> p_nums ,
3313+ p_values ,
3314+ NULL ,
3315+ NULL ,
3316+ 0 ))
3317+ pgfdw_report_error (ERROR , NULL , fmstate -> conn , false, fmstate -> query );
3318+
3319+ /*
3320+ * Get the result, and check for success.
3321+ *
3322+ * We don't use a PG_TRY block here, so be careful not to throw error
3323+ * without releasing the PGresult.
3324+ */
3325+ res = pgfdw_get_result (fmstate -> conn , fmstate -> query );
3326+ if (PQresultStatus (res ) !=
3327+ (fmstate -> has_returning ? PGRES_TUPLES_OK : PGRES_COMMAND_OK ))
3328+ pgfdw_report_error (ERROR , res , fmstate -> conn , true, fmstate -> query );
3329+
3330+ /* Check number of rows affected, and fetch RETURNING tuple if any */
3331+ if (fmstate -> has_returning )
3332+ {
3333+ n_rows = PQntuples (res );
3334+ if (n_rows > 0 )
3335+ store_returning_result (fmstate , slot , res );
3336+ }
3337+ else
3338+ n_rows = atoi (PQcmdTuples (res ));
3339+
3340+ /* And clean up */
3341+ PQclear (res );
3342+
3343+ MemoryContextReset (fmstate -> temp_cxt );
3344+
3345+ /*
3346+ * Return NULL if nothing was inserted/updated/deleted on the remote end
3347+ */
3348+ return (n_rows > 0 ) ? slot : NULL ;
3349+ }
3350+
34283351/*
34293352 * prepare_foreign_modify
34303353 * Establish a prepared statement for execution of INSERT/UPDATE/DELETE
0 commit comments