@@ -391,6 +391,11 @@ static PgFdwModifyState *create_foreign_modify(EState *estate,
391
391
List * target_attrs ,
392
392
bool has_returning ,
393
393
List * retrieved_attrs );
394
+ static TupleTableSlot * execute_foreign_modify (EState * estate ,
395
+ ResultRelInfo * resultRelInfo ,
396
+ CmdType operation ,
397
+ TupleTableSlot * slot ,
398
+ TupleTableSlot * planSlot );
394
399
static void prepare_foreign_modify (PgFdwModifyState * fmstate );
395
400
static const char * * convert_prep_stmt_params (PgFdwModifyState * fmstate ,
396
401
ItemPointer tupleid ,
@@ -1776,58 +1781,8 @@ postgresExecForeignInsert(EState *estate,
1776
1781
TupleTableSlot * slot ,
1777
1782
TupleTableSlot * planSlot )
1778
1783
{
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 );
1831
1786
}
1832
1787
1833
1788
/*
@@ -1840,70 +1795,8 @@ postgresExecForeignUpdate(EState *estate,
1840
1795
TupleTableSlot * slot ,
1841
1796
TupleTableSlot * planSlot )
1842
1797
{
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 );
1907
1800
}
1908
1801
1909
1802
/*
@@ -1916,70 +1809,8 @@ postgresExecForeignDelete(EState *estate,
1916
1809
TupleTableSlot * slot ,
1917
1810
TupleTableSlot * planSlot )
1918
1811
{
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 );
1983
1814
}
1984
1815
1985
1816
/*
@@ -3425,6 +3256,98 @@ create_foreign_modify(EState *estate,
3425
3256
return fmstate ;
3426
3257
}
3427
3258
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
+
3428
3351
/*
3429
3352
* prepare_foreign_modify
3430
3353
* Establish a prepared statement for execution of INSERT/UPDATE/DELETE
0 commit comments