// must be run from the SQLite thread
    public static void Run(Notebook notebook, ScriptEnv env, ScriptRunner runner, Ast.ImportCsvStmt stmt)
    {
        var importer = new ImportCsvStmtRunner(notebook, env, runner, stmt);

        SqlUtil.WithTransaction(notebook, importer.Import);
    }
    private ImportCsvStmtRunner(Notebook notebook, ScriptEnv env, ScriptRunner runner, Ast.ImportCsvStmt stmt)
    {
        _notebook = notebook;
        _env      = env;
        _runner   = runner;
        _stmt     = stmt;

        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 "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("IMPORT CSV: The separator must be a single character.");
                }
                _separator = separator[0];
                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;

            case "IF_CONVERSION_FAILS":
                _ifConversionFails = (IfConversionFails)_stmt.OptionsList.GetOptionLong(
                    option, _runner, _env, 1, minValue: 1, maxValue: 3);
                break;

            case "BLANK_VALUES":
                _blankValuesMethod = (BlankValuesOption)_stmt.OptionsList.GetOptionLong(
                    option, _runner, _env, 2, minValue: 1, maxValue: 3);
                break;

            default:
                throw new Exception($"\"{option}\" is not a recognized option name.");
            }
        }
    }
 private void ExecuteImportCsvStmt(Ast.ImportCsvStmt stmt, ScriptEnv env)
 {
     ImportCsvStmtRunner.Run(_notebook, env, this, stmt);
 }