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]