diff --git a/createas.c b/createas.c index 338650d..10a09c0 100644 --- a/createas.c +++ b/createas.c @@ -62,8 +62,8 @@ typedef struct } DR_intorel; /* utility functions for IMMV definition creation */ -static ObjectAddress create_immv_internal(List *attrList, IntoClause *into); -static ObjectAddress create_immv_nodata(List *tlist, IntoClause *into); +static ImmvAddress create_immv_internal(List *attrList, IntoClause *into); +static ImmvAddress create_immv_nodata(List *tlist, IntoClause *into); typedef struct { @@ -74,15 +74,15 @@ typedef struct int sublevels_up; /* (current) nesting depth */ } check_ivm_restriction_context; -static void CreateIvmTriggersOnBaseTablesRecurse(Query *qry, Node *node, Oid matviewOid, +static void CreateIvmTriggersOnBaseTablesRecurse(Query *qry, Node *node, ImmvAddress immv_addr, Relids *relids, bool ex_lock); -static void CreateIvmTrigger(Oid relOid, Oid viewOid, int16 type, int16 timing, bool ex_lock); +static void CreateIvmTrigger(Oid relOid, ImmvAddress immv_addr, int16 type, int16 timing, bool ex_lock); static void check_ivm_restriction(Node *node); static bool check_ivm_restriction_walker(Node *node, check_ivm_restriction_context *context); static Bitmapset *get_primary_key_attnos_from_query(Query *query, List **constraintList); static bool check_aggregate_supports_ivm(Oid aggfnoid); -static void StoreImmvQuery(Oid viewOid, Query *viewQuery); +static void StoreImmvQuery(ImmvAddress immv_addr, Query *viewQuery); #if defined(PG_VERSION_NUM) && (PG_VERSION_NUM < 140000) static bool CreateTableAsRelExists(CreateTableAsStmt *ctas); @@ -96,14 +96,15 @@ static bool CreateTableAsRelExists(CreateTableAsStmt *ctas); * * This imitates PostgreSQL's create_ctas_internal(). */ -static ObjectAddress +static ImmvAddress create_immv_internal(List *attrList, IntoClause *into) { CreateStmt *create = makeNode(CreateStmt); char relkind; Datum toast_options; static char *validnsps[] = HEAP_RELOPT_NAMESPACES; - ObjectAddress intoRelationAddr; + ImmvAddress immv_addr; + pg_uuid_t *immv_uuid; /* This code supports both CREATE TABLE AS and CREATE MATERIALIZED VIEW */ /* relkind of IMMV must be RELKIND_RELATION */ @@ -128,7 +129,12 @@ create_immv_internal(List *attrList, IntoClause *into) * Create the relation. (This will error out if there's an existing view, * so we don't need more code to complain if "replace" is false.) */ - intoRelationAddr = DefineRelation(create, relkind, InvalidOid, NULL, NULL); + immv_addr.address = DefineRelation(create, relkind, InvalidOid, NULL, NULL); + /* Generate the IMMV UUID. */ + // TODO: check for hash collision + immv_uuid = DatumGetUUIDP(DirectFunctionCall1(gen_random_uuid, (Datum) NULL)); + memcpy(&immv_addr.immv_uuid, immv_uuid, sizeof(*immv_uuid)); + pfree(immv_uuid); /* * If necessary, create a TOAST table for the target table. Note that @@ -146,13 +152,13 @@ create_immv_internal(List *attrList, IntoClause *into) (void) heap_reloptions(RELKIND_TOASTVALUE, toast_options, true); - NewRelationCreateToastTable(intoRelationAddr.objectId, toast_options); + NewRelationCreateToastTable(immv_addr.address.objectId, toast_options); /* Create the "view" part of an IMMV. */ - StoreImmvQuery(intoRelationAddr.objectId, (Query *) into->viewQuery); + StoreImmvQuery(immv_addr, (Query *) into->viewQuery); CommandCounterIncrement(); - return intoRelationAddr; + return immv_addr; } /* @@ -163,7 +169,7 @@ create_immv_internal(List *attrList, IntoClause *into) * * This imitates PostgreSQL's create_ctas_nodata(). */ -static ObjectAddress +static ImmvAddress create_immv_nodata(List *tlist, IntoClause *into) { List *attrList; @@ -240,7 +246,7 @@ ExecCreateImmv(ParseState *pstate, CreateTableAsStmt *stmt, Query *query = castNode(Query, stmt->query); IntoClause *into = stmt->into; bool do_refresh = false; - ObjectAddress address; + ImmvAddress immv_addr; /* Check if the relation exists or not */ if (CreateTableAsRelExists(stmt)) @@ -275,7 +281,7 @@ ExecCreateImmv(ParseState *pstate, CreateTableAsStmt *stmt, * similar to CREATE VIEW. This avoids dump/restore problems stemming * from running the planner before all dependencies are set up. */ - address = create_immv_nodata(query->targetList, into); + immv_addr = create_immv_nodata(query->targetList, into); /* * For materialized views, reuse the REFRESH logic, which locks down @@ -286,18 +292,18 @@ ExecCreateImmv(ParseState *pstate, CreateTableAsStmt *stmt, { Relation matviewRel; - RefreshImmvByOid(address.objectId, true, false, pstate->p_sourcetext, qc); + RefreshImmvByOid(immv_addr, true, false, pstate->p_sourcetext, qc); if (qc) qc->commandTag = CMDTAG_SELECT; - matviewRel = table_open(address.objectId, NoLock); + matviewRel = table_open(immv_addr.address.objectId, NoLock); /* Create an index on incremental maintainable materialized view, if possible */ CreateIndexOnIMMV(query, matviewRel); /* Create triggers to prevent IMMV from being changed */ - CreateChangePreventTrigger(address.objectId); + CreateChangePreventTrigger(immv_addr.address.objectId); table_close(matviewRel, NoLock); @@ -309,7 +315,7 @@ ExecCreateImmv(ParseState *pstate, CreateTableAsStmt *stmt, "or execute refresh_immv to make sure the view is consistent."))); } - return address; + return immv_addr.address; } /* @@ -548,7 +554,7 @@ makeIvmAggColumn(ParseState *pstate, Aggref *aggref, char *resname, AttrNumber * * CreateIvmTriggersOnBaseTables -- create IVM triggers on all base tables */ void -CreateIvmTriggersOnBaseTables(Query *qry, Oid matviewOid) +CreateIvmTriggersOnBaseTables(Query *qry, ImmvAddress immv_addr) { Relids relids = NULL; bool ex_lock = false; @@ -582,13 +588,13 @@ CreateIvmTriggersOnBaseTables(Query *qry, Oid matviewOid) qry->distinctClause || (qry->hasAggs && qry->groupClause)) ex_lock = true; - CreateIvmTriggersOnBaseTablesRecurse(qry, (Node *)qry, matviewOid, &relids, ex_lock); + CreateIvmTriggersOnBaseTablesRecurse(qry, (Node *)qry, immv_addr, &relids, ex_lock); bms_free(relids); } static void -CreateIvmTriggersOnBaseTablesRecurse(Query *qry, Node *node, Oid matviewOid, +CreateIvmTriggersOnBaseTablesRecurse(Query *qry, Node *node, ImmvAddress immv_addr, Relids *relids, bool ex_lock) { if (node == NULL) @@ -604,12 +610,12 @@ CreateIvmTriggersOnBaseTablesRecurse(Query *qry, Node *node, Oid matviewOid, Query *query = (Query *) node; ListCell *lc; - CreateIvmTriggersOnBaseTablesRecurse(qry, (Node *) query->jointree, matviewOid, relids, ex_lock); + CreateIvmTriggersOnBaseTablesRecurse(qry, (Node *) query->jointree, immv_addr, relids, ex_lock); foreach(lc, query->cteList) { CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc); Assert(IsA(cte->ctequery, Query)); - CreateIvmTriggersOnBaseTablesRecurse((Query *) cte->ctequery, cte->ctequery, matviewOid, relids, ex_lock); + CreateIvmTriggersOnBaseTablesRecurse((Query *) cte->ctequery, cte->ctequery, immv_addr, relids, ex_lock); } } break; @@ -621,14 +627,14 @@ CreateIvmTriggersOnBaseTablesRecurse(Query *qry, Node *node, Oid matviewOid, if (rte->rtekind == RTE_RELATION && !bms_is_member(rte->relid, *relids)) { - CreateIvmTrigger(rte->relid, matviewOid, TRIGGER_TYPE_INSERT, TRIGGER_TYPE_BEFORE, ex_lock); - CreateIvmTrigger(rte->relid, matviewOid, TRIGGER_TYPE_DELETE, TRIGGER_TYPE_BEFORE, ex_lock); - CreateIvmTrigger(rte->relid, matviewOid, TRIGGER_TYPE_UPDATE, TRIGGER_TYPE_BEFORE, ex_lock); - CreateIvmTrigger(rte->relid, matviewOid, TRIGGER_TYPE_TRUNCATE, TRIGGER_TYPE_BEFORE, true); - CreateIvmTrigger(rte->relid, matviewOid, TRIGGER_TYPE_INSERT, TRIGGER_TYPE_AFTER, ex_lock); - CreateIvmTrigger(rte->relid, matviewOid, TRIGGER_TYPE_DELETE, TRIGGER_TYPE_AFTER, ex_lock); - CreateIvmTrigger(rte->relid, matviewOid, TRIGGER_TYPE_UPDATE, TRIGGER_TYPE_AFTER, ex_lock); - CreateIvmTrigger(rte->relid, matviewOid, TRIGGER_TYPE_TRUNCATE, TRIGGER_TYPE_AFTER, true); + CreateIvmTrigger(rte->relid, immv_addr, TRIGGER_TYPE_INSERT, TRIGGER_TYPE_BEFORE, ex_lock); + CreateIvmTrigger(rte->relid, immv_addr, TRIGGER_TYPE_DELETE, TRIGGER_TYPE_BEFORE, ex_lock); + CreateIvmTrigger(rte->relid, immv_addr, TRIGGER_TYPE_UPDATE, TRIGGER_TYPE_BEFORE, ex_lock); + CreateIvmTrigger(rte->relid, immv_addr, TRIGGER_TYPE_TRUNCATE, TRIGGER_TYPE_BEFORE, true); + CreateIvmTrigger(rte->relid, immv_addr, TRIGGER_TYPE_INSERT, TRIGGER_TYPE_AFTER, ex_lock); + CreateIvmTrigger(rte->relid, immv_addr, TRIGGER_TYPE_DELETE, TRIGGER_TYPE_AFTER, ex_lock); + CreateIvmTrigger(rte->relid, immv_addr, TRIGGER_TYPE_UPDATE, TRIGGER_TYPE_AFTER, ex_lock); + CreateIvmTrigger(rte->relid, immv_addr, TRIGGER_TYPE_TRUNCATE, TRIGGER_TYPE_AFTER, true); *relids = bms_add_member(*relids, rte->relid); } @@ -636,7 +642,7 @@ CreateIvmTriggersOnBaseTablesRecurse(Query *qry, Node *node, Oid matviewOid, { Query *subquery = rte->subquery; Assert(rte->subquery != NULL); - CreateIvmTriggersOnBaseTablesRecurse(subquery, (Node *) subquery, matviewOid, relids, ex_lock); + CreateIvmTriggersOnBaseTablesRecurse(subquery, (Node *) subquery, immv_addr, relids, ex_lock); } } break; @@ -647,7 +653,7 @@ CreateIvmTriggersOnBaseTablesRecurse(Query *qry, Node *node, Oid matviewOid, ListCell *l; foreach(l, f->fromlist) - CreateIvmTriggersOnBaseTablesRecurse(qry, lfirst(l), matviewOid, relids, ex_lock); + CreateIvmTriggersOnBaseTablesRecurse(qry, lfirst(l), immv_addr, relids, ex_lock); } break; @@ -655,8 +661,8 @@ CreateIvmTriggersOnBaseTablesRecurse(Query *qry, Node *node, Oid matviewOid, { JoinExpr *j = (JoinExpr *) node; - CreateIvmTriggersOnBaseTablesRecurse(qry, j->larg, matviewOid, relids, ex_lock); - CreateIvmTriggersOnBaseTablesRecurse(qry, j->rarg, matviewOid, relids, ex_lock); + CreateIvmTriggersOnBaseTablesRecurse(qry, j->larg, immv_addr, relids, ex_lock); + CreateIvmTriggersOnBaseTablesRecurse(qry, j->rarg, immv_addr, relids, ex_lock); } break; @@ -669,7 +675,7 @@ CreateIvmTriggersOnBaseTablesRecurse(Query *qry, Node *node, Oid matviewOid, * CreateIvmTrigger -- create IVM trigger on a base table */ static void -CreateIvmTrigger(Oid relOid, Oid viewOid, int16 type, int16 timing, bool ex_lock) +CreateIvmTrigger(Oid relOid, ImmvAddress immv_addr, int16 type, int16 timing, bool ex_lock) { ObjectAddress refaddr; ObjectAddress address; @@ -679,7 +685,7 @@ CreateIvmTrigger(Oid relOid, Oid viewOid, int16 type, int16 timing, bool ex_lock Assert(timing == TRIGGER_TYPE_BEFORE || timing == TRIGGER_TYPE_AFTER); refaddr.classId = RelationRelationId; - refaddr.objectId = viewOid; + refaddr.objectId = immv_addr.address.objectId; refaddr.objectSubId = 0; ivm_trigger = makeNode(CreateTrigStmt); @@ -753,7 +759,7 @@ CreateIvmTrigger(Oid relOid, Oid viewOid, int16 type, int16 timing, bool ex_lock ivm_trigger->initdeferred = false; ivm_trigger->constrrel = NULL; ivm_trigger->args = list_make2( - makeString(DatumGetPointer(DirectFunctionCall1(oidout, ObjectIdGetDatum(viewOid)))), + makeString(DatumGetPointer(UUIDPGetDatum(&immv_addr.immv_uuid))), makeString(DatumGetPointer(DirectFunctionCall1(boolout, BoolGetDatum(ex_lock)))) ); @@ -1708,7 +1714,7 @@ get_primary_key_attnos_from_query(Query *query, List **constraintList) * Store the query for the IMMV to pg_ivm_immv */ static void -StoreImmvQuery(Oid viewOid, Query *viewQuery) +StoreImmvQuery(ImmvAddress immv_addr, Query *viewQuery) { char *querytree = nodeToString((Node *) viewQuery); char *querystring; @@ -1736,10 +1742,11 @@ StoreImmvQuery(Oid viewOid, Query *viewQuery) memset(values, 0, sizeof(values)); memset(isNulls, false, sizeof(isNulls)); - values[Anum_pg_ivm_immv_immvrelid -1 ] = ObjectIdGetDatum(viewOid); + values[Anum_pg_ivm_immv_immvrelid -1 ] = ObjectIdGetDatum(immv_addr.address.objectId); values[Anum_pg_ivm_immv_ispopulated -1 ] = BoolGetDatum(false); values[Anum_pg_ivm_immv_viewdef -1 ] = CStringGetTextDatum(querytree); values[Anum_pg_ivm_immv_querystring - 1] = CStringGetTextDatum(querystring); + values[Anum_pg_ivm_immv_immvuuid -1 ] = UUIDPGetDatum(&immv_addr.immv_uuid); pgIvmImmv = table_open(PgIvmImmvRelationId(), RowExclusiveLock); @@ -1749,7 +1756,7 @@ StoreImmvQuery(Oid viewOid, Query *viewQuery) CatalogTupleInsert(pgIvmImmv, heapTuple); address.classId = RelationRelationId; - address.objectId = viewOid; + address.objectId = immv_addr.address.objectId; address.objectSubId = 0; recordDependencyOnExpr(&address, (Node *) viewQuery, NIL, diff --git a/matview.c b/matview.c index e6db540..b42001c 100644 --- a/matview.c +++ b/matview.c @@ -50,6 +50,7 @@ #include "utils/rel.h" #include "utils/snapmgr.h" #include "utils/typcache.h" +#include "utils/uuid.h" #include "utils/xid8.h" #include "pg_ivm.h" @@ -251,6 +252,7 @@ ExecRefreshImmv(const RangeVar *relation, bool skipData, { Oid matviewOid; LOCKMODE lockmode; + ImmvAddress immv_addr; /* Determine strength of lock needed. */ //concurrent = stmt->concurrent; @@ -272,7 +274,12 @@ ExecRefreshImmv(const RangeVar *relation, bool skipData, NULL); #endif - return RefreshImmvByOid(matviewOid, false, skipData, queryString, qc); + immv_addr.address.classId = RelationRelationId; + immv_addr.address.objectId = matviewOid; + immv_addr.address.objectSubId = 0; + + // TODO: get uuid + return RefreshImmvByOid(immv_addr, false, skipData, queryString, qc); } /* @@ -283,7 +290,7 @@ ExecRefreshImmv(const RangeVar *relation, bool skipData, * This imitates PostgreSQL's RefreshMatViewByOid(). */ ObjectAddress -RefreshImmvByOid(Oid matviewOid, bool is_create, bool skipData, +RefreshImmvByOid(ImmvAddress immv_addr, bool is_create, bool skipData, const char *queryString, QueryCompletion *qc) { Relation matviewRel; @@ -300,6 +307,7 @@ RefreshImmvByOid(Oid matviewOid, bool is_create, bool skipData, int save_nestlevel; ObjectAddress address; bool oldPopulated; + Oid matviewOid = immv_addr.address.objectId; Relation pgIvmImmv; TupleDesc tupdesc; @@ -486,10 +494,7 @@ RefreshImmvByOid(Oid matviewOid, bool is_create, bool skipData, * is created. */ if (!skipData && !oldPopulated) - { - CreateIvmTriggersOnBaseTables(dataQuery, matviewOid); - CreateChangePreventTrigger(matviewOid); - } + CreateIvmTriggersOnBaseTables(dataQuery, immv_addr); /* * Create the transient table that will receive the regenerated data. Lock @@ -844,15 +849,17 @@ Datum IVM_immediate_before(PG_FUNCTION_ARGS) { TriggerData *trigdata = (TriggerData *) fcinfo->context; - char *matviewOid_text = trigdata->tg_trigger->tgargs[0]; + char *immv_uuid_text = trigdata->tg_trigger->tgargs[0]; char *ex_lock_text = trigdata->tg_trigger->tgargs[1]; + pg_uuid_t *immv_uuid; Oid matviewOid; MV_TriggerHashEntry *entry; bool found; bool ex_lock; - matviewOid = DatumGetObjectId(DirectFunctionCall1(oidin, CStringGetDatum(matviewOid_text))); + immv_uuid = DatumGetUUIDP(CStringGetDatum(immv_uuid_text)); ex_lock = DatumGetBool(DirectFunctionCall1(boolin, CStringGetDatum(ex_lock_text))); + matviewOid = GetImmvRelid(immv_uuid); /* If the view has more than one tables, we have to use an exclusive lock. */ if (ex_lock) @@ -967,10 +974,11 @@ IVM_immediate_maintenance(PG_FUNCTION_ARGS) Oid matviewOid; Query *query; Query *rewritten = NULL; - char *matviewOid_text = trigdata->tg_trigger->tgargs[0]; + char *immv_uuid_text = trigdata->tg_trigger->tgargs[0]; Relation matviewRel; int old_depth = immv_maintenance_depth; SubTransactionId subxid; + pg_uuid_t *immv_uuid; Oid relowner; Tuplestorestate *old_tuplestore = NULL; @@ -998,7 +1006,8 @@ IVM_immediate_maintenance(PG_FUNCTION_ARGS) rel = trigdata->tg_relation; relid = rel->rd_id; - matviewOid = DatumGetObjectId(DirectFunctionCall1(oidin, CStringGetDatum(matviewOid_text))); + immv_uuid = DatumGetUUIDP(CStringGetDatum(immv_uuid_text)); + matviewOid = GetImmvRelid(immv_uuid); /* * On the first call initialize the hashtable diff --git a/pg_ivm--1.10--1.11.sql b/pg_ivm--1.10--1.11.sql index c5aeaca..1e718de 100644 --- a/pg_ivm--1.10--1.11.sql +++ b/pg_ivm--1.10--1.11.sql @@ -1,4 +1,6 @@ ALTER TABLE pgivm.pg_ivm_immv ADD COLUMN querystring text NOT NULL; +ALTER TABLE pgivm.pg_ivm_immv ADD COLUMN immvuuid uuid NOT NULL; +ALTER TABLE pgivm.pg_ivm_immv ADD CONSTRAINT pg_ivm_immv_uuid UNIQUE (immvuuid); CREATE FUNCTION pgivm.recreate_all_immvs() RETURNS VOID LANGUAGE PLPGSQL AS $$ diff --git a/pg_ivm.c b/pg_ivm.c index a005e07..6b8e1d4 100644 --- a/pg_ivm.c +++ b/pg_ivm.c @@ -32,6 +32,7 @@ #include "utils/lsyscache.h" #include "utils/regproc.h" #include "utils/rel.h" +#include "utils/uuid.h" #include "utils/varlena.h" #include "pg_ivm.h" @@ -365,6 +366,17 @@ PgIvmImmvPrimaryKeyIndexId(void) AccessShareLock, true); } +/* + * Get relid of pg_ivm_immv's UUID unique key. + */ +Oid +PgIvmImmvUuidIndexId(void) +{ + return RangeVarGetRelid( + makeRangeVar("pgivm", "pg_ivm_immv_uuid", -1), + AccessShareLock, true); +} + /* * Return the SELECT part of an IMMV */ @@ -488,3 +500,77 @@ RestrictSearchPath(void) PGC_S_SESSION, GUC_ACTION_SAVE, true, 0, false); } #endif + +/* + * GetImmvOid + * + * Look up the immvrelid of an IMMV from its immv_uuid. + */ +Oid +GetImmvRelid(pg_uuid_t *immv_uuid) +{ + Datum datum; + HeapTuple tup; + Relation pgIvmImmv = table_open(PgIvmImmvRelationId(), AccessShareLock); + ScanKeyData key; + SysScanDesc scan; + TupleDesc tupdesc = RelationGetDescr(pgIvmImmv); + bool isnull; + + ScanKeyInit(&key, Anum_pg_ivm_immv_immvuuid, BTEqualStrategyNumber, + F_UUID_EQ, UUIDPGetDatum(immv_uuid)); + scan = systable_beginscan(pgIvmImmv, PgIvmImmvUuidIndexId(), true, NULL, 1, + &key); + tup = systable_getnext(scan); + + if (!HeapTupleIsValid(tup)) + { + systable_endscan(scan); + table_close(pgIvmImmv, NoLock); + return InvalidOid; + } + + datum = heap_getattr(tup, Anum_pg_ivm_immv_immvrelid, tupdesc, &isnull); + Assert(!isnull); + + systable_endscan(scan); + table_close(pgIvmImmv, NoLock); + return DatumGetObjectId(datum); +} + +/* + * GetImmvUuid + * + * Look up the immv_uuid of an IMMV from its immvrelid. + */ +pg_uuid_t * +GetImmvUuid(Oid immvrelid) +{ + Datum datum; + HeapTuple tup; + Relation pgIvmImmv = table_open(PgIvmImmvRelationId(), AccessShareLock); + ScanKeyData key; + SysScanDesc scan; + TupleDesc tupdesc = RelationGetDescr(pgIvmImmv); + bool isnull; + + ScanKeyInit(&key, Anum_pg_ivm_immv_immvrelid, BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(immvrelid)); + scan = systable_beginscan(pgIvmImmv, PgIvmImmvPrimaryKeyIndexId(), + true, NULL, 1, &key); + tup = systable_getnext(scan); + + if (!HeapTupleIsValid(tup)) + { + systable_endscan(scan); + table_close(pgIvmImmv, NoLock); + return NULL; + } + + datum = heap_getattr(tup, Anum_pg_ivm_immv_immvuuid, tupdesc, &isnull); + Assert(!isnull); + + systable_endscan(scan); + table_close(pgIvmImmv, NoLock); + return DatumGetUUIDP(datum); +} diff --git a/pg_ivm.h b/pg_ivm.h index c8b29c6..d8f80f9 100644 --- a/pg_ivm.h +++ b/pg_ivm.h @@ -19,30 +19,41 @@ #include "parser/parse_node.h" #include "tcop/dest.h" #include "utils/queryenvironment.h" +#include "utils/uuid.h" -#define Natts_pg_ivm_immv 5 +#define Natts_pg_ivm_immv 6 #define Anum_pg_ivm_immv_immvrelid 1 #define Anum_pg_ivm_immv_viewdef 2 #define Anum_pg_ivm_immv_ispopulated 3 #define Anum_pg_ivm_immv_lastivmupdate 4 #define Anum_pg_ivm_immv_querystring 5 +#define Anum_pg_ivm_immv_immvuuid 6 + +typedef struct ImmvAddress +{ + ObjectAddress address; + pg_uuid_t immv_uuid; +} ImmvAddress; /* pg_ivm.c */ extern void CreateChangePreventTrigger(Oid matviewOid); extern Oid PgIvmImmvRelationId(void); extern Oid PgIvmImmvPrimaryKeyIndexId(void); +extern Oid PgIvmImmvUuidIndexId(void); extern bool isImmv(Oid immv_oid); extern List *PgIvmFuncName(char *name); extern void parse_immv_query(const char *relname, const char *sql, Query **query_ret, ParseState **pstate_ret); +extern Oid GetImmvRelid(pg_uuid_t *immv_uuid); +extern pg_uuid_t *GetImmvUuid(Oid immvrelid); /* createas.c */ extern ObjectAddress ExecCreateImmv(ParseState *pstate, CreateTableAsStmt *stmt, QueryCompletion *qc); -extern void CreateIvmTriggersOnBaseTables(Query *qry, Oid matviewOid); +extern void CreateIvmTriggersOnBaseTables(Query *qry, ImmvAddress immv_addr); extern void CreateIndexOnIMMV(Query *query, Relation matviewRel); extern Query *rewriteQueryForIMMV(Query *query, List *colNames); extern void makeIvmAggColumn(ParseState *pstate, Aggref *aggref, char *resname, AttrNumber *next_resno, List **aggs); @@ -52,7 +63,7 @@ extern void makeIvmAggColumn(ParseState *pstate, Aggref *aggref, char *resname, extern Query *get_immv_query(Relation matviewRel); extern ObjectAddress ExecRefreshImmv(const RangeVar *relation, bool skipData, const char *queryString, QueryCompletion *qc); -extern ObjectAddress RefreshImmvByOid(Oid matviewOid, bool is_create, bool skipData, +extern ObjectAddress RefreshImmvByOid(ImmvAddress immv_addr, bool is_create, bool skipData, const char *queryString, QueryCompletion *qc); extern bool ImmvIncrementalMaintenanceIsEnabled(void); extern Datum IVM_immediate_before(PG_FUNCTION_ARGS);