summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Paquier2012-07-09 00:40:37 +0000
committerMichael Paquier2012-07-09 00:40:37 +0000
commitcc12ea8e67c46f9782804105915dcc90725a1f66 (patch)
tree3c4c3150d87c75bd52ab44704c3277fea21e9f3c
parent7cda4f342bd3b9bff628685a2d77505e266295e2 (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.c4
-rw-r--r--src/backend/pgxc/pool/execRemote.c46
-rw-r--r--src/test/regress/input/xc_copy.source14
-rw-r--r--src/test/regress/output/xc_copy.source19
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;