Hi Robert,

Thanks very much for your quick response. PFA the patch containing the BE 
changes for pgwire v3.1, correctly formatted using pgindent this time 😊

A few salient points:

>> SendServerProtocolVersionMessage should be adjusted to use the new
>> facilities added by commit 1de09ad8eb1fa673ee7899d6dfbb2b49ba204818.

The new functionality is for sending 64bit ints. I think 32bits is sufficient 
for the information we want to pass around in the protocol negotiation phase, 
so I left this part unchanged.

>> Also, this really doesn't belong in guc.c at all.  We should be separating 
>> out
>> these options in ProcessStartupPacket() just as we do for existing protocol-
>> level options.  When we actually have some options, I think they should be
>> segregated into a separate list hanging off of the port, instead of letting 
>> them
>> get mixed into
>> port->guc_options, but for right now we don't have any yet, so a bunch
>> of this complexity can go away.

You are right, it is more elegant to make this a part of the port struct; I 
made the necessary changes in the patch.

Thanks,
Badrul

>> -----Original Message-----
>> From: Robert Haas [mailto:robertmh...@gmail.com]
>> Sent: Friday, October 13, 2017 11:16 AM
>> To: Badrul Chowdhury <bac...@microsoft.com>
>> Cc: Tom Lane <t...@sss.pgh.pa.us>; Satyanarayana Narlapuram
>> <satyanarayana.narlapu...@microsoft.com>; Craig Ringer
>> <cr...@2ndquadrant.com>; Peter Eisentraut <pete...@gmx.net>; Magnus
>> Hagander <mag...@hagander.net>; PostgreSQL-development <pgsql-
>> hack...@postgresql.org>
>> Subject: Re: [HACKERS] Re: protocol version negotiation (Re: Libpq
>> PGRES_COPY_BOTH - version compatibility)
>> 
>> On Fri, Oct 6, 2017 at 5:07 PM, Badrul Chowdhury <bac...@microsoft.com>
>> wrote:
>> > I added a mechanism to fall back to v3.0 if the BE fails to start when FE
>> initiates a connection with v3.1 (with optional startup parameters). This
>> completely eliminates the need to backpatch older servers, ie newer FE can
>> connect to older BE. Please let me know what you think.
>> 
>> Well, I think it needs a good bit of cleanup before we can really get to the
>> substance of the patch.
>> 
>> +    fe_utils \
>>      interfaces \
>>      backend/replication/libpqwalreceiver \
>>      backend/replication/pgoutput \
>> -    fe_utils \
>> 
>> Useless change, omit.
>> 
>> +    if (whereToSendOutput != DestRemote ||
>> +        PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
>> +        return -1;
>> +
>> +    int sendStatus = 0;
>> 
>> Won't compile on older compilers.  We generally aim for C89 compliance, with
>> a few exceptions for newer features.
>> 
>> Also, why initialize sendStatus and then overwrite the value in the very next
>> line of code?
>> 
>> Also, the PG_PROTOCOL_MAJOR check here seems to be redundant with the
>> one in the caller.
>> 
>> +    /* NegotiateServerProtocol packet structure
>> +     *
>> +     * [ 'Y' | msgLength | min_version | max_version | param_list_len
>> | list of param names ]
>> +     */
>> +
>> 
>> Please pgindent your patches.  I suspect you'll find this gets garbled.
>> 
>> Is there really any reason to separate NegotiateServerProtocol and
>> ServerProtocolVersion into separate functions?
>> 
>> -libpq = -L$(libpq_builddir) -lpq
>> +libpq = -L$(libpq_builddir) -lpq -L$(top_builddir)/src/common
>> -lpgcommon -L$(top_builddir)/src/fe_utils -lpgfeutils
>> +    $libpq->AddReference($libpgcommon, $libpgfeutils, $libpgport);
>> 
>> I haven't done any research to try to figure out why you did this, but I 
>> don't
>> think these are likely to be acceptable changes.
>> 
>> SendServerProtocolVersionMessage should be adjusted to use the new
>> facilities added by commit 1de09ad8eb1fa673ee7899d6dfbb2b49ba204818.
>> 
>> -    /* Check we can handle the protocol the frontend is using. */
>> -
>> -    if (PG_PROTOCOL_MAJOR(proto) <
>> PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) ||
>> -        PG_PROTOCOL_MAJOR(proto) >
>> PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) ||
>> -        (PG_PROTOCOL_MAJOR(proto) ==
>> PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) &&
>> -         PG_PROTOCOL_MINOR(proto) >
>> PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)))
>> -        ereport(FATAL,
>> -                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
>> -                 errmsg("unsupported frontend protocol %u.%u: server 
>> supports %
>> u.0 to %u.%u",
>> -                        PG_PROTOCOL_MAJOR(proto), PG_PROTOCOL_MINOR(proto),
>> -                        PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST),
>> -                        PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST),
>> -                        PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST))));
>> 
>> The way you've arranged things here looks like it'll cause us to accept
>> connections even for protocol versions 4.x or higher; I don't think we want
>> that.  I suggest checking the major version number at this point in the code;
>> then, the code path for version 3+ needs no additional check and the code
>> path for version 2 can enforce 2.0.
>> 
>> +bool
>> +is_optional(const char *guc_name)
>> +{
>> +    const char *optionalPrefix = "_pq_";
>> +    bool isOptional = false;
>> +
>> +    /* "_pq_" must be a proper prefix of the guc name in all encodings */
>> +    if (guc_name_compare(guc_name, optionalPrefix) == 1 &&
>> +        strstr(guc_name, optionalPrefix))
>> +        isOptional = true;
>> +
>> +    return isOptional;
>> +}
>> 
>> This seems like very strange coding for all kinds of reasons.  Why is
>> guc_name_compare() used to do the comparison and strstr() then used
>> afterwards?  Why do we need two tests instead of just one, and why should
>> one of them be case-sensitive and the other not?  Why not just use strncmp?
>> Why write bool var = false; if (blah blah) var = true; return var; instead 
>> of just
>> return blah blah?  Why the comment about encodings - that doesn't seem
>> particularly relevant here?  Why redeclare the prefix here instead of having 
>> a
>> common definition someplace that can be used by both the frontend and the
>> backend, probably a header file #define?
>> 
>> Also, this really doesn't belong in guc.c at all.  We should be separating 
>> out
>> these options in ProcessStartupPacket() just as we do for existing protocol-
>> level options.  When we actually have some options, I think they should be
>> segregated into a separate list hanging off of the port, instead of letting 
>> them
>> get mixed into
>> port->guc_options, but for right now we don't have any yet, so a bunch
>> of this complexity can go away.
>> 
>> +    ListCell *gucopts = list_head(port->guc_options);
>> +    while (gucopts)
>> +    {
>> +        char       *name;
>> +
>> +        /* First comes key, which we need. */
>> +        name = lfirst(gucopts);
>> +        gucopts = lnext(gucopts);
>> +
>> +        /* Then comes value, which we don't need. */
>> +        gucopts = lnext(gucopts);
>> +
>> +        pq_sendstring(&buf, name);
>> +    }
>> 
>> This is another coding rule violation because the declaration of gucopts
>> follows executable statements.
>> 
>> -    SimpleStringList roles = {NULL, NULL};
>> +    SimpleStringList roles = {NULL, NULL, NULL};
>> 
>> I don't think it's a good idea to change SimpleStringList like this -- it's 
>> used in
>> lots of places already.  If we were going to do it, a bool needs to be set to
>> false, not NULL.
>> 
>> +    /* Cannot append to immutable list */
>> +    if (list->is_immutable)
>> +        return;
>> 
>> Even if I were inclined to support changing the SimpleStringList abstraction,
>> this seems like super-confusing behavior -- just don't append, and don't warn
>> the user that nothing happened in any way?
>> Ugh.
>> 
>> +override CPPFLAGS := -DFRONTEND $(CPPFLAGS) -fPIC override CPPFLAGS :=
>> +-DFRONTEND -I$(libpq_srcdir) $(CPPFLAGS) -fPIC
>> 
>> Seems unrelated to anything this patch is about.
>> 
>> +#include "postgres.h"
>> 
>> We never include "postgres.h" in other header files.
>> 
>> +#include "libpq/libpq-be.h"
>> +
>> +extern int NegotiateServerProtocol(Port *port); extern int
>> +SendServerProtocolVersionMessage(Port *port);
>> 
>> These changes aren't needed.  The functions aren't called from outside the 
>> file
>> where they are defined, so just make them static and prototype them in that
>> file.  That avoids sucking in additional headers into this file.
>> 
>> +                /*
>> +                * Block until message length is read.
>> +                *
>> +                * No need to account for 2.x fixed-length message
>> because this state cannot
>> +                * be reached by pre-3.0 server.
>> +                */
>> 
>> Wrong formatting.  pgindent will fix it.
>> 
>> +                {
>> +                    return PGRES_POLLING_READING;
>> +                }
>> 
>> Superfluous braces.
>> 
>> +                {
>> +                    server_is_older = true;
>> +                }
>> 
>> And here.
>> 
>> +                    runningMsgLength -= buf->len + 1; /* +1 for NULL */
>> 
>> NUL or \0, not NULL.  You're talking about the byte, not the pointer value.
>> 
>> In general, I think it might be a good idea for the client to send a
>> 3.0 connection request unless the user requests some feature that requires
>> use of a >3.0 protocol version -- and right now there are no such features.  
>> It's
>> a little hard to predict what we might want to do with minor protocol 
>> versions
>> in the future so maybe at some point there will be a good reason for us to
>> request the newest protocol version we can get (e.g. if we make some
>> protocol change that improves performance).  Right now, though, there's a big
>> advantage to not requesting anything beyond 3.0 unless we need it -- it works
>> with existing servers.  So I suggest that for right now we just make the 
>> server
>> side changes here to 3.x,x>0 protocol versions and accept _pq_.whatever
>> parameters, and leave all of these libpq changes out completely.  Some future
>> patch might need those changes but this one doesn't.
>> 
>> --
>> Robert Haas
>> EnterpriseDB:
>> https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.ent
>> erprisedb.com&data=02%7C01%7Cbachow%40microsoft.com%7Ce68db1491
>> 10b426ceb4e08d51266842c%7C72f988bf86f141af91ab2d7cd011db47%7C1
>> %7C0%7C636435153876276748&sdata=1Y%2FLhfYfN9Km8PxKAN7ghF1siYUt
>> hXoIY0LGxQNywk8%3D&reserved=0
>> The Enterprise PostgreSQL Company

Attachment: pgwire_be.patch
Description: pgwire_be.patch

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to