refresh_immv: reparse the query string
This commit is contained in:
parent
3524de96ac
commit
0a5bd500e6
3 changed files with 108 additions and 7 deletions
80
matview.c
80
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 void setLastUpdateXid(Oid immv_oid, FullTransactionId xid);
|
||||||
static FullTransactionId getLastUpdateXid(Oid immv_oid);
|
static FullTransactionId getLastUpdateXid(Oid immv_oid);
|
||||||
|
|
||||||
|
static Query *recreate_immv_query(Relation matviewRel);
|
||||||
|
|
||||||
/* SQL callable functions */
|
/* SQL callable functions */
|
||||||
PG_FUNCTION_INFO_V1(IVM_immediate_before);
|
PG_FUNCTION_INFO_V1(IVM_immediate_before);
|
||||||
|
|
@ -388,7 +389,7 @@ RefreshImmvByOid(Oid matviewOid, bool is_create, bool skipData,
|
||||||
systable_endscan(scan);
|
systable_endscan(scan);
|
||||||
table_close(pgIvmImmv, NoLock);
|
table_close(pgIvmImmv, NoLock);
|
||||||
|
|
||||||
viewQuery = get_immv_query(matviewRel);
|
viewQuery = recreate_immv_query(matviewRel);
|
||||||
|
|
||||||
/* For IMMV, we need to rewrite matview query */
|
/* For IMMV, we need to rewrite matview query */
|
||||||
if (!skipData)
|
if (!skipData)
|
||||||
|
|
@ -713,6 +714,83 @@ get_immv_query(Relation matviewRel)
|
||||||
return query;
|
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 *
|
static Tuplestorestate *
|
||||||
tuplestore_copy(Tuplestorestate *tuplestore, Relation rel)
|
tuplestore_copy(Tuplestorestate *tuplestore, Relation rel)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
33
pg_ivm.c
33
pg_ivm.c
|
|
@ -177,17 +177,39 @@ create_immv(PG_FUNCTION_ARGS)
|
||||||
text *t_sql = PG_GETARG_TEXT_PP(1);
|
text *t_sql = PG_GETARG_TEXT_PP(1);
|
||||||
char *relname = text_to_cstring(t_relname);
|
char *relname = text_to_cstring(t_relname);
|
||||||
char *sql = text_to_cstring(t_sql);
|
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;
|
List *parsetree_list;
|
||||||
RawStmt *parsetree;
|
RawStmt *parsetree;
|
||||||
Query *query;
|
|
||||||
QueryCompletion qc;
|
|
||||||
List *names = NIL;
|
List *names = NIL;
|
||||||
List *colNames = NIL;
|
List *colNames = NIL;
|
||||||
|
|
||||||
ParseState *pstate = make_parsestate(NULL);
|
|
||||||
CreateTableAsStmt *ctas;
|
CreateTableAsStmt *ctas;
|
||||||
StringInfoData command_buf;
|
StringInfoData command_buf;
|
||||||
|
Query *query;
|
||||||
|
ParseState *pstate;
|
||||||
|
|
||||||
|
pstate = make_parsestate(NULL);
|
||||||
parseNameAndColumns(relname, &names, &colNames);
|
parseNameAndColumns(relname, &names, &colNames);
|
||||||
|
|
||||||
initStringInfo(&command_buf);
|
initStringInfo(&command_buf);
|
||||||
|
|
@ -230,9 +252,8 @@ create_immv(PG_FUNCTION_ARGS)
|
||||||
query = transformStmt(pstate, (Node *)ctas);
|
query = transformStmt(pstate, (Node *)ctas);
|
||||||
Assert(query->commandType == CMD_UTILITY && IsA(query->utilityStmt, CreateTableAsStmt));
|
Assert(query->commandType == CMD_UTILITY && IsA(query->utilityStmt, CreateTableAsStmt));
|
||||||
|
|
||||||
ExecCreateImmv(pstate, (CreateTableAsStmt *) query->utilityStmt, &qc);
|
*query_ret = query;
|
||||||
|
*pstate_ret = pstate;
|
||||||
PG_RETURN_INT64(qc.nprocessed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
2
pg_ivm.h
2
pg_ivm.h
|
|
@ -35,6 +35,8 @@ extern Oid PgIvmImmvRelationId(void);
|
||||||
extern Oid PgIvmImmvPrimaryKeyIndexId(void);
|
extern Oid PgIvmImmvPrimaryKeyIndexId(void);
|
||||||
extern bool isImmv(Oid immv_oid);
|
extern bool isImmv(Oid immv_oid);
|
||||||
extern List *PgIvmFuncName(char *name);
|
extern List *PgIvmFuncName(char *name);
|
||||||
|
extern void parse_immv_query(const char *relname, const char *sql,
|
||||||
|
Query **query_ret, ParseState **pstate_ret);
|
||||||
|
|
||||||
/* createas.c */
|
/* createas.c */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue