fix(mysql): retry StarRocks cast errors during connection setup
This commit is contained in:
2 files changed
+87
No files matched your search
@@ -1489,6 +1489,11 @@ fn mysql_group_concat_setup_fallback_mode(setup_mode: MySqlSetupMode, error: &st
|
||||
&& compact.contains(&format!(
|
||||
"strconv.parseint:parsing\"cast(greatest(@@session.group_concat_max_len,{MYSQL_GROUP_CONCAT_MAX_LEN})asunsigned)\":invalidsyntax"
|
||||
));
|
||||
// StarRocks 3.1 can fail expression folding without echoing the SET statement.
|
||||
let starrocks_setup_expression_rejected = lower.contains("error 1064 (hy000)")
|
||||
&& lower.contains(
|
||||
"class com.starrocks.analysis.castexpr cannot be cast to class com.starrocks.analysis.literalexpr",
|
||||
);
|
||||
// SphinxQL / Manticore reject the built-in `group_concat_max_len` setup with a
|
||||
// boolean-typed 1064 error. The quoted token after `near` depends on the exact
|
||||
// statement text, so accept any boolean rejection from SphinxQL that mentions
|
||||
@@ -1507,6 +1512,7 @@ fn mysql_group_concat_setup_fallback_mode(setup_mode: MySqlSetupMode, error: &st
|
||||
|| compact.contains(&format!("..._len,{MYSQL_GROUP_CONCAT_MAX_LEN})asunsigned)"));
|
||||
if (floor_statement_rejected && (setup_query_rejected || setup_value_rejected))
|
||||
|| gaea_setup_expression_rejected
|
||||
|| starrocks_setup_expression_rejected
|
||||
|| sphinxql_setup_query_rejected
|
||||
|| gateway_session_variable_rejected
|
||||
{
|
||||
@@ -8412,6 +8418,31 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mysql_group_concat_starrocks_cast_error_retries_without_session_variable() {
|
||||
let error = "MySQL connection failed: Server error: `ERROR 1064 (HY000): class com.starrocks.analysis.CastExpr cannot be cast to class com.starrocks.analysis.LiteralExpr (com.starrocks.analysis.CastExpr and com.starrocks.analysis.LiteralExpr are in unnamed module of loader 'app')'";
|
||||
|
||||
assert_eq!(
|
||||
mysql_group_concat_setup_fallback_mode(MySqlSetupMode::Standard, error),
|
||||
Some(MySqlSetupMode::Compatible)
|
||||
);
|
||||
assert_eq!(mysql_group_concat_setup_fallback_mode(MySqlSetupMode::Compatible, error), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mysql_group_concat_starrocks_cast_retry_requires_exact_error() {
|
||||
for error in [
|
||||
"Server error: `ERROR 1105 (HY000): class com.starrocks.analysis.CastExpr cannot be cast to class com.starrocks.analysis.LiteralExpr'",
|
||||
"Server error: `ERROR 1064 (42000): class com.starrocks.analysis.CastExpr cannot be cast to class com.starrocks.analysis.LiteralExpr'",
|
||||
"Server error: `ERROR 1064 (HY000): class com.starrocks.analysis.SlotRef cannot be cast to class com.starrocks.analysis.LiteralExpr'",
|
||||
"Server error: `ERROR 1064 (HY000): class com.starrocks.analysis.CastExpr cannot be cast to class com.starrocks.analysis.SlotRef'",
|
||||
"Server error: `ERROR 1064 (HY000): class com.example.CastExpr cannot be cast to class com.example.LiteralExpr'",
|
||||
"Server error: `ERROR 1064 (HY000): You have an error in your SQL syntax'",
|
||||
] {
|
||||
assert_eq!(mysql_group_concat_setup_fallback_mode(MySqlSetupMode::Standard, error), None, "{error}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mysql_gateway_forbidden_global_variables_error_retries_without_session_variable() {
|
||||
let error = "MySQL connection failed: Server error: `ERROR 10192 (HY000): SET GLOBAL VARIABLES is forbidden'";
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
use dbx_drivers::db::mysql;
|
||||
use mysql_async::prelude::Queryable;
|
||||
use std::time::Duration;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore = "requires DBX_LIVE_STARROCKS_URL for a remote StarRocks with the SET CastExpr failure"]
|
||||
async fn live_starrocks_group_concat_setup_fallback() {
|
||||
let url = std::env::var("DBX_LIVE_STARROCKS_URL").expect("DBX_LIVE_STARROCKS_URL");
|
||||
let timeout = Duration::from_secs(15);
|
||||
let bare_pool = mysql::connect_bare(&url, timeout).await.expect("bare StarRocks connection");
|
||||
let mut bare_connection = bare_pool.get_conn().await.unwrap();
|
||||
let version: Option<String> = bare_connection.query_first("SELECT current_version()").await.unwrap();
|
||||
println!("StarRocks version: {version:?}");
|
||||
let error = bare_connection
|
||||
.query_drop(
|
||||
"SET SESSION group_concat_max_len = \
|
||||
cast(greatest(@@session.group_concat_max_len, 1048576) as unsigned)",
|
||||
)
|
||||
.await
|
||||
.expect_err("server must reproduce the reported initialization failure")
|
||||
.to_string();
|
||||
println!("Rejected built-in setup: {error}");
|
||||
assert!(error.contains("ERROR 1064 (HY000)"), "{error}");
|
||||
assert!(
|
||||
error.contains(
|
||||
"class com.starrocks.analysis.CastExpr cannot be cast to class com.starrocks.analysis.LiteralExpr"
|
||||
),
|
||||
"{error}"
|
||||
);
|
||||
drop(bare_connection);
|
||||
bare_pool.disconnect().await.unwrap();
|
||||
|
||||
let extra_setup = ["SET query_timeout = 42".to_string()];
|
||||
let pool = mysql::connect_with_ca_cert_pool_limit_idle_and_setup(&url, None, timeout, 2, None, &extra_setup)
|
||||
.await
|
||||
.expect("normal DBX connection must retry without its optional GROUP_CONCAT setup");
|
||||
let mut first_connection = pool.get_conn().await.unwrap();
|
||||
let mut second_connection = pool.get_conn().await.unwrap();
|
||||
for connection in [&mut first_connection, &mut second_connection] {
|
||||
let configured_timeout: Option<u64> = connection.query_first("SELECT @@query_timeout").await.unwrap();
|
||||
assert_eq!(configured_timeout, Some(42));
|
||||
let result: Option<u64> = connection.query_first("SELECT 1").await.unwrap();
|
||||
assert_eq!(result, Some(1));
|
||||
connection.query_drop("SHOW DATABASES").await.unwrap();
|
||||
}
|
||||
drop(first_connection);
|
||||
drop(second_connection);
|
||||
pool.disconnect().await.unwrap();
|
||||
|
||||
let invalid_setup = ["SET dbx_nonexistent_setup_variable = 1".to_string()];
|
||||
let error = mysql::connect_with_ca_cert_pool_limit_idle_and_setup(&url, None, timeout, 2, None, &invalid_setup)
|
||||
.await
|
||||
.err()
|
||||
.expect("invalid user setup must not be swallowed by the compatibility retry");
|
||||
assert!(error.contains("dbx_nonexistent_setup_variable"), "{error}");
|
||||
}
|
||||
Reference in new issue
Block a user