Skip to content

Commit d7ec445

Browse files
committed
Add ISqlBackupable interface and implementations for MSSQL and SQLite. Bump version to 1.9.18
1 parent 4d3ccaa commit d7ec445

7 files changed

Lines changed: 77 additions & 5 deletions

File tree

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
<Authors>vkuttyp</Authors>
88
<PackageLicenseExpression>MIT</PackageLicenseExpression>
99
<RepositoryUrl>https://github.com/vkuttyp/CosmoSQLClient-Dotnet</RepositoryUrl>
10-
<Version>1.9.17</Version>
10+
<Version>1.9.18</Version>
1111
</PropertyGroup>
1212
</Project>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace CosmoSQLClient.Core;
2+
3+
public record BackupOptions
4+
{
5+
public required string DestinationPath { get; init; }
6+
public bool Compression { get; init; } = true;
7+
public bool Format { get; init; } = true;
8+
public string? Password { get; init; }
9+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.Threading;
2+
using System.Threading.Tasks;
3+
4+
namespace CosmoSQLClient.Core;
5+
6+
public interface ISqlBackupable
7+
{
8+
Task BackupDatabaseAsync(string databaseName, BackupOptions options, CancellationToken ct = default);
9+
Task RestoreDatabaseAsync(string databaseName, string sourcePath, CancellationToken ct = default);
10+
}

src/CosmoSQLClient.MsSql/MsSqlConnection.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public sealed record SqlServerInfoMessage
121121
public byte State { get; init; }
122122
}
123123

124-
public sealed class MsSqlConnection : DbConnection, ISqlDatabase
124+
public sealed class MsSqlConnection : DbConnection, ISqlDatabase, ISqlBackupable
125125
{
126126
private readonly MsSqlConfiguration _config;
127127
private readonly ILogger _logger;
@@ -695,6 +695,21 @@ private static void WritePlpBytes(BinaryWriter bw, byte[]? b) {
695695
bw.Write((uint)0); // Terminator
696696
}
697697
}
698+
699+
public async Task BackupDatabaseAsync(string databaseName, BackupOptions options, CancellationToken ct = default)
700+
{
701+
var compression = options.Compression ? ", COMPRESSION" : "";
702+
var format = options.Format ? ", FORMAT" : "";
703+
var sql = $"BACKUP DATABASE [{databaseName}] TO DISK = '{options.DestinationPath}' WITH {format}{compression};";
704+
705+
await ExecuteAsync(sql, null, ct).ConfigureAwait(false);
706+
}
707+
708+
public async Task RestoreDatabaseAsync(string databaseName, string sourcePath, CancellationToken ct = default)
709+
{
710+
var sql = $"RESTORE DATABASE [{databaseName}] FROM DISK = '{sourcePath}' WITH REPLACE;";
711+
await ExecuteAsync(sql, null, ct).ConfigureAwait(false);
712+
}
698713
}
699714

700715
internal static class MsSqlConnectionPoolManager

src/CosmoSQLClient.MySql/MySqlConnection.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public static MySqlConfiguration Parse(string connectionString)
5454
}
5555
}
5656

57-
public sealed class MySqlConnection : DbConnection, ISqlDatabase
57+
public sealed class MySqlConnection : DbConnection, ISqlDatabase, ISqlBackupable
5858
{
5959
private readonly MySqlConfiguration _config;
6060
private readonly SemaphoreSlim _lock = new(1, 1);
@@ -351,4 +351,16 @@ public Task<SqlDataTable> QueryTableAsync(string sql, IReadOnlyList<SqlParameter
351351
protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) => throw new NotSupportedException();
352352
public override void ChangeDatabase(string databaseName) => throw new NotSupportedException();
353353
protected override DbCommand CreateDbCommand() => throw new NotSupportedException();
354+
355+
public Task BackupDatabaseAsync(string databaseName, BackupOptions options, CancellationToken ct = default)
356+
{
357+
// MySql typically requires external CLI tools (mysqldump/pg_dump).
358+
// Some cloud providers support SQL-based backups, but standard installations do not.
359+
throw new NotSupportedException("MySql does not support native backups via SQL commands. Use external CLI tools.");
360+
}
361+
362+
public Task RestoreDatabaseAsync(string databaseName, string sourcePath, CancellationToken ct = default)
363+
{
364+
throw new NotSupportedException("MySql does not support native restore via SQL commands.");
365+
}
354366
}

src/CosmoSQLClient.Postgres/PostgresConnection.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public static PostgresConfiguration Parse(string connectionString)
4747
}
4848
}
4949

50-
public sealed class PostgresConnection : DbConnection, ISqlDatabase
50+
public sealed class PostgresConnection : DbConnection, ISqlDatabase, ISqlBackupable
5151
{
5252
private readonly PostgresConfiguration _config;
5353
private readonly SemaphoreSlim _lock = new(1, 1);
@@ -345,4 +345,16 @@ public Task<SqlDataTable> QueryTableAsync(string sql, IReadOnlyList<SqlParameter
345345
protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) => throw new NotSupportedException();
346346
public override void ChangeDatabase(string databaseName) => throw new NotSupportedException();
347347
protected override DbCommand CreateDbCommand() => throw new NotSupportedException();
348+
349+
public Task BackupDatabaseAsync(string databaseName, BackupOptions options, CancellationToken ct = default)
350+
{
351+
// Postgres typically requires external CLI tools (mysqldump/pg_dump).
352+
// Some cloud providers support SQL-based backups, but standard installations do not.
353+
throw new NotSupportedException("Postgres does not support native backups via SQL commands. Use external CLI tools.");
354+
}
355+
356+
public Task RestoreDatabaseAsync(string databaseName, string sourcePath, CancellationToken ct = default)
357+
{
358+
throw new NotSupportedException("Postgres does not support native restore via SQL commands.");
359+
}
348360
}

src/CosmoSQLClient.Sqlite/SqliteConnection.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public static SqliteConfiguration Parse(string connectionString)
5959
/// SQLite connection for CosmoSQLClient. Wraps <see cref="Microsoft.Data.Sqlite.SqliteConnection"/>
6060
/// and inherits from <see cref="DbConnection"/> for compatibility with ADO.NET.
6161
/// </summary>
62-
public sealed class SqliteConnection : DbConnection, ISqlDatabase
62+
public sealed class SqliteConnection : DbConnection, ISqlDatabase, ISqlBackupable
6363
{
6464
private SqliteConfiguration _config;
6565
private readonly Microsoft.Data.Sqlite.SqliteConnection _conn;
@@ -426,4 +426,18 @@ private static SqlValue TryParseString(string s)
426426
return new SqlValue.Date(dt);
427427
return new SqlValue.Text(s);
428428
}
429+
430+
public async Task BackupDatabaseAsync(string databaseName, BackupOptions options, CancellationToken ct = default)
431+
{
432+
// SQLite uses VACUUM INTO for a safe, consistent online backup
433+
var sql = $"VACUUM INTO '{options.DestinationPath}';";
434+
await ExecuteAsync(sql, null, ct).ConfigureAwait(false);
435+
}
436+
437+
public Task RestoreDatabaseAsync(string databaseName, string sourcePath, CancellationToken ct = default)
438+
{
439+
// For SQLite, restore is usually just a file copy, but since we are a driver,
440+
// we can't easily overwrite the file we are currently connected to.
441+
throw new NotSupportedException("SQLite restore via SQL command is not supported. Use file copy while the connection is closed.");
442+
}
429443
}

0 commit comments

Comments
 (0)