Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wPxoG-001BDR-2H for pgsql-hackers@arkaria.postgresql.org; Thu, 21 May 2026 07:27:12 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wPxoE-009bjB-2D for pgsql-hackers@arkaria.postgresql.org; Thu, 21 May 2026 07:27:11 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wPxoE-009bj2-0T for pgsql-hackers@lists.postgresql.org; Thu, 21 May 2026 07:27:11 +0000 Received: from mail-pl1-x62f.google.com ([2607:f8b0:4864:20::62f]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wPxoC-00000000475-22S3 for pgsql-hackers@postgresql.org; Thu, 21 May 2026 07:27:10 +0000 Received: by mail-pl1-x62f.google.com with SMTP id d9443c01a7336-2bdeed4f717so25922925ad.0 for ; Thu, 21 May 2026 00:27:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779348427; x=1779953227; darn=postgresql.org; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=flqR1xku+ezNybtCSr/bSph3acI/Qeyq1VM5KoAWbgs=; b=dvRlvIn8cn4hqNIBvZCi+oHI8AokqkLAIhsUNp5M/sdiV2MLQLttjMszhqOTBZBK8N hY99fjuwYwm0uMzuw/PzwMQ9Asok7RtoihL6yYjLG68HFANNOsJDEykBCUufEBJDZafI mdvJClyrRYJhyu6i6j/xO2aoLxv1UytIt++n76amMQ5trzO7XwvXxE7K8nBllg9yr+Qz pYIIQYp+sh+pwrAg+6MjxfR7TuPFAxShFqJ1iB+OmjZhfAIR0ryg64QGMAeJrk7V+tap Pq3NQJXe7ehAe2PoqNefOZcMp2+DgIHA3Cg3sub2afp4CttORk3TCoIVUJoSGAyWmt2w qYow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779348427; x=1779953227; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=flqR1xku+ezNybtCSr/bSph3acI/Qeyq1VM5KoAWbgs=; b=AzNSkRxY/uWZo3/zzaKxyeYWX+AB8QBDWq5RQ+Oa950RhNbUHxKq5jj8xNbhJjHwsC qomWKw4s+bkKOKNVJS7epPrcORreb06mk53ckvz2+hFth8XiKYrVPxF+8ge/hO1f55OG q8rvbGyO2T1bsSk99jfABJ0sl09IO0uhe5v9Je7GvGmMZg3QOetr2oMvBwojnfjGZYrz hr/G19Xh/GCtPqumwv63EQftSzL6MS0xXadC/EIhBXT0oxiN7hHYcl+0bVm1Yx4kk80R eyO0jFYgCJ/R6FCaWnxdAOOmZkoNizJjk0NCJRiPCDHePQrXw5AYWANL47nxYZtChiqP YwiQ== X-Forwarded-Encrypted: i=1; AFNElJ//+09sutN4uTa81rGJpGNb95fmWsWlnU5k7oLAXouU458wMZFNe+iiq8lT/uZd46LjGKKCuFiiV9JvhuOr@postgresql.org X-Gm-Message-State: AOJu0Yyivlks6rd6y9b9rYPd3BFvx+bWh2G6KQWMtrrNiITQ+PYpaxG6 AlFk+84chOeZuJC/CzAfYJ2XBiVznfPI3fNH/rww4AyzNQ75crhXmTMG X-Gm-Gg: Acq92OFqM14EwxHpKvdnqN1QTrvVIpplXNpd1x4ZErAzaEST2OyxmdEUaiRd0SaCrYJ nLJkk8AvMD4Cj4EKX3UXLxnHT6oy69xQCCsVk6pf6anM9Ifb60ooY5z+91yL4ysbf9rCZ219jTk tSAGyOV32mdTyOo1RVtd8Q17dNKPDY2eagizk6vv41G9PYMOx3ltrJNffdMaQeHy6J9evTj+eSg oDrvgo0uDJQuSlpU6bpj8Ftfna09NGdsILC6CHNIAWMWbh8GV+evSHSiwLgSKy6UKI2/YdSdnke BpDfwklUs48QOQmGrHmnR/74u0FOi9BamRO5FoqbpwayT6k5zTM5Z/TdDNbRTtY5e+Ny753ZUJb c7BTU6pmMKU1KgCsfWOE1GdIIl+qLvmamc+TJXODhqnI+Cww0I31bY4QWncsFLmsuC5qeyEyF1k MbYM0lrMZpOKq0dOO1I3Pyx8iA8wNEITw= X-Received: by 2002:a17:903:2441:b0:2bc:7c62:187 with SMTP id d9443c01a7336-2bea33949b9mr17921065ad.29.1779348427209; Thu, 21 May 2026 00:27:07 -0700 (PDT) Received: from smtpclient.apple ([45.32.121.103]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2bea9900e39sm740415ad.59.2026.05.21.00.27.04 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 21 May 2026 00:27:06 -0700 (PDT) From: Chao Li Message-Id: <6B9A85F9-B632-4286-98AF-9EC435019055@gmail.com> Content-Type: multipart/mixed; boundary="Apple-Mail=_CF9F3BB0-4D8B-4367-BE58-99B3B8A6151D" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.600.51.1.1\)) Subject: Re: Set notice receiver before libpq connection startup Date: Thu, 21 May 2026 15:26:27 +0800 In-Reply-To: Cc: Fujii Masao , PostgreSQL-development To: vignesh C References: <978D8971-08C3-4AAD-AE8B-976D753C882A@gmail.com> X-Mailer: Apple Mail (2.3864.600.51.1.1) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --Apple-Mail=_CF9F3BB0-4D8B-4367-BE58-99B3B8A6151D Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On May 21, 2026, at 13:03, vignesh C wrote: >=20 > On Thu, 21 May 2026 at 07:40, Chao Li wrote: >>=20 >>=20 >>=20 >>> On May 20, 2026, at 17:19, Fujii Masao = wrote: >>>=20 >>> On Wed, May 20, 2026 at 4:21=E2=80=AFPM Chao Li = wrote: >>>>=20 >>>> Hi, >>>>=20 >>>> While testing =E2=80=9CLog remote NOTICE, WARNING, and similar = messages using ereport()=E2=80=9D, I noticed that = libpqsrv_notice_receiver is only installed after libpqsrv_connect() = finishes. As a result, NOTICE messages generated during connection = establishment are missed by ereport() and are still printed to stderr. >>>>=20 >>>> To reproduce the issue, I created a separate database called = remotedb and defined a login trigger that emits a NOTICE message: >>>> ``` >>>> CREATE DATABASE remotedb; >>>>=20 >>>> \c remotedb >>>>=20 >>>> CREATE OR REPLACE FUNCTION repro_login_notice() >>>> RETURNS event_trigger >>>> LANGUAGE plpgsql AS $$ >>>> BEGIN >>>> RAISE NOTICE 'startup notice from remotedb login trigger'; >>>> END; >>>> $$; >>>>=20 >>>> CREATE EVENT TRIGGER repro_login_notice_trg >>>> ON login >>>> EXECUTE FUNCTION repro_login_notice(); >>>>=20 >>>> ALTER EVENT TRIGGER repro_login_notice_trg ENABLE ALWAYS; >>>> ``` >>>>=20 >>>> Then, from another database: >>>> ``` >>>> evantest=3D# create extension dblink; >>>> CREATE EXTENSION >>>> evantest=3D# SELECT dblink_connect('host=3D127.0.0.1 port=3D5432 = dbname=3Dremotedb user=3Dchaol sslmode=3Ddisable gssencmode=3Ddisable'); >>>> dblink_connect >>>> ---------------- >>>> OK >>>> (1 row) >>>> ``` >>>>=20 >>>> In the system log, the NOTICE message is printed directly: >>>> ``` >>>> 2026-05-20 13:02:19.350 CST [24909] STATEMENT: SELECT = dblink_connect('host=3D127.0.0.1 port=3D5432 dbname=3Dremotedb = user=3Dchaol sslmode=3Ddisable gssencmode=3Ddisable'); >>>> NOTICE: startup notice from remotedb login trigger >>>> ``` >>>>=20 >>>> To fix that, I think we should install libpqsrv_notice_receiver = before libpqsrv_connect_internal(). In the attached patch, I added two = helpers: libpqsrv_connect_with_notice_receiver() and = libpqsrv_connect_params_with_notice_receiver(). >>>>=20 >>>> With the fix, the NOTICE message now looks like this: >>>> ``` >>>> 2026-05-20 14:44:49.296 CST [45567] LOG: received message via = remote connection: NOTICE: startup notice from remotedb login trigger >>>> 2026-05-20 14:44:49.296 CST [45567] STATEMENT: SELECT = dblink_connect('host=3D127.0.0.1 port=3D5432 dbname=3Dremotedb = user=3Dchaol sslmode=3Ddisable gssencmode=3Ddisable'); >>>> ``` >>>>=20 >>>> Please see the attached patch for details. >>>=20 >>> Thanks for the report and patch! >>>=20 >>> I'd prefer to avoid adding notice-receiver-specific wrappers such as >>> libpqsrv_connect_with_notice_receiver(). Instead, how about = splitting >>> libpqsrv_connect() into two steps: libpqsrv_connect_start(), which = performs >>> libpqsrv_connect_prepare() and PQconnectStart(), and >>> libpqsrv_connect_complete(), which runs libpqsrv_connect_internal()? >>>=20 >>> With this approach, callers could invoke PQsetNoticeReceiver() after >>> libpqsrv_connect_start() returns but before = libpqsrv_connect_complete() is >>> called. This would allow startup-time notices to be handled = correctly without >>> introducing a dedicated wrapper function. >>>=20 >>> Compared to the *_with_notice_receiver() approach, this design is = more >>> general because it exposes the phase between PQconnectStart() and = connection >>> completion. It could also support other kinds of per-connection = setup in the >>> future, not just notice receiver installation. Thought? >>>=20 >>> Regards, >>>=20 >>> -- >>> Fujii Masao >>=20 >> The idea sounds good to me, so v2 is implemented following that idea. >>=20 >> A few things I want to point out abut v2: >>=20 >> * Since libpqsrv_connect_complete() would only wrap = libpqsrv_connect_internal(), I just renamed libpqsrv_connect_internal() = to libpqsrv_connect_complete(). >> * Since libpqsrv_connect() is now split into two phases, = libpqsrv_connect_complete() must be called even if conn is NULL, because = it may need to call ReleaseExternalFD(). I mentioned this in the header = comment of libpqsrv_connect_start(). >> * In the postgres_fdw/connection.c change, I introduced a new local = variable, start_conn, to keep the original logic unchanged. Because = there is a PG_TRY/PG_CATCH block, conn is assigned only after = libpqsrv_connect_complete() finishes successfully. >=20 > Thanks for reporting this issue. I was able to reproduce the issue > with the steps provided and your patch fixes the issue. > Few comments: > 1) No need of conn variable here, we can directly return > PQconnectStart(conninfo) in this function: > +static inline PGconn * > +libpqsrv_connect_start(const char *conninfo) > +{ > + PGconn *conn =3D NULL; > + > + libpqsrv_connect_prepare(); > + > + conn =3D PQconnectStart(conninfo); > + > + return conn; > +} >=20 > 2) Similarly here too: > +static inline PGconn * > +libpqsrv_connect_params_start(const char *const *keywords, > + const char *const *values, > + int expand_dbname) > { > PGconn *conn =3D NULL; >=20 > libpqsrv_connect_prepare(); >=20 > - conn =3D PQconnectStart(conninfo); > - > - libpqsrv_connect_internal(conn, wait_event_info); > + conn =3D PQconnectStartParams(keywords, values, expand_dbname); >=20 > return conn; > } >=20 > Regards, > Vignesh Thanks for your comment. Addressed in v3. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ --Apple-Mail=_CF9F3BB0-4D8B-4367-BE58-99B3B8A6151D Content-Disposition: attachment; filename=v3-0001-Set-notice-receiver-before-libpq-connection-start.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v3-0001-Set-notice-receiver-before-libpq-connection-start.patch" Content-Transfer-Encoding: quoted-printable =46rom=208549b8bfbaa48a954687c12d732f4bb4443a4d85=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20"Chao=20Li=20(Evan)"=20=0A= Date:=20Wed,=2020=20May=202026=2014:57:25=20+0800=0ASubject:=20[PATCH=20= v3]=20Set=20notice=20receiver=20before=20libpq=20connection=20startup=0A=0A= libpqsrv_connect()=20and=20libpqsrv_connect_params()=20complete=20the=20= libpq=0Aconnection=20startup=20before=20returning=20the=20PGconn.=20=20= As=20a=20result,=20callers=20that=0Ainstall=20a=20notice=20receiver=20= after=20these=20functions=20return=20can=20miss=20NOTICE,=0AWARNING,=20= and=20similar=20messages=20emitted=20during=20connection=20= establishment.=0A=0ASplit=20the=20connection=20helper=20API=20into=20= start=20and=20complete=20steps,=20so=20callers=0Acan=20install=20= per-connection=20setup=20such=20as=20notice=20receivers=20after=0A= PQconnectStart()=20returns=20but=20before=20the=20startup=20sequence=20= is=20completed.=0A=0ADocument=20the=20resource-lifetime=20rule=20for=20= the=20split=20API:=20callers=20must=20either=0Acall=20= libpqsrv_connect_complete(),=20even=20when=20the=20start=20function=20= returns=20NULL,=0Aor=20otherwise=20clean=20up=20the=20partially-started=20= connection=20and=20release=20the=0Areserved=20external=20FD=20if=20an=20= error=20is=20thrown=20before=20completion.=0A=0AAuthor:=20Chao=20Li=20= =0AReviewed-by:=20Fujii=20Masao=20= =0AReviewed-by:=20Vignesh=20C=20= =0ADiscussion:=20= https://postgr.es/m/A2B8B7DE-C119-492F-A9FA-14CF86849777@gmail.com=0A---=0A= =20contrib/dblink/dblink.c=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20|=2018=20++---=0A=20= contrib/postgres_fdw/connection.c=20=20=20=20=20=20=20=20=20=20=20=20=20= |=2014=20++--=0A=20.../libpqwalreceiver/libpqwalreceiver.c=20=20=20=20=20= =20=20|=2013=20++--=0A=20src/include/libpq/libpq-be-fe-helpers.h=20=20=20= =20=20=20=20|=2065=20++++++++++++++-----=0A=204=20files=20changed,=2073=20= insertions(+),=2037=20deletions(-)=0A=0Adiff=20--git=20= a/contrib/dblink/dblink.c=20b/contrib/dblink/dblink.c=0Aindex=20= d843eee7e97..0751df9e444=20100644=0A---=20a/contrib/dblink/dblink.c=0A= +++=20b/contrib/dblink/dblink.c=0A@@=20-222,7=20+222,11=20@@=20= dblink_get_conn(char=20*conname_or_str,=0A=20=09=09=09dblink_we_get_conn=20= =3D=20WaitEventExtensionNew("DblinkGetConnect");=0A=20=0A=20=09=09/*=20= OK=20to=20make=20connection=20*/=0A-=09=09conn=20=3D=20= libpqsrv_connect(connstr,=20dblink_we_get_conn);=0A+=09=09conn=20=3D=20= libpqsrv_connect_start(connstr);=0A+=09=09if=20(conn=20!=3D=20NULL)=0A+=09= =09=09PQsetNoticeReceiver(conn,=20libpqsrv_notice_receiver,=0A+=09=09=09=09= =09=09=09=09"received=20message=20via=20remote=20connection");=0A+=09=09= libpqsrv_connect_complete(conn,=20dblink_we_get_conn);=0A=20=0A=20=09=09= if=20(PQstatus(conn)=20=3D=3D=20CONNECTION_BAD)=0A=20=09=09{=0A@@=20= -235,9=20+239,6=20@@=20dblink_get_conn(char=20*conname_or_str,=0A=20=09=09= =09=09=09=20errdetail_internal("%s",=20msg)));=0A=20=09=09}=0A=20=0A-=09=09= PQsetNoticeReceiver(conn,=20libpqsrv_notice_receiver,=0A-=09=09=09=09=09=09= =09"received=20message=20via=20remote=20connection");=0A-=0A=20=09=09= dblink_security_check(conn,=20NULL,=20connstr);=0A=20=09=09if=20= (PQclientEncoding(conn)=20!=3D=20GetDatabaseEncoding())=0A=20=09=09=09= PQsetClientEncoding(conn,=20GetDatabaseEncodingName());=0A@@=20-321,7=20= +322,11=20@@=20dblink_connect(PG_FUNCTION_ARGS)=0A=20=09}=0A=20=0A=20=09= /*=20OK=20to=20make=20connection=20*/=0A-=09conn=20=3D=20= libpqsrv_connect(connstr,=20dblink_we_connect);=0A+=09conn=20=3D=20= libpqsrv_connect_start(connstr);=0A+=09if=20(conn=20!=3D=20NULL)=0A+=09=09= PQsetNoticeReceiver(conn,=20libpqsrv_notice_receiver,=0A+=09=09=09=09=09=09= =09"received=20message=20via=20remote=20connection");=0A+=09= libpqsrv_connect_complete(conn,=20dblink_we_connect);=0A=20=0A=20=09if=20= (PQstatus(conn)=20=3D=3D=20CONNECTION_BAD)=0A=20=09{=0A@@=20-336,9=20= +341,6=20@@=20dblink_connect(PG_FUNCTION_ARGS)=0A=20=09=09=09=09=20= errdetail_internal("%s",=20msg)));=0A=20=09}=0A=20=0A-=09= PQsetNoticeReceiver(conn,=20libpqsrv_notice_receiver,=0A-=09=09=09=09=09=09= "received=20message=20via=20remote=20connection");=0A-=0A=20=09/*=20= check=20password=20actually=20used=20if=20not=20superuser=20*/=0A=20=09= dblink_security_check(conn,=20connname,=20connstr);=0A=20=0Adiff=20--git=20= a/contrib/postgres_fdw/connection.c=20= b/contrib/postgres_fdw/connection.c=0Aindex=203d2a8d0519d..86178ec5fb2=20= 100644=0A---=20a/contrib/postgres_fdw/connection.c=0A+++=20= b/contrib/postgres_fdw/connection.c=0A@@=20-638,6=20+638,7=20@@=20= connect_pg_server(ForeignServer=20*server,=20UserMapping=20*user)=0A=20=09= =09const=20char=20**keywords;=0A=20=09=09const=20char=20**values;=0A=20=09= =09char=09=20=20=20*appname;=0A+=09=09PGconn=09=20=20=20*start_conn;=0A=20= =0A=20=09=09construct_connection_params(server,=20user,=20&keywords,=20= &values,=20&appname);=0A=20=0A@@=20-646,9=20+647,13=20@@=20= connect_pg_server(ForeignServer=20*server,=20UserMapping=20*user)=0A=20=09= =09=09pgfdw_we_connect=20=3D=20= WaitEventExtensionNew("PostgresFdwConnect");=0A=20=0A=20=09=09/*=20OK=20= to=20make=20connection=20*/=0A-=09=09conn=20=3D=20= libpqsrv_connect_params(keywords,=20values,=0A-=09=09=09=09=09=09=09=09=09= =20=20=20false,=09/*=20expand_dbname=20*/=0A-=09=09=09=09=09=09=09=09=09=20= =20=20pgfdw_we_connect);=0A+=09=09start_conn=20=3D=20= libpqsrv_connect_params_start(keywords,=20values,=0A+=09=09=09=09=09=09=09= =09=09=09=09=09=20=20=20/*=20expand_dbname=20=3D=20*/=20false);=0A+=09=09= if=20(start_conn=20!=3D=20NULL)=0A+=09=09=09= PQsetNoticeReceiver(start_conn,=20libpqsrv_notice_receiver,=0A+=09=09=09=09= =09=09=09=09"received=20message=20via=20remote=20connection");=0A+=09=09= libpqsrv_connect_complete(start_conn,=20pgfdw_we_connect);=0A+=09=09conn=20= =3D=20start_conn;=0A=20=0A=20=09=09if=20(!conn=20||=20PQstatus(conn)=20= !=3D=20CONNECTION_OK)=0A=20=09=09=09ereport(ERROR,=0A@@=20-657,9=20= +662,6=20@@=20connect_pg_server(ForeignServer=20*server,=20UserMapping=20= *user)=0A=20=09=09=09=09=09=09=09server->servername),=0A=20=09=09=09=09=09= =20errdetail_internal("%s",=20pchomp(PQerrorMessage(conn)))));=0A=20=0A-=09= =09PQsetNoticeReceiver(conn,=20libpqsrv_notice_receiver,=0A-=09=09=09=09=09= =09=09"received=20message=20via=20remote=20connection");=0A-=0A=20=09=09= /*=20Perform=20post-connection=20security=20checks.=20*/=0A=20=09=09= pgfdw_security_check(keywords,=20values,=20user,=20conn);=0A=20=0Adiff=20= --git=20a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c=20= b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c=0Aindex=20= 9f04c9ed25d..af2734cb328=20100644=0A---=20= a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c=0A+++=20= b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c=0A@@=20= -223,9=20+223,13=20@@=20libpqrcv_connect(const=20char=20*conninfo,=20= bool=20replication,=20bool=20logical,=0A=20=0A=20=09conn=20=3D=20= palloc0_object(WalReceiverConn);=0A=20=09conn->streamConn=20=3D=0A-=09=09= libpqsrv_connect_params(keys,=20vals,=0A-=09=09=09=09=09=09=09=09=20/*=20= expand_dbname=20=3D=20*/=20true,=0A-=09=09=09=09=09=09=09=09= WAIT_EVENT_LIBPQWALRECEIVER_CONNECT);=0A+=09=09= libpqsrv_connect_params_start(keys,=20vals,=0A+=09=09=09=09=09=09=09=09=09= =20=20/*=20expand_dbname=20=3D=20*/=20true);=0A+=09if=20= (conn->streamConn=20!=3D=20NULL)=0A+=09=09= PQsetNoticeReceiver(conn->streamConn,=20libpqsrv_notice_receiver,=0A+=09=09= =09=09=09=09=09"received=20message=20via=20replication");=0A+=09= libpqsrv_connect_complete(conn->streamConn,=0A+=09=09=09=09=09=09=09=20=20= WAIT_EVENT_LIBPQWALRECEIVER_CONNECT);=0A=20=0A=20=09if=20(options_val=20= !=3D=20NULL)=0A=20=09=09pfree(options_val);=0A@@=20-245,9=20+249,6=20@@=20= libpqrcv_connect(const=20char=20*conninfo,=20bool=20replication,=20bool=20= logical,=0A=20=09=09=09=09=20errhint("Target=20server's=20authentication=20= method=20must=20be=20changed,=20or=20set=20password_required=3Dfalse=20= in=20the=20subscription=20parameters.")));=0A=20=09}=0A=20=0A-=09= PQsetNoticeReceiver(conn->streamConn,=20libpqsrv_notice_receiver,=0A-=09=09= =09=09=09=09"received=20message=20via=20replication");=0A-=0A=20=09/*=0A=20= =09=20*=20Set=20always-secure=20search=20path=20for=20the=20cases=20= where=20the=20connection=20is=0A=20=09=20*=20used=20to=20run=20SQL=20= queries,=20so=20malicious=20users=20can't=20get=20control.=0Adiff=20= --git=20a/src/include/libpq/libpq-be-fe-helpers.h=20= b/src/include/libpq/libpq-be-fe-helpers.h=0Aindex=20= 85d8b63f019..cff68cd1c37=20100644=0A---=20= a/src/include/libpq/libpq-be-fe-helpers.h=0A+++=20= b/src/include/libpq/libpq-be-fe-helpers.h=0A@@=20-39,10=20+39,28=20@@=0A=20= =0A=20=0A=20static=20inline=20void=20libpqsrv_connect_prepare(void);=0A= -static=20inline=20void=20libpqsrv_connect_internal(PGconn=20*conn,=20= uint32=20wait_event_info);=0A+static=20inline=20void=20= libpqsrv_connect_complete(PGconn=20*conn,=20uint32=20wait_event_info);=0A= =20static=20inline=20PGresult=20*libpqsrv_get_result_last(PGconn=20= *conn,=20uint32=20wait_event_info);=0A=20static=20inline=20PGresult=20= *libpqsrv_get_result(PGconn=20*conn,=20uint32=20wait_event_info);=0A=20=0A= +/*=0A+=20*=20Start=20a=20connection=20using=20PQconnectStart().=0A+=20*=0A= +=20*=20The=20returned=20connection=20has=20not=20yet=20completed=20its=20= startup=20sequence.=20=20Callers=0A+=20*=20may=20perform=20= per-connection=20setup,=20such=20as=20installing=20a=20notice=20= receiver,=0A+=20*=20before=20calling=20libpqsrv_connect_complete().=0A+=20= *=0A+=20*=20Callers=20must=20call=20libpqsrv_connect_complete(),=20even=20= if=20this=20function=20returns=0A+=20*=20NULL,=20because=20= libpqsrv_connect_prepare()=20may=20already=20have=20reserved=20an=0A+=20= *=20external=20FD=20that=20must=20be=20released.=0A+=20*/=0A+static=20= inline=20PGconn=20*=0A+libpqsrv_connect_start(const=20char=20*conninfo)=0A= +{=0A+=09libpqsrv_connect_prepare();=0A+=0A+=09return=20= PQconnectStart(conninfo);=0A+}=0A=20=0A=20/*=0A=20=20*=20PQconnectdb()=20= wrapper=20that=20reserves=20a=20file=20descriptor=20and=20processes=0A@@=20= -55,17=20+73,30=20@@=20static=20inline=20PGresult=20= *libpqsrv_get_result(PGconn=20*conn,=20uint32=20wait_event_info=0A=20= static=20inline=20PGconn=20*=0A=20libpqsrv_connect(const=20char=20= *conninfo,=20uint32=20wait_event_info)=0A=20{=0A-=09PGconn=09=20=20=20= *conn=20=3D=20NULL;=0A+=09PGconn=09=20=20=20*conn;=0A=20=0A-=09= libpqsrv_connect_prepare();=0A-=0A-=09conn=20=3D=20= PQconnectStart(conninfo);=0A+=09conn=20=3D=20= libpqsrv_connect_start(conninfo);=0A=20=0A-=09= libpqsrv_connect_internal(conn,=20wait_event_info);=0A+=09= libpqsrv_connect_complete(conn,=20wait_event_info);=0A=20=0A=20=09return=20= conn;=0A=20}=0A=20=0A+/*=0A+=20*=20Start=20a=20connection=20using=20= PQconnectStartParams().=0A+=20*=0A+=20*=20See=20libpqsrv_connect_start()=20= for=20the=20resource-lifetime=20rules.=0A+=20*/=0A+static=20inline=20= PGconn=20*=0A+libpqsrv_connect_params_start(const=20char=20*const=20= *keywords,=0A+=09=09=09=09=09=09=09=20=20const=20char=20*const=20= *values,=0A+=09=09=09=09=09=09=09=20=20int=20expand_dbname)=0A+{=0A+=09= libpqsrv_connect_prepare();=0A+=0A+=09return=20= PQconnectStartParams(keywords,=20values,=20expand_dbname);=0A+}=0A+=0A=20= /*=0A=20=20*=20Like=20libpqsrv_connect(),=20except=20that=20this=20is=20= a=20wrapper=20for=0A=20=20*=20PQconnectdbParams().=0A@@=20-76,13=20= +107,11=20@@=20libpqsrv_connect_params(const=20char=20*const=20= *keywords,=0A=20=09=09=09=09=09=09int=20expand_dbname,=0A=20=09=09=09=09=09= =09uint32=20wait_event_info)=0A=20{=0A-=09PGconn=09=20=20=20*conn=20=3D=20= NULL;=0A+=09PGconn=09=20=20=20*conn;=0A=20=0A-=09= libpqsrv_connect_prepare();=0A+=09conn=20=3D=20= libpqsrv_connect_params_start(keywords,=20values,=20expand_dbname);=0A=20= =0A-=09conn=20=3D=20PQconnectStartParams(keywords,=20values,=20= expand_dbname);=0A-=0A-=09libpqsrv_connect_internal(conn,=20= wait_event_info);=0A+=09libpqsrv_connect_complete(conn,=20= wait_event_info);=0A=20=0A=20=09return=20conn;=0A=20}=0A@@=20-90,8=20= +119,9=20@@=20libpqsrv_connect_params(const=20char=20*const=20*keywords,=0A= =20/*=0A=20=20*=20PQfinish()=20wrapper=20that=20additionally=20releases=20= the=20reserved=20file=20descriptor.=0A=20=20*=0A-=20*=20It=20is=20= allowed=20to=20call=20this=20with=20a=20NULL=20pgconn=20iff=20NULL=20was=20= returned=20by=0A-=20*=20libpqsrv_connect*.=0A+=20*=20It=20is=20allowed=20= to=20call=20this=20with=20NULL=20only=20when=20the=20external=20FD=20= reservation=0A+=20*=20has=20already=20been=20released,=20for=20example=20= after=20calling=0A+=20*=20libpqsrv_connect_complete()=20with=20a=20NULL=20= connection.=0A=20=20*/=0A=20static=20inline=20void=0A=20= libpqsrv_disconnect(PGconn=20*conn)=0A@@=20-101,7=20+131,7=20@@=20= libpqsrv_disconnect(PGconn=20*conn)=0A=20=09=20*=20already=20released=20= it).=20This=20rule=20makes=20it=20easier=20to=20write=20PG_CATCH()=0A=20=09= =20*=20handlers=20for=20this=20facility's=20users.=0A=20=09=20*=0A-=09=20= *=20See=20also=20libpqsrv_connect_internal().=0A+=09=20*=20See=20also=20= libpqsrv_connect_complete().=0A=20=09=20*/=0A=20=09if=20(conn=20=3D=3D=20= NULL)=0A=20=09=09return;=0A@@=20-111,7=20+141,7=20@@=20= libpqsrv_disconnect(PGconn=20*conn)=0A=20}=0A=20=0A=20=0A-/*=20internal=20= helper=20functions=20follow=20*/=0A+/*=20lower-level=20connection=20= helper=20functions=20follow=20*/=0A=20=0A=20=0A=20/*=0A@@=20-144,10=20= +174,11=20@@=20libpqsrv_connect_prepare(void)=0A=20}=0A=20=0A=20/*=0A-=20= *=20Helper=20function=20for=20all=20connection=20establishment=20= functions.=0A+=20*=20Complete=20a=20connection=20started=20by=20= libpqsrv_connect_start()=20or=0A+=20*=20libpqsrv_connect_params_start().=0A= =20=20*/=0A=20static=20inline=20void=0A-libpqsrv_connect_internal(PGconn=20= *conn,=20uint32=20wait_event_info)=0A+libpqsrv_connect_complete(PGconn=20= *conn,=20uint32=20wait_event_info)=0A=20{=0A=20=09/*=0A=20=09=20*=20With=20= conn=20=3D=3D=20NULL=20libpqsrv_disconnect()=20wouldn't=20release=20the=20= FD.=20So=20do=0A--=20=0A2.50.1=20(Apple=20Git-155)=0A=0A= --Apple-Mail=_CF9F3BB0-4D8B-4367-BE58-99B3B8A6151D--