Refactor PostgreSQL Connection-Level Parameters Handling#4899
Refactor PostgreSQL Connection-Level Parameters Handling#4899renecannao merged 7 commits intov3.0from
Conversation
* Accept all parameters sent by the client, mirroring PostgreSQL's permissive handling. * Validate and apply parameters only after successful authentication. This avoids wasting resources on invalid connections.
Optimized RESET ALL command handling. Few optimizations. Code cleanup
Note:
- Using libpq to test ProxySQL's handling of undocumented parameters isn't possible, as libpq enforces a strict subset of PostgreSQL
connection parameters as per the official documentation, rejecting any undocumented parameters. However, actual
PostgreSQL servers accept additional parameters (e.g., extra_float_digits) and apply them at the connection/session level.
To test this behavior, a raw socket is used to connect to a ProxySQL server and send custom built messages to communicate
with ProxySQL. It currently works with plain text password authentication, without ssl support.
- Failure due to an invalid parameter returned by the PostgreSQL server, differs from ProxySQL's behavior.
PostgreSQL returns an error during the connection handshake phase, whereas in ProxySQL, the connection succeeds,
but the error is encountered when executing a query.
This is behaviour is intentional, as newer PostgreSQL versions may introduce new parameters that ProxySQL is not yet aware of.
…ving direct usage of pgsql_tracked_variables[idx].idx. This change improves consistency and reduces potential human error. * Fixed some warning
noizu
left a comment
There was a problem hiding this comment.
This looks like working code to me.
I would avoid the
#if FALSE
#endif
macros if these serve a purpose for debugging give them a meaningful macro name or at least include a comment in the macro'd out code for why it's macro'd out. // Debug X functionality, etc.
Maybe verify mallocs but it's highly unlikely to fail and the end user has bigger problems at hand if it does.
Consider sticking to // style comments to make commented out code during dev/debug easier. outside of doc generation comments.
Loooks good to me but I am a neophyte to this code base ^_^.
|
|
||
| // Generate parameter array | ||
| constexpr const char* param_name[] = { | ||
| #define PARAM(name, val) name, |
There was a problem hiding this comment.
would
#define PARAM(name, val) (name) ,break the macro logic?
There was a problem hiding this comment.
Thanks for pointing this out. In the current context, the macro:
#define PARAM(name, val) name,
is intended to extract just the name part, which is a plain c-string, not a complex expression. Since name is not an expression and there’s no operator precedence or evaluation involved, parentheses are not strictly necessary here.
| static const Param_Name_Validation target_session_attrs {(const char*[]){"any","read-write","read-only","primary","standby","prefer-standby",nullptr},0 }; | ||
| static const Param_Name_Validation load_balance_hosts {(const char*[]){"disable","random",nullptr},-1}; | ||
| static const std::unordered_map<std::string_view, const Param_Name_Validation*> PgSQL_Param_Name_Str = { | ||
| #define PARAM(name, val) {name, val}, |
There was a problem hiding this comment.
same question would {(name), (val)}, // break the macro logic.
There was a problem hiding this comment.
(check previous reply)
include/PgSQL_Connection.h
Outdated
| #undef PARAM | ||
| }; | ||
|
|
||
| #if 0 |
There was a problem hiding this comment.
if this isn't removed later on consider a macro with a meaningful name #if DEBUGGING_X
There was a problem hiding this comment.
(check comments section)
include/PgSQL_Connection.h
Outdated
| #define PG_EVENT_EXCEPT 0x04 | ||
| #define PG_EVENT_TIMEOUT 0x08 | ||
|
|
||
| #if 0 |
There was a problem hiding this comment.
magic number, magic exclusion.
There was a problem hiding this comment.
(check comments section)
| }; | ||
| #endif | ||
|
|
||
| class PgSQL_Conn_Param { |
There was a problem hiding this comment.
methods are straight forward but a doxygen compatible or whatever we use class doc section might be nice for other code readers. PPgSQL_Conn_Param is straight forward but it is also undocumented params now so might be worth mentioning.
There was a problem hiding this comment.
Yes, noted. The class is now documented.
| return result; | ||
| } | ||
|
|
||
| #if 0 |
There was a problem hiding this comment.
use a const or define for macro commented out sections like this and or add a comment on why it's disabled.
There was a problem hiding this comment.
(check comments section)
| if (validation != nullptr && validation->accepted_values) { | ||
| const char** accepted_value = validation->accepted_values; | ||
| while (accepted_value != nullptr) { | ||
| while (*accepted_value) { |
| @@ -0,0 +1,909 @@ | |||
| /** | |||
| * @file pgsql-connection_parameters_test-t-t.cpp | |||
There was a problem hiding this comment.
Should we consider an alternative to libpq if not already doing so for validation here?
There was a problem hiding this comment.
We can, for normal cases, but what we're doing here is somewhat taboo, and other connectors might have the same limitations as libpq. I know the Java Connector also bypasses some rules, but I'm not sure if it's as lenient when the client does the same.
| }; | ||
|
|
||
|
|
||
| int main(int argc, char** argv) { |
There was a problem hiding this comment.
does the testing framework generate branch/line coverage or is it necessary to manually ensure new logic is covered?
There was a problem hiding this comment.
Yes, we do have code coverage in place. However, if you're referring to test-wise code coverage (i.e., ensuring every test case covers specific branches or lines of code), then no, that's not automatically handled. We rely on manual verification to ensure that new logic is adequately covered by tests.
| @@ -244,7 +244,7 @@ enum mysql_variable_name { | |||
| }; | |||
|
|
|||
| /* NOTE: | |||
There was a problem hiding this comment.
use // style comments to allow commenting out code during dev with out resorting to macro #if logic.
There was a problem hiding this comment.
(check comments section)
958cf7d to
982be8b
Compare
|
Thank you for the feedback! Regarding the use of On the comment style, I appreciate the suggestion. As there's no strict in-house guideline, I typically use |
Changes
Previously, ProxySQL enforced a strict subset of PostgreSQL connection parameters as per the official documentation, rejecting any undocumented parameters. However, actual PostgreSQL servers accept additional parameters (e.g., extra_float_digits) and apply them at the connection/session level. To align with PostgreSQL's behavior and improve compatibility, ProxySQL now:
Other changes:
client_encodingas normal server parameter/variable.RESET ALLcommand handling.Information regarding the TAP test:
Using libpq to test ProxySQL's handling of undocumented parameters isn't possible, as libpq enforces a strict subset of PostgreSQL connection parameters as per the official documentation, rejecting any undocumented parameters. However, actual PostgreSQL servers accept additional parameters (e.g., extra_float_digits) and apply them at the connection/session level. To test this behavior, a raw socket is used to connect to a ProxySQL server and send custom built messages to communicate with ProxySQL. It currently works with plain text password authentication, without ssl support.
Failure due to an invalid parameter returned by the PostgreSQL server, differs from ProxySQL's behavior. PostgreSQL returns an error during the connection handshake phase, whereas in ProxySQL, the connection succeeds, but the error is encountered when executing a query. This is behaviour is intentional, as newer PostgreSQL versions may introduce new parameters that ProxySQL is not yet aware of.
Closes #4890
Closes #4898