diff options
author | Michael Paquier | 2012-07-09 00:40:37 +0000 |
---|---|---|
committer | Michael Paquier | 2012-07-09 00:40:37 +0000 |
commit | cc12ea8e67c46f9782804105915dcc90725a1f66 (patch) | |
tree | 3c4c3150d87c75bd52ab44704c3277fea21e9f3c | |
parent | 7cda4f342bd3b9bff628685a2d77505e266295e2 (diff) |
Fix for bug 3540784: Incorrect COPY for partially distributed tables
When a table was distributed on a portion of nodes. COPY process
was not correctly choosing the output node during a COPY TO. This
problem has been put into light by a case where table was replicated
without using the first datanode of the cluster. It happened that
there was the same problem for hash/modulo tables as well.
A test case in xc_copy has been added to cover this problem, and
a small portion managing COPY TO in execRemote.c has been cleaned.
-rw-r--r-- | src/backend/pgxc/locator/locator.c | 4 | ||||
-rw-r--r-- | src/backend/pgxc/pool/execRemote.c | 46 | ||||
-rw-r--r-- | src/test/regress/input/xc_copy.source | 14 | ||||
-rw-r--r-- | src/test/regress/output/xc_copy.source | 19 |
4 files changed, 58 insertions, 25 deletions
diff --git a/src/backend/pgxc/locator/locator.c b/src/backend/pgxc/locator/locator.c index 1bba86b379..8c44f70308 100644 --- a/src/backend/pgxc/locator/locator.c +++ b/src/backend/pgxc/locator/locator.c @@ -149,8 +149,8 @@ GetAnyDataNode(List *relNodes) } } - /* Nothing found? Return the 1st one */ - return lappend_int(NULL, 0); + /* Nothing found? Return the first one in relation node list */ + return lappend_int(NULL, linitial_int(relNodes)); } /* diff --git a/src/backend/pgxc/pool/execRemote.c b/src/backend/pgxc/pool/execRemote.c index ed2e841ad8..73fa752f3b 100644 --- a/src/backend/pgxc/pool/execRemote.c +++ b/src/backend/pgxc/pool/execRemote.c @@ -2322,7 +2322,6 @@ DataNodeCopyOut(ExecNodes *exec_nodes, PGXCNodeHandle** copy_connections, FILE* { RemoteQueryState *combiner; int conn_count = list_length(exec_nodes->nodeList) == 0 ? NumDataNodes : list_length(exec_nodes->nodeList); - int count = 0; ListCell *nodeitem; uint64 processed; @@ -2334,32 +2333,33 @@ DataNodeCopyOut(ExecNodes *exec_nodes, PGXCNodeHandle** copy_connections, FILE* foreach(nodeitem, exec_nodes->nodeList) { - PGXCNodeHandle *handle = copy_connections[count]; - count++; + PGXCNodeHandle *handle = copy_connections[lfirst_int(nodeitem)]; + int read_status = 0; + + Assert(handle && handle->state == DN_CONNECTION_STATE_COPY_OUT); - if (handle && handle->state == DN_CONNECTION_STATE_COPY_OUT) + /* + * H message has been consumed, continue to manage data row messages. + * Continue to read as long as there is data. + */ + while (read_status >= 0 && handle->state == DN_CONNECTION_STATE_COPY_OUT) { - int read_status = 0; - /* H message has been consumed, continue to manage data row messages */ - while (read_status >= 0 && handle->state == DN_CONNECTION_STATE_COPY_OUT) /* continue to read as long as there is data */ + if (handle_response(handle,combiner) == RESPONSE_EOF) { - if (handle_response(handle,combiner) == RESPONSE_EOF) - { - /* read some extra-data */ - read_status = pgxc_node_read_data(handle, true); - if (read_status < 0) - ereport(ERROR, - (errcode(ERRCODE_CONNECTION_FAILURE), - errmsg("unexpected EOF on datanode connection"))); - else - /* - * Set proper connection status - handle_response - * has changed it to DN_CONNECTION_STATE_QUERY - */ - handle->state = DN_CONNECTION_STATE_COPY_OUT; - } - /* There is no more data that can be read from connection */ + /* read some extra-data */ + read_status = pgxc_node_read_data(handle, true); + if (read_status < 0) + ereport(ERROR, + (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("unexpected EOF on datanode connection"))); + else + /* + * Set proper connection status - handle_response + * has changed it to DN_CONNECTION_STATE_QUERY + */ + handle->state = DN_CONNECTION_STATE_COPY_OUT; } + /* There is no more data that can be read from connection */ } } diff --git a/src/test/regress/input/xc_copy.source b/src/test/regress/input/xc_copy.source index 2376dd9e36..efce40287b 100644 --- a/src/test/regress/input/xc_copy.source +++ b/src/test/regress/input/xc_copy.source @@ -1,3 +1,9 @@ +-- +-- XC_COPY +-- + +-- COPY tests for a Postgres-XC cluster + create or replace function pgxc_nodetype() returns varchar as $$ declare @@ -85,3 +91,11 @@ drop function deffunc_bytea(); drop function deffunc_str(); drop function deffunc_str_i(); drop function deffunc_nullstring(); + +-- Tests related to COPY for a Postgres-XC cluster +-- Create a table not using the first node of cluster +SELECT create_table_nodes('xc_copy_1(a int, b int)', '{2}'::int[], 'replication', NULL); +INSERT INTO xc_copy_1 VALUES (1,23),(34,5),(9,11); +-- Extract its data +COPY xc_copy_1 TO STDOUT; +DROP TABLE xc_copy_1; diff --git a/src/test/regress/output/xc_copy.source b/src/test/regress/output/xc_copy.source index 828325c06d..ee95542890 100644 --- a/src/test/regress/output/xc_copy.source +++ b/src/test/regress/output/xc_copy.source @@ -1,3 +1,7 @@ +-- +-- XC_COPY +-- +-- COPY tests for a Postgres-XC cluster create or replace function pgxc_nodetype() returns varchar as $$ declare @@ -81,3 +85,18 @@ drop function deffunc_bytea(); drop function deffunc_str(); drop function deffunc_str_i(); drop function deffunc_nullstring(); +-- Tests related to COPY for a Postgres-XC cluster +-- Create a table not using the first node of cluster +SELECT create_table_nodes('xc_copy_1(a int, b int)', '{2}'::int[], 'replication', NULL); + create_table_nodes +-------------------- + +(1 row) + +INSERT INTO xc_copy_1 VALUES (1,23),(34,5),(9,11); +-- Extract its data +COPY xc_copy_1 TO STDOUT; +1 23 +34 5 +9 11 +DROP TABLE xc_copy_1; |