Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7c84bc0

Browse files
committed
Provide for forward compatibility with future minor protocol versions.
Previously, any attempt to request a 3.x protocol version other than3.0 would lead to a hard connection failure, which made the minorprotocol version really no different from the major protocol versionand precluded gentle protocol version breaks. Instead, when theclient requests a 3.x protocol version where x is greater than 0, sendthe new NegotiateProtocolVersion message to convey that we supportonly 3.0. This makes it possible to introduce new minor protocolversions without requiring a connection retry when the server isolder.In addition, if the startup packet includes name/value pairs wherethe name starts with "_pq_.", assume that those are protocol options,not GUCs. Include those we don't support (i.e. all of them, atpresent) in the NegotiateProtocolVersion message so that the clientknows they were not understood. This makes it possible for theclient to request previously-unsupported features without bumpingthe protocol version at all; the client can tell from the server'sresponse whether the option was understood.It will take some time before servers that support these newfacilities become common in the wild; to speed things up and makethings easier for a future 3.1 protocol version, back-patch to allsupported releases.Robert Haas and Badrul ChowdhuryDiscussion:http://postgr.es/m/BN6PR21MB0772FFA0CBD298B76017744CD1730@BN6PR21MB0772.namprd21.prod.outlook.comDiscussion:http://postgr.es/m/30788.1498672033@sss.pgh.pa.us
1 parentfa9a69d commit7c84bc0

File tree

2 files changed

+158
-16
lines changed

2 files changed

+158
-16
lines changed

‎doc/src/sgml/protocol.sgml‎

Lines changed: 105 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,18 @@
2222
<productname>PostgreSQL</productname> 7.4 and later. For descriptions
2323
of the earlier protocol versions, see previous releases of the
2424
<productname>PostgreSQL</productname> documentation. A single server
25-
can support multiple protocol versions. The initial
26-
startup-request message tells the server which protocol version the
27-
client is attempting to use, and then the server follows that protocol
28-
if it is able.
25+
can support multiple protocol versions. The initial startup-request
26+
message tells the server which protocol version the client is attempting to
27+
use. If the major version requested by the client is not supported by
28+
the server, the connection will be rejected (for example, this would occur
29+
if the client requested protocol version 4.0, which does not exist as of
30+
this writing). If the minor version requested by the client is not
31+
supported by the server (e.g. the client requests version 3.1, but the
32+
server supports only 3.0), the server may either reject the connection or
33+
may respond with a NegotiateProtocolVersion message containing the highest
34+
minor protocol version which it supports. The client may then choose either
35+
to continue with the connection using the specified protocol version or
36+
to abort the connection.
2937
</para>
3038

3139
<para>
@@ -366,6 +374,20 @@
366374
</listitem>
367375
</varlistentry>
368376

377+
<varlistentry>
378+
<term>NegotiateProtocolVersion</term>
379+
<listitem>
380+
<para>
381+
The server does not support the minor protocol version requested
382+
by the client, but does support an earlier version of the protocol;
383+
this message indicates the highest supported minor version. This
384+
message will also be sent if the client requested unsupported protocol
385+
options (i.e. beginning with <literal>_pq_.</literal>) in the
386+
startup packet. This message will be followed by an ErrorResponse or
387+
a message indicating the success or failure of authentication.
388+
</para>
389+
</listitem>
390+
</varlistentry>
369391
</variablelist>
370392
</para>
371393

@@ -380,8 +402,10 @@
380402
for further messages from the server. In this phase a backend process
381403
is being started, and the frontend is just an interested bystander.
382404
It is still possible for the startup attempt
383-
to fail (ErrorResponse), but in the normal case the backend will send
384-
some ParameterStatus messages, BackendKeyData, and finally ReadyForQuery.
405+
to fail (ErrorResponse) or the server to decline support for the requested
406+
minor protocol version (NegotiateProtocolVersion), but in the normal case
407+
the backend will send some ParameterStatus messages, BackendKeyData, and
408+
finally ReadyForQuery.
385409
</para>
386410

387411
<para>
@@ -3927,6 +3951,74 @@ FunctionCallResponse (B)
39273951
</listitem>
39283952
</varlistentry>
39293953

3954+
<varlistentry>
3955+
<term>
3956+
NegotiateProtocolVersion (B)
3957+
</term>
3958+
<listitem>
3959+
<para>
3960+
3961+
<variablelist>
3962+
<varlistentry>
3963+
<term>
3964+
Byte1('v')
3965+
</term>
3966+
<listitem>
3967+
<para>
3968+
Identifies the message as a protocol version negotiation
3969+
message.
3970+
</para>
3971+
</listitem>
3972+
</varlistentry>
3973+
<varlistentry>
3974+
<term>
3975+
Int32
3976+
</term>
3977+
<listitem>
3978+
<para>
3979+
Length of message contents in bytes, including self.
3980+
</para>
3981+
</listitem>
3982+
</varlistentry>
3983+
<varlistentry>
3984+
<term>
3985+
Int32
3986+
</term>
3987+
<listitem>
3988+
<para>
3989+
Newest minor protocol version supported by the server
3990+
for the major protocol version requested by the client.
3991+
</para>
3992+
</listitem>
3993+
</varlistentry>
3994+
<varlistentry>
3995+
<term>
3996+
Int32
3997+
</term>
3998+
<listitem>
3999+
<para>
4000+
Number of protocol options not recognized by the server.
4001+
</para>
4002+
</listitem>
4003+
</varlistentry>
4004+
</variablelist>
4005+
Then, for protocol option not recognized by the server, there
4006+
is the following:
4007+
<variablelist>
4008+
<varlistentry>
4009+
<term>
4010+
String
4011+
</term>
4012+
<listitem>
4013+
<para>
4014+
The option name.
4015+
</para>
4016+
</listitem>
4017+
</varlistentry>
4018+
</variablelist>
4019+
</para>
4020+
</listitem>
4021+
</varlistentry>
39304022

39314023
<varlistentry>
39324024
<term>
@@ -4754,11 +4846,13 @@ StartupMessage (F)
47544846
</varlistentry>
47554847
</variablelist>
47564848

4757-
In addition to the above, any run-time parameter that can be
4758-
set at backend start time might be listed. Such settings
4759-
will be applied during backend start (after parsing the
4760-
command-line arguments if any). The values will act as
4761-
session defaults.
4849+
In addition to the above, others parameter may be listed.
4850+
Parameter names beginning with <literal>_pq_.</literal> are
4851+
reserved for use as protocol extensions, while others are
4852+
treated as run-time parameters to be set at backend start
4853+
time. Such settings will be applied during backend start
4854+
(after parsing the command-line arguments if any) and will
4855+
act as session defaults.
47624856
</para>
47634857
</listitem>
47644858
</varlistentry>

‎src/backend/postmaster/postmaster.c‎

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
#include"libpq/auth.h"
104104
#include"libpq/ip.h"
105105
#include"libpq/libpq.h"
106+
#include"libpq/pqformat.h"
106107
#include"libpq/pqsignal.h"
107108
#include"miscadmin.h"
108109
#include"pg_getopt.h"
@@ -402,6 +403,7 @@ static void ExitPostmaster(int status) pg_attribute_noreturn();
402403
staticintServerLoop(void);
403404
staticintBackendStartup(Port*port);
404405
staticintProcessStartupPacket(Port*port,boolSSLdone);
406+
staticvoidSendNegotiateProtocolVersion(List*unrecognized_protocol_options);
405407
staticvoidprocessCancelRequest(Port*port,void*pkt);
406408
staticintinitMasks(fd_set*rmask);
407409
staticvoidreport_fork_failure_to_client(Port*port,interrnum);
@@ -2016,12 +2018,9 @@ ProcessStartupPacket(Port *port, bool SSLdone)
20162018
*/
20172019
FrontendProtocol=proto;
20182020

2019-
/* Check we can handle the protocol the frontend is using. */
2020-
2021+
/* Check that the major protocol version is in range. */
20212022
if (PG_PROTOCOL_MAJOR(proto)<PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST)||
2022-
PG_PROTOCOL_MAJOR(proto)>PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST)||
2023-
(PG_PROTOCOL_MAJOR(proto)==PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST)&&
2024-
PG_PROTOCOL_MINOR(proto)>PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)))
2023+
PG_PROTOCOL_MAJOR(proto)>PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST))
20252024
ereport(FATAL,
20262025
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
20272026
errmsg("unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u",
@@ -2043,6 +2042,7 @@ ProcessStartupPacket(Port *port, bool SSLdone)
20432042
if (PG_PROTOCOL_MAJOR(proto) >=3)
20442043
{
20452044
int32offset=sizeof(ProtocolVersion);
2045+
List*unrecognized_protocol_options=NIL;
20462046

20472047
/*
20482048
* Scan packet body for name/option pairs. We can assume any string
@@ -2092,6 +2092,16 @@ ProcessStartupPacket(Port *port, bool SSLdone)
20922092
valptr),
20932093
errhint("Valid values are: \"false\", 0, \"true\", 1, \"database\".")));
20942094
}
2095+
elseif (strncmp(nameptr,"_pq_.",5)==0)
2096+
{
2097+
/*
2098+
* Any option beginning with _pq_. is reserved for use as a
2099+
* protocol-level option, but at present no such options are
2100+
* defined.
2101+
*/
2102+
unrecognized_protocol_options=
2103+
lappend(unrecognized_protocol_options,pstrdup(nameptr));
2104+
}
20952105
else
20962106
{
20972107
/* Assume it's a generic GUC option */
@@ -2111,6 +2121,16 @@ ProcessStartupPacket(Port *port, bool SSLdone)
21112121
ereport(FATAL,
21122122
(errcode(ERRCODE_PROTOCOL_VIOLATION),
21132123
errmsg("invalid startup packet layout: expected terminator as last byte")));
2124+
2125+
/*
2126+
* If the client requested a newer protocol version or if the client
2127+
* requested any protocol options we didn't recognize, let them know
2128+
* the newest minor protocol version we do support and the names of any
2129+
* unrecognized options.
2130+
*/
2131+
if (PG_PROTOCOL_MINOR(proto)>PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)||
2132+
unrecognized_protocol_options!=NIL)
2133+
SendNegotiateProtocolVersion(unrecognized_protocol_options);
21142134
}
21152135
else
21162136
{
@@ -2224,6 +2244,34 @@ ProcessStartupPacket(Port *port, bool SSLdone)
22242244
returnSTATUS_OK;
22252245
}
22262246

2247+
/*
2248+
* Send a NegotiateProtocolVersion to the client. This lets the client know
2249+
* that they have requested a newer minor protocol version than we are able
2250+
* to speak. We'll speak the highest version we know about; the client can,
2251+
* of course, abandon the connection if that's a problem.
2252+
*
2253+
* We also include in the response a list of protocol options we didn't
2254+
* understand. This allows clients to include optional parameters that might
2255+
* be present either in newer protocol versions or third-party protocol
2256+
* extensions without fear of having to reconnect if those options are not
2257+
* understood, while at the same time making certain that the client is aware
2258+
* of which options were actually accepted.
2259+
*/
2260+
staticvoid
2261+
SendNegotiateProtocolVersion(List*unrecognized_protocol_options)
2262+
{
2263+
StringInfoDatabuf;
2264+
ListCell*lc;
2265+
2266+
pq_beginmessage(&buf,'v');/* NegotiateProtocolVersion */
2267+
pq_sendint(&buf,PG_PROTOCOL_LATEST,4);
2268+
pq_sendint(&buf,list_length(unrecognized_protocol_options),4);
2269+
foreach(lc,unrecognized_protocol_options)
2270+
pq_sendstring(&buf,lfirst(lc));
2271+
pq_endmessage(&buf);
2272+
2273+
/* no need to flush, some other message will follow */
2274+
}
22272275

22282276
/*
22292277
* The client has sent a cancel request packet, not a normal

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp