t8y2/dbx · info
valid ES SQL pagination regex
Error message
valid ES SQL pagination regex
What it means
Panic from Regex::new(...).expect when compiling the hard-coded ES SQL pagination pattern `(?i)^(.*?)\s+limit\s+(\d+)(?:\s+offset\s+(\d+))?\s*$`. The pattern is a compile-time constant known to be valid, so the expect documents a build-time invariant; a panic means the constant itself was corrupted in an edit. Users cannot trigger it via query input since the regex is never built from user data.
Source
Thrown at crates/dbx-core/src/db/elasticsearch_driver.rs:2468
) -> Result<QueryResult, String> {
let search = EsIndexedSearch {
index: translated.index,
body: translated.body,
from_plan_pagination: translated.from_plan_pagination,
// 用户自己写了 LIMIT 时不覆盖行数,否则会把「取 10 条」显示成索引总量。
report_index_total: !translated.user_limited,
};
execute_indexed_search(client, search, start, sql_response_parser, cursor).await
}
/// Split a trailing `LIMIT n OFFSET m` from an ES SQL statement. The OFFSET
/// form is produced by the DBX pagination plan; it must be removed before
/// sending the query to `_sql` so ES SQL cursor pagination can drive paging.
/// A bare user `LIMIT n` (no OFFSET) is preserved as an explicit row cap.
fn es_sql_pagination(query: &str) -> (String, Option<usize>) {
let trimmed = query.trim().trim_end_matches(';').trim();
let re =
Regex::new(r"(?i)^(.*?)\s+limit\s+(\d+)(?:\s+offset\s+(\d+))?\s*$").expect("valid ES SQL pagination regex");
if let Some(caps) = re.captures(trimmed) {
let limit = caps.get(2).and_then(|value| value.as_str().parse::<usize>().ok());
let offset = caps.get(3).and_then(|value| value.as_str().parse::<usize>().ok());
// Only the plan's `OFFSET 0` first page is safe to strip. A
// user-written `OFFSET > 0` must keep its explicit offset semantics.
if offset == Some(0) {
let base = caps.get(1).map(|value| value.as_str().trim().to_string()).unwrap_or_default();
(base, limit)
} else {
(trimmed.to_string(), limit)
}
} else {
(trimmed.to_string(), None)
}
}
async fn execute_sql_query(
client: &EsClient,View on GitHub (pinned to c0390bff16)
Solutions
- Keep the pattern as a validated constant; never interpolate user input into it
- Use once_cell::sync::Lazy<Regex> (or std OnceLock) to compile once and fail fast at first use with a clear message
- If the pattern ever becomes dynamic, replace expect with match Regex::new(...) returning a proper error
- Add a unit test that es_sql_pagination parses sample LIMIT/OFFSET queries to catch accidental corruption
Example fix
// before
let re =
Regex::new(r"(?i)^(.*?)\s+limit\s+(\d+)(?:\s+offset\s+(\d+))?\s*$").expect("valid ES SQL pagination regex");
// after
static ES_SQL_PAGINATION: Lazy<Regex> = Lazy::new(|| {
Regex::new(r"(?i)^(.*?)\s+limit\s+(\d+)(?:\s+offset\s+(\d+))?\s*$")
.expect("valid ES SQL pagination regex")
});
let re = &*ES_SQL_PAGINATION; Defensive patterns
Strategy: try-catch
Validate before calling
let q = query.trim().trim_end_matches(';');
let has_limit = q.to_lowercase().contains(" limit ");
// no caller-side action needed; the regex is a library constant
let _ = has_limit; Try / catch
let (sql, limit) = es_sql_pagination(query); // panics only on corrupted constant; catch_unwind is unnecessary — pin with a unit test
assert!(!sql.to_lowercase().contains("offset 0")); Prevention
- Never interpolate user input into regex patterns
- Compile fixed patterns once with once_cell Lazy
- Add unit tests covering LIMIT-only, LIMIT OFFSET 0, and LIMIT OFFSET n queries
When it happens
Trigger: Only fires if the literal regex string is edited into an invalid pattern (typo'd group, unbalanced paren), or if the code is changed to interpolate user/runtime input into the pattern.
Common situations: Hand-edits to the regex literal; refactors parameterizing the pattern with dynamic content; not reachable from es_sql() query input.
Related errors
- DBX_PUBLIC_BASE_PATH contains invalid characters
- error while building tauri application: {error}
- SQL is required
- a batch cancellation token is always available
- driver token registered
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/e225f50fe93440d8.
Report an issue: GitHub.