pgpool2.git / summary / log / commit / refs

commit    9832bb38dbad14e0137b946ea163ffa1aed9b0d1
Author:   Tatsuo Ishii <ishii at sraoss.co.jp>
Date:     Mon Jul 19 12:02:33 2010 +0000

    Add modules to handle where to send map for SQL level
    PREPARE/EXECUTE/DEALLOCATE. This is used for non-extended protocol
    only.


pool_proto_modules.c | 10 ++++-- pool_query_context.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ pool_session_context.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ pool_session_context.h | 19 ++++++++++++ 4 files changed, 194 insertions(+), 2 deletions(-) diff --git a/pool_proto_modules.c b/pool_proto_modules.c index 3a264f656..be2a7439c 100644 --- a/pool_proto_modules.c +++ b/pool_proto_modules.c @@ -293,7 +293,7 @@ static int is_temp_table(POOL_CONNECTION_POOL *backend, Node *node); if (IsA(node, PrepareStmt)) { PreparedStatement *ps; - +#ifdef NOT_USED ps = pool_create_prepared_statement(((PrepareStmt *)node)->name, 0, query_context); if (ps == NULL) @@ -304,12 +304,13 @@ static int is_temp_table(POOL_CONNECTION_POOL *backend, Node *node); session_context->pending_pstmt = ps; session_context->pending_function = pool_add_prepared_statement; +#endif } else if (IsA(node, DeallocateStmt)) { char *name; PreparedStatement *ps; - +#ifdef NOT_USED name = ((DeallocateStmt *)node)->name; if (name == NULL) ps = pool_create_prepared_statement("", 0, query_context); @@ -327,6 +328,7 @@ static int is_temp_table(POOL_CONNECTION_POOL *backend, Node *node); session_context->pending_function = pool_clear_prepared_statement_list; else session_context->pending_function = pool_remove_prepared_statement; +#endif } else if (IsA(node, DiscardStmt)) { @@ -342,6 +344,7 @@ static int is_temp_table(POOL_CONNECTION_POOL *backend, Node *node); if (frontend && IsA(node, ExecuteStmt)) { +#ifdef NOT_USED PreparedStatement *ps; ps = pool_get_prepared_statement_by_pstmt_name(((ExecuteStmt *)node)->name); @@ -351,6 +354,7 @@ static int is_temp_table(POOL_CONNECTION_POOL *backend, Node *node); pool_query_context_destroy(query_context); query_context = ps->qctxt; } +#endif } /* @@ -420,8 +424,10 @@ static int is_temp_table(POOL_CONNECTION_POOL *backend, Node *node); if (IsA(node, PrepareStmt)) { +#ifdef NOT_USED ps = session_context->pending_pstmt; ps->num_tsparams = 0; +#endif } else if (IsA(node, ExecuteStmt)) ps = pool_get_prepared_statement_by_pstmt_name(((ExecuteStmt *) node)->name); diff --git a/pool_query_context.c b/pool_query_context.c index 3be00d699..094f80057 100644 --- a/pool_query_context.c +++ b/pool_query_context.c @@ -344,6 +344,54 @@ void pool_where_to_send(POOL_QUERY_CONTEXT *query_context, char *query, Node *no pool_set_node_to_be_sent(query_context, REAL_MASTER_NODE_ID); } } + + /* PREPARE? */ + if (IsA(node, PrepareStmt)) + { + /* Make sure that same prepared statement does not exist */ + if (pool_get_prep_where(((PrepareStmt *)node)->name) == NULL) + { + /* Save the send map */ + pool_add_prep_where(((PrepareStmt *)node)->name, query_context->where_to_send); + } + } + + /* + * EXECUTE? + */ + else if (IsA(node, ExecuteStmt)) + { + bool *wts; + + wts = pool_get_prep_where(((ExecuteStmt *)node)->name); + if (wts) + { + /* Inherit same map from PREPARE */ + pool_copy_prep_where(wts, query_context->where_to_send); + } + } + + /* + * DEALLOCATE? + */ + else if (IsA(node, DeallocateStmt)) + { + DeallocateStmt *d = (DeallocateStmt *)node; + bool *wts; + + /* DELLOCATE ALL? */ + if (d->name == NULL) + { + return POOL_BOTH; + } + + wts = pool_get_prep_where(d->name); + if (wts) + { + /* Inherit same map from PREPARE */ + pool_copy_prep_where(wts, query_context->where_to_send); + } + } } else /* Slony-I case */ { @@ -792,6 +840,41 @@ static POOL_DEST send_to_where(Node *node, char *query) return POOL_BOTH; } + /* + * PREPARE + */ + else if (IsA(node, PrepareStmt)) + { + PrepareStmt *prepare_statement = (PrepareStmt *)node; + + char *string = nodeToString(prepare_statement->query); + + /* Note that this is a recursive call */ + return send_to_where((Node *)(prepare_statement->query), string); + } + + /* + * EXECUTE + */ + else if (IsA(node, ExecuteStmt)) + { + /* This is temporary decision. where_to_send will inherit + * same destination AS PREPARE. + */ + return POOL_PRIMARY; + } + + /* + * DEALLOCATE + */ + else if (IsA(node, DeallocateStmt)) + { + /* This is temporary decision. where_to_send will inherit + * same destination AS PREPARE. + */ + return POOL_PRIMARY; + } + /* * Other statements are sent to primary */ diff --git a/pool_session_context.c b/pool_session_context.c index bd7272bf4..5a0884ea2 100644 --- a/pool_session_context.c +++ b/pool_session_context.c @@ -128,6 +128,10 @@ void pool_init_session_context(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL * /* Forget transaction isolation mode */ pool_unset_transaction_isolation(); + + /* Initialize where to send map for PREPARE statemets */ + memset(&session_context->prep_where, 0, sizeof(session_context->prep_where)); + session_context->prep_where.nelem = POOL_MAX_PREPARED_STATEMENTS; } /* @@ -817,3 +821,83 @@ bool pool_is_command_success(void) } return session_context->command_success; } + +/* + * Copy send map + */ +void pool_copy_prep_where(bool *src, bool *dest) +{ + memcpy(dest, src, sizeof(bool)*MAX_NUM_BACKENDS); +} + +/* + * Add to send map a PREPARED statement + */ +void pool_add_prep_where(char *name, bool *map) +{ + int i; + + if (!session_context) + { + pool_error("pool_add_prep_where: session context is not initialized"); + return; + } + + for (i=0;i<POOL_MAX_PREPARED_STATEMENTS;i++) + { + if (*session_context->prep_where.name[i] == '\0') + { + strncpy(session_context->prep_where.name[i], name, POOL_MAX_PREPARED_NAME); + pool_copy_prep_where(map, session_context->prep_where.where_to_send[i]); + return; + } + } + pool_error("pool_add_prep_where: no empty slot found"); +} + +/* + * Search send map by PREPARED statement name + */ +bool *pool_get_prep_where(char *name) +{ + int i; + + if (!session_context) + { + pool_error("pool_get_prep_where: session context is not initialized"); + return NULL; + } + + for (i=0;i<POOL_MAX_PREPARED_STATEMENTS;i++) + { + if (!strcmp(session_context->prep_where.name[i], name)) + { + return session_context->prep_where.where_to_send[i]; + } + } + return NULL; +} + +/* + * Remove PREPARED statement by name + */ +void pool_delete_prep_where(char *name) +{ + int i; + + if (!session_context) + { + pool_error("pool_delete_prep_where: session context is not initialized"); + return; + } + + for (i=0;i<POOL_MAX_PREPARED_STATEMENTS;i++) + { + if (!strcmp(session_context->prep_where.name[i], name)) + { + memcpy(&session_context->prep_where.where_to_send[i], 0, sizeof(bool)*MAX_NUM_BACKENDS); + *session_context->prep_where.name[i] = '\0'; + return; + } + } +} diff --git a/pool_session_context.h b/pool_session_context.h index bdc27830f..a81777c92 100644 --- a/pool_session_context.h +++ b/pool_session_context.h @@ -78,6 +78,18 @@ typedef enum { POOL_SERIALIZABLE /* Serializable */ } POOL_TRANSACTION_ISOLATION; +/* + * where to send map for PREPARE/EXECUTE/DEALLOCATE + */ +#define POOL_MAX_PREPARED_STATEMENTS 128 +#define POOL_MAX_PREPARED_NAME 64 + +typedef struct { + int nelem; /* Number of elements */ + char name[POOL_MAX_PREPARED_STATEMENTS][POOL_MAX_PREPARED_NAME]; /* Prepared statement name */ + bool where_to_send[POOL_MAX_PREPARED_STATEMENTS][MAX_NUM_BACKENDS]; +} POOL_PREPARED_SEND_MAP; + /* * Per session context: */ @@ -110,6 +122,9 @@ typedef struct { */ POOL_QUERY_CONTEXT *query_context; + /* where to send map for PREPARE/EXECUTE/DEALLOCATE */ + POOL_PREPARED_SEND_MAP prep_where; + POOL_MEMORY_POOL *memory_context; /* memory context for session */ PreparedStatement *unnamed_pstmt; /* unnamed statement */ PreparedStatement *pending_pstmt; /* used until receive backend response */ @@ -200,5 +215,9 @@ extern POOL_TRANSACTION_ISOLATION pool_get_transaction_isolation(void); extern void pool_unset_command_success(void); extern void pool_set_command_success(void); extern bool pool_is_command_success(void); +extern void pool_copy_prep_where(bool *src, bool *dest); +extern void pool_add_prep_where(char *name, bool *map); +extern bool *pool_get_prep_where(char *name); +extern void pool_delete_prep_where(char *name); #endif /* POOL_SESSION_CONTEXT_H */ [parent: 9d6b45b61f53]