New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement CLIENT_DEPRECATE_EOF for mariadb-connector-c #131
Conversation
359860b
to
1d6d824
Compare
| @@ -23,6 +23,8 @@ | |||
| #include <mysql.h> | |||
| #include <ma_hash.h> | |||
|
|
|||
| #define MAX_PACKET_LENGTH (256L*256L*256L-1) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved from ma_net.c from below: https://github.com/mariadb-corporation/mariadb-connector-c/pull/131/files#diff-4ad0e2e8b53cd72422b2c0863655c5e5L42 since it is required in mariadb_lib.c
| @@ -188,11 +189,14 @@ void net_get_error(char *buf, size_t buf_len, | |||
| *****************************************************************************/ | |||
|
|
|||
| ulong | |||
| ma_net_safe_read(MYSQL *mysql) | |||
| ma_net_safe_read(MYSQL *mysql, my_bool *is_data_packet) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| */ | ||
|
|
||
| int | ||
| unpack_field(const MYSQL *mysql, MA_MEM_ROOT *alloc, my_bool default_value, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is extracted as is from unpack_fields function below so it can be called directly when reading packet metadata similar to mysql source code here
| * and is called by both | ||
| * mthd_my_read_query_result and mthd_stmt_read_prepare_response | ||
| */ | ||
| MYSQL_FIELD *mthd_my_read_metadata_ex(MYSQL *mysql, MA_MEM_ROOT *alloc, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to mysql client
| return result; | ||
| } | ||
|
|
||
| MYSQL_FIELD *mthd_my_read_metadata(MYSQL *mysql, ulong field_count, uint field) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason mthd_my_read_metadata_ex and mthd_my_read_metadata are two methods: similar to how it is implemented in mysql client. mthd_my_read_metadata_ex takes MA_MEM_ROOT so it can be called from mthd_stmt_read_prepare_response
| @@ -4341,41 +4488,41 @@ struct st_mariadb_api MARIADB_API= | |||
| */ | |||
| struct st_mariadb_methods MARIADB_DEFAULT_METHODS = { | |||
| /* open a connection */ | |||
| mthd_my_real_connect, | |||
| mthd_my_real_connect, // db_connect | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding the actual names so it's easier to grep.
| p+=2; | ||
| stmt->upsert_status.server_status= stmt->mysql->server_status= uint2korr(p); | ||
| /* save status info */ | ||
| if (stmt->mysql->server_capabilities & CLIENT_DEPRECATE_EOF && !is_data_packet) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| } | ||
| if (packet_len < 8 && *pos == 254) /* EOF */ | ||
| else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The else part is as is as before. Only the upper if conditional is different.
|
|
||
| if (is_data_packet) | ||
| { | ||
| // TODO: <metadata><row(s)><OK> not supported right now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that I'm still unsure how to reproduce it here. Non of the existing tests capture it yet.
| @@ -1869,6 +1925,48 @@ int stmt_read_execute_response(MYSQL_STMT *stmt) | |||
| if (!stmt->mysql) | |||
| return(1); | |||
|
|
|||
| if ((mysql->server_capabilities & CLIENT_DEPRECATE_EOF)) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
@9E0R9 do you have some time to look into this? |
|
Thanks for your pull request - I will review it next week. |
|
Can you please stash multiple commits into one commit? That makes reviewing much easier. Thans |
03fd847
to
0c23b1d
Compare
With CLIENT_DEPRECATE_EOF, there are few changes how the server sends back the packets. The protocol changes are explained in Worklog https://dev.mysql.com/worklog/task/?id=7766
0c23b1d
to
1bb5927
Compare
|
Done, I squashed them all into a single one. |
|
From a technical standpoint the code looks more or less ok, but from legal it doesn't: There is a lot of code (and even comments) just copied from Oracle/MySQL libmysql which is under GPL license and therefore not compatible with LGPL license of MariaDB Connector/C. |
|
@9E0R9 I see, I'll approach the code in a different way than mysql. |
|
I'm playing around with this feature, what are the benefits of CLIENT_DEPRECATE_EOF? |
|
Hi @ioquatix, SessionTracking is not just for pre-defined data, but you can write plugins to send back custom data too. At work, we're using this to send back performance metrics from inside the database. PS: We also added support for session-tracking to mysql2 gem in brianmario/mysql2#1092 (merged into master, not yet released.) |
|
The MySQL implementation was done by someone without much experience in MySQL protocol, and is even conceptually broken w.r.t old features. For example, the "stored procedure output parameters" from 5.5, is now broken because it is not possible to determine from the result set whether it is this special "output parameters" result set, from the metadata, until the whole result set is read. Because somebody wanted optimize out the 9 bytes in the result set metadata. CLIENT_DEPRECATE_EOF decided to encode key-value in its own, unique way, dismissing the 20 years old notion of "result set" in the protocol and misused OK packet for this purpose. It was definitely a low quality design work by newly hired MySQL trainee by Oracle. Someone needs to stop these people from screwing the protocol. |
|
@vaintroub that's interesting insight regarding compatibility. Given that is how the protocol works now, and most other connectors have it implemented, and without |
|
I do not know about the good way forward. Luckily in this situation I'm almost a bystander/observer. But the snarky remark I told, is the same I told maybe back in 2014, when MySQL trainee developers successfully conquered their first challenge of the protocol butchering. What now? We're debating to implement a MariaDB protocol extension, for our server, and our clients which would workaround what this CLIENT_DEPRECATE_EOF broke. We need extension for https://jira.mariadb.org/browse/MDEV-19237 anyway, so maybe we can include the status flags that newbie developers throw away in intermediate EOF (2 of the whooping 9 bytes they spared per result set) I guess most of the client APIs are doing OK without that extra trailing stuff at the end of OK packet. They did it for decades, and they can work with servers not supporting it. There is no notion of "client change state notification" in any of standard database APIs I know of. This stuff is mostly special needs for proxies, I think |
|
@bibstha , now what do you need this capability for, exactly? Can you replace it with something more well-formed, e.g a SELECT for a variable you're interested in, after the "COMMIT". In case you're concerned about network roundtrips, semicolon batching is your friend |
|
These projects: both already support the CLIENT_DEPRECATE_EOF. Wouldn't it simplify therefore to also have support in the c-connector? Maybe a flag to enable disable the support on client side? The primary use-case for us to have this support is to be able to read session-tracking data. We are very much interested to gather query-metadata (specially performance) and return it in-line (realtime) so we can monitor / build systems that analyze queries behavior. The best way to do this for now is to have it return in the OK_packet as a session tracking variable. We haven't considered batching queries yet, that's something we can look into. But the larger issue is still how you guys decide to move forward with the protocol support.
IMO having a way to send back metadata of a query is very very useful. If not session_tracking, while you guys discuss protocol extension, please consider someway of sending back the metadata. |
|
Closing PR - we will not implement DEPRECATE_EOF due to broken design (see CONC-461) |
Fix for CONC-461
mariadb-connector-c client now sends CLIENT_DEPRECATE_EOF flag to the server.
There are some major changes on how the server responds. Mainly the way packets are sent back from server changes which are documented in https://dev.mysql.com/worklog/task/?id=7766
I will try to add as much comment on the code changes as possible.
Note:
Most of the changes have been studied on the worklog, looking into the packets through wireshark and how mysql client behaves.