fix(pgsql-session): don't lock hostgroup on parse fail for tracked vars

When the SET parser returns an empty map for a SET that targets a
proxysql-tracked variable (search_path, datestyle, ...), the previous
behaviour called unable_to_parse_set_statement(), which set
*lock_hostgroup = true. From that point on, the entire SET-handling
function was short-circuited for the rest of the session, so every
subsequent SET -- including ones that DO parse and would have been
caught by the per-variable validator -- bypassed proxysql entirely
and went straight to PG.

That cascade is what pgsql-set_parameter_validation_test-t case #184
hit: case #172's malformed `SET search_path = "unclosed_quote, public`
caused the parser to (correctly) reject, locked the hostgroup, and
from then on case #184's 64-char delimited identifier
`SET search_path TO "1234...64chars..."` skipped the search_path
validator's "> 63 chars -> reject" check and reached PG, which silently
accepts/truncates such identifiers. The test then saw the SET succeed
unexpectedly and reported the misleading "Value changed unexpectedly
from '"$user"' to ''" message (test_ok flipped before the SHOW value
was read; new_value defaults to "" in that branch).

The fix: at this specific call site (inside the
`match_regexes[1]->match(dig)` block, i.e. we already know the SET
targets a tracked variable), drop the unable_to_parse_set_statement()
call. Log a warning and return false so the SET is forwarded to PG
normally. PG itself rejects truly malformed SETs (which was already
the observed behaviour for cases #172-#183), and subsequent valid
SETs on the same connection continue to flow through proxysql's
validator. The locking branch at the outer `else` (when the regex
didn't match -- i.e. genuinely unknown SET) is unchanged.

End-to-end verification gates on CI -- there's no local PG infra
in this build -- but the in-process unit test
TestWalkerToValidatorChain184 (added in the previous commit) already
confirmed that walker + validator together reject the 64-char input,
which is exactly the path #184 now reaches with the lock removed.

Diagnostic SET-VALIDATE proxy_info logging from the previous commit
is removed.
pull/5809/head
Rene Cannao 3 weeks ago
parent 950f6415b5
commit 35f84c384b

@ -4584,26 +4584,11 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___handle_
value1 = value;
}
// TEMP DEBUG (delete after diagnosing case #184 of pgsql-set_parameter_validation_test-t):
// log every entry to the validator block so the CI proxysql.log
// shows what value the validator actually receives for search_path
// and what it returns. Set_parser_algorithm_3 is leaking through
// some path that bypasses the validator-reject error packet and we
// don't yet know why.
proxy_info("SET-VALIDATE pre var=%s idx=%d value1_len=%zu value1=[%s]\n",
var.c_str(), idx, value1.length(), value1.c_str());
char* transformed_value = nullptr;
bool _validator_ok = true;
if (pgsql_tracked_variables[idx].validator && pgsql_tracked_variables[idx].validator->validate) {
_validator_ok = (*pgsql_tracked_variables[idx].validator->validate)(
value1.c_str(), &pgsql_tracked_variables[idx].validator->params, this, &transformed_value);
}
proxy_info("SET-VALIDATE post var=%s validator_ok=%s transformed=[%s]\n",
var.c_str(),
_validator_ok ? "true" : "false",
transformed_value ? transformed_value : "(null)");
if (pgsql_tracked_variables[idx].validator && pgsql_tracked_variables[idx].validator->validate &&
_validator_ok == false
(
*pgsql_tracked_variables[idx].validator->validate)(
value1.c_str(), &pgsql_tracked_variables[idx].validator->params, this, &transformed_value) == false
) {
char* m = NULL;
char* errmsg = NULL;
@ -4680,7 +4665,22 @@ bool PgSQL_Session::handler___status_WAITING_CLIENT_DATA___STATE_SLEEP___handle_
}
if (failed_to_parse_var) {
unable_to_parse_set_statement(lock_hostgroup);
// Reached here means match_regexes[1] matched (the outer `if` at
// line 4492 above) so the SET targets a variable proxysql tracks
// (search_path, datestyle, etc.), but the SET parser couldn't
// build a usable map (malformed value, unclosed delimiter,
// trailing comma, etc.). Forward to the backend without locking
// the hostgroup: PG itself will reject the bad SET (or for
// silently-accepted edge cases like a 64-char delimited ident,
// the subsequent tracked-variable SETs need to still flow
// through proxysql's validator -- locking here would short-circuit
// every later SET on this connection past PgSQL_Session's
// handle_SET_command and let invalid SETs slip through to PG
// uncriticized. See pgsql-set_parameter_validation_test-t
// case #184 cascade for the concrete failure mode.
string query_str = string((char*)CurrentQuery.QueryPointer, CurrentQuery.QueryLength);
proxy_warning("Unable to parse SET query for tracked variable; forwarding to backend without hostgroup lock: %s\n",
query_str.c_str());
return false;
}

Loading…
Cancel
Save