#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CacheHint {
Default,
Cache,
NoCache,
}
impl Default for CacheHint {
fn default() -> Self {
Self::Default
}
}
#[must_use]
pub fn extract_cache_hint(sql: &str) -> (CacheHint, String) {
let trimmed = sql.trim();
if let Some(rest) = trimmed.strip_prefix("/*+") {
if let Some(end_pos) = rest.find("*/") {
let hint_content = rest[..end_pos].trim().to_uppercase();
let remaining_sql = rest[end_pos + 2..].trim().to_string();
let hint = match hint_content.as_str() {
"CACHE" => CacheHint::Cache,
"NO_CACHE" | "NOCACHE" => CacheHint::NoCache,
_ => CacheHint::Default,
};
return (hint, remaining_sql);
}
}
(CacheHint::Default, sql.to_string())
}
#[must_use]
#[allow(dead_code)]
pub fn is_cacheable_statement(sql: &str) -> bool {
let normalized = sql.trim().to_uppercase();
if normalized.starts_with("SELECT") || normalized.starts_with("/*+") {
if normalized.starts_with("/*+") {
if let Some(end) = normalized.find("*/") {
let after_hint = normalized[end + 2..].trim();
return after_hint.starts_with("SELECT");
}
}
return true;
}
false
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_extract_cache_hint() {
let (hint, sql) = extract_cache_hint("/*+ CACHE */ SELECT * FROM users");
assert_eq!(hint, CacheHint::Cache);
assert_eq!(sql, "SELECT * FROM users");
}
#[test]
fn test_extract_no_cache_hint() {
let (hint, sql) = extract_cache_hint("/*+ NO_CACHE */ SELECT * FROM orders");
assert_eq!(hint, CacheHint::NoCache);
assert_eq!(sql, "SELECT * FROM orders");
}
#[test]
fn test_extract_nocache_hint() {
let (hint, sql) = extract_cache_hint("/*+ NOCACHE */ SELECT * FROM products");
assert_eq!(hint, CacheHint::NoCache);
assert_eq!(sql, "SELECT * FROM products");
}
#[test]
fn test_no_hint() {
let (hint, sql) = extract_cache_hint("SELECT * FROM users");
assert_eq!(hint, CacheHint::Default);
assert_eq!(sql, "SELECT * FROM users");
}
#[test]
fn test_unknown_hint() {
let (hint, sql) = extract_cache_hint("/*+ UNKNOWN */ SELECT * FROM users");
assert_eq!(hint, CacheHint::Default);
assert_eq!(sql, "SELECT * FROM users");
}
#[test]
fn test_case_insensitive_hint() {
let (hint, _) = extract_cache_hint("/*+ cache */ SELECT * FROM users");
assert_eq!(hint, CacheHint::Cache);
let (hint, _) = extract_cache_hint("/*+ Cache */ SELECT * FROM users");
assert_eq!(hint, CacheHint::Cache);
}
#[test]
fn test_hint_with_whitespace() {
let (hint, sql) = extract_cache_hint(" /*+ CACHE */ SELECT * FROM users ");
assert_eq!(hint, CacheHint::Cache);
assert_eq!(sql, "SELECT * FROM users");
}
#[test]
fn test_is_cacheable_select() {
assert!(is_cacheable_statement("SELECT * FROM users"));
assert!(is_cacheable_statement(" SELECT * FROM users "));
assert!(is_cacheable_statement("/*+ CACHE */ SELECT * FROM users"));
}
#[test]
fn test_is_not_cacheable() {
assert!(!is_cacheable_statement("INSERT INTO users VALUES (1)"));
assert!(!is_cacheable_statement("UPDATE users SET name = 'test'"));
assert!(!is_cacheable_statement("DELETE FROM users"));
assert!(!is_cacheable_statement("CREATE TABLE users (id INT)"));
assert!(!is_cacheable_statement("DROP TABLE users"));
}
}