Skip to content

Commit bba35ff

Browse files
pgduck client: resolve env-supplied conninfo for log
Add ResolvePgduckConninfo(), which uses PQconnectStart + PQconninfo to let libpq overlay environment variables (PGHOSTADDR, PGPORT, etc.) and compiled-in defaults onto pg_lake_engine.host, then formats the result as a conninfo string with passwords and debug-only fields stripped. The LOG_SERVER_ONLY errdetail emitted on connection failure now uses this resolved string, so an administrator debugging issue #293-style env-var overrides sees the values libpq actually used rather than just the configured GUC. Signed-off-by: David Christensen <david.christensen@snowflake.com>
1 parent 085dd9b commit bba35ff

1 file changed

Lines changed: 76 additions & 1 deletion

File tree

pg_lake_engine/src/pgduck/client.c

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939

4040
static void InitializePGDuckClient(void);
4141
static void SetupPgDuckConnectionHash(void);
42+
static char *ResolvePgduckConninfo(void);
4243

4344
static void PGDuckClientTransactionCallback(XactEvent event, void *arg);
4445
static void PGDuckClientSubtransactionCallback(SubXactEvent event,
@@ -127,6 +128,77 @@ SetupPgDuckConnectionHash(void)
127128
}
128129

129130

131+
/*
132+
* ResolvePgduckConninfo returns a palloc'd connection string showing the
133+
* options libpq would actually use to reach pgduck_server, including values
134+
* supplied via environment variables (e.g. PGHOSTADDR, PGPORT) and libpq's
135+
* compiled-in defaults. This is what an administrator needs to debug a
136+
* misconfigured server -- PgduckServerConninfo alone hides any env-supplied
137+
* overrides.
138+
*
139+
* We resolve options without opening a socket: PQconndefaults() returns the
140+
* options with environment variables and compiled-in defaults applied, and
141+
* PQconninfoParse() returns the values from the configured conninfo string.
142+
* Configured values override defaults. Options whose dispchar starts with
143+
* '*' (passwords) or 'D' (debug-only) are omitted, as are empty values.
144+
*/
145+
static char *
146+
ResolvePgduckConninfo(void)
147+
{
148+
StringInfoData buf;
149+
150+
initStringInfo(&buf);
151+
152+
PQconninfoOption *defaults = PQconndefaults();
153+
PQconninfoOption *configured = PQconninfoParse(PgduckServerConninfo, NULL);
154+
155+
if (defaults == NULL)
156+
{
157+
/* OOM inside libpq; fall back to the raw configured string */
158+
if (configured != NULL)
159+
PQconninfoFree(configured);
160+
appendStringInfoString(&buf, PgduckServerConninfo);
161+
return buf.data;
162+
}
163+
164+
bool first = true;
165+
166+
for (PQconninfoOption *opt = defaults; opt->keyword != NULL; opt++)
167+
{
168+
const char *val = opt->val;
169+
170+
if (configured != NULL)
171+
{
172+
for (PQconninfoOption *c = configured; c->keyword != NULL; c++)
173+
{
174+
if (strcmp(c->keyword, opt->keyword) == 0)
175+
{
176+
if (c->val != NULL)
177+
val = c->val;
178+
break;
179+
}
180+
}
181+
}
182+
183+
if (val == NULL || val[0] == '\0')
184+
continue;
185+
if (opt->dispchar != NULL &&
186+
(opt->dispchar[0] == '*' || opt->dispchar[0] == 'D'))
187+
continue;
188+
189+
appendStringInfo(&buf, "%s%s='%s'",
190+
first ? "" : " ", opt->keyword, val);
191+
first = false;
192+
}
193+
194+
PQconninfoFree(defaults);
195+
if (configured != NULL)
196+
PQconninfoFree(configured);
197+
198+
return buf.data;
199+
}
200+
201+
130202
/*
131203
* GetPGDuckConnection returns the main PGDuck connection.
132204
*/
@@ -150,9 +222,12 @@ GetPGDuckConnection(void)
150222
* intentionally do not include the libpq error message here; it is
151223
* surfaced only in the assertion-enabled ERROR below.
152224
*/
225+
char *resolved = ResolvePgduckConninfo();
226+
153227
ereport(LOG_SERVER_ONLY,
154228
(errmsg("could not start query engine"),
155-
errdetail("connection string: %s", PgduckServerConninfo)));
229+
errdetail("connection string: %s", resolved)));
230+
pfree(resolved);
156231

157232
#ifdef USE_ASSERT_CHECKING
158233
ereport(ERROR, (errmsg("could not start query engine: %s", errorMessage)));

0 commit comments

Comments
 (0)