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 1wQRIE-001Yf1-31 for pgsql-hackers@arkaria.postgresql.org; Fri, 22 May 2026 14:56:07 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wQRIB-00DSID-0i for pgsql-hackers@arkaria.postgresql.org; Fri, 22 May 2026 14:56:04 +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 1wQRIA-00DSI4-24 for pgsql-hackers@lists.postgresql.org; Fri, 22 May 2026 14:56:03 +0000 Received: from mail-pl1-x62a.google.com ([2607:f8b0:4864:20::62a]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wQRI8-00000000Hie-36ui for pgsql-hackers@postgresql.org; Fri, 22 May 2026 14:56:02 +0000 Received: by mail-pl1-x62a.google.com with SMTP id d9443c01a7336-2bea7176c72so14146755ad.0 for ; Fri, 22 May 2026 07:56:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779461760; x=1780066560; 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=A/7706qSKSNho6B6Zw6KOAEyf/IjrstTm0uPH1PdkDw=; b=bJ/P5Zi+CMgFKaLpPKTQH90igIw62/wZ1OIXEjln/V+PT3HCWgRjznq+NUyNKinEGc swtohdpMIMn1e1bSI5w1x9MWokCiaBMLL6qDuILvhRsnk0wGIJiwoqeljzbJR/hvEUfA QqdKnaKeBsssVC2DBakz8Kn8yc9RlaQO2DznJMC04uhR02pHimJ7rUoN/sbINC3U+cb7 udwAbf3BKmbRFj0uPeqMOZdNXVI1XH3zuX6tvFFsVFdclZM6UagrmHnUOUABJmEAQVW+ aCS644Tf4pjT6Fx1PdO55l8hJfBdYXmTkhiu6mCxvn4R9txGErhEbLnXwa+sSOc3jTyg VuUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779461760; x=1780066560; 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=A/7706qSKSNho6B6Zw6KOAEyf/IjrstTm0uPH1PdkDw=; b=a9c49OMVni9aHExDHWKFxgO71O60nWSSvsrbc7w2NUbjax5cutpv+8I5KjM8DlOujj IzB7DxwD9ObBmgC3qTwDtgGfTr8ttJkVuN6IMeMUx2mzVqOksmIAY908oZ2da8gFwvlM cHQvJahjDtTzDUiaGDxdn0LTHY2soXX0+knlVAud1qJk+1odXe/EPkOdib5MGOAIwr3a SxyqtW262XGP3byHpLp5LMW4X4zPyS6RDYF0idMrTsIJ+ahy2F1iLFHGCTVAzPyi+fDi xv1cauPBHHbOtKxElDgmX9kJpO821GN7x18DYVkaRp7538CW9WdsMnefUVRdah9pyHXc aHug== X-Forwarded-Encrypted: i=1; AFNElJ8Wsk4QN9q7MBg8AGTyREVxm1s5ZGtepLlYFvS3fJTFk3d7ka6kP6GDXW34MKD7tZqntRfF0qrWSDvvx+EE@postgresql.org X-Gm-Message-State: AOJu0YxC8VtVliTpYQlbfhSdNECoh1orJigKu/CE/rIIilRZpCYzDqXq xG0KQl2W1o5KED7ojnl0kYI9uZIbwyCrLClzd0XCBlrZEG/SzL3CdTf2 X-Gm-Gg: Acq92OHN86qoa+a2WySTvAxhBDIMUHiAGv98Rf6/xHl/WJqyM7x0NShDZFXJyRzi1fa Cseay8SeaUZ1lZYSEYU2emneu792+aJQt106UG2F80195Z4HTWvzpHRG/w+JWZTVQ9qFrqEfhi1 RZx48UkYIkTnk/svrRLXR029TS1xPyM5zE1FdtAFssvcswO78AszLyZP7AxR7XqFguZ85ro+CI/ wO3vMmCdj9XK4uXEozUMLSRs8vd6h/Zwui9e+7T18GdDUJNAi/ljX4tjFDBUPo7oX8xSBjwmD8u z2yraciYfDC84iZYbKAfGcdrrITzp1WiyAomWrAlej7qEKPLopvLU2YCy+sctu3t6bThbvQyDiC 4oCK8V1aNaIdVgBiEc1j7JA7/2oxkjIvHVKVq8ynpsP0QL/W88L0f9xzlnL4BJL9SbFHHJWIQLO ATcJ4/qS8U0XkcMERiQXnDQurAdItEOBo4DNgfuyHtfg== X-Received: by 2002:a17:902:e785:b0:2b4:5f96:184d with SMTP id d9443c01a7336-2beb05a4873mr40881915ad.5.1779461759722; Fri, 22 May 2026 07:55:59 -0700 (PDT) Received: from smtpclient.apple ([45.32.121.103]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2beb56d68adsm26393495ad.32.2026.05.22.07.55.56 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 22 May 2026 07:55:58 -0700 (PDT) From: Chao Li Message-Id: <0DCA82A4-7C10-40A7-AEF5-827171160FE8@gmail.com> Content-Type: multipart/mixed; boundary="Apple-Mail=_42D50D32-923B-4861-8708-68BD7346E4A3" 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: Fri, 22 May 2026 22:55:18 +0800 In-Reply-To: Cc: Rafia Sabih , vignesh C , PostgreSQL-development To: Fujii Masao References: <978D8971-08C3-4AAD-AE8B-976D753C882A@gmail.com> <6B9A85F9-B632-4286-98AF-9EC435019055@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=_42D50D32-923B-4861-8708-68BD7346E4A3 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On May 22, 2026, at 21:42, Fujii Masao wrote: >=20 > On Fri, May 22, 2026 at 8:33=E2=80=AFPM Rafia Sabih = wrote: >> Here are my two cents, >> we need not to check conn is null here >> + conn =3D libpqsrv_connect_start(connstr); >> + if (conn !=3D NULL) >> + PQsetNoticeReceiver(conn, libpqsrv_notice_receiver, >> + "received message via remote connection"); >> because it is done so in PQsetNoticeReceiver anyway. Also, since = there is no else here so it doesn't make sense more, because if it is = null then also we will just continue with the next function call. >=20 > Yes, but I'm fine with the current code in the patch. That code makes > the intent explicit, i.e., install the notice receiver only when a = connection > object actually exists. That said, I'm also OK with simply calling > PQsetNoticeReceiver() without that check. >=20 Every PG**() function checks if conn is NULL, so I am okay to remove the = check. >=20 >> Another point is, in pg_connect_server I don't get the value of = adding another PGConn variable start_conn, can't we use conn itself...? >> I hope this helps. >=20 > Not only connect_pg_server() but libpqsrv_connect_complete() has > a PG_TRY/PG_CATCH block. So if start_conn were not used, an error = thrown > in libpqsrv_connect_complete() could cause the current connection = (conn) to > be cleaned up twice unexpectedly: once in libpqsrv_connect_complete() = and > again in connect_pg_server(). I guess that's why Chao introduced = start_conn. >=20 Exactly. With introducing start_conn, when libpqsrv_connect_complete() = raises an error, conn is still NULL, so that PG_CATCH clause won=E2=80=99t= cleanup conn, which keeps the same behavior as the old code. PFA v4, just removed conn NULL check. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ --Apple-Mail=_42D50D32-923B-4861-8708-68BD7346E4A3 Content-Disposition: attachment; filename=v4-0001-Set-notice-receiver-before-libpq-connection-start.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v4-0001-Set-notice-receiver-before-libpq-connection-start.patch" Content-Transfer-Encoding: quoted-printable =46rom=2061d2a96f062473be47bd267f50ba71d5b85d1a71=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= v4]=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= =0AReviewed-by:=20Rafia=20Sabih=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|=2017=20++---=0A=20= contrib/postgres_fdw/connection.c=20=20=20=20=20=20=20=20=20=20=20=20=20= |=2013=20++--=0A=20.../libpqwalreceiver/libpqwalreceiver.c=20=20=20=20=20= =20=20|=2012=20++--=0A=20src/include/libpq/libpq-be-fe-helpers.h=20=20=20= =20=20=20=20|=2065=20++++++++++++++-----=0A=204=20files=20changed,=2070=20= insertions(+),=2037=20deletions(-)=0A=0Adiff=20--git=20= a/contrib/dblink/dblink.c=20b/contrib/dblink/dblink.c=0Aindex=20= d843eee7e97..3ac47ce3e0e=20100644=0A---=20a/contrib/dblink/dblink.c=0A= +++=20b/contrib/dblink/dblink.c=0A@@=20-222,7=20+222,10=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=09PQsetNoticeReceiver(conn,=20= libpqsrv_notice_receiver,=0A+=09=09=09=09=09=09=09"received=20message=20= via=20remote=20connection");=0A+=09=09libpqsrv_connect_complete(conn,=20= dblink_we_get_conn);=0A=20=0A=20=09=09if=20(PQstatus(conn)=20=3D=3D=20= CONNECTION_BAD)=0A=20=09=09{=0A@@=20-235,9=20+238,6=20@@=20= dblink_get_conn(char=20*conname_or_str,=0A=20=09=09=09=09=09=20= errdetail_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= +321,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= +340,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..c3a1c5f46ca=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,12=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=20/*=20expand_dbname=20=3D=20*/=20false);=0A+=09= =09PQsetNoticeReceiver(start_conn,=20libpqsrv_notice_receiver,=0A+=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= +661,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..ebfd64bdf05=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,12=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=20/*=20expand_dbname=20=3D=20*/=20true);=0A+=09= PQsetNoticeReceiver(conn->streamConn,=20libpqsrv_notice_receiver,=0A+=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+248,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=_42D50D32-923B-4861-8708-68BD7346E4A3--