use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use polyglot_sql::dialects::DialectType;
use polyglot_sql::transpile;
const SIMPLE_SELECT: &str = "SELECT a, b, c FROM table1";
const MEDIUM_SELECT: &str = r#"
SELECT
u.id,
u.name,
u.email,
COUNT(o.id) as order_count,
SUM(o.total) as total_spent
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.created_at > '2024-01-01'
AND u.status = 'active'
GROUP BY u.id, u.name, u.email
HAVING COUNT(o.id) > 5
ORDER BY total_spent DESC
LIMIT 100
"#;
const COMPLEX_SELECT: &str = r#"
WITH
active_users AS (
SELECT
u.id,
u.name,
u.email,
u.created_at
FROM users u
WHERE u.status = 'active'
AND u.last_login > CURRENT_DATE - INTERVAL '30 days'
),
user_orders AS (
SELECT
o.user_id,
COUNT(*) as order_count,
SUM(o.total) as total_spent,
AVG(o.total) as avg_order_value,
MAX(o.created_at) as last_order_date
FROM orders o
WHERE o.status = 'completed'
GROUP BY o.user_id
)
SELECT
au.id as user_id,
au.name as user_name,
au.email,
COALESCE(uo.order_count, 0) as total_orders,
COALESCE(uo.total_spent, 0) as lifetime_value,
COALESCE(uo.avg_order_value, 0) as average_order,
uo.last_order_date,
CASE
WHEN uo.total_spent > 10000 THEN 'VIP'
WHEN uo.total_spent > 1000 THEN 'Premium'
ELSE 'Regular'
END as customer_tier
FROM active_users au
LEFT JOIN user_orders uo ON au.id = uo.user_id
ORDER BY uo.total_spent DESC NULLS LAST
LIMIT 1000
"#;
fn bench_transpile_by_query_size(c: &mut Criterion) {
let mut group = c.benchmark_group("transpile_by_size");
group.bench_function("simple", |b| {
b.iter(|| {
transpile(
black_box(SIMPLE_SELECT),
DialectType::PostgreSQL,
DialectType::MySQL,
)
})
});
group.bench_function("medium", |b| {
b.iter(|| {
transpile(
black_box(MEDIUM_SELECT),
DialectType::PostgreSQL,
DialectType::MySQL,
)
})
});
group.bench_function("complex", |b| {
b.iter(|| {
transpile(
black_box(COMPLEX_SELECT),
DialectType::PostgreSQL,
DialectType::MySQL,
)
})
});
group.finish();
}
fn bench_transpile_dialect_pairs(c: &mut Criterion) {
let mut group = c.benchmark_group("transpile_dialect_pairs");
let dialect_pairs = [
(
"PostgreSQL_to_MySQL",
DialectType::PostgreSQL,
DialectType::MySQL,
),
(
"PostgreSQL_to_BigQuery",
DialectType::PostgreSQL,
DialectType::BigQuery,
),
(
"MySQL_to_PostgreSQL",
DialectType::MySQL,
DialectType::PostgreSQL,
),
(
"BigQuery_to_Snowflake",
DialectType::BigQuery,
DialectType::Snowflake,
),
(
"Snowflake_to_DuckDB",
DialectType::Snowflake,
DialectType::DuckDB,
),
(
"Generic_to_PostgreSQL",
DialectType::Generic,
DialectType::PostgreSQL,
),
];
for (name, source, target) in dialect_pairs {
group.bench_with_input(
BenchmarkId::new("medium_query", name),
&MEDIUM_SELECT,
|b, sql| b.iter(|| transpile(black_box(sql), source, target)),
);
}
group.finish();
}
fn bench_roundtrip(c: &mut Criterion) {
let mut group = c.benchmark_group("roundtrip");
use polyglot_sql::dialects::Dialect;
let dialect = Dialect::get(DialectType::PostgreSQL);
group.bench_function("medium_query", |b| {
b.iter(|| {
let ast = dialect.parse(black_box(MEDIUM_SELECT)).unwrap();
for expr in &ast {
let _ = dialect.generate(black_box(expr));
}
})
});
group.finish();
}
criterion_group!(
benches,
bench_transpile_by_query_size,
bench_transpile_dialect_pairs,
bench_roundtrip
);
criterion_main!(benches);