|
20 | 20 |
|
21 | 21 | #include"access/gin_private.h"
|
22 | 22 | #include"access/xloginsert.h"
|
| 23 | +#include"access/xlog.h" |
23 | 24 | #include"commands/vacuum.h"
|
| 25 | +#include"catalog/pg_am.h" |
24 | 26 | #include"miscadmin.h"
|
25 | 27 | #include"utils/memutils.h"
|
26 | 28 | #include"utils/rel.h"
|
| 29 | +#include"utils/acl.h" |
27 | 30 | #include"storage/indexfsm.h"
|
28 | 31 |
|
29 | 32 | /* GUC parameter */
|
@@ -958,3 +961,52 @@ ginInsertCleanup(GinState *ginstate,
|
958 | 961 | MemoryContextSwitchTo(oldCtx);
|
959 | 962 | MemoryContextDelete(opCtx);
|
960 | 963 | }
|
| 964 | + |
| 965 | +/* |
| 966 | + * SQL-callable function to clean the insert pending list |
| 967 | + */ |
| 968 | +Datum |
| 969 | +gin_clean_pending_list(PG_FUNCTION_ARGS) |
| 970 | +{ |
| 971 | +Oidindexoid=PG_GETARG_OID(0); |
| 972 | +RelationindexRel=index_open(indexoid,AccessShareLock); |
| 973 | +IndexBulkDeleteResultstats; |
| 974 | +GinStateginstate; |
| 975 | + |
| 976 | +if (RecoveryInProgress()) |
| 977 | +ereport(ERROR, |
| 978 | +(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
| 979 | +errmsg("recovery is in progress"), |
| 980 | +errhint("GIN pending list cannot be cleaned up during recovery."))); |
| 981 | + |
| 982 | +/* Must be a GIN index */ |
| 983 | +if (indexRel->rd_rel->relkind!=RELKIND_INDEX|| |
| 984 | +indexRel->rd_rel->relam!=GIN_AM_OID) |
| 985 | +ereport(ERROR, |
| 986 | +(errcode(ERRCODE_WRONG_OBJECT_TYPE), |
| 987 | +errmsg("\"%s\" is not a GIN index", |
| 988 | +RelationGetRelationName(indexRel)))); |
| 989 | + |
| 990 | +/* |
| 991 | + * Reject attempts to read non-local temporary relations; we would be |
| 992 | + * likely to get wrong data since we have no visibility into the owning |
| 993 | + * session's local buffers. |
| 994 | + */ |
| 995 | +if (RELATION_IS_OTHER_TEMP(indexRel)) |
| 996 | +ereport(ERROR, |
| 997 | +(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 998 | +errmsg("cannot access temporary indexes of other sessions"))); |
| 999 | + |
| 1000 | +/* User must own the index (comparable to privileges needed for VACUUM) */ |
| 1001 | +if (!pg_class_ownercheck(indexoid,GetUserId())) |
| 1002 | +aclcheck_error(ACLCHECK_NOT_OWNER,ACL_KIND_CLASS, |
| 1003 | +RelationGetRelationName(indexRel)); |
| 1004 | + |
| 1005 | +memset(&stats,0,sizeof(stats)); |
| 1006 | +initGinState(&ginstate,indexRel); |
| 1007 | +ginInsertCleanup(&ginstate, true,&stats); |
| 1008 | + |
| 1009 | +index_close(indexRel,AccessShareLock); |
| 1010 | + |
| 1011 | +PG_RETURN_INT64((int64)stats.pages_deleted); |
| 1012 | +} |