diff --git a/matview.c b/matview.c index 66709b5..aa95b58 100644 --- a/matview.c +++ b/matview.c @@ -233,6 +233,7 @@ static void clean_up_IVM_hash_entry(MV_TriggerHashEntry *entry, bool is_abort, static void setLastUpdateXid(Oid immv_oid, FullTransactionId xid); static FullTransactionId getLastUpdateXid(Oid immv_oid); +static Query *recreate_immv_query(Relation matviewRel); /* SQL callable functions */ PG_FUNCTION_INFO_V1(IVM_immediate_before); @@ -388,7 +389,7 @@ RefreshImmvByOid(Oid matviewOid, bool is_create, bool skipData, systable_endscan(scan); table_close(pgIvmImmv, NoLock); - viewQuery = get_immv_query(matviewRel); + viewQuery = recreate_immv_query(matviewRel); /* For IMMV, we need to rewrite matview query */ if (!skipData) @@ -713,6 +714,83 @@ get_immv_query(Relation matviewRel) return query; } +/* + * recreate_immv_query + * + * Parse the querystring for this IMMV. Update the viewdef column in + * pg_ivm_immv and return the Query tree. + */ +static Query * +recreate_immv_query(Relation matviewRel) +{ + Relation pgIvmImmv = table_open(PgIvmImmvRelationId(), AccessShareLock); + TupleDesc tupdesc = RelationGetDescr(pgIvmImmv); + SysScanDesc scan; + ScanKeyData key; + HeapTuple tup; + bool isnull; + Datum datum; + Query *query = NULL; + IntoClause *into; + ParseState *pstate = NULL; + CreateTableAsStmt *stmt; + const char *querystring; + const char *relname; + const char *querytree; + + Datum values[Natts_pg_ivm_immv]; + bool nulls[Natts_pg_ivm_immv]; + bool replaces[Natts_pg_ivm_immv]; + HeapTuple newtup = NULL; + + ScanKeyInit(&key, + Anum_pg_ivm_immv_immvrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(matviewRel))); + 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_querystring, tupdesc, &isnull); + Assert(!isnull); + querystring = TextDatumGetCString(datum); + + relname = psprintf("%s.%s", + get_namespace_name(get_rel_namespace(matviewRel->rd_id)), + get_rel_name(matviewRel->rd_id)); + + parse_immv_query(relname, querystring, &query, &pstate); + stmt = castNode(CreateTableAsStmt, query->utilityStmt); + into = stmt->into; + + query = castNode(Query, stmt->query); + query = rewriteQueryForIMMV(query, into->colNames); + querytree = nodeToString((Node *) query); + + memset(values, 0, sizeof(values)); + memset(nulls, 0, sizeof(nulls)); + memset(replaces, 0, sizeof(replaces)); + values[Anum_pg_ivm_immv_viewdef - 1] = CStringGetTextDatum(querytree); + replaces[Anum_pg_ivm_immv_viewdef - 1] = true; + + newtup = heap_modify_tuple(tup, tupdesc, values, nulls, replaces); + CatalogTupleUpdate(pgIvmImmv, &newtup->t_self, newtup); + heap_freetuple(newtup); + + systable_endscan(scan); + table_close(pgIvmImmv, NoLock); + + return query; +} + static Tuplestorestate * tuplestore_copy(Tuplestorestate *tuplestore, Relation rel) { diff --git a/pg_ivm.c b/pg_ivm.c index fe5c9bb..a005e07 100644 --- a/pg_ivm.c +++ b/pg_ivm.c @@ -177,17 +177,39 @@ create_immv(PG_FUNCTION_ARGS) text *t_sql = PG_GETARG_TEXT_PP(1); char *relname = text_to_cstring(t_relname); char *sql = text_to_cstring(t_sql); + + Query *query = NULL; + QueryCompletion qc; + ParseState *pstate = NULL; + + parse_immv_query(relname, sql, &query, &pstate); + + ExecCreateImmv(pstate, (CreateTableAsStmt *) query->utilityStmt, &qc); + + PG_RETURN_INT64(qc.nprocessed); +} + +/* + * parse_immv_query + * + * Parse an IMMV definition query and return the Query tree and ParseState using + * the supplied pointers. + */ +void +parse_immv_query(const char *relname, const char *sql, Query **query_ret, + ParseState **pstate_ret) +{ List *parsetree_list; RawStmt *parsetree; - Query *query; - QueryCompletion qc; List *names = NIL; List *colNames = NIL; - ParseState *pstate = make_parsestate(NULL); CreateTableAsStmt *ctas; StringInfoData command_buf; + Query *query; + ParseState *pstate; + pstate = make_parsestate(NULL); parseNameAndColumns(relname, &names, &colNames); initStringInfo(&command_buf); @@ -230,9 +252,8 @@ create_immv(PG_FUNCTION_ARGS) query = transformStmt(pstate, (Node *)ctas); Assert(query->commandType == CMD_UTILITY && IsA(query->utilityStmt, CreateTableAsStmt)); - ExecCreateImmv(pstate, (CreateTableAsStmt *) query->utilityStmt, &qc); - - PG_RETURN_INT64(qc.nprocessed); + *query_ret = query; + *pstate_ret = pstate; } /* diff --git a/pg_ivm.h b/pg_ivm.h index e334141..04c83f0 100644 --- a/pg_ivm.h +++ b/pg_ivm.h @@ -35,6 +35,8 @@ extern Oid PgIvmImmvRelationId(void); extern Oid PgIvmImmvPrimaryKeyIndexId(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); /* createas.c */