public static long GetOptionLong(this Ast.OptionsList optionsList, string name, ScriptRunner runner, ScriptEnv env, long defaultValue, long?minValue = null, long?maxValue = null) { var num = optionsList.GetOption <long>(name, runner, env, defaultValue); bool outOfRange = (minValue.HasValue && num < minValue.Value) || (maxValue.HasValue && num > maxValue.Value); if (outOfRange) { if (minValue.HasValue && !maxValue.HasValue) { throw new Exception($"{name} must be an integer ≥ {minValue.Value}."); } else if (minValue.HasValue && maxValue.HasValue) { throw new Exception($"{name} must be an integer between {minValue.Value} and {maxValue.Value}."); } else if (!minValue.HasValue && maxValue.HasValue) { throw new Exception($"{name} must be an integer ≤ {maxValue.Value}."); } } return(num); }
public static void Import( IReadOnlyList <string> srcColNames, IEnumerable <object[]> dataRows, Ast.ImportTable importTable, bool temporaryTable, bool truncateExistingTable, bool stopAtFirstBlankRow, IfConversionFails ifConversionFails, BlankValuesOption blankValuesMethod, Notebook notebook, ScriptRunner runner, ScriptEnv env ) { var dstTableName = runner.EvaluateIdentifierOrExpr(importTable.TableName, env); var mappings = GetImportColumnMappings(importTable.ImportColumns, runner, env, srcColNames); if (!mappings.Any()) { throw new Exception("No columns chosen for import."); } CreateOrTruncateTable(mappings, dstTableName, temporaryTable, truncateExistingTable, notebook); VerifyColumnsExist(mappings.Select(x => x.DstColumnName), dstTableName, notebook); InsertDataRows(dataRows, srcColNames, mappings, dstTableName, ifConversionFails, stopAtFirstBlankRow, blankValuesMethod, notebook); }
private ExportTxtStmtRunner(Notebook notebook, ScriptEnv env, ScriptRunner runner, Ast.ExportTxtStmt stmt) { _notebook = notebook; _env = env; _runner = runner; _stmt = stmt; _filePath = GetFilePath(); foreach (var option in _stmt.OptionsList.GetOptionKeys()) { switch (option) { case "TRUNCATE_EXISTING_FILE": _truncateExistingFile = _stmt.OptionsList.GetOptionBool(option, _runner, _env, false); break; case "FILE_ENCODING": _fileEncoding = _stmt.OptionsList.GetOptionEncoding(option, _runner, _env); break; default: throw new Exception($"\"{option}\" is not a recognized option name."); } } if (_fileEncoding == null) { _fileEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); } }
private void ExecuteWhileStmt(Ast.WhileStmt stmt, ScriptEnv env) { long condition; do { condition = EvaluateExpr <long>(stmt.Condition, env); if (condition == 1) { ExecuteBlock(stmt.Block, env); if (env.DidReturn) { return; } else if (env.DidBreak) { env.DidBreak = false; break; } else if (env.DidContinue) { env.DidContinue = false; } } else if (condition != 0) { throw new ScriptException( $"Evaluation of WHILE condition expression \"{stmt.Condition.Sql}\" " + $"produced a value of {condition} instead of the expected 0 or 1."); } } while (condition == 1); }
public ScriptOutput ExecuteScriptEx(string code, IReadOnlyDictionary <string, object> args, TransactionType transactionType, out Dictionary <string, object> vars) { var env = new ScriptEnv(); var output = Invoke(() => { var parser = new ScriptParser(Notebook); var script = parser.Parse(code); var runner = new ScriptRunner(Notebook, Notebook.GetScripts()); if (transactionType == TransactionType.Transaction) { return(SqlUtil.WithTransaction(Notebook, () => runner.Execute(script, env, args ?? new Dictionary <string, object>()))); } else if (transactionType == TransactionType.RollbackTransaction) { return(SqlUtil.WithRollbackTransaction(Notebook, () => runner.Execute(script, env, args ?? new Dictionary <string, object>()))); } else { return(runner.Execute(script, env, args ?? new Dictionary <string, object>())); } }); vars = env.Vars; return(output); }
// must be run from the SQLite thread public static void Run(Notebook notebook, ScriptEnv env, ScriptRunner runner, Ast.ImportDatabaseStmt stmt, CancellationToken cancel ) { ImportDatabaseStmtRunner importer = new(notebook, env, runner, stmt, cancel); SqlUtil.WithTransaction(notebook, importer.Import); }
private void ExecuteReturnStmt(Ast.ReturnStmt stmt, ScriptEnv env) { if (stmt.Value != null) { env.Output.ScalarResult = EvaluateExpr(stmt.Value, env); } env.DidReturn = true; }
// must be run from the SQLite thread public static void Run(Notebook notebook, ScriptEnv env, ScriptRunner runner, Ast.ExportCsvStmt stmt, CancellationToken cancel ) { ExportCsvStmtRunner exporter = new(notebook, env, runner, stmt, cancel); exporter.Export(); }
private void ExecuteTryCatchStmt(Ast.TryCatchStmt stmt, ScriptEnv env) { try { ExecuteBlock(stmt.TryBlock, env); } catch (Exception ex) { Notebook.ErrorMessage = ex.GetExceptionMessage(); ExecuteBlock(stmt.CatchBlock, env); } }
public ScriptOutput Execute(Ast.Script script, ScriptEnv env, IReadOnlyDictionary <string, object> args) { foreach (var arg in args) { var lowercaseKey = arg.Key.ToLower(); env.Vars[lowercaseKey] = arg.Value; } Execute(script, env); return(env.Output); }
public string EvaluateIdentifierOrExpr(Ast.IdentifierOrExpr idOrExpr, ScriptEnv env) { if (idOrExpr.Expr != null) { return(EvaluateExpr <string>(idOrExpr.Expr, env)); } else { return(idOrExpr.Identifier); } }
private void ExecuteBlock(Ast.Block block, ScriptEnv env) { foreach (var stmt in block.Statements) { ExecuteStmt(stmt, env); if (env.DidReturn || env.DidBreak || env.DidContinue) { return; } } }
private void ExecuteThrowStmt(Ast.ThrowStmt stmt, ScriptEnv env) { if (stmt.HasErrorValues) { var errorMessage = EvaluateExpr(stmt.Message, env); Throw(errorMessage.ToString()); } else { Throw(Notebook.ErrorMessage); } }
private void ExecutePrintStmt(Ast.PrintStmt stmt, ScriptEnv env) { var value = EvaluateExpr(stmt.Value, env); if (value is byte[] byteArray) { env.Output.TextOutput.Add(BlobUtil.ToString(byteArray)); return; } env.Output.TextOutput.Add(value.ToString()); }
private void ExecuteForStmt(Ast.ForStmt stmt, ScriptEnv env) { var firstNumber = EvaluateExpr <long>(stmt.FirstNumberExpr, env); var lastNumber = EvaluateExpr <long>(stmt.LastNumberExpr, env); long step = firstNumber <= lastNumber ? 1 : -1; if (stmt.StepExpr != null) { step = EvaluateExpr <long>(stmt.StepExpr, env); } if (step == 0) { throw new ScriptException("The STEP value in a FOR statement must not be zero."); } else if (step < 0 && firstNumber < lastNumber) { throw new ScriptException( "The STEP value in a FOR statement must be positive if \"first-number\" < \"last-number\"."); } else if (step > 0 && firstNumber > lastNumber) { throw new ScriptException( "The STEP value in a FOR statement must be negative if \"first-number\" > \"last-number\"."); } var upward = step > 0; long counter = firstNumber; while ((upward && counter <= lastNumber) || (!upward && counter >= lastNumber)) { env.Vars[stmt.VariableName] = counter; ExecuteBlock(stmt.Block, env); if (env.DidReturn) { return; } else if (env.DidBreak) { env.DidBreak = false; break; } else if (env.DidContinue) { env.DidContinue = false; } counter += step; } }
public object EvaluateExpr(Ast.Expr expr, ScriptEnv env) { using var dt = _notebook.Query($"SELECT ({expr.Sql})", env.Vars); if (dt.Columns.Count == 1 && dt.Rows.Count == 1) { return(dt.Rows[0][0]); } else { throw new ScriptException( $"Evaluation of expression \"{expr.Sql}\" did not produce a value."); } }
private void ExecuteExecuteStmt(Ast.ExecuteStmt stmt, ScriptEnv env) { var subOutput = ExecuteSubScript(stmt.ScriptName, stmt.Arguments, env); env.Output.Append(subOutput); var returnCode = subOutput.ScalarResult; if (stmt.ReturnVariableName != null) { var name = stmt.ReturnVariableName.ToLower(); env.Vars[name] = returnCode ?? DBNull.Value; } }
private void ExecuteSetStmt(Ast.SetStmt stmt, ScriptEnv env) { var name = stmt.VariableName.ToLower(); if (env.Vars.ContainsKey(name)) { env.Vars[name] = EvaluateExpr(stmt.InitialValue, env); } else { throw new ScriptException($"Attempted to SET the undeclared variable \"{stmt.VariableName}\"."); } }
public static bool GetOptionBool(this Ast.OptionsList optionsList, string name, ScriptRunner runner, ScriptEnv env, bool defaultValue) { long num = optionsList.GetOption <long>(name, runner, env, defaultValue ? 1 : 0); if (num != 0 && num != 1) { throw new Exception($"{name} must be 0 or 1."); } else { return(num == 1); } }
public static int GetOptionInt(this Ast.OptionsList optionsList, string name, ScriptRunner runner, ScriptEnv env, int defaultValue, int?minValue = null, int?maxValue = null) { var longValue = GetOptionLong(optionsList, name, runner, env, defaultValue, minValue, maxValue); if (longValue < int.MinValue || longValue > int.MaxValue) { throw new Exception($"{name} must be a 32-bit integer."); } else { return((int)longValue); } }
public T EvaluateExpr <T>(Ast.Expr expr, ScriptEnv env) { var value = EvaluateExpr(expr, env); if (typeof(T).IsAssignableFrom(value.GetType())) { return((T)value); } else { throw new ScriptException( $"Evaluation of expression \"{expr.Sql}\" produced a value of type " + $"\"{value.GetType().Name}\" instead of the expected \"{typeof(T).Name}\"."); } }
private ExportCsvStmtRunner(Notebook notebook, ScriptEnv env, ScriptRunner runner, Ast.ExportCsvStmt stmt, CancellationToken cancel ) { _notebook = notebook; _env = env; _runner = runner; _stmt = stmt; _cancel = cancel; _filePath = GetFilePath(); foreach (var option in _stmt.OptionsList.GetOptionKeys()) { switch (option) { case "HEADER_ROW": _headerRow = _stmt.OptionsList.GetOptionBool(option, _runner, _env, true); break; case "SEPARATOR": { var separator = _stmt.OptionsList.GetOption(option, _runner, _env, ","); if (separator.Length != 1) { throw new Exception("EXPORT CSV: The separator must be a single character."); } _separator = separator[0]; break; } case "TRUNCATE_EXISTING_FILE": _truncateExistingFile = _stmt.OptionsList.GetOptionBool(option, _runner, _env, false); break; case "FILE_ENCODING": _fileEncoding = _stmt.OptionsList.GetOptionEncoding(option, _runner, _env); break; default: throw new Exception($"EXPORT CSV: \"{option}\" is not a recognized option name."); } } if (_fileEncoding == null) { _fileEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); } }
public static void Import(string[] srcColNames, IEnumerable <object[]> dataRows, Ast.ImportTable importTable, bool temporaryTable, bool truncateExistingTable, IfConversionFails ifConversionFails, INotebook notebook, ScriptRunner runner, ScriptEnv env) { Ast.ImportColumn[] dstColNodes; string[] dstColNames; var dstTableName = runner.EvaluateIdentifierOrExpr(importTable.TableName, env); GetDestinationColumns(importTable.ImportColumns, runner, env, srcColNames, out dstColNodes, out dstColNames); CreateOrTruncateTable(srcColNames, dstColNodes, dstColNames, dstTableName, temporaryTable, truncateExistingTable, notebook); VerifyColumnsExist(dstColNames, dstTableName, notebook); InsertDataRows(dataRows, dstColNames, dstColNodes, dstTableName, ifConversionFails, notebook); }
private void ExecuteDeclareStmt(Ast.DeclareStmt stmt, ScriptEnv env) { var name = stmt.VariableName.ToLower(); var declarationExists = env.Vars.ContainsKey(name); if (stmt.IsParameter) { if (env.ParNames.Contains(name)) { throw new ScriptException($"Duplicate DECLARE for parameter \"{stmt.VariableName}\"."); } else { env.ParNames.Add(name); } if (declarationExists) { // do nothing; the parameter value was specified by the caller } else if (stmt.InitialValue != null) { // the caller did not specify a value, but there is an initial value in the DECLARE statement. env.Vars[name] = EvaluateExpr(stmt.InitialValue, env); } else { throw new ScriptException( $"An argument value was not provided for parameter \"{stmt.VariableName}\"."); } } else if (declarationExists) { throw new ScriptException($"Duplicate DECLARE for variable \"{stmt.VariableName}\"."); } else { if (stmt.InitialValue != null) { env.Vars[name] = EvaluateExpr(stmt.InitialValue, env); } else { env.Vars[name] = DBNull.Value; } } }
protected virtual void OnDestroy() { if (_luaOnDestroy != null) { _luaOnDestroy(); } if (ScriptEnv != null) { ScriptEnv.Dispose(); _scriptEnv = null; } _luaStart = null; _luaUpdate = null; _luaOnDestroy = null; }
private ImportTxtStmtRunner(Notebook notebook, ScriptEnv env, ScriptRunner runner, Ast.ImportTxtStmt stmt) { _notebook = notebook; _env = env; _runner = runner; _stmt = stmt; _tableName = _runner.EvaluateIdentifierOrExpr(_stmt.TableName, _env); _lineNumberColumnName = _stmt.LineNumberColumnName == null ? null : _runner.EvaluateIdentifierOrExpr(_stmt.LineNumberColumnName, _env); _textColumnName = _stmt.TextColumnName == null ? null : _runner.EvaluateIdentifierOrExpr(_stmt.TextColumnName, _env); foreach (var option in _stmt.OptionsList.GetOptionKeys()) { switch (option) { case "SKIP_LINES": _skipLines = _stmt.OptionsList.GetOptionLong(option, _runner, _env, 0, minValue: 0); break; case "TAKE_LINES": _takeLines = _stmt.OptionsList.GetOptionLong(option, _runner, _env, -1, minValue: -1); if (_takeLines == -1) { _takeLines = null; } break; case "TRUNCATE_EXISTING_TABLE": _truncateExistingTable = _stmt.OptionsList.GetOptionBool(option, _runner, _env, false); break; case "TEMPORARY_TABLE": _temporaryTable = _stmt.OptionsList.GetOptionBool(option, _runner, _env, false); break; case "FILE_ENCODING": _fileEncoding = _stmt.OptionsList.GetOptionEncoding(option, _runner, _env); break; default: throw new Exception($"\"{option}\" is not a recognized option name."); } } }
public ScriptOutput ExecuteSubScript(string scriptName, List <Ast.ArgumentPair> arguments, ScriptEnv env) { var parser = new ScriptParser(_notebook); var runner = new ScriptRunner(_notebook, _scripts); var script = parser.Parse(GetScriptCode(scriptName)); var subEnv = new ScriptEnv { OnRow = env.OnRow }; foreach (var arg in arguments) { if (arg.Value != null) { subEnv.Vars[arg.Name.ToLower()] = EvaluateExpr(arg.Value, env); } } runner.Execute(script, subEnv); return(subEnv.Output); }
private const float GcInterval = 1; //1 second protected virtual void Awake() { var meta = LuaEnv.NewTable(); meta.Set("__index", LuaEnv.Global); ScriptEnv.SetMetaTable(meta); meta.Dispose(); ScriptEnv.Set("self", this); foreach (var injection in Injections) { ScriptEnv.Set(injection.Name, injection.Value); } var content = LuaEnv.DoString(string.Format(@" local content = require '{0}' return content", _luaFilePath), "LuaMonoBehaviour", ScriptEnv); if (content != null) { LuaTable luaTable = (LuaTable)content[0]; var contentMeta = LuaEnv.NewTable(); contentMeta.Set("__index", ScriptEnv); luaTable.SetMetaTable(contentMeta); contentMeta.Dispose(); var luaAwake = luaTable.Get <Action>("awake"); _luaStart = luaTable.Get <Action>("start"); _luaUpdate = luaTable.Get <Action>("update"); _luaOnDestroy = luaTable.Get <Action>("destroy"); if (luaAwake != null) { luaAwake(); } } }
public void Execute(Ast.Script script, ScriptEnv env) { try { ExecuteBlock(script.Block, env); if (env.DidBreak) { throw new ScriptException($"Attempted to BREAK outside of a WHILE loop."); } else if (env.DidContinue) { throw new ScriptException($"Attempted to CONTINUE outside of a WHILE loop."); } } catch (Exception ex) { var snippet = ex is SqliteException s ? s.Snippet : null; throw new UncaughtErrorScriptException(ex.GetExceptionMessage(), ex) { Snippet = snippet }; } }
private void ExecuteIfStmt(Ast.IfStmt stmt, ScriptEnv env) { var condition = EvaluateExpr <long>(stmt.Condition, env); if (condition == 0) { if (stmt.ElseBlock != null) { ExecuteBlock(stmt.ElseBlock, env); } } else if (condition == 1) { ExecuteBlock(stmt.Block, env); } else { throw new ScriptException( $"Evaluation of IF condition expression \"{stmt.Condition.Sql}\" " + $"produced a value of {condition} instead of the expected 0 or 1."); } }