pgpool2.git / summary / log / commit / refs

commit    e1c1e9432adeb3fa44fd2c35885c58b0b8548195
Author:   Tatsuo Ishii <ishii at sraoss.co.jp>
Date:     Thu Aug 18 01:27:45 2011 +0000

    Fix send_to_where() so that it correctly recognizes FOR SHARE/UPDATE
    clause even if it's in subquery. Before it only recognized
    when the clause was in top level of SELECT. For this new function
    pool_has_insertinto_or_locking_clause() is added.
    
    Make pattern_compare() to static since it's not used anywhere outside
    of pool_select_walker.c


pool_config.h | 1 - pool_query_context.c | 9 ++------- pool_select_walker.c | 43 ++++++++++++++++++++++++++++++++++++++++++- pool_select_walker.h | 1 + 4 files changed, 45 insertions(+), 9 deletions(-) diff --git a/pool_config.h b/pool_config.h index 6a43ba36b..280be8e68 100644 --- a/pool_config.h +++ b/pool_config.h @@ -204,6 +204,5 @@ extern int set_syslog_facility (char *); /* methods used for regexp support */ extern int add_regex_pattern(char *type, char *s); extern int growPatternArray (RegPattern item); -extern int pattern_compare(char *str, const int type); #endif /* POOL_CONFIG_H */ diff --git a/pool_query_context.c b/pool_query_context.c index 7305dc252..e6deb9601 100644 --- a/pool_query_context.c +++ b/pool_query_context.c @@ -1010,14 +1010,9 @@ static POOL_DEST send_to_where(Node *node, char *query) */ if (IsA(node, SelectStmt)) { - /* SELECT INTO? */ - if (((SelectStmt *)node)->intoClause) + /* SELECT INTO or SELECT FOR SHARE or UPDATE ? */ + if (pool_has_insertinto_or_locking_clause(node)) return POOL_PRIMARY; - - /* SELECT FOR SHARE or UPDATE */ - else if (((SelectStmt *)node)->lockingClause) - return POOL_PRIMARY; - /* * SELECT nextval(), setval() * XXX: We do not search in subquery. diff --git a/pool_select_walker.c b/pool_select_walker.c index ea846c5fb..3d1b670d7 100644 --- a/pool_select_walker.c +++ b/pool_select_walker.c @@ -34,6 +34,7 @@ typedef struct { bool has_temp_table; /* True if temporary table is used */ bool has_unlogged_table; /* True if unlogged table is used */ bool has_function_call; /* True if write function call is used */ + bool has_insertinto_or_locking_clause; /* True if it has SELECT INTO or FOR SHARE/UPDATE */ } SelectContext; static bool function_call_walker(Node *node, void *context); @@ -43,6 +44,8 @@ static bool temp_table_walker(Node *node, void *context); static bool unlogged_table_walker(Node *node, void *context); static bool is_temp_table(char *table_name); static bool is_unlogged_table(char *table_name); +static bool insertinto_or_locking_clause_walker(Node *node, void *context); +static int pattern_compare(char *str, const int type); /* * Return true if this SELECT has function calls *and* supposed to @@ -117,6 +120,26 @@ bool pool_has_unlogged_table(Node *node) return ctx.has_unlogged_table; } +/* + * Return true if this SELECT has INSERT INTO or FOR SHARE or FOR UDPATE. + */ +bool pool_has_insertinto_or_locking_clause(Node *node) +{ + SelectContext ctx; + + if (!IsA(node, SelectStmt)) + return false; + + ctx.has_insertinto_or_locking_clause = false; + + raw_expression_tree_walker(node, insertinto_or_locking_clause_walker, &ctx); + + pool_debug("pool_has_insertinto_or_locking_clause: returns %d", + ctx.has_insertinto_or_locking_clause); + + return ctx.has_insertinto_or_locking_clause; +} + /* * Search function name in whilelist or blacklist regex array * Return 1 on success (found in list) @@ -124,7 +147,7 @@ bool pool_has_unlogged_table(Node *node) * Return -1 if the given search type doesn't exist. * Search type supported are: WHITELIST and BLACKLIST */ -int pattern_compare(char *str, const int type) +static int pattern_compare(char *str, const int type) { int i = 0; @@ -590,3 +613,21 @@ bool pool_has_pgpool_regclass(void) result = pool_search_relcache(relcache, backend, "pgpool_regclass")==0?0:1; return result; } + +/* + * Walker function to find intoClause or lockingClause. + */ +static bool insertinto_or_locking_clause_walker(Node *node, void *context) +{ + SelectContext *ctx = (SelectContext *) context; + + if (node == NULL) + return false; + + if (IsA(node, IntoClause) || IsA(node, LockingClause)) + { + ctx->has_insertinto_or_locking_clause = true; + return false; + } + return raw_expression_tree_walker(node, insertinto_or_locking_clause_walker, ctx); +} diff --git a/pool_select_walker.h b/pool_select_walker.h index 24ff6070a..222e1449e 100644 --- a/pool_select_walker.h +++ b/pool_select_walker.h @@ -33,6 +33,7 @@ extern bool pool_has_function_call(Node *node); extern bool pool_has_system_catalog(Node *node); extern bool pool_has_temp_table(Node *node); extern bool pool_has_unlogged_table(Node *node); +extern bool pool_has_insertinto_or_locking_clause(Node *node); extern bool pool_has_pgpool_regclass(void); extern bool raw_expression_tree_walker(Node *node, bool (*walker) (), void *context); [parent: 4d58bfbe2adf]