Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix trigger failure with FK reference on table variables/temp tables #522

71 changes: 35 additions & 36 deletions src/backend/utils/adt/ri_triggers.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "utils/ruleutils.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/guc_hooks.h"

/*
* Local definitions
Expand Down Expand Up @@ -95,29 +96,27 @@
#define RUN_AS_PSQL(qplan) \
do \
{ \
bool reset_dialect = (sql_dialect == SQL_DIALECT_TSQL); \
if (reset_dialect) \
set_config_option("babelfishpg_tsql.sql_dialect", "postgres", \
GUC_CONTEXT_CONFIG, \
PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); \
\
PG_TRY(); \
if (sql_dialect == SQL_DIALECT_TSQL) \
{ \
qplan; \
int sql_dialect_old = sql_dialect; \
void *newextra = NULL; \
sql_dialect = SQL_DIALECT_PG; \
roshan0708 marked this conversation as resolved.
Show resolved Hide resolved
assign_sql_dialect(sql_dialect, newextra); \
PG_TRY(); \
{ \
qplan; \
} \
PG_FINALLY(); \
{ \
sql_dialect = sql_dialect_old; \
assign_sql_dialect(sql_dialect, newextra); \
} \
PG_END_TRY(); \
} \
PG_CATCH(); \
else \
{ \
if (reset_dialect) \
set_config_option("babelfishpg_tsql.sql_dialect", "tsql", \
GUC_CONTEXT_CONFIG, \
PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); \
PG_RE_THROW(); \
roshan0708 marked this conversation as resolved.
Show resolved Hide resolved
qplan; \
} \
PG_END_TRY(); \
if (reset_dialect) \
set_config_option("babelfishpg_tsql.sql_dialect", "tsql", \
GUC_CONTEXT_CONFIG, \
PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); \
} while (0)


Expand Down Expand Up @@ -430,11 +429,11 @@ RI_FKey_check(TriggerData *trigdata)
* referenced side. The reason is that our snapshot must be fresh in
* order for the hack in find_inheritance_children() to work.
*/
ri_PerformCheck(riinfo, &qkey, qplan,
RUN_AS_PSQL(ri_PerformCheck(riinfo, &qkey, qplan,
roshan0708 marked this conversation as resolved.
Show resolved Hide resolved
fk_rel, pk_rel,
NULL, newslot,
pk_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE,
SPI_OK_SELECT);
SPI_OK_SELECT));

if (SPI_finish() != SPI_OK_FINISH)
elog(ERROR, "SPI_finish failed");
Expand Down Expand Up @@ -557,11 +556,11 @@ ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel,
/*
* We have a plan now. Run it.
*/
result = ri_PerformCheck(riinfo, &qkey, qplan,
RUN_AS_PSQL(result = ri_PerformCheck(riinfo, &qkey, qplan,
fk_rel, pk_rel,
oldslot, NULL,
true, /* treat like update */
SPI_OK_SELECT);
SPI_OK_SELECT));

if (SPI_finish() != SPI_OK_FINISH)
elog(ERROR, "SPI_finish failed");
Expand Down Expand Up @@ -749,11 +748,11 @@ ri_restrict(TriggerData *trigdata, bool is_no_action)
/*
* We have a plan now. Run it to check for existing references.
*/
ri_PerformCheck(riinfo, &qkey, qplan,
RUN_AS_PSQL(ri_PerformCheck(riinfo, &qkey, qplan,
roshan0708 marked this conversation as resolved.
Show resolved Hide resolved
fk_rel, pk_rel,
oldslot, NULL,
true, /* must detect new rows */
SPI_OK_SELECT);
SPI_OK_SELECT));

if (SPI_finish() != SPI_OK_FINISH)
elog(ERROR, "SPI_finish failed");
Expand Down Expand Up @@ -855,11 +854,11 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
* We have a plan now. Build up the arguments from the key values in the
* deleted PK tuple and delete the referencing rows
*/
ri_PerformCheck(riinfo, &qkey, qplan,
RUN_AS_PSQL(ri_PerformCheck(riinfo, &qkey, qplan,
roshan0708 marked this conversation as resolved.
Show resolved Hide resolved
fk_rel, pk_rel,
oldslot, NULL,
true, /* must detect new rows */
SPI_OK_DELETE);
SPI_OK_DELETE));

if (SPI_finish() != SPI_OK_FINISH)
elog(ERROR, "SPI_finish failed");
Expand Down Expand Up @@ -976,11 +975,11 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
/*
* We have a plan now. Run it to update the existing references.
*/
ri_PerformCheck(riinfo, &qkey, qplan,
RUN_AS_PSQL(ri_PerformCheck(riinfo, &qkey, qplan,
roshan0708 marked this conversation as resolved.
Show resolved Hide resolved
fk_rel, pk_rel,
oldslot, newslot,
true, /* must detect new rows */
SPI_OK_UPDATE);
SPI_OK_UPDATE));

if (SPI_finish() != SPI_OK_FINISH)
elog(ERROR, "SPI_finish failed");
Expand Down Expand Up @@ -1208,11 +1207,11 @@ ri_set(TriggerData *trigdata, bool is_set_null, int tgkind)
/*
* We have a plan now. Run it to update the existing references.
*/
ri_PerformCheck(riinfo, &qkey, qplan,
RUN_AS_PSQL(ri_PerformCheck(riinfo, &qkey, qplan,
roshan0708 marked this conversation as resolved.
Show resolved Hide resolved
fk_rel, pk_rel,
oldslot, NULL,
true, /* must detect new rows */
SPI_OK_UPDATE);
SPI_OK_UPDATE));

if (SPI_finish() != SPI_OK_FINISH)
elog(ERROR, "SPI_finish failed");
Expand Down Expand Up @@ -1597,11 +1596,11 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
* register the snapshot, because SPI_execute_snapshot will see to it. We
* need at most one tuple returned, so pass limit = 1.
*/
spi_result = SPI_execute_snapshot(qplan,
RUN_AS_PSQL(spi_result = SPI_execute_snapshot(qplan,
roshan0708 marked this conversation as resolved.
Show resolved Hide resolved
NULL, NULL,
GetLatestSnapshot(),
InvalidSnapshot,
true, false, 1);
true, false, 1));

/* Check result */
if (spi_result != SPI_OK_SELECT)
Expand Down Expand Up @@ -1824,7 +1823,7 @@ RI_PartitionRemove_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
* Generate the plan. We don't need to cache it, and there are no
* arguments to the plan.
*/
qplan = SPI_prepare(querybuf.data, 0, NULL);
RUN_AS_PSQL(qplan = SPI_prepare(querybuf.data, 0, NULL));

if (qplan == NULL)
elog(ERROR, "SPI_prepare returned %s for %s",
Expand All @@ -1837,11 +1836,11 @@ RI_PartitionRemove_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel)
* register the snapshot, because SPI_execute_snapshot will see to it. We
* need at most one tuple returned, so pass limit = 1.
*/
spi_result = SPI_execute_snapshot(qplan,
RUN_AS_PSQL(spi_result = SPI_execute_snapshot(qplan,
NULL, NULL,
GetLatestSnapshot(),
InvalidSnapshot,
true, false, 1);
true, false, 1));

/* Check result */
if (spi_result != SPI_OK_SELECT)
Expand Down