// 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 ImportDatabaseStmtRunner(Notebook notebook, ScriptEnv env, ScriptRunner runner, Ast.ImportDatabaseStmt stmt,
                                     CancellationToken cancel
                                     )
    {
        _notebook = notebook;
        _env      = env;
        _runner   = runner;
        _stmt     = stmt;
        _cancel   = cancel;

        // vendor
        var vendorObj = _runner.EvaluateExpr(_stmt.VendorExpr, _env);

        if (vendorObj is not string)
        {
            throw new Exception("IMPORT DATABASE: The 'vendor' parameter must be a string.");
        }
        _vendor = ((string)vendorObj).ToLowerInvariant();
        switch (_vendor)
        {
        case "mssql":
        case "pgsql":
        case "mysql":
            break;

        default:
            throw new Exception($"IMPORT DATABASE: The vendor \"{_vendor}\" is not recognized.");
        }

        // src-schema-name
        if (stmt.SrcSchemaNameExprOrNull != null)
        {
            _srcSchemaName = _runner.EvaluateIdentifierOrExpr(stmt.SrcSchemaNameExprOrNull, _env);
        }

        // src-table-name, sql
        if (stmt.SrcTableNameExprOrNull != null)
        {
            _srcTableName = _runner.EvaluateIdentifierOrExpr(stmt.SrcTableNameExprOrNull, _env);
            _sql          = null;
        }
        else if (stmt.SqlExprOrNull != null)
        {
            var sqlObj = _runner.EvaluateExpr(stmt.SqlExprOrNull, _env);
            if (sqlObj is not string)
            {
                throw new Exception("IMPORT DATABASE: The 'sql' parameter must be a string.");
            }
            _sql          = (string)sqlObj;
            _srcTableName = null;
        }
        else
        {
            throw new Exception("IMPORT DATABASE: Internal error. No source table and no query specified.");
        }

        // dst-table-name
        if (_stmt.DstTableNameExprOrNull != null)
        {
            _dstTableName = _runner.EvaluateIdentifierOrExpr(_stmt.DstTableNameExprOrNull, _env);
        }
        else if (_stmt.SrcTableNameExprOrNull != null)
        {
            _dstTableName = _runner.EvaluateIdentifierOrExpr(_stmt.SrcTableNameExprOrNull, _env);
        }
        else if (_stmt.SqlExprOrNull != null)
        {
            throw new Exception("IMPORT DATABASE: A target table name (with INTO) is required when the source is a query.");
        }
        else
        {
            throw new Exception("IMPORT DATABASE: Internal error. No destination table name.");
        }

        // connection-string
        var connectionStringObj = _runner.EvaluateExpr(_stmt.ConnectionStringExpr, _env);

        if (connectionStringObj is not string)
        {
            throw new Exception("IMPORT DATABASE: The 'connection-string' parameter must be a string.");
        }
        _connectionString = (string)connectionStringObj;

        // OPTIONS
        foreach (var option in _stmt.OptionsList.GetOptionKeys())
        {
            switch (option)
            {
            case "LINK":
                _link = _stmt.OptionsList.GetOptionBool(option, _runner, _env, false);
                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;

            default:
                throw new Exception($"\"{option}\" is not a recognized option name.");
            }
        }

        // validate option LINK
        if (_link)
        {
            if (_sql != null)
            {
                throw new Exception("IMPORT DATABASE: When creating a live link, a source table name must be provided, not an SQL query.");
            }
            if (TableExists(_dstTableName))
            {
                throw new Exception($"IMPORT DATABASE: The table \"{_dstTableName}\" already exists.");
            }
            if (_truncateExistingTable)
            {
                throw new Exception($"IMPORT DATABASE: When creating a live link, the TRUNCATE_EXISTING_TABLE option is not valid.");
            }
            if (_temporaryTable)
            {
                throw new Exception($"IMPORT DATABASE: When creating a live link, the TEMPORARY_TABLE option is not valid.");
            }
        }
    }
Beispiel #3
0
 private void ExecuteImportDatabaseStmt(Ast.ImportDatabaseStmt stmt, ScriptEnv env)
 {
     Notebook.WithCancellationToken(cancel =>
                                    ImportDatabaseStmtRunner.Run(_notebook, env, this, stmt, cancel));
 }