diff --git a/tests/custom_syntax.rs b/tests/custom_syntax.rs index ac504dfe7..9a2a3fbd3 100644 --- a/tests/custom_syntax.rs +++ b/tests/custom_syntax.rs @@ -1,6 +1,5 @@ #![cfg(not(feature = "no_custom_syntax"))] - -use rhai::{Dynamic, Engine, EvalAltResult, FnPtr, ImmutableString, LexError, ParseErrorType, Position, Scope, INT}; +use rhai::{Dynamic, Engine, EvalAltResult, ImmutableString, LexError, ParseErrorType, Position, Scope, INT}; #[test] fn test_custom_syntax() { @@ -432,3 +431,69 @@ fn test_custom_syntax_raw2() { assert_eq!(engine.eval::("#42/2").unwrap(), 21); assert_eq!(engine.eval::("sign(#1)").unwrap(), 1); } + +#[test] +fn test_custom_syntax_raw_sql() { + let mut engine = Engine::new(); + + engine.register_custom_syntax_with_state_raw( + "SELECT", + |symbols, lookahead, state| { + // Build a SQL statement as the state + let mut sql: String = if state.is_unit() { Default::default() } else { state.take().cast::().into() }; + + // At every iteration, the last symbol is the new one + let r = match symbols.last().unwrap().as_str() { + // Terminate parsing when we see `;` + ";" => None, + // Variable substitution -- parse the following as a block + "$" => Some("$block$".into()), + // Block parsed, replace it with `?` as SQL parameter + "$block$" => { + if !sql.is_empty() { + sql.push(' '); + } + sql.push('?'); + Some(lookahead.into()) // Always accept the next token + } + // Otherwise simply concat the tokens + _ => { + if !sql.is_empty() { + sql.push(' '); + } + sql.push_str(symbols.last().unwrap().as_str()); + Some(lookahead.into()) // Always accept the next token + } + }; + + // SQL statement done! + *state = sql.into(); + + match lookahead { + // End of script? + "{EOF}" => Ok(None), + _ => Ok(r), + } + }, + false, + |context, inputs, state| { + // Our SQL statement + let sql = state.as_immutable_string_ref().unwrap(); + let mut output = sql.to_string(); + + // Inputs will be parameters + for input in inputs { + let value = context.eval_expression_tree(input).unwrap(); + output.push('\n'); + output.push_str(&value.to_string()); + } + + Ok(output.into()) + }, + ); + + let mut scope = Scope::new(); + scope.push("id", 123 as INT); + + assert_eq!(engine.eval_with_scope::(&mut scope, "SELECT * FROM table WHERE id = ${id}").unwrap(), "SELECT * FROM table WHERE id = ?\n123"); +}