You can subscribe to this list here.
2010 |
Jan
|
Feb
|
Mar
|
Apr
(4) |
May
(28) |
Jun
(12) |
Jul
(11) |
Aug
(12) |
Sep
(5) |
Oct
(19) |
Nov
(14) |
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2011 |
Jan
(18) |
Feb
(30) |
Mar
(115) |
Apr
(89) |
May
(50) |
Jun
(44) |
Jul
(22) |
Aug
(13) |
Sep
(11) |
Oct
(30) |
Nov
(28) |
Dec
(39) |
2012 |
Jan
(38) |
Feb
(18) |
Mar
(43) |
Apr
(91) |
May
(108) |
Jun
(46) |
Jul
(37) |
Aug
(44) |
Sep
(33) |
Oct
(29) |
Nov
(36) |
Dec
(15) |
2013 |
Jan
(35) |
Feb
(611) |
Mar
(5) |
Apr
(55) |
May
(30) |
Jun
(28) |
Jul
(458) |
Aug
(34) |
Sep
(9) |
Oct
(39) |
Nov
(22) |
Dec
(32) |
2014 |
Jan
(16) |
Feb
(16) |
Mar
(42) |
Apr
(179) |
May
(7) |
Jun
(6) |
Jul
(9) |
Aug
|
Sep
(4) |
Oct
|
Nov
(3) |
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
(2) |
May
(4) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
|
|
|
1
(2) |
2
(3) |
3
|
4
|
5
|
6
(2) |
7
(1) |
8
|
9
(4) |
10
|
11
|
12
|
13
|
14
(1) |
15
(1) |
16
(1) |
17
|
18
|
19
|
20
|
21
(1) |
22
|
23
|
24
(2) |
25
|
26
|
27
(2) |
28
(1) |
29
(1) |
30
(22) |
|
|
From: Ashutosh B. <ash...@us...> - 2011-06-01 09:06:31
|
Project "Postgres-XC". The branch, master has been updated via 4a81fdc503a2a7cccc7610cc54db94d4e2d1b857 (commit) from a39d99c7ac6888edc2b1c711839708e1eb7718cf (commit) - Log ----------------------------------------------------------------- commit 4a81fdc503a2a7cccc7610cc54db94d4e2d1b857 Author: Ashutosh Bapat <ash...@en...> Date: Wed Jun 1 14:24:51 2011 +0530 Push GROUP BY clause to the datanode for grouping without aggregation (i.e. when we choose Group plan for grouping. Group plan requires that the input to this node be sorted on columns/expression involved in GROUP BY clause. Hence construct a ORDER BY clause corresponding to GROUP BY clause. Also add the same information to the RemoteQuery node, so that the sorted data from different datanodes can be merged at the coordinator so as to feed the sorted output to the Group node. The number of rows resulting after grouping is lesser or equal to the qualifying rows from the relations/joins. Hence by pushing GROUP BY to the datanodes, we reduce (in rare cases keep same) the number of rows fetched from datanodes, thus saving bandwidth. The optimization works under following restrictions 1. Group plan has Sort->Result->Material->RemoteQuery nodes under it. Result and Material nodes are optional. 2. There is no having clause, ORDER BY clause, windowing clause, Distinct clause in the query. 3. Such grouping uses Sorting for Grouping. (direct implication of first restriction) The patch also adds more test to file xc_groupby. diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 4acef77..b73c08e 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -5054,7 +5054,7 @@ create_remotedelete_plan(PlannerInfo *root, Plan *topplan) } /* - * create_remotegrouping_plan + * create_remoteagg_plan * tries to see if the grouping and aggregates can be pushed down to the * datanodes. * Right now we can push with following restrictions @@ -5073,7 +5073,7 @@ create_remotedelete_plan(PlannerInfo *root, Plan *topplan) * node in case there are no local clauses. */ Plan * -create_remotegrouping_plan(PlannerInfo *root, Plan *local_plan) +create_remoteagg_plan(PlannerInfo *root, Plan *local_plan) { Query *query = root->parse; RemoteQuery *agg_left; @@ -5339,6 +5339,245 @@ create_remotegrouping_plan(PlannerInfo *root, Plan *local_plan) } /* + * create_remotegroup_plan + * given a Group plan, try to push as much of the query to the datanodes and + * build a Group plan to combiner the results across the datanodes. The Sort + * node under the Group plan is pushed down to RemoteQuery plan, since the + * combiner knows how to merge the results across datanodes in sorted manner. + * Hence there is no separate Sort node. + * + * This optimization is applied under following conditions + * 1. The scan plans under the Group->Sort node is RemoteQuery + * 2. There is not separate Sort, distinct, having clause in the query. + * + * PGXCTODO: we should lift up as many of these restrictions as possible or give + * reasons why those restrictions are needed. + */ +Plan * +create_remotegroup_plan(PlannerInfo *root, Plan *local_plan) +{ + Group *group_plan; + Query *query = root->parse; + Sort *sort_plan; + RemoteQuery *remote_scan; /* remote query in the passed in plan */ + RemoteQuery *remote_group; /* remote query after optimization */ + Plan *remote_group_plan; /* plan portion of remote_group */ + Plan *temp_plan; + List *local_tlist; /* target list of the local plan */ + List *temp_vars; /* temporarily hold the VARs */ + List *temp_vartlist; /* temporarity hold tlist of VARs */ + ListCell *temp; + StringInfo remote_targetlist = makeStringInfo();/* SELECT clause of remote query */ + StringInfo remote_sql_stmt = makeStringInfo(); + StringInfo groupby_clause = makeStringInfo(); /* remote query GROUP BY */ + StringInfo orderby_clause = makeStringInfo(); /* remote query ORDER BY */ + StringInfo remote_fromlist = makeStringInfo(); /* remote query FROM */ + StringInfo in_alias = makeStringInfo(); + Relids in_relids; + Index dummy_rtindex; + List *base_tlist; + RangeTblEntry *dummy_rte; + int cntCols; + + if (query->havingQual || + query->distinctClause || + query->sortClause || + query->hasWindowFuncs) + return local_plan; + + /* for now only for Group plans */ + Assert(IsA(local_plan, Group)); + group_plan = (Group *)local_plan; + remote_scan = NULL; + temp_plan = local_plan->lefttree; + /* + * we expect plan tree as Group->Sort->{Result}?->{Material}?->RemoteQuery, + * anything else is not handled right now. + */ + if (IsA(temp_plan, Sort)) + { + sort_plan = (Sort *)temp_plan; + temp_plan = temp_plan->lefttree; + } + if (IsA(temp_plan, Result)) + temp_plan = temp_plan->lefttree; + if (IsA(temp_plan, Material)) + temp_plan = temp_plan->lefttree; + if (IsA(temp_plan, RemoteQuery)) + remote_scan = (RemoteQuery *)temp_plan; + + if (!remote_scan || !sort_plan) + return local_plan; + + Assert(IsA(remote_scan, RemoteQuery)); + Assert(IsA(sort_plan, Sort)); + /* + * grouping_planner will add Sort node before Group node to sort the rows + * based on the columns in GROUP BY clause. Hence the columns in Sort and + * those in Group node in should be same. The columns are usually in the + * same order in both nodes, hence check the equality in order. If this + * condition fails, we can not handle this GROUP plan for now. + */ + if (sort_plan->numCols != group_plan->numCols) + return local_plan; + for (cntCols = 0; cntCols < group_plan->numCols; cntCols++) + { + if (sort_plan->sortColIdx[cntCols] != group_plan->grpColIdx[cntCols]) + return local_plan; + } + /* + * We are now ready to create the RemoteQuery node to push the query to + * datanode. + * 1. create a remote query node reflecting the query to be pushed to the + * datanode + * 2. Modify the Group node passed in, to accept the results sent by the + * datanodes and group them + */ + + local_tlist = local_plan->targetlist; + appendStringInfo(in_alias, "%s_%d", "group", root->rs_alias_index); + + /* find all the relations referenced by targetlist of Group node */ + temp_vars = pull_var_clause((Node *)local_tlist, PVC_REJECT_PLACEHOLDERS); + findReferencedVars(temp_vars, (Plan *)remote_scan, &temp_vartlist, &in_relids); + /* + * build partial RemoteQuery node to be used for creating the Select clause + * to be sent to the remote node. Rest of the node will be built later + */ + remote_group = makeNode(RemoteQuery); + /* + * Save information about the plan we are reducing. + * We may need this information later if more entries are added to it + * as part of the remote expression optimization. + */ + remote_group->remotejoin = false; + remote_group->inner_alias = pstrdup(in_alias->data); + remote_group->inner_reduce_level = remote_scan->reduce_level; + remote_group->inner_relids = in_relids; + remote_group->inner_statement = pstrdup(remote_scan->sql_statement); + remote_group->exec_nodes = remote_scan->exec_nodes; + /* don't forget to increment the index for the next time around! */ + remote_group->reduce_level = root->rs_alias_index++; + + /* generate the select clause of the remote query */ + appendStringInfoString(remote_targetlist, "SELECT"); + foreach (temp, local_tlist) + { + TargetEntry *tle = lfirst(temp); + Node *expr = (Node *)tle->expr; + + create_remote_expr(root, local_plan, remote_targetlist, expr, remote_group); + /* if this is not last target entry, add a comma with space */ + if (lnext(temp)) + appendStringInfoString(remote_targetlist, ","); + } + + /* generate the from clause of the remote query */ + appendStringInfo(remote_fromlist, "FROM (%s) %s", + remote_group->inner_statement, remote_group->inner_alias); + + /* + * generate group by clause for the remote query and recompute the group by + * column locations. We want the tuples from remote node to be ordered by + * the grouping columns so that ExecGroup can work without any modification, + * hence create a SimpleSort structure to be added to RemoteQuery (which + * will merge the sorted results and present to Group node in sorted + * manner). + */ + if (query->groupClause) + { + SimpleSort *remote_sort = makeNode(SimpleSort); + char *sep = ""; + + /* + * reuse the arrays allocated in sort_plan to create SimpleSort + * structure. sort_plan is useless henceforth. + */ + remote_sort->numCols = group_plan->numCols; + remote_sort->sortColIdx = sort_plan->sortColIdx; + remote_sort->sortOperators = sort_plan->sortOperators; + remote_sort->nullsFirst = sort_plan->nullsFirst; + + pgxc_locate_grouping_columns(root, local_tlist, group_plan->grpColIdx); + + appendStringInfoString(groupby_clause, "GROUP BY "); + appendStringInfoString(orderby_clause, "ORDER BY "); + for (cntCols = 0; cntCols < group_plan->numCols; cntCols++) + { + appendStringInfo(groupby_clause, "%s%d", sep, + group_plan->grpColIdx[cntCols]); + remote_sort->sortColIdx[cntCols] = group_plan->grpColIdx[cntCols]; + appendStringInfo(orderby_clause, "%s%d", sep, + remote_sort->sortColIdx[cntCols]); + sep = ", "; + } + remote_group->sort = remote_sort; + } + + /* generate the remote sql statement from the pieces */ + appendStringInfo(remote_sql_stmt, "%s %s %s %s", remote_targetlist->data, + remote_fromlist->data, groupby_clause->data, + orderby_clause->data); + /* + * set the base_tlist for the RemoteQuery node being created, it's used to + * create the tuple descriptor for the result from RemoteQuery and rewrite + * the Aggregates targetlist accept the results of the RemoteQuery. + */ + base_tlist = add_to_flat_tlist(NIL, get_tlist_exprs(local_tlist, true)); + /* + * create a dummy RTE for the remote query being created. Append the dummy + * range table entry to the range table. Note that this modifies the master + * copy the caller passed us, otherwise e.g EXPLAIN VERBOSE will fail to + * find the rte the Vars built below refer to. + */ + /* cook up the reltupdesc using this base_tlist */ + dummy_rte = makeNode(RangeTblEntry); + dummy_rte->reltupdesc = ExecTypeFromTL(base_tlist, false); + dummy_rte->rtekind = RTE_RELATION; + /* use a dummy relname... */ + dummy_rte->relname = "__FOREIGN_QUERY__"; + dummy_rte->eref = makeAlias("__FOREIGN_QUERY__", NIL); + /* rest will be zeroed out in makeNode() */ + root->parse->rtable = lappend(root->parse->rtable, dummy_rte); + dummy_rtindex = list_length(root->parse->rtable); + + /* build rest of the RemoteQuery node and the plan there */ + remote_group_plan = &remote_group->scan.plan; + /* the join targetlist becomes this node's tlist */ + remote_group_plan->targetlist = base_tlist; + remote_group_plan->lefttree = NULL; + remote_group_plan->righttree = NULL; + remote_group->scan.scanrelid = dummy_rtindex; + remote_group->sql_statement = remote_sql_stmt->data; + /* set_plan_refs needs this later */ + remote_group->base_tlist = base_tlist; + remote_group->relname = "__FOREIGN_QUERY__"; + remote_group->partitioned_replicated = remote_scan->partitioned_replicated; + /* + * Only quals that can be pushed to the remote side are the ones in the having + * clause. Till we work out how to handle having quals in XC, we don't have + * any quals here. + * PGXCTODO: the RemoteQuery node that was earlier the lefttree of Agg + * node, may have local quals. In such case, we have to aggregate and group + * at coordinator and can not push the grouping clause to the datanodes. Is + * there a case in XC, where we can have local quals? + */ + /* we actually need not worry about costs since this is the final plan */ + remote_group_plan->startup_cost = remote_scan->scan.plan.startup_cost; + remote_group_plan->total_cost = remote_scan->scan.plan.total_cost; + remote_group_plan->plan_rows = remote_scan->scan.plan.plan_rows; + remote_group_plan->plan_width = remote_scan->scan.plan.plan_width; + + /* modify the passed in Group plan according to the remote query we built */ + /* + * Materialization is always need for RemoteQuery in case we need to restart + * the scan + */ + group_plan->plan.lefttree = (Plan *) make_material(remote_group_plan); + return (Plan *)group_plan; +} + +/* * locates the grouping clauses in the given target list. This is very similar * to locate_grouping_columns except that there is only one target list to * search into diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index aa629f6..182a18f 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -1336,10 +1336,13 @@ grouping_planner(PlannerInfo *root, double tuple_fraction) result_plan); #ifdef PGXC /* - * can we push any clauses to the remote node? try doing that + * Grouping will certainly not increase the number of rows + * coordinator fetches from datanode, in fact it's expected to + * reduce the number drastically. Hence, try pushing GROUP BY + * clauses and aggregates to the datanode, thus saving bandwidth. */ if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) - result_plan = create_remotegrouping_plan(root, result_plan); + result_plan = create_remoteagg_plan(root, result_plan); #endif /* PGXC */ /* Hashed aggregation produces randomly-ordered results */ current_pathkeys = NIL; @@ -1412,7 +1415,16 @@ grouping_planner(PlannerInfo *root, double tuple_fraction) extract_grouping_ops(parse->groupClause), dNumGroups, result_plan); - /* The Group node won't change sort ordering */ +#ifdef PGXC + /* + * Grouping will certainly not increase the number of rows + * coordinator fetches from datanode, in fact it's expected to + * reduce the number drastically. Hence, try pushing GROUP BY + * clauses and aggregates to the datanode, thus saving bandwidth. + */ + if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) + result_plan = create_remotegroup_plan(root, result_plan); +#endif /* PGXC */ } else if (root->hasHavingQual) { diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index 71aba2b..a068d47 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -82,7 +82,8 @@ extern ModifyTable *make_modifytable(CmdType operation, List *resultRelations, List *subplans, List *returningLists, List *rowMarks, int epqParam); extern bool is_projection_capable_plan(Plan *plan); -extern Plan *create_remotegrouping_plan(PlannerInfo *root, Plan *agg_plan); +extern Plan *create_remotegroup_plan(PlannerInfo *root, Plan *local_plan); +extern Plan *create_remoteagg_plan(PlannerInfo *root, Plan *agg_plan); /* * prototypes for plan/initsplan.c diff --git a/src/test/regress/expected/xc_groupby.out b/src/test/regress/expected/xc_groupby.out index 672084a..e403e37 100644 --- a/src/test/regress/expected/xc_groupby.out +++ b/src/test/regress/expected/xc_groupby.out @@ -66,7 +66,8 @@ explain verbose select sum(y) from (select sum(val) y, val2%2 x from tab1 group Output: tab1.val, tab1.val2 (8 rows) --- group by without aggregate, just like distinct? +-- group by without aggregate +set enable_hashagg to off; select val2 from tab1 group by val2; val2 ------ @@ -78,7 +79,7 @@ select val2 from tab1 group by val2; explain verbose select val2 from tab1 group by val2; QUERY PLAN ---------------------------------------------------------------------------------- - HashAggregate (cost=1.02..1.03 rows=1 width=4) + Group (cost=1.02..1.03 rows=1 width=4) Output: tab1.val2 -> Materialize (cost=0.00..0.00 rows=0 width=0) Output: tab1.val2 @@ -86,6 +87,95 @@ explain verbose select val2 from tab1 group by val2; Output: tab1.val2 (6 rows) +select val + val2 from tab1 group by val + val2; + ?column? +---------- + 2 + 3 + 4 + 7 + 8 + 9 +(6 rows) + +explain verbose select val + val2 from tab1 group by val + val2; + QUERY PLAN +---------------------------------------------------------------------------------- + Group (cost=1.03..1.04 rows=1 width=8) + Output: ((tab1.val + tab1.val2)) + -> Materialize (cost=0.00..0.00 rows=0 width=0) + Output: ((tab1.val + tab1.val2)) + -> Data Node Scan (Node Count [2]) (cost=0.00..1.01 rows=1000 width=8) + Output: (tab1.val + tab1.val2) +(6 rows) + +select val + val2, val, val2 from tab1 group by val, val2; + ?column? | val | val2 +----------+-----+------ + 2 | 1 | 1 + 4 | 1 | 3 + 3 | 2 | 1 + 4 | 2 | 2 + 4 | 3 | 1 + 7 | 4 | 3 + 8 | 6 | 2 + 9 | 6 | 3 +(8 rows) + +explain verbose select val + val2, val, val2 from tab1 group by val, val2; + QUERY PLAN +---------------------------------------------------------------------------------- + Group (cost=1.02..1.04 rows=1 width=8) + Output: ((tab1.val + tab1.val2)), tab1.val, tab1.val2 + -> Materialize (cost=0.00..0.00 rows=0 width=0) + Output: ((tab1.val + tab1.val2)), tab1.val, tab1.val2 + -> Data Node Scan (Node Count [2]) (cost=0.00..1.01 rows=1000 width=8) + Output: (tab1.val + tab1.val2), tab1.val, tab1.val2 +(6 rows) + +select tab1.val + tab2.val2, tab1.val, tab2.val2 from tab1, tab2 where tab1.val = tab2.val group by tab1.val, tab2.val2; + ?column? | val | val2 +----------+-----+------ + 2 | 1 | 1 + 6 | 2 | 4 + 5 | 3 | 2 + 7 | 3 | 4 + 5 | 4 | 1 + 6 | 4 | 2 +(6 rows) + +explain verbose select tab1.val + tab2.val2, tab1.val, tab2.val2 from tab1, tab2 where tab1.val = tab2.val group by tab1.val, tab2.val2; + QUERY PLAN +------------------------------------------------------------------------------- + Group (cost=0.01..0.02 rows=1 width=0) + Output: ((tab1.val + tab2.val2)), tab1.val, tab2.val2 + -> Materialize (cost=0.00..0.00 rows=0 width=0) + Output: ((tab1.val + tab2.val2)), tab1.val, tab2.val2 + -> Data Node Scan (Node Count [2]) (cost=0.00..1.01 rows=1 width=4) + Output: (tab1.val + tab2.val2), tab1.val, tab2.val2 +(6 rows) + +select tab1.val + tab2.val2 from tab1, tab2 where tab1.val = tab2.val group by tab1.val + tab2.val2; + ?column? +---------- + 2 + 5 + 6 + 7 +(4 rows) + +explain verbose select tab1.val + tab2.val2 from tab1, tab2 where tab1.val = tab2.val group by tab1.val + tab2.val2; + QUERY PLAN +------------------------------------------------------------------------------- + Group (cost=0.01..0.02 rows=1 width=0) + Output: ((tab1.val + tab2.val2)) + -> Materialize (cost=0.00..0.00 rows=0 width=0) + Output: ((tab1.val + tab2.val2)) + -> Data Node Scan (Node Count [2]) (cost=0.00..1.01 rows=1 width=4) + Output: (tab1.val + tab2.val2) +(6 rows) + +reset enable_hashagg; -- group by with aggregates in expression select count(*) + sum(val) + avg(val), val2 from tab1 group by val2; ?column? | val2 @@ -210,7 +300,8 @@ explain verbose select sum(y) from (select sum(val) y, val2%2 x from tab1 group Output: tab1.val, tab1.val2 (8 rows) --- group by without aggregate, just like distinct? +-- group by without aggregate +set enable_hashagg to off; select val2 from tab1 group by val2; val2 ------ @@ -222,7 +313,7 @@ select val2 from tab1 group by val2; explain verbose select val2 from tab1 group by val2; QUERY PLAN ---------------------------------------------------------------------------------- - HashAggregate (cost=1.02..1.03 rows=1 width=4) + Group (cost=1.02..1.03 rows=1 width=4) Output: tab1.val2 -> Materialize (cost=0.00..0.00 rows=0 width=0) Output: tab1.val2 @@ -230,6 +321,95 @@ explain verbose select val2 from tab1 group by val2; Output: tab1.val2 (6 rows) +select val + val2 from tab1 group by val + val2; + ?column? +---------- + 2 + 3 + 4 + 7 + |
From: Koichi S. <koi...@us...> - 2011-06-01 08:49:22
|
Project "Postgres-XC". The branch, ha_support has been updated via 612265336a7d8bc0666983f8b4d6c165aa15efb5 (commit) from 029f58652a406ed58ee392b317b358dc7841353f (commit) - Log ----------------------------------------------------------------- commit 612265336a7d8bc0666983f8b4d6c165aa15efb5 Author: Koichi Suzuki <koi...@gm...> Date: Wed Jun 1 17:41:42 2011 +0900 This commit corrects some problem related to node registration from gtm-proxy and gtm-standby. Problems scatters in various files and the causes are: 1) Some character strings obtained by pq_getmsgbytes() were left unterminated. Cleaned up most of them but there may be some more related issues not directly related to pq_getmsgbytes(). So far, as much as tested in five server environement, it works correctly. 2) Corrected node_get_local_addr() to obtain "local" address information. Was obtaining "remote" address instead. Modifed fies are: modified: src/gtm/client/gtm_client.c modified: src/gtm/main/gtm_txn.c modified: src/gtm/main/main.c modified: src/gtm/proxy/proxy_main.c modified: src/gtm/recovery/register.c diff --git a/src/gtm/client/gtm_client.c b/src/gtm/client/gtm_client.c index d4b98f3..c9dea5b 100644 --- a/src/gtm/client/gtm_client.c +++ b/src/gtm/client/gtm_client.c @@ -1182,31 +1182,31 @@ send_failed: char * node_get_local_addr(GTM_Conn *conn, char *buf, size_t buflen, int *rc) { - char remote_host[NI_MAXHOST]; - char remote_port[NI_MAXSERV]; + char local_host[NI_MAXHOST]; + char local_port[NI_MAXSERV]; *rc = 0; - memset(remote_host, 0, sizeof(remote_host)); - memset(remote_port, 0, sizeof(remote_port)); + memset(local_host, 0, sizeof(local_host)); + memset(local_port, 0, sizeof(local_port)); memset(buf, 0, buflen); if (conn->remote_type != PGXC_NODE_GTM_PROXY) { - if (gtm_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen, - remote_host, sizeof(remote_host), - remote_port, sizeof(remote_port), + if (gtm_getnameinfo_all(&conn->laddr.addr, conn->laddr.salen, + local_host, sizeof(local_host), + local_port, sizeof(local_port), NI_NUMERICSERV)) { - *rc = gtm_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen, - remote_host, sizeof(remote_host), - remote_port, sizeof(remote_port), + *rc = gtm_getnameinfo_all(&conn->laddr.addr, conn->laddr.salen, + local_host, sizeof(local_host), + local_port, sizeof(local_port), NI_NUMERICHOST | NI_NUMERICSERV); } } - if ( remote_host[0]!='\0' ) - strncpy(buf, remote_host, buflen); + if ( local_host[0]!='\0' ) + strncpy(buf, local_host, buflen); return buf; } diff --git a/src/gtm/main/gtm_txn.c b/src/gtm/main/gtm_txn.c index 0c6c238..809cc06 100644 --- a/src/gtm/main/gtm_txn.c +++ b/src/gtm/main/gtm_txn.c @@ -1514,7 +1514,7 @@ void ProcessGetGIDDataTransactionCommand(Port *myport, StringInfo message) { StringInfoData buf; - char *gid; + char gid[1024]; int gidlen; GTM_IsolationLevel txn_isolation_level; bool txn_read_only; @@ -1531,7 +1531,8 @@ ProcessGetGIDDataTransactionCommand(Port *myport, StringInfo message) /* receive GID */ gidlen = pq_getmsgint(message, sizeof (GTM_StrLen)); - gid = (char *)pq_getmsgbytes(message, gidlen); + memcpy(gid, (char *)pq_getmsgbytes(message, gidlen), gidlen); + gid[gidlen] = '\0'; pq_getmsgend(message); @@ -1971,7 +1972,7 @@ ProcessStartPreparedTransactionCommand(Port *myport, StringInfo message) PGXC_NodeId *coordinators = NULL; PGXC_NodeId *datanodes = NULL; MemoryContext oldContext; - char *gid; + char gid[1024]; isgxid = pq_getmsgbyte(message); @@ -1997,7 +1998,8 @@ ProcessStartPreparedTransactionCommand(Port *myport, StringInfo message) /* get GID */ gidlen = pq_getmsgint(message, sizeof (GTM_StrLen)); - gid = (char *)pq_getmsgbytes(message, gidlen); + memcpy(gid, (char *)pq_getmsgbytes(message, gidlen), gidlen); + gid[gidlen] = '\0'; /* Get Datanode Count Data */ datanodecnt = pq_getmsgint(message, 4); diff --git a/src/gtm/main/main.c b/src/gtm/main/main.c index 66096f5..96c90ed 100644 --- a/src/gtm/main/main.c +++ b/src/gtm/main/main.c @@ -421,7 +421,7 @@ main(int argc, char *argv[]) if ( gtm_is_standby() ) { - if ( !gtm_standby_register_self(node_num, GTMPortNumber, GTMDataDir) ) + if ( !gtm_standby_register_self(node_num, GTMPortNumber, GTMDataDir) ) { elog(ERROR, "Failed to register myself on the active-GTM as a GTM node."); exit(1); diff --git a/src/gtm/proxy/proxy_main.c b/src/gtm/proxy/proxy_main.c index 183a877..e0b5ca9 100644 --- a/src/gtm/proxy/proxy_main.c +++ b/src/gtm/proxy/proxy_main.c @@ -2847,10 +2847,13 @@ RegisterProxy(void) gtmpqPutInt(MSG_NODE_REGISTER, sizeof (GTM_MessageType), master_conn) || gtmpqPutnchar((char *)&type, sizeof(GTM_PGXCNodeType), master_conn) || gtmpqPutnchar((char *)>MProxyID, sizeof(GTM_PGXCNodeId), master_conn) || /* nodenum */ + gtmpqPutInt((int)strlen(ListenAddresses), sizeof(int), master_conn) || + gtmpqPutnchar(ListenAddresses, (int)strlen(ListenAddresses), master_conn) || gtmpqPutnchar((char *)&port, sizeof(GTM_PGXCNodePort), master_conn) || gtmpqPutnchar((char *)&proxynum, sizeof(GTM_PGXCNodeId), master_conn) || - gtmpqPutInt(strlen(GTMProxyDataDir), 4, master_conn) || - gtmpqPutnchar(GTMProxyDataDir, strlen(GTMProxyDataDir), master_conn)) + gtmpqPutInt((int)strlen(GTMProxyDataDir), 4, master_conn) || + gtmpqPutnchar(GTMProxyDataDir, strlen(GTMProxyDataDir), master_conn)|| + gtmpqPutInt(NODE_CONNECTED, sizeof(GTM_PGXCNodeStatus), master_conn)) goto failed; /* Finish the message. */ diff --git a/src/gtm/recovery/register.c b/src/gtm/recovery/register.c index 6fa11ff..f1a61fd 100644 --- a/src/gtm/recovery/register.c +++ b/src/gtm/recovery/register.c @@ -309,12 +309,13 @@ pgxcnode_copy_char(const char *str) * contextes. */ retstr = (char *) MemoryContextAlloc(TopMostMemoryContext, - strlen(str)); + strlen(str) + 1); if (retstr == NULL) ereport(ERROR, (ENOMEM, errmsg("Out of memory"))); memcpy(retstr, str, strlen(str)); + retstr[strlen(str)] = '\0'; return retstr; } @@ -385,8 +386,10 @@ Recovery_PGXCNodeRegister(GTM_PGXCNodeType type, nodeinfo->status = status; nodeinfo->socket = socket; - elog(LOG, "type=%d, nodenum=%d, port=%d, datafolder=%s, ipaddress=%s, status=%d", + elog(LOG, "Recovery_PGXCNodeRegister Request info: type=%d, nodenum=%d, port=%d, datafolder=%s, ipaddress=%s, status=%d", type, nodenum, port, datafolder, ipaddress, status); + elog(LOG, "Recovery_PGXCNodeRegister Node info: type=%d, nodenum=%d, port=%d, datafolder=%s, ipaddress=%s, status=%d", + nodeinfo->type, nodeinfo->nodenum, nodeinfo->port, nodeinfo->datafolder, nodeinfo->ipaddress, nodeinfo->status); /* Add PGXC Node Info to the global hash table */ errcode = pgxcnode_add_info(nodeinfo); @@ -413,7 +416,7 @@ ProcessPGXCNodeRegister(Port *myport, StringInfo message) GTM_PGXCNodePort port; char remote_host[NI_MAXHOST]; char remote_port[NI_MAXSERV]; - char *datafolder; + char datafolder[NI_MAXHOST]; char *ipaddress; MemoryContext oldContext; int strlen; @@ -425,7 +428,7 @@ ProcessPGXCNodeRegister(Port *myport, StringInfo message) remote_port[0] = '\0'; memset(remote_host, 0, sizeof(remote_host)); - +#if 0 if (myport->remote_type != PGXC_NODE_GTM_PROXY) { if (gtm_getnameinfo_all(&myport->raddr.addr, myport->raddr.salen, @@ -443,7 +446,7 @@ ProcessPGXCNodeRegister(Port *myport, StringInfo message) (errmsg_internal("gtm_getnameinfo_all() failed"))); } } - +#endif /* Read Node Type */ memcpy(&type, pq_getmsgbytes(message, sizeof (GTM_PGXCNodeType)), sizeof (GTM_PGXCNodeType)); @@ -474,7 +477,7 @@ ProcessPGXCNodeRegister(Port *myport, StringInfo message) else ipaddress = remote_host; #else - strlen = pq_getmsgint(message, sizeof (GTM_StrLen)); + strlen = pq_getmsgint(message, sizeof (int)); memcpy(remote_host, (char *)pq_getmsgbytes(message, strlen), strlen); remote_host[strlen] = '\0'; ipaddress = remote_host; @@ -488,14 +491,19 @@ ProcessPGXCNodeRegister(Port *myport, StringInfo message) /* Read Proxy ID number (0 if no proxy used) */ memcpy(&proxynum, pq_getmsgbytes(message, sizeof (GTM_PGXCNodeId)), sizeof (GTM_PGXCNodeId)); - elog(LOG, "ProcessPGXCNodeRegister: ipaddress = %s", ipaddress); /* * Finish by reading Data Folder (length and then string) */ strlen = pq_getmsgint(message, sizeof (GTM_StrLen)); + /* The next code was incorrect. Fixed. */ +#if 1 + memcpy(datafolder, (char *)pq_getmsgbytes(message, strlen), strlen); + datafolder[strlen] = '\0'; +#else datafolder = (char *)pq_getmsgbytes(message, strlen); +#endif status = pq_getmsgint(message, sizeof (GTM_PGXCNodeStatus)); ----------------------------------------------------------------------- Summary of changes: src/gtm/client/gtm_client.c | 24 ++++++++++++------------ src/gtm/main/gtm_txn.c | 10 ++++++---- src/gtm/main/main.c | 2 +- src/gtm/proxy/proxy_main.c | 7 +++++-- src/gtm/recovery/register.c | 22 +++++++++++++++------- 5 files changed, 39 insertions(+), 26 deletions(-) hooks/post-receive -- Postgres-XC |