From b91bf61c7b87df5c5a2a37d65a69e1f2700bd297 Mon Sep 17 00:00:00 2001 From: Mark Kincaid Date: Wed, 29 Oct 2025 08:09:00 -0700 Subject: [PATCH] Change dynamic importer variable to interface --- .../Migration/Databases/IDatabaseImporter.cs | 92 +++++++++++++++++++ .../Migration/Databases/MariaDbImporter.cs | 2 +- .../Migration/Databases/PostgresImporter.cs | 2 +- .../Migration/Databases/SqlServerImporter.cs | 2 +- .../Migration/Databases/SqliteImporter.cs | 2 +- util/Seeder/Recipes/CsvMigrationRecipe.cs | 8 +- 6 files changed, 100 insertions(+), 8 deletions(-) create mode 100644 util/Seeder/Migration/Databases/IDatabaseImporter.cs diff --git a/util/Seeder/Migration/Databases/IDatabaseImporter.cs b/util/Seeder/Migration/Databases/IDatabaseImporter.cs new file mode 100644 index 0000000000..6da2da8a66 --- /dev/null +++ b/util/Seeder/Migration/Databases/IDatabaseImporter.cs @@ -0,0 +1,92 @@ +namespace Bit.Seeder.Migration.Databases; + +/// +/// Interface for database importers that migrate data from SQL Server to various database systems. +/// +public interface IDatabaseImporter : IDisposable +{ + /// + /// Establishes a connection to the target database. + /// + /// True if connection was successful, false otherwise. + bool Connect(); + + /// + /// Closes the connection to the target database. + /// + void Disconnect(); + + /// + /// Creates a table in the target database from a schema definition. + /// + /// Name of the table to create. + /// List of column names. + /// Dictionary mapping column names to their SQL Server data types. + /// Optional list of columns that require special handling (e.g., JSON columns). + /// True if table was created successfully, false otherwise. + bool CreateTableFromSchema( + string tableName, + List columns, + Dictionary columnTypes, + List? specialColumns = null); + + /// + /// Retrieves the list of column names for a table. + /// + /// Name of the table. + /// List of column names. + List GetTableColumns(string tableName); + + /// + /// Imports data into a table. + /// + /// Name of the target table. + /// List of column names in the data. + /// Data rows to import. + /// Number of rows to import per batch. + /// True if import was successful, false otherwise. + bool ImportData( + string tableName, + List columns, + List data, + int batchSize = 1000); + + /// + /// Checks if a table exists in the target database. + /// + /// Name of the table to check. + /// True if table exists, false otherwise. + bool TableExists(string tableName); + + /// + /// Gets the number of rows in a table. + /// + /// Name of the table. + /// Number of rows in the table. + int GetTableRowCount(string tableName); + + /// + /// Drops a table from the database. + /// + /// Name of the table to drop. + /// True if table was dropped successfully, false otherwise. + bool DropTable(string tableName); + + /// + /// Disables foreign key constraints to allow data import without referential integrity checks. + /// + /// True if foreign keys were disabled successfully, false otherwise. + bool DisableForeignKeys(); + + /// + /// Re-enables foreign key constraints after data import. + /// + /// True if foreign keys were enabled successfully, false otherwise. + bool EnableForeignKeys(); + + /// + /// Tests the connection to the database. + /// + /// True if connection test was successful, false otherwise. + bool TestConnection(); +} diff --git a/util/Seeder/Migration/Databases/MariaDbImporter.cs b/util/Seeder/Migration/Databases/MariaDbImporter.cs index d7baaf7e9c..e3983f9f1f 100644 --- a/util/Seeder/Migration/Databases/MariaDbImporter.cs +++ b/util/Seeder/Migration/Databases/MariaDbImporter.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.Logging; namespace Bit.Seeder.Migration.Databases; -public class MariaDbImporter(DatabaseConfig config, ILogger logger) : IDisposable +public class MariaDbImporter(DatabaseConfig config, ILogger logger) : IDatabaseImporter { private readonly ILogger _logger = logger; private readonly string _host = config.Host; diff --git a/util/Seeder/Migration/Databases/PostgresImporter.cs b/util/Seeder/Migration/Databases/PostgresImporter.cs index 06c0e88fdd..9d7d58857a 100644 --- a/util/Seeder/Migration/Databases/PostgresImporter.cs +++ b/util/Seeder/Migration/Databases/PostgresImporter.cs @@ -4,7 +4,7 @@ using Microsoft.Extensions.Logging; namespace Bit.Seeder.Migration.Databases; -public class PostgresImporter(DatabaseConfig config, ILogger logger) : IDisposable +public class PostgresImporter(DatabaseConfig config, ILogger logger) : IDatabaseImporter { private readonly ILogger _logger = logger; private readonly string _host = config.Host; diff --git a/util/Seeder/Migration/Databases/SqlServerImporter.cs b/util/Seeder/Migration/Databases/SqlServerImporter.cs index b48c835778..215d8784d9 100644 --- a/util/Seeder/Migration/Databases/SqlServerImporter.cs +++ b/util/Seeder/Migration/Databases/SqlServerImporter.cs @@ -6,7 +6,7 @@ using System.Data; namespace Bit.Seeder.Migration.Databases; -public class SqlServerImporter(DatabaseConfig config, ILogger logger) : IDisposable +public class SqlServerImporter(DatabaseConfig config, ILogger logger) : IDatabaseImporter { private readonly ILogger _logger = logger; private readonly string _host = config.Host; diff --git a/util/Seeder/Migration/Databases/SqliteImporter.cs b/util/Seeder/Migration/Databases/SqliteImporter.cs index 2b81d40372..fd4e13c845 100644 --- a/util/Seeder/Migration/Databases/SqliteImporter.cs +++ b/util/Seeder/Migration/Databases/SqliteImporter.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.Logging; namespace Bit.Seeder.Migration.Databases; -public class SqliteImporter(DatabaseConfig config, ILogger logger) : IDisposable +public class SqliteImporter(DatabaseConfig config, ILogger logger) : IDatabaseImporter { private readonly ILogger _logger = logger; private readonly string _databasePath = config.Database; diff --git a/util/Seeder/Recipes/CsvMigrationRecipe.cs b/util/Seeder/Recipes/CsvMigrationRecipe.cs index 7f30851ed7..7cbfb0e646 100644 --- a/util/Seeder/Recipes/CsvMigrationRecipe.cs +++ b/util/Seeder/Recipes/CsvMigrationRecipe.cs @@ -212,7 +212,7 @@ public class CsvMigrationRecipe(MigrationConfig config, ILoggerFactory loggerFac return false; } - dynamic? importer = CreateImporter(dbType, destConfig); + IDatabaseImporter? importer = CreateImporter(dbType, destConfig); if (importer == null) { _logger.LogError("Failed to create importer for {DbType}", dbType); @@ -354,7 +354,7 @@ public class CsvMigrationRecipe(MigrationConfig config, ILoggerFactory loggerFac return false; } - dynamic? importer = CreateImporter(dbType, destConfig); + IDatabaseImporter? importer = CreateImporter(dbType, destConfig); if (importer == null) { _logger.LogError("Failed to create importer for {DbType}", dbType); @@ -453,7 +453,7 @@ public class CsvMigrationRecipe(MigrationConfig config, ILoggerFactory loggerFac return false; } - dynamic? importer = CreateImporter(dbType, destConfig); + IDatabaseImporter? importer = CreateImporter(dbType, destConfig); if (importer == null) { _logger.LogError("Failed to create importer for {DbType}", dbType); @@ -481,7 +481,7 @@ public class CsvMigrationRecipe(MigrationConfig config, ILoggerFactory loggerFac } } - private dynamic? CreateImporter(string dbType, DatabaseConfig config) => + private IDatabaseImporter? CreateImporter(string dbType, DatabaseConfig config) => dbType.ToLower() switch { "postgres" or "postgresql" => new PostgresImporter(config, _loggerFactory.CreateLogger()),