Merge branch 'main' of https://github.com/sraoss/pg_ivm into main

This commit is contained in:
Yugo Nagata 2022-09-30 23:57:01 +09:00
commit 6eddcd2a63
3 changed files with 57 additions and 0 deletions

View file

@ -101,6 +101,12 @@ refresh_immv(immv_name text, with_data bool) RETURNS bigint
The with_data flag is corresponding to `WITH [NO] DATA` option of REFRESH MATERIALIZED VIEW` command. If with_data is true, the backing query is executed to provide the new data, and if the IMMV is unpopulated, triggers for maintaining the view are created. Also, a unique index is created for IMMV if it is possible and the view doesn't have that yet. If with_data is false, no new data is generated and the IMMV become unpopulated, and the triggers are dropped from the IMMV. Note that unpopulated IMMV is still scannable although the result is empty. This behaviour may be changed in future to raise an error when an unpopulated IMMV is scanned. The with_data flag is corresponding to `WITH [NO] DATA` option of REFRESH MATERIALIZED VIEW` command. If with_data is true, the backing query is executed to provide the new data, and if the IMMV is unpopulated, triggers for maintaining the view are created. Also, a unique index is created for IMMV if it is possible and the view doesn't have that yet. If with_data is false, no new data is generated and the IMMV become unpopulated, and the triggers are dropped from the IMMV. Note that unpopulated IMMV is still scannable although the result is empty. This behaviour may be changed in future to raise an error when an unpopulated IMMV is scanned.
#### get_immv_def
`get_immv_def` reconstructs the underlying SELECT command for an IMMV. (This is a decompiled reconstruction, not the original text of the command.)
```
get_immv_def(immv regclass) RETURNS text
```
### IMMV metadata catalog ### IMMV metadata catalog

View file

@ -11,3 +11,8 @@ RETURNS text
STRICT STRICT
AS 'MODULE_PATHNAME', 'get_immv_def' AS 'MODULE_PATHNAME', 'get_immv_def'
LANGUAGE C; LANGUAGE C;
-- event trigger
DROP EVENT TRIGGER pg_ivm_sql_drop_trigger;
DROP FUNCTION pg_ivm_sql_drop_trigger_func;

View file

@ -11,10 +11,13 @@
*/ */
#include "postgres.h" #include "postgres.h"
#include "access/genam.h"
#include "access/table.h" #include "access/table.h"
#include "access/xact.h" #include "access/xact.h"
#include "catalog/dependency.h" #include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h" #include "catalog/namespace.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_namespace_d.h" #include "catalog/pg_namespace_d.h"
#include "catalog/pg_trigger_d.h" #include "catalog/pg_trigger_d.h"
#include "commands/trigger.h" #include "commands/trigger.h"
@ -23,6 +26,7 @@
#include "parser/scansup.h" #include "parser/scansup.h"
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/regproc.h" #include "utils/regproc.h"
#include "utils/rel.h" #include "utils/rel.h"
@ -35,6 +39,8 @@ PG_MODULE_MAGIC;
static Oid pg_ivm_immv_id = InvalidOid; static Oid pg_ivm_immv_id = InvalidOid;
static Oid pg_ivm_immv_pkey_id = InvalidOid; static Oid pg_ivm_immv_pkey_id = InvalidOid;
static object_access_hook_type PrevObjectAccessHook = NULL;
void _PG_init(void); void _PG_init(void);
static void IvmXactCallback(XactEvent event, void *arg); static void IvmXactCallback(XactEvent event, void *arg);
@ -42,6 +48,9 @@ static void IvmSubXactCallback(SubXactEvent event, SubTransactionId mySubid,
SubTransactionId parentSubid, void *arg); SubTransactionId parentSubid, void *arg);
static void parseNameAndColumns(const char *string, List **names, List **colNames); static void parseNameAndColumns(const char *string, List **names, List **colNames);
static void PgIvmObjectAccessHook(ObjectAccessType access, Oid classId,
Oid objectId, int subId, void *arg);
/* SQL callable functions */ /* SQL callable functions */
PG_FUNCTION_INFO_V1(create_immv); PG_FUNCTION_INFO_V1(create_immv);
PG_FUNCTION_INFO_V1(refresh_immv); PG_FUNCTION_INFO_V1(refresh_immv);
@ -75,6 +84,9 @@ _PG_init(void)
{ {
RegisterXactCallback(IvmXactCallback, NULL); RegisterXactCallback(IvmXactCallback, NULL);
RegisterSubXactCallback(IvmSubXactCallback, NULL); RegisterSubXactCallback(IvmSubXactCallback, NULL);
PrevObjectAccessHook = object_access_hook;
object_access_hook = PgIvmObjectAccessHook;
} }
/* /*
@ -350,3 +362,37 @@ get_immv_def(PG_FUNCTION_ARGS)
table_close(matviewRel, NoLock); table_close(matviewRel, NoLock);
PG_RETURN_TEXT_P(cstring_to_text(querystring)); PG_RETURN_TEXT_P(cstring_to_text(querystring));
} }
/*
* object_access_hook function for dropping an IMMV
*/
static void
PgIvmObjectAccessHook(ObjectAccessType access, Oid classId,
Oid objectId, int subId, void *arg)
{
if (PrevObjectAccessHook)
PrevObjectAccessHook(access, classId, objectId, subId, arg);
if (access == OAT_DROP && classId == RelationRelationId && !OidIsValid(subId))
{
Relation pgIvmImmv = table_open(PgIvmImmvRelationId(), AccessShareLock);
SysScanDesc scan;
ScanKeyData key;
HeapTuple tup;
ScanKeyInit(&key,
Anum_pg_ivm_immv_immvrelid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(objectId));
scan = systable_beginscan(pgIvmImmv, PgIvmImmvPrimaryKeyIndexId(),
true, NULL, 1, &key);
tup = systable_getnext(scan);
if (HeapTupleIsValid(tup))
CatalogTupleDelete(pgIvmImmv, &tup->t_self);
systable_endscan(scan);
table_close(pgIvmImmv, NoLock);
}
}