if (pool_has_unlogged_table(node))
return false;
}
+
+ /*
+ * If Data-modifying statements in WITH clause, it's not allowed to cache.
+ */
+ if(IsA(node, SelectStmt) && ((SelectStmt *) node)->withClause)
+ {
+ ListCell *lc;
+ WithClause *withClause = ((SelectStmt *) node)->withClause;
+
+ foreach(lc, withClause->ctes)
+ {
+ CommonTableExpr *cte = (CommonTableExpr *)lfirst(lc);
+ if(IsA(cte->ctequery, InsertStmt) ||
+ IsA(cte->ctequery, DeleteStmt) ||
+ IsA(cte->ctequery, UpdateStmt))
+ {
+ return false;
+ }
+ }
+ }
+
return true;
}
/*
* Extract table oid from INSERT/UPDATE/DELETE/TRUNCATE/
* DROP TABLE/ALTER TABLE/COPY FROM statement.
+ * For SELECT, if Data-modifying statements in its WITH clause,
+ * extract table oid from Data-modifying statements too.
* Returns number of oids.
* In case of error, returns 0 (InvalidOid).
* oids buffer (oidsp) will be discarded by subsequent call.
if (IsA(node, InsertStmt))
{
- InsertStmt *stmt = (InsertStmt *)node;
+ InsertStmt *stmt = (InsertStmt *) node;
+
+ num_oids = pool_extract_withclause_oids((Node *) stmt->withClause, *oidsp);
table = make_table_name_from_rangevar(stmt->relation);
}
else if (IsA(node, UpdateStmt))
{
- UpdateStmt *stmt = (UpdateStmt *)node;
+ UpdateStmt *stmt = (UpdateStmt *) node;
+
+ num_oids = pool_extract_withclause_oids((Node *) stmt->withClause, *oidsp);
table = make_table_name_from_rangevar(stmt->relation);
}
else if (IsA(node, DeleteStmt))
{
- DeleteStmt *stmt = (DeleteStmt *)node;
+ DeleteStmt *stmt = (DeleteStmt *) node;
+
+ num_oids = pool_extract_withclause_oids((Node *) stmt->withClause, *oidsp);
table = make_table_name_from_rangevar(stmt->relation);
}
-
+ else if(IsA(node, SelectStmt))
+ {
+ SelectStmt *stmt = (SelectStmt *) node;
+ num_oids = pool_extract_withclause_oids((Node *) stmt->withClause, *oidsp);
+ table = NULL;
+ }
#ifdef NOT_USED
/*
* We do not handle CREATE TABLE here. It is possible that
return num_oids;
}
+/*
+ * Extract table oid from INSERT/UPDATE/DELETE
+ * FROM statement in WITH clause.
+ * Returns number of oids.
+ * oids buffer (oidsp) will be discarded by subsequent call.
+ */
+int
+pool_extract_withclause_oids(Node *node, int *oidsp)
+{
+ int num_oids = 0;
+ int oid;
+ char *table;
+ ListCell *lc;
+ WithClause *with;
+
+ if(oidsp == NULL)
+ {
+ return 0;
+ }
+
+ if(!node || !IsA(node, WithClause))
+ {
+ return 0;
+ }
+
+ with = (WithClause *) node;
+ foreach(lc, with->ctes)
+ {
+ CommonTableExpr *cte = (CommonTableExpr *)lfirst(lc);
+ if(IsA(cte->ctequery, InsertStmt))
+ {
+ InsertStmt *stmt = (InsertStmt *) cte->ctequery;
+ table = make_table_name_from_rangevar(stmt->relation);
+ }
+ else if(IsA(cte->ctequery, DeleteStmt))
+ {
+ DeleteStmt *stmt = (DeleteStmt *) cte->ctequery;
+ table = make_table_name_from_rangevar(stmt->relation);
+ }
+ else if(IsA(cte->ctequery, UpdateStmt))
+ {
+ UpdateStmt *stmt = (UpdateStmt *) cte->ctequery;
+ table = make_table_name_from_rangevar(stmt->relation);
+ }
+ else
+ {
+ /* only check INSERT/DELETE/UPDATE in WITH clause */
+ table = NULL;
+ }
+
+ oid = pool_table_name_to_oid(table);
+ if (oid > 0)
+ {
+ if (num_oids >= POOL_MAX_DML_OIDS)
+ {
+ break;
+ }
+
+ oidsp[num_oids++] = pool_table_name_to_oid(table);
+ ereport(DEBUG1,
+ (errmsg("memcache: extracting table oids: table: \"%s\" oid:%d", table, oidsp[num_oids - 1])));
+ }
+ }
+
+ return num_oids;
+}
+
#define POOL_OIDBUF_SIZE 1024
static int* oidbuf;
static int oidbufp;
/* Non cachable SELECT */
if (node && IsA(node, SelectStmt))
{
+ /* Extract table oids from buffer */
+ num_oids = pool_get_dml_table_oid(&oids);
+
if (state == 'I')
{
+ /*
+ * If Data-modifying statements in SELECT's WITH clause,
+ * invalidate query cache.
+ */
+ if (num_oids > 0 && pool_config->memqcache_auto_cache_invalidation)
+ {
+ POOL_SETMASK2(&BlockSig, &oldmask);
+ pool_shmem_lock();
+ pool_invalidate_query_cache(num_oids, oids, true, 0);
+ pool_shmem_unlock();
+ POOL_SETMASK(&oldmask);
+ }
+
/* Count up SELECT stats */
pool_stats_count_up_num_selects(1);
pool_reset_memqcache_buffer(true);
}
else
{
+ /*
+ * If we are inside a transaction, we cannot invalidate
+ * query cache yet. However we can clear cache buffer, if
+ * DML/DDL modifies the TABLE which SELECT uses.
+ */
+ if (num_oids > 0 && pool_config->memqcache_auto_cache_invalidation)
+ {
+ pool_check_and_discard_cache_buffer(num_oids, oids);
+ pool_reset_memqcache_buffer(false);
+ }
+
/* Count up temporary SELECT stats */
pool_tmp_stats_count_up_num_selects();
}