fix(ci): split checks and enforce warning-free Rust builds

This commit is contained in:
t8y2 committed 2026-07-20 13:45:59 +08:00
1 parent dcbb1c69c5
commit 083ffe7a35
44 files changed
+363 -324

No files matched your search

+5 -2
View File
@@ -3139,9 +3139,9 @@ fn clone_pool_kind(pool: &PoolKind) -> PoolKind {
#[cfg(feature = "duckdb-bundled")]
PoolKind::DuckDbWorker(client) => PoolKind::DuckDbWorker(client.clone()),
#[cfg(not(feature = "duckdb-bundled"))]
PoolKind::DuckDb(con) => PoolKind::DuckDb(con.clone()),
PoolKind::DuckDb(_) => PoolKind::DuckDb(()),
#[cfg(not(feature = "duckdb-bundled"))]
PoolKind::DuckDbWorker(client) => PoolKind::DuckDbWorker(client.clone()),
PoolKind::DuckDbWorker(_) => PoolKind::DuckDbWorker(()),
PoolKind::MongoDb(client) => PoolKind::MongoDb(client.clone()),
PoolKind::ClickHouse(client) => PoolKind::ClickHouse(client.clone()),
PoolKind::SqlServer(client) => PoolKind::SqlServer(client.clone()),
@@ -3149,7 +3149,10 @@ fn clone_pool_kind(pool: &PoolKind) -> PoolKind {
PoolKind::VectorDb(client) => PoolKind::VectorDb(client.clone()),
PoolKind::InfluxDb(client) => PoolKind::InfluxDb(client.clone()),
PoolKind::Agent(client) => PoolKind::Agent(client.clone()),
#[cfg(feature = "duckdb-bundled")]
PoolKind::ExternalTabular(ext) => PoolKind::ExternalTabular(ext.clone()),
#[cfg(not(feature = "duckdb-bundled"))]
PoolKind::ExternalTabular(_) => PoolKind::ExternalTabular(()),
PoolKind::ExternalDriver { driver_id, config, session } => {
PoolKind::ExternalDriver { driver_id: driver_id.clone(), config: config.clone(), session: session.clone() }
}
+2
View File
@@ -38,6 +38,8 @@ impl DuckDbConnection {
self.draining.load(Ordering::SeqCst)
}
// Preserve PoisonError ownership so close_connection can still release the contained DuckDB handle.
#[allow(clippy::result_large_err)]
fn into_inner(self) -> std::sync::LockResult<duckdb::Connection> {
self.connection.into_inner()
}
+8 -6
View File
@@ -183,13 +183,15 @@ fn find_as_keyword_outside_quotes(sql: &str) -> Option<usize> {
}
in_double = !in_double;
}
b'a' | b'A' if !in_single && !in_double && i + 1 < bytes.len() => {
if (bytes[i + 1] == b's' || bytes[i + 1] == b'S')
b'a' | b'A'
if !in_single
&& !in_double
&& i + 1 < bytes.len()
&& (bytes[i + 1] == b's' || bytes[i + 1] == b'S')
&& is_sql_word_boundary(bytes.get(i.wrapping_sub(1)).copied())
&& is_sql_word_boundary(bytes.get(i + 2).copied())
{
return Some(i);
}
&& is_sql_word_boundary(bytes.get(i + 2).copied()) =>
{
return Some(i);
}
_ => {}
}
@@ -513,7 +513,8 @@ impl DuckDbWorkerClient {
let mut pending = self.inner.pending.lock().await;
let ids = pending
.iter()
.filter_map(|(id, request)| (request.generation == generation).then(|| id.clone()))
.filter(|&(_id, request)| request.generation == generation)
.map(|(id, _request)| id.clone())
.collect::<Vec<_>>();
ids.into_iter().filter_map(|id| pending.remove(&id).map(|request| (id, request.sender))).collect::<Vec<_>>()
};
@@ -631,7 +632,8 @@ fn spawn_stdout_reader(
let mut pending = pending.lock().await;
let ids = pending
.iter()
.filter_map(|(id, request)| (request.generation == generation).then(|| id.clone()))
.filter(|&(_id, request)| request.generation == generation)
.map(|(id, _request)| id.clone())
.collect::<Vec<_>>();
ids.into_iter().filter_map(|id| pending.remove(&id).map(|request| (id, request.sender))).collect::<Vec<_>>()
};
+3 -3
View File
@@ -222,7 +222,7 @@ fn build_query_url(client: &InfluxdbClient, database: Option<&str>, sql: &str) -
}
let encoded_sql = utf8_percent_encode(sql, NON_ALPHANUMERIC);
params.push(format!("q={encoded_sql}"));
format!("{}/query?{}", &client.base_url, params.join("&").as_str())
format!("{}/query?{}", client.base_url, params.join("&").as_str())
}
fn encode_url_param(value: &str) -> String {
@@ -231,12 +231,12 @@ fn encode_url_param(value: &str) -> String {
fn build_v2_buckets_url(client: &InfluxdbClient, offset: usize) -> Result<String, String> {
let org = client.org.as_deref().ok_or_else(|| "InfluxDB 2.x organization is required".to_string())?;
Ok(format!("{}/api/v2/buckets?org={}&limit=100&offset={offset}", &client.base_url, encode_url_param(org)))
Ok(format!("{}/api/v2/buckets?org={}&limit=100&offset={offset}", client.base_url, encode_url_param(org)))
}
fn build_v2_query_url(client: &InfluxdbClient) -> Result<String, String> {
let org = client.org.as_deref().ok_or_else(|| "InfluxDB 2.x organization is required".to_string())?;
Ok(format!("{}/api/v2/query?org={}", &client.base_url, encode_url_param(org)))
Ok(format!("{}/api/v2/query?org={}", client.base_url, encode_url_param(org)))
}
fn build_request(client: &InfluxdbClient, req: reqwest::RequestBuilder) -> reqwest::RequestBuilder {
+3 -3
View File
@@ -1692,7 +1692,7 @@ fn parse_legacy_mongo_date_display(value: &str) -> Option<DateTime> {
if !millis.chars().all(|ch| ch.is_ascii_digit()) {
return None;
}
DateTime::parse_rfc3339_str(format!("{date}T{seconds}.{}Z", format!("{millis:0<3}"))).ok()
DateTime::parse_rfc3339_str(format!("{date}T{seconds}.{millis:0<3}Z")).ok()
}
fn parse_extended_json_date(obj: &serde_json::Map<String, serde_json::Value>) -> Option<DateTime> {
@@ -2003,7 +2003,7 @@ mod tests {
#[test]
fn document_id_filters_try_object_id_then_string_for_hex_ids() {
let id = "507f1f77bcf86cd799439011";
let filters = document_id_filters(&id);
let filters = document_id_filters(id);
assert_eq!(filters.len(), 2);
assert!(matches!(filters[0].get("_id"), Some(Bson::ObjectId(_))));
@@ -2013,7 +2013,7 @@ mod tests {
#[test]
fn document_id_filters_use_string_only_for_non_hex_ids() {
let id = "customer-42";
let filters = document_id_filters(&id);
let filters = document_id_filters(id);
assert_eq!(filters.len(), 1);
assert!(matches!(filters[0].get("_id"), Some(Bson::String(value)) if value == id));
-1
View File
@@ -4547,7 +4547,6 @@ UNIQUE KEY(`tenant_id`, `name``part`)
#[test]
fn mysql_tcp_keepalive_uses_milliseconds_not_seconds() {
assert_eq!(MYSQL_TCP_KEEPALIVE_MS, 30_000);
assert!(MYSQL_TCP_KEEPALIVE_MS >= 1_000);
}
#[test]
+1 -1
View File
@@ -1400,7 +1400,7 @@ fn sqlite_completion_tables(
if type_filters.is_empty() {
type_filters.extend(["table", "view"]);
}
let placeholders = std::iter::repeat("?").take(type_filters.len()).collect::<Vec<_>>().join(", ");
let placeholders = std::iter::repeat_n("?", type_filters.len()).collect::<Vec<_>>().join(", ");
let sql = format!(
"SELECT name, type FROM {}.sqlite_master WHERE type IN ({}) AND name NOT LIKE 'sqlite_%' AND {} ORDER BY name LIMIT ?",
sqlite_quote_ident(&schema),
+1 -1
View File
@@ -1315,7 +1315,7 @@ fn sqlserver_completion_assistant_sql(request: &crate::types::CompletionAssistan
}
if queries.is_empty() {
format!("SELECT TOP (0) CAST('' AS NVARCHAR(128)) AS name, CAST('' AS NVARCHAR(128)) AS schema_name, CAST('' AS NVARCHAR(60)) AS object_type, CAST(NULL AS NVARCHAR(128)) AS parent_schema, CAST(NULL AS NVARCHAR(128)) AS parent_name, CAST(NULL AS NVARCHAR(MAX)) AS object_comment, CAST(NULL AS NVARCHAR(128)) AS data_type")
"SELECT TOP (0) CAST('' AS NVARCHAR(128)) AS name, CAST('' AS NVARCHAR(128)) AS schema_name, CAST('' AS NVARCHAR(60)) AS object_type, CAST(NULL AS NVARCHAR(128)) AS parent_schema, CAST(NULL AS NVARCHAR(128)) AS parent_name, CAST(NULL AS NVARCHAR(MAX)) AS object_comment, CAST(NULL AS NVARCHAR(128)) AS data_type".to_string()
} else if queries.len() == 1 {
format!("SELECT * FROM ({}) AS dbx_completion ORDER BY name", queries.remove(0))
} else {
+1 -1
View File
@@ -198,7 +198,7 @@ async fn list_milvus_databases(client: &VectorClient) -> Result<Vec<String>, Str
if !names.iter().any(|name| name == "default") {
names.push("default".to_string());
}
names.sort_by(|a, b| a.cmp(b));
names.sort();
Ok(names)
}
+2 -2
View File
@@ -53,7 +53,7 @@ pub async fn list_databases_core(state: &AppState, connection_id: &str) -> Resul
Err(error) => Err(error),
},
PoolKind::Elasticsearch(_) => Ok(vec!["default".to_string()]),
PoolKind::VectorDb(client) => vector_driver::list_databases(&client).await,
PoolKind::VectorDb(client) => vector_driver::list_databases(client).await,
PoolKind::Agent(client) => {
let mut client = client.lock().await;
match client.mongo_list_databases::<Vec<serde_json::Value>>().await {
@@ -216,7 +216,7 @@ pub async fn list_collections_core(
.map(|n| CollectionInfo { name: n.clone(), id: n, dimension: None, kind: None, bucket_name: None })
.collect())
}
PoolKind::VectorDb(client) => vector_driver::list_collections_with_db(&client, database).await,
PoolKind::VectorDb(client) => vector_driver::list_collections_with_db(client, database).await,
PoolKind::Agent(client) => {
let mut client = client.lock().await;
let names = sort_names(client.mongo_list_collections(database).await?);
+3 -3
View File
@@ -161,7 +161,7 @@ impl MessageQueueAdmin for PulsarAdmin {
async fn list_tenants(&self) -> Result<Vec<TenantInfo>, String> {
let names: Vec<String> = self.get_json(&self.profile.tenants_path()).await?;
stream::iter(names.into_iter())
stream::iter(names)
.map(|name| async move {
match self.get_tenant(&name).await {
Ok(tenant) => Ok(tenant),
@@ -214,7 +214,7 @@ impl MessageQueueAdmin for PulsarAdmin {
async fn list_namespaces(&self, tenant: &str) -> Result<Vec<NamespaceInfo>, String> {
// Returns fully-qualified `tenant/namespace` strings.
let names: Vec<String> = self.get_json(&self.profile.namespaces_path(tenant)).await?;
stream::iter(names.into_iter())
stream::iter(names)
.map(|full| async move {
let namespace = full.rsplit('/').next().unwrap_or(&full).to_string();
let admin_roles = match self.namespace_admin_roles(tenant, &namespace).await {
@@ -282,7 +282,7 @@ impl MessageQueueAdmin for PulsarAdmin {
};
let partitioned_set: std::collections::HashSet<String> = partitioned.iter().cloned().collect();
let domain = if persistent { "persistent" } else { "non-persistent" };
let partitioned_topics = stream::iter(partitioned.into_iter())
let partitioned_topics = stream::iter(partitioned)
.map(|full| async move {
let partitions = self.partition_count_for_topic(domain, &full).await?;
Ok::<_, String>(TopicInfo {
+5 -17
View File
@@ -16,22 +16,16 @@ use super::util::truncate;
/// project's encrypted connection-secrets / keychain path and are never logged.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "camelCase")]
#[derive(Default)]
pub enum MqAuth {
#[default]
None,
/// Pulsar JWT bearer token.
Token {
token: String,
},
Token { token: String },
/// HTTP Basic auth.
Basic {
username: String,
password: String,
},
Basic { username: String, password: String },
/// Arbitrary API key header, e.g. `Authorization: <value>` or a custom header.
ApiKey {
header: String,
value: String,
},
ApiKey { header: String, value: String },
/// OAuth2 client-credentials flow (Pulsar's `oauth2` auth plugin).
OAuth2 {
issuer_url: String,
@@ -44,12 +38,6 @@ pub enum MqAuth {
},
}
impl Default for MqAuth {
fn default() -> Self {
MqAuth::None
}
}
/// Caches an OAuth2 access token with its expiry so repeated requests reuse it.
/// Also tracks in-flight token requests to prevent concurrent fetches.
#[derive(Debug, Default, Clone)]
+1 -25
View File
@@ -31,6 +31,7 @@ impl MqSystemKind {
/// features are hidden rather than failing at call time.
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[derive(Default)]
pub struct MqCapabilities {
pub supports_tenants: bool,
pub supports_namespaces: bool,
@@ -54,31 +55,6 @@ pub struct MqCapabilities {
pub supports_send_message: bool,
}
impl Default for MqCapabilities {
fn default() -> Self {
Self {
supports_tenants: false,
supports_namespaces: false,
supports_partitioned_topics: false,
supports_subscriptions: false,
supports_create_subscription: false,
supports_reset_cursor: false,
supports_skip_messages: false,
supports_clear_backlog: false,
supports_peek_messages: false,
supports_expire_messages: false,
supports_rate_limits: false,
supports_backlog_quota: false,
supports_retention: false,
supports_permissions: false,
supports_geo_replication: false,
supports_token_management: false,
supports_raw_admin_api: false,
supports_send_message: false,
}
}
}
/// Result of a connectivity test, including the detected server version and how
/// it was determined (probe vs. fallback) so the UI can warn appropriately.
#[derive(Debug, Clone, Serialize, Deserialize)]
+6 -7
View File
@@ -4,15 +4,14 @@ use crate::models::connection::ConnectionConfig;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(tag = "kind", rename_all = "camelCase")]
#[derive(Default)]
pub enum NacosAuthConfig {
#[default]
None,
UsernamePassword { username: String, password: String },
}
impl Default for NacosAuthConfig {
fn default() -> Self {
Self::None
}
UsernamePassword {
username: String,
password: String,
},
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
+3 -1
View File
@@ -1063,7 +1063,9 @@ fn push_optional(params: &mut Vec<(String, String)>, key: &str, value: Option<St
}
}
fn build_publish_forms(req: NacosConfigUpsert, namespace: String) -> (Vec<(String, String)>, Vec<(String, String)>) {
type NacosForm = Vec<(String, String)>;
fn build_publish_forms(req: NacosConfigUpsert, namespace: String) -> (NacosForm, NacosForm) {
let mut v3_form = vec![
("dataId".to_string(), req.data_id.clone()),
("groupName".to_string(), req.group.clone()),
+3 -1
View File
@@ -25,9 +25,11 @@ use crate::nacos::port::NacosAdmin;
pub use crate::nacos::config::{NacosAdminConfig as NacosConfig, NacosAuthConfig};
pub use crate::nacos::types::*;
type NacosAdminEntry = (NacosAdminConfig, Arc<dyn NacosAdmin>);
#[derive(Default)]
pub struct NacosAdminRegistry {
instances: RwLock<HashMap<String, (NacosAdminConfig, Arc<dyn NacosAdmin>)>>,
instances: RwLock<HashMap<String, NacosAdminEntry>>,
build_locks: RwLock<HashMap<String, Arc<Mutex<()>>>>,
}
+1 -1
View File
@@ -129,7 +129,7 @@ pub async fn nacos_raw_request_core(
req: NacosRawRequest,
) -> Result<NacosRawResponse, String> {
crate::nacos::http::validate_raw_api_path(&req.path)?;
if req.method.to_ascii_uppercase() != "GET" {
if !req.method.eq_ignore_ascii_case("GET") {
ensure_connection_writable(state, conn_id, "Run mutating Nacos raw request").await?;
}
let admin = get_admin(state, conn_id).await?;
+2 -2
View File
@@ -445,7 +445,7 @@ fn informix_view_definition(schema: Option<&str>, name: &str, source: &str) -> (
let view_name = captures.get(1).unwrap();
let target_name = strip_informix_owner_qualifiers(view_name.as_str(), schema);
let body = strip_informix_owner_qualifiers(&trimmed[view_name.end()..], schema);
return (target_name.trim().to_string(), body);
(target_name.trim().to_string(), body)
} else {
let body = strip_informix_owner_qualifiers(trimmed, schema);
(informix_identifier(name), format!(" AS\n{body}"))
@@ -579,7 +579,7 @@ fn informix_owner_qualifier_replacement<'a>(source: &'a str, start: usize, schem
return None;
}
let ident_start = skip_sql_whitespace(source, dot + 1);
read_informix_identifier_text(source, ident_start).map(|(ident_end, ident_text)| (ident_end, ident_text))
read_informix_identifier_text(source, ident_start)
}
fn sql_single_quoted_literal_end(source: &str, start: usize) -> Option<usize> {
+3 -3
View File
@@ -407,7 +407,7 @@ fn append_sql_target_safety_text(chars: &[char], result: &mut SqlTargetSafetyTex
continue;
}
if ch == '/' && next == Some('*') {
if let Some((body, close_index)) = mysql_executable_comment_body(&chars, index) {
if let Some((body, close_index)) = mysql_executable_comment_body(chars, index) {
result.text.push(' ');
let body_chars: Vec<char> = body.chars().collect();
append_sql_target_safety_text(&body_chars, result);
@@ -423,7 +423,7 @@ fn append_sql_target_safety_text(chars: &[char], result: &mut SqlTargetSafetyTex
}
continue;
}
if let Some((tag, tag_len)) = dollar_quote_tag_at(&chars, index) {
if let Some((tag, tag_len)) = dollar_quote_tag_at(chars, index) {
index += tag_len;
while index + tag_len <= chars.len() && !chars[index..index + tag_len].iter().collect::<String>().eq(&tag) {
index += 1;
@@ -433,7 +433,7 @@ fn append_sql_target_safety_text(chars: &[char], result: &mut SqlTargetSafetyTex
continue;
}
if ch == '\'' {
index = skip_string_literal(&chars, index, '\'', '\'');
index = skip_string_literal(chars, index, '\'', '\'');
result.text.push(' ');
continue;
}
+2 -7
View File
@@ -12,21 +12,16 @@ pub struct RunningQueryDiagnostics {
type InterruptFn = Box<dyn Fn() + Send + 'static>;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum RunningTaskKind {
Query,
Count,
Explain,
Export,
#[default]
Unknown,
}
impl Default for RunningTaskKind {
fn default() -> Self {
Self::Unknown
}
}
#[derive(Clone, Debug, Default)]
pub struct RunningTaskMetadata {
pub kind: RunningTaskKind,
+1 -1
View File
@@ -158,7 +158,7 @@ fn effective_row_limit(format: &str, request: &QueryResultExportRequest) -> Opti
}
fn xlsx_hard_limit_active(format: &str, request: &QueryResultExportRequest) -> bool {
format == "xlsx" && request.row_limit.map_or(true, |limit| limit > XLSX_MAX_DATA_ROWS)
format == "xlsx" && request.row_limit.is_none_or(|limit| limit > XLSX_MAX_DATA_ROWS)
}
fn format_text_export_header(format: &str, columns: &[String]) -> String {
+1 -1
View File
@@ -963,7 +963,7 @@ fn add_standard_limit(
offset: usize,
dedup_projection_count: Option<usize>,
) -> String {
let order_sql = dedup_projection_count.map_or(String::new(), |count| format_positional_order_by(count));
let order_sql = dedup_projection_count.map_or(String::new(), format_positional_order_by);
if has_top_level_limit(statement) {
if !order_sql.is_empty() {
+4 -6
View File
@@ -774,12 +774,10 @@ fn command_may_target_first_key(argv: &[String]) -> bool {
if argv.len() < 2 {
return false;
}
match argv[0].to_ascii_uppercase().as_str() {
"PING" | "INFO" | "DBSIZE" | "TIME" | "ROLE" | "CLUSTER" | "CLIENT" | "COMMAND" | "HELLO" | "AUTH" | "QUIT" => {
false
}
_ => true,
}
!matches!(
argv[0].to_ascii_uppercase().as_str(),
"PING" | "INFO" | "DBSIZE" | "TIME" | "ROLE" | "CLUSTER" | "CLIENT" | "COMMAND" | "HELLO" | "AUTH" | "QUIT"
)
}
pub async fn redis_load_more_in_db_core(
+1 -1
View File
@@ -1611,7 +1611,7 @@ fn oracle_object_info_can_have_table_comment(object: &db::ObjectInfo) -> bool {
}
fn oracle_type_is_table_or_view(value: &str) -> bool {
let normalized = value.to_ascii_uppercase().replace(' ', "_").replace('-', "_");
let normalized = value.to_ascii_uppercase().replace([' ', '-'], "_");
matches!(normalized.as_str(), "TABLE" | "BASE_TABLE" | "VIEW")
}
+5 -21
View File
@@ -395,9 +395,9 @@ impl SqlStatementSplitter {
self.buffer.push(ch);
}
';' if !self.in_single_quote && !self.in_double_quote && !self.in_backtick => {
if self.options.profile.supports_custom_delimiter_commands && self.on_delimiter_line() {
self.buffer.push(ch);
} else if self.custom_delimiter.is_some() {
if (self.options.profile.supports_custom_delimiter_commands && self.on_delimiter_line())
|| self.custom_delimiter.is_some()
{
self.buffer.push(ch);
} else if self.options.profile.supports_mysql_routine_blocks
&& starts_with_mysql_routine_block(&self.buffer)
@@ -1567,6 +1567,7 @@ fn parse_insert_values_tail(tail: &str) -> Option<String> {
}
}
#[derive(Default)]
struct SqlScanner {
profile: SqlDialectProfile,
in_single_quote: bool,
@@ -1609,9 +1610,7 @@ impl SqlScanner {
}
if !self.in_single_quote && !self.in_double_quote && !self.in_backtick {
if ch == '-' && next == Some('-') {
self.in_line_comment = true;
} else if self.profile.supports_hash_line_comments && ch == '#' {
if (ch == '-' && next == Some('-')) || (self.profile.supports_hash_line_comments && ch == '#') {
self.in_line_comment = true;
} else if ch == '/' && next == Some('*') {
self.in_block_comment = true;
@@ -1647,21 +1646,6 @@ impl SqlScanner {
}
}
impl Default for SqlScanner {
fn default() -> Self {
Self {
profile: SqlDialectProfile::default(),
in_single_quote: false,
in_double_quote: false,
in_backtick: false,
in_line_comment: false,
in_block_comment: false,
dollar_quote_tag: None,
previous: None,
}
}
}
fn keyword_at(sql: &str, idx: usize, keyword: &str) -> bool {
let end = idx + keyword.len();
sql.get(idx..end).is_some_and(|candidate| candidate.eq_ignore_ascii_case(keyword))
+12 -16
View File
@@ -158,25 +158,21 @@ fn redact_sensitive_assignments(sql: &str) -> String {
while j < chars.len() && chars[j].is_whitespace() {
j += 1;
}
if j < chars.len() && (chars[j] == '=' || chars[j] == ':') {
if is_sensitive_key(&key) {
out.push_str(&key);
for k in i..j {
out.push(chars[k]);
}
if j < chars.len() && (chars[j] == '=' || chars[j] == ':') && is_sensitive_key(&key) {
out.push_str(&key);
out.extend(chars[i..j].iter().copied());
out.push(chars[j]);
j += 1;
while j < chars.len() && chars[j].is_whitespace() {
out.push(chars[j]);
j += 1;
while j < chars.len() && chars[j].is_whitespace() {
out.push(chars[j]);
j += 1;
}
while j < chars.len() && !chars[j].is_whitespace() {
j += 1;
}
out.push_str("[REDACTED]");
i = j;
continue;
}
while j < chars.len() && !chars[j].is_whitespace() {
j += 1;
}
out.push_str("[REDACTED]");
i = j;
continue;
}
out.push_str(&key);
}
+5 -5
View File
@@ -1063,10 +1063,10 @@ fn merge_missing_tunnel_profile_secrets(profile: &mut TransportLayerConfig, prev
current.password = previous.password.clone();
}
}
(TransportLayerConfig::HttpTunnel(current), TransportLayerConfig::HttpTunnel(previous)) => {
if current.token.is_empty() {
current.token = previous.token.clone();
}
(TransportLayerConfig::HttpTunnel(current), TransportLayerConfig::HttpTunnel(previous))
if current.token.is_empty() =>
{
current.token = previous.token.clone();
}
_ => {}
}
@@ -3246,7 +3246,7 @@ mod tests {
let storage = Storage::open(&path).await.unwrap();
let original = mq_connection("pulsar", "existing-token");
storage.save_connections(&[original.clone()]).await.unwrap();
storage.save_connections(std::slice::from_ref(&original)).await.unwrap();
let mut metadata = original;
metadata.name = "Pulsar renamed".to_string();
+7 -7
View File
@@ -547,7 +547,7 @@ async fn try_export_native_table_stream(
let row_csv = format_csv_rows(&[formatted]);
write!(file, "\n{row_csv}").map_err(|e| format!("Failed to write CSV rows: {e}"))?;
rows_exported += 1;
if rows_exported % progress_interval == 0 {
if rows_exported.is_multiple_of(progress_interval) {
on_progress(TableExportProgress {
export_id: request.export_id.clone(),
table_name: request.table_name.clone(),
@@ -591,7 +591,7 @@ async fn try_export_native_table_stream(
let row_tsv = format_tsv_rows(&[formatted]);
write!(file, "\n{row_tsv}").map_err(|e| format!("Failed to write TXT rows: {e}"))?;
rows_exported += 1;
if rows_exported % progress_interval == 0 {
if rows_exported.is_multiple_of(progress_interval) {
on_progress(TableExportProgress {
export_id: request.export_id.clone(),
table_name: request.table_name.clone(),
@@ -636,7 +636,7 @@ async fn try_export_native_table_stream(
);
writer.write_row(&formatted).map_err(|e| format!("Failed to write XLSX row: {e}"))?;
rows_exported += 1;
if rows_exported % progress_interval == 0 {
if rows_exported.is_multiple_of(progress_interval) {
on_progress(TableExportProgress {
export_id: request.export_id.clone(),
table_name: request.table_name.clone(),
@@ -691,7 +691,7 @@ async fn try_export_native_table_stream(
write_json_row_object(&mut file, col_names, &formatted)?;
is_first_row = false;
rows_exported += 1;
if rows_exported % progress_interval == 0 {
if rows_exported.is_multiple_of(progress_interval) {
on_progress(TableExportProgress {
export_id: request.export_id.clone(),
table_name: request.table_name.clone(),
@@ -742,7 +742,7 @@ async fn try_export_native_table_stream(
wrote_rows = true;
}
rows_exported += 1;
if rows_exported % progress_interval == 0 {
if rows_exported.is_multiple_of(progress_interval) {
on_progress(TableExportProgress {
export_id: request.export_id.clone(),
table_name: request.table_name.clone(),
@@ -808,7 +808,7 @@ async fn try_export_native_table_stream(
flush_pending(&mut file, &mut pending_rows)?;
}
rows_exported += 1;
if rows_exported % progress_interval == 0 {
if rows_exported.is_multiple_of(progress_interval) {
on_progress(TableExportProgress {
export_id: request.export_id.clone(),
table_name: request.table_name.clone(),
@@ -839,7 +839,7 @@ async fn try_export_native_table_stream(
match stream_result {
Ok(false) => Ok(false),
Ok(true) => {
if rows_exported % progress_interval != 0 {
if !rows_exported.is_multiple_of(progress_interval) {
on_progress(TableExportProgress {
export_id: request.export_id.clone(),
table_name: request.table_name.clone(),
+1 -3
View File
@@ -2085,9 +2085,7 @@ where
pending_rows.push(delimited_record_to_row(&record, columns.len(), config));
}
let mut source_row_number = config.row_range.data_start_row;
for record in reader.records() {
source_row_number += 1;
for (source_row_number, record) in (config.row_range.data_start_row.saturating_add(1)..).zip(reader.records()) {
if config.row_range.last_data_row.is_some_and(|last| source_row_number > last) {
break;
}
+9 -20
View File
@@ -344,12 +344,7 @@ pub(crate) fn wrap_dameng_identity_insert_sql(insert_sql: &str, table: &str, sch
pub(crate) fn wrap_dameng_identity_insert_sql_for_table(insert_sql: &str, full_table: &str) -> String {
let trimmed = insert_sql.trim().trim_end_matches(';').trim();
format!(
"{};\n{};\n{};",
format!("SET IDENTITY_INSERT {full_table} ON"),
trimmed,
format!("SET IDENTITY_INSERT {full_table} OFF")
)
format!("SET IDENTITY_INSERT {full_table} ON;\n{trimmed};\nSET IDENTITY_INSERT {full_table} OFF;")
}
async fn execute_transfer_write_statement(
@@ -4139,7 +4134,7 @@ where
can_reuse_source_table_ddl(source_db_type, target_db_type, preserves_target_table_name);
let ddl = if can_reuse_source_ddl {
let source_ddl = crate::schema::get_table_ddl_core(
&state,
state,
&request.source_connection_id,
&request.source_database,
&request.source_schema,
@@ -5222,19 +5217,13 @@ mod tests {
#[test]
fn transfer_create_table_result_treats_existing_table_as_preexisting() {
assert_eq!(
transfer_create_table_created(
Err("ERROR: relation \"items\" already exists (SQLSTATE 42P07)".to_string()),
"create"
)
.unwrap(),
false
);
assert_eq!(
transfer_create_table_created(Err("错误: 关系 \"items\" 已经存在".to_string()), "create").unwrap(),
false
);
assert_eq!(transfer_create_table_created(Ok(()), "create").unwrap(), true);
assert!(!transfer_create_table_created(
Err("ERROR: relation \"items\" already exists (SQLSTATE 42P07)".to_string()),
"create"
)
.unwrap());
assert!(!transfer_create_table_created(Err("错误: 关系 \"items\" 已经存在".to_string()), "create").unwrap());
assert!(transfer_create_table_created(Ok(()), "create").unwrap());
assert_eq!(
transfer_create_table_created(Err("permission denied for schema public".to_string()), "create")
.unwrap_err(),