From: Peter Eisentraut =0A= Date: Wed, 5 Apr 2017 10:44:23 -0400=0A= Subject: [PATCH 1/2] Fix logical replication between different encodings=0A= =0A= When sending a tuple attribute, the previous coding erroneously sent the=0A= length byte before encoding conversion, which would lead to protocol=0A= failures on the receiving side if the length did not match the following=0A= string.=0A= =0A= To fix that, use pq_sendcountedtext() for sending tuple attributes,=0A= which takes care of all of that internally. To match the API of=0A= pq_sendcountedtext(), send even text values without a trailing zero byte=0A= and have the receiving end put it in place instead. This matches how=0A= the standard FE/BE protocol behaves.=0A= =0A= Reported-by: Kyotaro HORIGUCHI =0A= ---=0A= doc/src/sgml/protocol.sgml | 7 +++++--=0A= src/backend/replication/logical/proto.c | 10 ++++------=0A= 2 files changed, 9 insertions(+), 8 deletions(-)=0A= =0A= diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml=0A= index 5f971412ae..9d46d74113 100644=0A= --- a/doc/src/sgml/protocol.sgml=0A= +++ b/doc/src/sgml/protocol.sgml=0A= @@ -6107,11 +6107,14 @@ Logical Replication Message Formats= =0A= =0A= =0A= =0A= - String=0A= + Byten=0A= =0A= =0A= =0A= - The text value.=0A= + The value of the column, in text format. (A future releas= e=0A= + might support additional formats.)=0A= + n is the above length.=0A= +=0A= =0A= =0A= =0A= diff --git a/src/backend/replication/logical/proto.c b/src/backend/replicat= ion/logical/proto.c=0A= index bc6e9b5a98..bb607b6147 100644=0A= --- a/src/backend/replication/logical/proto.c=0A= +++ b/src/backend/replication/logical/proto.c=0A= @@ -417,7 +417,6 @@ logicalrep_write_tuple(StringInfo out, Relation rel, He= apTuple tuple)=0A= Form_pg_type typclass;=0A= Form_pg_attribute att =3D desc->attrs[i];=0A= char *outputstr;=0A= - int len;=0A= =20=0A= /* skip dropped columns */=0A= if (att->attisdropped)=0A= @@ -442,10 +441,7 @@ logicalrep_write_tuple(StringInfo out, Relation rel, H= eapTuple tuple)=0A= pq_sendbyte(out, 't'); /* 'text' data follows */=0A= =20=0A= outputstr =3D OidOutputFunctionCall(typclass->typoutput, values[i]);=0A= - len =3D strlen(outputstr) + 1; /* null terminated */=0A= - pq_sendint(out, len, 4); /* length */=0A= - pq_sendstring(out, outputstr); /* data */=0A= -=0A= + pq_sendcountedtext(out, outputstr, strlen(outputstr), false);=0A= pfree(outputstr);=0A= =20=0A= ReleaseSysCache(typtup);=0A= @@ -492,7 +488,9 @@ logicalrep_read_tuple(StringInfo in, LogicalRepTupleDat= a *tuple)=0A= len =3D pq_getmsgint(in, 4); /* read length */=0A= =20=0A= /* and data */=0A= - tuple->values[i] =3D (char *) pq_getmsgbytes(in, len);=0A= + tuple->values[i] =3D palloc(len + 1);=0A= + pq_copymsgbytes(in, tuple->values[i], len);=0A= + tuple->values[i][len] =3D '\0';=0A= }=0A= break;=0A= default:=0A= --=20=0A= 2.12.2=0A= =0A= --------------55DA0F9A768EA133ABB756B4 Content-Type: invalid/octet-stream; name="0002-Add-test-for-logical-replication-with-different-enco.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename*0="0002-Add-test-for-logical-replication-with-different-enco.pa"; filename*1="tch"