pgpool2.git / summary / log / commit / refs
commit b5f26de7d67278db695e1be8f0c426e59b8a050b
Author: Tatsuo Ishii <ishii@postgresql.org>
Date: Sat Nov 17 10:12:40 2012 +0000
Fix bug with query cache returning incorrect data in some cases when a
persistent table and temp table have same name.
Here is a sequence to trigger the bug:
1) CREATE TABLE t1(i int); -- create a persistent table
2) INSERT INTO t1 VALUES(1);
3) SELECT * FROM t1; -- query cache entry created
4) CREATE TEMP TABLE t1(i int); -- create a temp table
5) SELECT * FROM t1; -- query cache entry mistakenly created!
Problem is #3 creates relcache entry for t1, and #5 incorrecly uses it
and believes that temp table t1 is not a temp table. To solve the
problem, new function discard_temp_table_relcache() added and it gets
called in ReadyforQuery if CREATE TEMP TABLE executed to discard
relcache for temp table info.
pool_proto_modules.c | 31 +++++++++++++++++++++++--------
pool_select_walker.c | 27 ++++++++++++++++++++-------
pool_select_walker.h | 1 +
3 files changed, 44 insertions(+), 15 deletions(-)
diff --git a/pool_proto_modules.c b/pool_proto_modules.c
index ed186a647..2fd2a1d8c 100644
--- a/pool_proto_modules.c
+++ b/pool_proto_modules.c
@@ -1724,15 +1724,30 @@ POOL_STATUS ReadyForQuery(POOL_CONNECTION *frontend,
return POOL_END;
}
- /*
- * If the query was not READ SELECT, and we are in an
- * explicit transaction, remember that we had a write
- * query in this transaction.
- */
- else if (!is_select_query(node, query) &&
- TSTATE(backend, MASTER_SLAVE ? PRIMARY_NODE_ID : REAL_MASTER_NODE_ID) == 'T')
+ else if (!is_select_query(node, query))
{
- pool_set_writing_transaction();
+ /*
+ * If the query was not READ SELECT, and we are in an
+ * explicit transaction, remember that we had a write
+ * query in this transaction.
+ */
+ if (TSTATE(backend, MASTER_SLAVE ? PRIMARY_NODE_ID : REAL_MASTER_NODE_ID) == 'T')
+ {
+ pool_set_writing_transaction();
+ }
+
+ /*
+ * If the query was CREATE TEMP TABLE, discard
+ * temp table relcache because we might have had
+ * persistent table relation cache which has table
+ * name as the tem table.
+ */
+ if (IsA(node, CreateStmt))
+ {
+ CreateStmt *create_table_stmt = (CreateStmt *)node;
+ if (create_table_stmt->relation->istemp)
+ discard_temp_table_relcache();
+ }
}
}
diff --git a/pool_select_walker.c b/pool_select_walker.c
index 8a2e23222..1f16d0d1f 100644
--- a/pool_select_walker.c
+++ b/pool_select_walker.c
@@ -493,6 +493,8 @@ static bool is_system_catalog(char *table_name)
* Judge the table used in a query represented by node is a temporary
* table or not.
*/
+static POOL_RELCACHE *is_temp_table_relcache;
+
static bool is_temp_table(char *table_name)
{
/*
@@ -520,7 +522,6 @@ static bool is_temp_table(char *table_name)
int hasrelistemp;
bool result;
static POOL_RELCACHE *hasrelistemp_cache;
- static POOL_RELCACHE *relcache;
char *query;
POOL_CONNECTION_POOL *backend;
@@ -555,12 +556,12 @@ static bool is_temp_table(char *table_name)
/*
* If relcache does not exist, create it.
*/
- if (!relcache)
+ if (!is_temp_table_relcache)
{
- relcache = pool_create_relcache(pool_config->relcache_size, query,
- int_register_func, int_unregister_func,
- true);
- if (relcache == NULL)
+ is_temp_table_relcache = pool_create_relcache(pool_config->relcache_size, query,
+ int_register_func, int_unregister_func,
+ true);
+ if (is_temp_table_relcache == NULL)
{
pool_error("is_temp_table: pool_create_relcache error");
return false;
@@ -570,10 +571,22 @@ static bool is_temp_table(char *table_name)
/*
* Search relcache.
*/
- result = pool_search_relcache(relcache, backend, table_name)==0?false:true;
+ result = pool_search_relcache(is_temp_table_relcache, backend, table_name)==0?false:true;
return result;
}
+/*
+ * Discard relcache used by is_temp_table_relcache().
+ */
+void discard_temp_table_relcache(void)
+{
+ if (is_temp_table_relcache)
+ {
+ pool_discard_relcache(is_temp_table_relcache);
+ is_temp_table_relcache = NULL;
+ }
+}
+
/*
* Judge the table used in a query represented by node is a unlogged
* table or not.
diff --git a/pool_select_walker.h b/pool_select_walker.h
index 5bf8afc28..3e6555b77 100644
--- a/pool_select_walker.h
+++ b/pool_select_walker.h
@@ -51,6 +51,7 @@ extern bool pool_has_function_call(Node *node);
extern bool pool_has_non_immutable_function_call(Node *node);
extern bool pool_has_system_catalog(Node *node);
extern bool pool_has_temp_table(Node *node);
+extern void discard_temp_table_relcache(void);
extern bool pool_has_unlogged_table(Node *node);
extern bool pool_has_view(Node *node);
extern bool pool_has_insertinto_or_locking_clause(Node *node);
[parent: ece0f8ffafcf]