Hi Man,

Your reading of the local logic is totally reasonable and correct: if
PQescapeLiteral() returns NULL for any reason, the existing if (!q_role ||
!q_dbname) path will indeed fall back to ALL, so quoting failures are
already handled.

The only thing I’m cautious about is treating “pset.db is NULL/invalid” as
just another “quoting failure” case. In this completion branch we call
PQescapeLiteral(pset.db, ...) before we ever reach exec_query(), so an
explicit guard is about avoiding passing an unusable handle into libpq in
the first place. Even if libpq were to return NULL in that situation, it’s
not something I’d want to rely on implicitly.

That’s why I suggested the explicit guard: it matches the general psql
style of checking !pset.db before calling libpq APIs (e.g.
psql_get_variable() in src/bin/psql/common.c checks !pset.db before calling
PQescapeLiteral()), and it makes the intent obviously safe. Behavior-wise
it’s the same (fall back to ALL), just more defensive/clear & explicit.

Thanks,
Dharin

On Tue, Jan 6, 2026 at 2:34 PM zengman <[email protected]> wrote:

> > That guard was actually my suggestion in review, and the reason is that
> it’s protecting the PQescapeLiteral() calls, not exec_query().
> > In the RESET completion branch we call PQescapeLiteral(pset.db, ...) to
> safely quote the role/dbname before we even build the SQL string. That
> happens before COMPLETE_WITH_QUERY_PLUS ever reaches complete_from_query()
> / exec_query(). So while exec_query() does guard query execution when
> pset.db is null or not CONNECTION_OK, it doesn’t p> revent us from passing
> a null conn into PQescapeLiteral(), which could crash or otherwise
> misbehave.
> > If we don’t have a usable connection, we can’t reliably quote and run
> the catalog query anyway, so falling back to a static completion like ALL
> seems like the safest behavior. Hence I think it's valid.
>
> Hi,
>
> Thank you both for clarifying my confusion. I hadn't paid much attention
> to `PQescapeLiteral` earlier.
> I checked the function, and it should return NULL on failure.
> ```
>         q_role = PQescapeLiteral(pset.db, role, strlen(role));
>         q_dbname = PQescapeLiteral(pset.db, dbname, strlen(dbname));
>         if (!q_role || !q_dbname)
>         {
>                 /* If quoting fails, just fall back to ALL */
>                 if (q_role)
>                         PQfreemem(q_role);
>                 if (q_dbname)
>                         PQfreemem(q_dbname);
>                 COMPLETE_WITH("ALL");
>         }
> ```
> When `pset.db` is NULL or for other reasons (resulting in q_role/q_dbname
> being NULL), `!q_role || !q_dbname` will be hit — this already meets our
> needs.
> I wonder if this understanding is correct — what do you think?
>
> --
> Regards,
> Man Zeng
> www.openhalo.org

Reply via email to