Strip temporal clauses from `sql` and return the rewritten text plus the extracted `TemporalScope`. Returns `Ok(None)` when no temporal clause is present so the caller can short-circuit to the existing pipeline.
(sql: &str)
| 56 | /// extracted `TemporalScope`. Returns `Ok(None)` when no temporal clause is |
| 57 | /// present so the caller can short-circuit to the existing pipeline. |
| 58 | pub fn extract(sql: &str) -> Result<Option<Extracted>, TemporalParseError> { |
| 59 | let mut scope = TemporalScope::default(); |
| 60 | let mut working = sql.to_string(); |
| 61 | let mut any = false; |
| 62 | |
| 63 | // FOR SYSTEM_TIME AS OF (table-scan style) |
| 64 | if let Some((rewritten, ms)) = strip_system_time_as_of(&working)? { |
| 65 | working = rewritten; |
| 66 | scope.system_as_of_ms = Some(ms); |
| 67 | any = true; |
| 68 | } |
| 69 | // __system_as_of__(<int>) function escape hatch |
| 70 | if let Some((rewritten, ms)) = strip_system_as_of_function(&working)? { |
| 71 | if scope.system_as_of_ms.is_some() { |
| 72 | return Err(TemporalParseError( |
| 73 | "multiple FOR SYSTEM_TIME / __system_as_of__ clauses".into(), |
| 74 | )); |
| 75 | } |
| 76 | working = rewritten; |
| 77 | scope.system_as_of_ms = Some(ms); |
| 78 | any = true; |
| 79 | } |
| 80 | // AS OF SYSTEM TIME <expr> (array read style, CockroachDB-inspired) |
| 81 | if let Some((rewritten, ms)) = strip_as_of_system_time(&working)? { |
| 82 | if scope.system_as_of_ms.is_some() { |
| 83 | return Err(TemporalParseError( |
| 84 | "multiple system-time AS OF clauses in one statement".into(), |
| 85 | )); |
| 86 | } |
| 87 | working = rewritten; |
| 88 | scope.system_as_of_ms = Some(ms); |
| 89 | any = true; |
| 90 | if strip_as_of_system_time(&working)?.is_some() { |
| 91 | return Err(TemporalParseError( |
| 92 | "multiple system-time AS OF clauses in one statement".into(), |
| 93 | )); |
| 94 | } |
| 95 | } |
| 96 | // FOR VALID_TIME CONTAINS/FROM…TO (table-scan style) |
| 97 | if let Some((rewritten, vt)) = strip_valid_time(&working)? { |
| 98 | working = rewritten; |
| 99 | scope.valid_time = vt; |
| 100 | any = true; |
| 101 | } |
| 102 | // AS OF VALID TIME <expr> (array read style) |
| 103 | if let Some((rewritten, ms)) = strip_as_of_valid_time(&working)? { |
| 104 | if !matches!(scope.valid_time, ValidTime::Any) { |
| 105 | return Err(TemporalParseError( |
| 106 | "multiple valid-time AS OF clauses in one statement".into(), |
| 107 | )); |
| 108 | } |
| 109 | working = rewritten; |
| 110 | scope.valid_time = ValidTime::At(ms); |
| 111 | any = true; |
| 112 | } |
| 113 | |
| 114 | if any { |
| 115 | Ok(Some(Extracted { |