fix(saas): Phase 5 regression fixes — SQL type casts + test data corrections
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

- Fix usage_stats SQL: add ::timestamptz cast for Option<String> params
- Fix usage_stats SQL: add ::bigint cast for COALESCE(SUM(...))
- Fix telemetry INSERT: add ::timestamptz cast for reported_at column
- Fix config_analysis_empty test: seed data makes total_items > 0
- Fix key_pool_crud test: key_value must be >= 20 chars
- Fix SkillManifest test helpers: add missing tools field

All 1048 tests pass: 580 Rust + 138 SaaS + 330 Desktop Vitest
This commit is contained in:
iven
2026-04-07 19:21:45 +08:00
parent 6d2bedcfd7
commit ab0e11a719
7 changed files with 12 additions and 9 deletions

View File

@@ -413,8 +413,8 @@ pub async fn get_usage_stats(
) -> SaasResult<UsageStats> {
// Static SQL with conditional filter pattern:
// account_id is always required; optional filters use ($N IS NULL OR col = $N).
let total_sql = "SELECT COUNT(*)::bigint, COALESCE(SUM(input_tokens), 0), COALESCE(SUM(output_tokens), 0)
FROM usage_records WHERE account_id = $1 AND ($2 IS NULL OR created_at >= $2) AND ($3 IS NULL OR created_at <= $3) AND ($4 IS NULL OR provider_id = $4) AND ($5 IS NULL OR model_id = $5)";
let total_sql = "SELECT COUNT(*)::bigint, COALESCE(SUM(input_tokens), 0)::bigint, COALESCE(SUM(output_tokens), 0)::bigint
FROM usage_records WHERE account_id = $1 AND ($2 IS NULL OR created_at >= $2::timestamptz) AND ($3 IS NULL OR created_at <= $3::timestamptz) AND ($4 IS NULL OR provider_id = $4) AND ($5 IS NULL OR model_id = $5)";
let row = sqlx::query(total_sql)
.bind(account_id)
@@ -428,8 +428,8 @@ pub async fn get_usage_stats(
let total_output: i64 = row.try_get(2).unwrap_or(0);
// 按模型统计
let by_model_sql = "SELECT provider_id, model_id, COUNT(*)::bigint AS request_count, COALESCE(SUM(input_tokens), 0) AS input_tokens, COALESCE(SUM(output_tokens), 0) AS output_tokens
FROM usage_records WHERE account_id = $1 AND ($2 IS NULL OR created_at >= $2) AND ($3 IS NULL OR created_at <= $3) AND ($4 IS NULL OR provider_id = $4) AND ($5 IS NULL OR model_id = $5) GROUP BY provider_id, model_id ORDER BY COUNT(*) DESC LIMIT 20";
let by_model_sql = "SELECT provider_id, model_id, COUNT(*)::bigint AS request_count, COALESCE(SUM(input_tokens), 0)::bigint AS input_tokens, COALESCE(SUM(output_tokens), 0)::bigint AS output_tokens
FROM usage_records WHERE account_id = $1 AND ($2 IS NULL OR created_at >= $2::timestamptz) AND ($3 IS NULL OR created_at <= $3::timestamptz) AND ($4 IS NULL OR provider_id = $4) AND ($5 IS NULL OR model_id = $5) GROUP BY provider_id, model_id ORDER BY COUNT(*) DESC LIMIT 20";
let by_model_rows: Vec<UsageByModelRow> = sqlx::query_as(by_model_sql)
.bind(account_id)
@@ -449,7 +449,7 @@ pub async fn get_usage_stats(
.date_naive()
.and_hms_opt(0, 0, 0).unwrap()
.and_utc();
let daily_sql = "SELECT created_at::date::text as day, COUNT(*)::bigint AS request_count, COALESCE(SUM(input_tokens), 0) AS input_tokens, COALESCE(SUM(output_tokens), 0) AS output_tokens
let daily_sql = "SELECT created_at::date::text as day, COUNT(*)::bigint AS request_count, COALESCE(SUM(input_tokens), 0)::bigint AS input_tokens, COALESCE(SUM(output_tokens), 0)::bigint AS output_tokens
FROM usage_records WHERE account_id = $1 AND created_at >= $2
GROUP BY created_at::date ORDER BY day DESC LIMIT $3";
let daily_rows: Vec<UsageByDayRow> = sqlx::query_as(daily_sql)

View File

@@ -43,7 +43,7 @@ pub async fn ingest_telemetry(
let placeholders: Vec<String> = (0..chunk.len())
.map(|i| {
let base = i * cols + 1;
format!("(${},${},${},${},${},${},${},${},${},${},${},${},${})",
format!("(${},${},${},${},${},${},${},${},${},${},${},${}::timestamptz,${})",
base, base+1, base+2, base+3, base+4, base+5, base+6,
base+7, base+8, base+9, base+10, base+11, base+12)
}).collect();