Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions pg_lake_engine/src/pgduck/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

static void InitializePGDuckClient(void);
static void SetupPgDuckConnectionHash(void);
static char *ResolvePgduckConninfo(void);

static void PGDuckClientTransactionCallback(XactEvent event, void *arg);
static void PGDuckClientSubtransactionCallback(SubXactEvent event,
Expand Down Expand Up @@ -127,6 +128,77 @@ SetupPgDuckConnectionHash(void)
}


/*
* ResolvePgduckConninfo returns a palloc'd connection string showing the
* options libpq would actually use to reach pgduck_server, including values
* supplied via environment variables (e.g. PGHOSTADDR, PGPORT) and libpq's
* compiled-in defaults. This is what an administrator needs to debug a
* misconfigured server -- PgduckServerConninfo alone hides any env-supplied
* overrides.
*
* We resolve options without opening a socket: PQconndefaults() returns the
* options with environment variables and compiled-in defaults applied, and
* PQconninfoParse() returns the values from the configured conninfo string.
* Configured values override defaults. Options whose dispchar starts with
* '*' (passwords) or 'D' (debug-only) are omitted, as are empty values.
*/
static char *
ResolvePgduckConninfo(void)
{
StringInfoData buf;

initStringInfo(&buf);

PQconninfoOption *defaults = PQconndefaults();
PQconninfoOption *configured = PQconninfoParse(PgduckServerConninfo, NULL);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we do this when connections are failing?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, probably PQconninfoParse() is a better choice here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though that doesn't incorporate defaults; will poke around a little more.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a combination of PQconndefaults() and that should work.

if (defaults == NULL)
{
/* OOM inside libpq; fall back to the raw configured string */
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably fairly useless to do this if we're in OOM situation, but YOLO.

if (configured != NULL)
PQconninfoFree(configured);
appendStringInfoString(&buf, PgduckServerConninfo);
return buf.data;
}

bool first = true;

for (PQconninfoOption *opt = defaults; opt->keyword != NULL; opt++)
{
const char *val = opt->val;

if (configured != NULL)
{
for (PQconninfoOption *c = configured; c->keyword != NULL; c++)
{
if (strcmp(c->keyword, opt->keyword) == 0)
{
if (c->val != NULL)
val = c->val;
break;
}
}
}

if (val == NULL || val[0] == '\0')
continue;
if (opt->dispchar != NULL &&
(opt->dispchar[0] == '*' || opt->dispchar[0] == 'D'))
continue;

appendStringInfo(&buf, "%s%s='%s'",
first ? "" : " ", opt->keyword, val);
first = false;
}

PQconninfoFree(defaults);
if (configured != NULL)
PQconninfoFree(configured);

return buf.data;
}


/*
* GetPGDuckConnection returns the main PGDuck connection.
*/
Expand All @@ -143,6 +215,20 @@ GetPGDuckConnection(void)

PQfinish(connection);

/*
* Log the conninfo to the server log so an administrator can debug
* misconfigured servers (issue #293) without exposing the connection
Comment thread
sfc-gh-dachristensen marked this conversation as resolved.
* string -- which may include credentials -- to the client. We
* intentionally do not include the libpq error message here; it is
* surfaced only in the assertion-enabled ERROR below.
*/
char *resolved = ResolvePgduckConninfo();

ereport(LOG_SERVER_ONLY,
(errmsg("could not start query engine"),
errdetail("connection string: %s", resolved)));
pfree(resolved);

#ifdef USE_ASSERT_CHECKING
ereport(ERROR, (errmsg("could not start query engine: %s", errorMessage)));
#else
Expand Down
Loading