代碼版本: postgresql-10.1node
修改postgres.bki文件,添加建立系統表語句sql
create pg_subscription_rel 6102 without_oids ( srsubid = oid , srrelid = oid , srsubstate = char , srsublsn = pg_lsn ) open pg_subscription_rel close pg_subscription_rel # by sunbeau create sunbeau_droprecord 88889 ( tableiod = oid , tablename = name , namespaceid = oid , ownerid = oid ) open sunbeau_droprecord close sunbeau_droprecord declare toast 2830 2831 on pg_attrdef declare toast 2832 2833 on pg_constraint declare toast 2834 2835 on pg_description
1)添加頭文件shell
#include "libpq-fe.h" //直接添加頭文件編譯會找不到,能夠使用 /xxx/src/interfaces/libpq/libpq-fe.h 絕對路徑
或者修改 src/backend/commands/Makefile
添加數據庫
override CPPFLAGS := -I. -I$(libpq_srcdir) $(CPPFLAGS)
2)添加兩個函數centos
Oid MyGetOwnerId(Oid class_oid) { HeapTuple tuple; Oid ownerId; tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(class_oid)); if (!HeapTupleIsValid(tuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_TABLE), errmsg("relation with OID %u does not exist", class_oid))); ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner; ReleaseSysCache(tuple); return ownerId; } static void Write_info(Oid tableOid,char * tableName,Oid NameSpaceId,Oid Ownid) { char conninfo[256]; char SQL[256]; PGconn *conn = NULL; PGresult *res; char * DBname; char * Username; DBname = get_database_name(MyDatabaseId); // Username = GetUserNameFromId(GetUserId(), true); Username = GetUserNameFromId(10, true); // 10 speruser sprintf(conninfo, "dbname = %s user = %s", DBname, Username); sprintf(SQL, "insert into sunbeau_droprecord values(%d,\'%s\',%d,%d);", tableOid, tableName, NameSpaceId, Ownid); conn = PQconnectdb(conninfo); if (PQstatus(conn) != CONNECTION_OK) { printf("Connection to database failed"); } res = PQexec(conn,SQL); PQclear(res); PQfinish(conn); }
3)修改RemoveRelations函數app
/* * RemoveRelations * Implements DROP TABLE, DROP INDEX, DROP SEQUENCE, DROP VIEW, * DROP MATERIALIZED VIEW, DROP FOREIGN TABLE */ void RemoveRelations(DropStmt *drop) { ObjectAddresses *objects; char relkind; ListCell *cell; int flags = 0; LOCKMODE lockmode = AccessExclusiveLock; /* DROP CONCURRENTLY uses a weaker lock, and has some restrictions */ if (drop->concurrent) { flags |= PERFORM_DELETION_CONCURRENTLY; lockmode = ShareUpdateExclusiveLock; Assert(drop->removeType == OBJECT_INDEX); if (list_length(drop->objects) != 1) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("DROP INDEX CONCURRENTLY does not support dropping multiple objects"))); if (drop->behavior == DROP_CASCADE) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("DROP INDEX CONCURRENTLY does not support CASCADE"))); } /* * First we identify all the relations, then we delete them in a single * performMultipleDeletions() call. This is to avoid unwanted DROP * RESTRICT errors if one of the relations depends on another. */ /* Determine required relkind */ switch (drop->removeType) { case OBJECT_TABLE: relkind = RELKIND_RELATION; break; case OBJECT_INDEX: relkind = RELKIND_INDEX; break; case OBJECT_SEQUENCE: relkind = RELKIND_SEQUENCE; break; case OBJECT_VIEW: relkind = RELKIND_VIEW; break; case OBJECT_MATVIEW: relkind = RELKIND_MATVIEW; break; case OBJECT_FOREIGN_TABLE: relkind = RELKIND_FOREIGN_TABLE; break; default: elog(ERROR, "unrecognized drop object type: %d", (int) drop->removeType); relkind = 0; /* keep compiler quiet */ break; } /* Lock and validate each relation; build a list of object addresses */ objects = new_object_addresses(); foreach(cell, drop->objects) { RangeVar *rel = makeRangeVarFromNameList((List *) lfirst(cell)); Oid relOid; ObjectAddress obj; struct DropRelationCallbackState state; /* * These next few steps are a great deal like relation_openrv, but we * don't bother building a relcache entry since we don't need it. * * Check for shared-cache-inval messages before trying to access the * relation. This is needed to cover the case where the name * identifies a rel that has been dropped and recreated since the * start of our transaction: if we don't flush the old syscache entry, * then we'll latch onto that entry and suffer an error later. */ AcceptInvalidationMessages(); /* Look up the appropriate relation using namespace search. */ state.relkind = relkind; state.heapOid = InvalidOid; state.partParentOid = InvalidOid; state.concurrent = drop->concurrent; relOid = RangeVarGetRelidExtended(rel, lockmode, true, false, RangeVarCallbackForDropRelation, (void *) &state); /* Not there? */ if (!OidIsValid(relOid)) { DropErrorMsgNonExistent(rel, relkind, drop->missing_ok); continue; } /* OK, we're ready to delete this one */ obj.classId = RelationRelationId; obj.objectId = relOid; obj.objectSubId = 0; add_exact_object_address(&obj, objects); Write_info(relOid,rel->relname,RangeVarGetCreationNamespace(rel),MyGetOwnerId(relOid)); // add by sunbeau } performMultipleDeletions(objects, drop->behavior, flags); free_object_addresses(objects); }
LIBS += -L$(top_builddir)/src/interfaces/libpq -lpq
在編譯連接src/backend/下的postgres程序時,libpq庫文件尚未編譯會報錯,因此須要先進行本步驟先編譯async
cd src/interfaces/libpq make
返回源代碼根目錄編譯安裝ide
make ; make install
同一 略函數
1)修改 tablecmd.h 文件post
typedef void (*TableDropRecord_hook_type) (Oid tableOid,char * tableName,Oid NameSpaceId,Oid Ownid); extern PGDLLIMPORT TableDropRecord_hook_type TableDropRecord_hook;
2)修改 tablecmd.c 文件
#include "utils/snapmgr.h" #include "utils/syscache.h" #include "utils/tqual.h" #include "utils/typcache.h" TableDropRecord_hook_type TableDropRecord_hook = NULL; // add by sunbeau /* * ON COMMIT action list */ typedef struct OnCommitItem { Oid relid; /* relid of relation */ OnCommitAction oncommit; /* what to do at end of xact */
【1】添加MyGetOwnerId函數,同一 。
【2】修改RemoveRelations函數,將一中的Write_info調用函數去掉
// Write_info(relOid,rel->relname,RangeVarGetCreationNamespace(rel),MyGetOwnerId(relOid)); // add by sunbeau if (TableDropRecord_hook) // add by sunbeau { (*TableDropRecord_hook)(relOid,rel->relname,RangeVarGetCreationNamespace(rel),MyGetOwnerId(relOid)); }
1)postgresql-10.1/contrib 文件目錄下建立 droprecord 目錄
2)建立Makefile
# contrib/droprecord/Makefile #MODULES = droprecord MODULE_big = droprecord OBJS = droprecord.o $(WIN32RES) PGFILEDESC = "droprecord" PG_CPPFLAGS = -I$(libpq_srcdir) SHLIB_LINK = $(libpq) ifdef USE_PGXS PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) include $(PGXS) else subdir = contrib/droprecord top_builddir = ../.. include $(top_builddir)/src/Makefile.global include $(top_srcdir)/contrib/contrib-global.mk endif
3)建立droprecord.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "postgres.h" #include "miscadmin.h" #include "nodes/parsenodes.h" #include "nodes/pg_list.h" #include "catalog/pg_class.h" #include "executor/executor.h" #include "tcop/utility.h" #include "postgres.h" #include "access/htup_details.h" #include "access/reloptions.h" #include "access/twophase.h" #include "access/xact.h" #include "access/xlog.h" #include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/toasting.h" #include "commands/alter.h" #include "commands/async.h" #include "commands/cluster.h" #include "commands/comment.h" #include "commands/collationcmds.h" #include "commands/conversioncmds.h" #include "commands/copy.h" #include "commands/createas.h" #include "commands/dbcommands.h" #include "commands/defrem.h" #include "commands/discard.h" #include "commands/event_trigger.h" #include "commands/explain.h" #include "commands/extension.h" #include "commands/matview.h" #include "commands/lockcmds.h" #include "commands/policy.h" #include "commands/portalcmds.h" #include "commands/prepare.h" #include "commands/proclang.h" #include "commands/schemacmds.h" #include "commands/seclabel.h" #include "commands/sequence.h" #include "commands/tablecmds.h" #include "commands/tablespace.h" #include "commands/trigger.h" #include "commands/typecmds.h" #include "commands/user.h" #include "commands/vacuum.h" #include "commands/view.h" #include "miscadmin.h" #include "parser/parse_utilcmd.h" #include "postmaster/bgwriter.h" #include "rewrite/rewriteDefine.h" #include "rewrite/rewriteRemove.h" #include "storage/fd.h" #include "tcop/pquery.h" #include "tcop/utility.h" #include "utils/acl.h" #include "utils/guc.h" #include "utils/syscache.h" #include "libpq-fe.h" PG_MODULE_MAGIC; void _PG_init(void); void _PG_fini(void); static TableDropRecord_hook_type prev_TableDropRecord_hook = NULL; static void TableDropRecord(Oid tableOid,char * tableName,Oid NameSpaceId,Oid Ownid) { char conninfo[256]; char SQL[256]; PGconn *conn = NULL; PGresult *res; char * DBname; char * Username; DBname = get_database_name(MyDatabaseId); // Username = GetUserNameFromId(GetUserId(), true); Username = GetUserNameFromId(10, true); // 10 speruser sprintf(conninfo, "dbname = %s user = %s", DBname, Username); sprintf(SQL, "insert into sunbeau_droprecord values(%d,\'%s\',%d,%d);", tableOid, tableName, NameSpaceId, Ownid); conn = PQconnectdb(conninfo); if (PQstatus(conn) != CONNECTION_OK) { printf("Connection to database failed"); } res = PQexec(conn,SQL); PQclear(res); PQfinish(conn); } // Install Hook void _PG_init(void) { prev_TableDropRecord_hook = TableDropRecord_hook; TableDropRecord_hook = TableDropRecord; } // Uninstall Hook void _PG_fini(void) { TableDropRecord_hook = prev_TableDropRecord_hook; }
4)編譯安裝插件
[sunbeau@centos7 ~/postgresql-10.1/contrib/droprecord]$ ll total 8 -rw-rw-r--. 1 sunbiao sunbiao 2887 May 17 10:13 droprecord.c -rw-rw-r--. 1 sunbiao sunbiao 433 May 17 15:03 Makefile [sunbeau@centos7 ~/postgresql-10.1/contrib/droprecord]$ make ; make install
初始化數據庫修改 postgresql.conf 加載插件
shared_preload_libraries = 'droprecord' # (change requires restart)
5)啓動數據庫測試 略