我有一个PostgreSQL 9.0服务器,我在一些表上使用遗产,因此我必须通过这样的触发器来模拟外键:
CREATE OR REPLACE FUNCTION othertable_before_update_trigger() RETURNS trigger AS $BODY$ DECLARE sql VARCHAR; rows SMALLINT; BEGIN IF (NEW.parenttable_id IS DISTINCT FROM OLD.parenttable_id) THEN sql := 'SELECT id ' || 'FROM parentTable ' || 'WHERE id = ' || NEW.parenttable_id || ';'; BEGIN EXECUTE sql; GET DIAGNOSTICS rows = ROW_COUNT; EXCEPTION WHEN OTHERS THEN RAISE EXCEPTION 'Error when I try find in parentTable the id %. SQL: %. ERROR: %', NEW.parenttable_id,sql,SQLERRM; END; IF rows = 0 THEN RAISE EXCEPTION 'Not found a row in parentTable with id %. SQL: %.',NEW.parenttable_id,sql; END IF; END IF; RETURN NEW; END; $BODY$ LANGUAGE plpgsql;
但由于性能,我尝试在C代码中创建一个等效的触发器:
#include "postgres.h" #include "executor/spi.h" /* this is what you need to work with SPI */ #include "commands/trigger.h" /* ... and triggers */ #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif extern Datum othertable_before_update_trigger(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(othertable_before_update_trigger); Datum othertable_before_update_trigger(PG_FUNCTION_ARGS) { TriggerData *trigdata = (TriggerData *) fcinfo->context; TupleDesc tupdesc; HeapTuple rettuple; bool isnull; int ret, i; /* make sure it's called as a trigger at all */ if (!CALLED_AS_TRIGGER(fcinfo)) elog(ERROR, "othertable_before_update_trigger: not called by trigger manager"); /* tuple to return to executor */ if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) rettuple = trigdata->tg_newtuple; else rettuple = trigdata->tg_trigtuple; tupdesc = trigdata->tg_relation->rd_att; /* connect to SPI manager */ if ((ret = SPI_connect()) < 0) elog(ERROR, "othertable_before_update_trigger (fired %s): SPI_connect returned %d", "before", ret); [A] [B] return PointerGetDatum(rettuple); }
我需要填写以下代码:
我只能得到parenttable_id的旧值,但不能得到新值。 即使我尝试使用列名而不是其编号:
GetAttributeByName (rettuple->t_data, "parenttable_id", &isnull);
获取错误: 记录类型尚未注册
我找到了函数SPI_execute_with_args ,但我没有找到这个例子。
提前致谢。
这并没有让我感觉到这种触发器会从转移到C中受益。您可以利用pl / pgsql中的大量缓存计划,这可能比移动到C更有助于加快速度。 此外,这里有两个重要的性能红旗,这让我觉得值得一试。
首先,EXCEPTION块具有显着的性能成本。 你在这里所做的只是以更友好的方式报告例外情况。 如果性能问题,你最好只删除它。
第二个是您的EXECUTE,这意味着永远不会缓存查询计划。 你真的应该把它改成直接查询。
当你把它与C语言触发器导致崩溃或后端更糟糕的可能性结合起来时,我认为你将花费大量精力来重写触发器,以获得比通过在pl中重写它所获得的性能提升更少的性能。 / pgsql的。
以上就是c/c++开发分享C中的等效plpgsql触发器相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/550157.html