Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6c61d7c

Browse files
author
Etsuro Fujita
committed
postgres_fdw: Remove duplicate code in DML execution callback functions.
postgresExecForeignInsert(), postgresExecForeignUpdate(), and postgresExecForeignDelete() are coded almost identically, except that postgresExecForeignInsert() does not need CTID. Extract that code into a separate function and use it in all the three function implementations. Author: Ashutosh Bapat Reviewed-By: Michael Paquier Discussion: https://postgr.es/m/CAFjFpRcz8yoY7cBTYofcrCLwjaDeCcGKyTUivUbRiA57y3v-bw%40mail.gmail.com
1 parent d723f56 commit 6c61d7c

File tree

1 file changed

+103
-180
lines changed

1 file changed

+103
-180
lines changed

contrib/postgres_fdw/postgres_fdw.c

Lines changed: 103 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -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);
394399
static void prepare_foreign_modify(PgFdwModifyState *fmstate);
395400
static 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

Comments
 (0)