// 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."); } } }
private void ExecuteImportDatabaseStmt(Ast.ImportDatabaseStmt stmt, ScriptEnv env) { Notebook.WithCancellationToken(cancel => ImportDatabaseStmtRunner.Run(_notebook, env, this, stmt, cancel)); }