Skip to content

Commit 2651e2b

Browse files
committed
Merge branch 'develop' of https://github.com/marcominerva/DatabaseGPT into develop
2 parents da256a2 + 415547f commit 2651e2b

File tree

10 files changed

+182
-3
lines changed

10 files changed

+182
-3
lines changed

DatabaseGpt.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DatabaseGpt.Npgsql", "src\D
2323
EndProject
2424
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DatabaseGpt.Web", "samples\DatabaseGpt.Web\DatabaseGpt.Web.csproj", "{C2769772-57CA-41EB-86EB-54DA07F560AE}"
2525
EndProject
26+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DatabaseGpt.Sqlite", "src\DatabaseGpt.Sqlite\DatabaseGpt.Sqlite.csproj", "{6676EE8F-7B09-43CB-832E-AC6E432D7D29}"
27+
EndProject
2628
Global
2729
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2830
Debug|Any CPU = Debug|Any CPU
@@ -53,6 +55,10 @@ Global
5355
{C2769772-57CA-41EB-86EB-54DA07F560AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
5456
{C2769772-57CA-41EB-86EB-54DA07F560AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
5557
{C2769772-57CA-41EB-86EB-54DA07F560AE}.Release|Any CPU.Build.0 = Release|Any CPU
58+
{6676EE8F-7B09-43CB-832E-AC6E432D7D29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
59+
{6676EE8F-7B09-43CB-832E-AC6E432D7D29}.Debug|Any CPU.Build.0 = Debug|Any CPU
60+
{6676EE8F-7B09-43CB-832E-AC6E432D7D29}.Release|Any CPU.ActiveCfg = Release|Any CPU
61+
{6676EE8F-7B09-43CB-832E-AC6E432D7D29}.Release|Any CPU.Build.0 = Release|Any CPU
5662
EndGlobalSection
5763
GlobalSection(SolutionProperties) = preSolution
5864
HideSolutionNode = FALSE

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Thanks to [Adam Buckley](https://github.com/happyadam73/tsql-chatgpt) for the [o
1212

1313
### Usage
1414

15-
Currently, SQL Server and PostgreSQL databases are supported.
15+
Currently, SQL Server, PostgreSQL and SQLite databases are supported.
1616

1717
#### Using DatabaseGpt in your project
1818

@@ -22,6 +22,7 @@ Database|Project to include
2222
-|-
2323
SQL Server|src/DatabaseGpt.SqlServer/DatabaseGpt.SqlServer.csproj
2424
PostgreSQL|src/DatabaseGpt.Npgsql/DatabaseGpt.Npgsql.csproj
25+
SQLite|src/DatabaseGpt.Sqlite/DatabaseGpt.Sqlite.csproj
2526

2627
After referencing the proper projects, you can easily initialize **DatabaseGpt** at the startup of your application.
2728

@@ -37,6 +38,10 @@ builder.Services.AddDatabaseGpt(database =>
3738
// For PostgreSQL.
3839
//database.UseConfiguration(context.Configuration)
3940
// .UseNpgsql(context.Configuration.GetConnectionString("NpgsqlConnection"));
41+
42+
// For SQLite.
43+
//database.UseConfiguration(context.Configuration)
44+
// .UseSqlite(context.Configuration.GetConnectionString("SqliteConnection"));
4045
},
4146
chatGpt =>
4247
{
@@ -50,6 +55,7 @@ You need to set the required values in the **appsettings.json** file:
5055
"ConnectionStrings": {
5156
"SqlConnection": "" // The SQL Server connection string
5257
//"NpgsqlConnection": "" // The PostgreSQL connection string
58+
//"SqliteConnection": "" // The SQLite connection string
5359
},
5460
"ChatGPT": {
5561
"Provider": "OpenAI", // Optional. Allowed values: OpenAI (default) or Azure

samples/DatabaseGpt.Web/Program.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
// For PostgreSQL.
3434
//database.UseConfiguration(context.Configuration)
3535
// .UseNpgsql(context.Configuration.GetConnectionString("NpgsqlConnection"));
36+
37+
// For SQLite.
38+
//database.UseConfiguration(context.Configuration)
39+
// .UseSqlite(context.Configuration.GetConnectionString("SqliteConnection"));
3640
},
3741
chatGpt =>
3842
{

samples/DatabaseGptConsole/DatabaseGptConsole.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
<ItemGroup>
1818
<ProjectReference Include="..\..\src\DatabaseGpt.Npgsql\DatabaseGpt.Npgsql.csproj" />
19+
<ProjectReference Include="..\..\src\DatabaseGpt.SQLite\DatabaseGpt.Sqlite.csproj" />
1920
<ProjectReference Include="..\..\src\DatabaseGpt.SqlServer\DatabaseGpt.SqlServer.csproj" />
2021
<ProjectReference Include="..\..\src\DatabaseGpt\DatabaseGpt.csproj" />
2122
</ItemGroup>

samples/DatabaseGptConsole/Program.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ static void ConfigureServices(HostBuilderContext context, IServiceCollection ser
3838
// For PostgreSQL.
3939
//database.UseConfiguration(context.Configuration)
4040
// .UseNpgsql(context.Configuration.GetConnectionString("NpgsqlConnection"));
41+
42+
// For SQLite.
43+
//database.UseConfiguration(context.Configuration)
44+
// .UseSqlite(context.Configuration.GetConnectionString("SqliteConnection"));
4145
},
4246
chatGpt =>
4347
{

src/DatabaseGpt.Npgsql/NpgsqlDatabaseGptProvider.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,13 @@ public async Task<string> GetCreateTablesScriptAsync(IEnumerable<string> tables,
6161
CASE WHEN CHARACTER_MAXIMUM_LENGTH = -1 THEN 'MAX' ELSE CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR(10)) END || ')','') || ' ' ||
6262
CASE WHEN IS_NULLABLE = 'YES' THEN 'NULL' ELSE 'NOT NULL' END
6363
FROM INFORMATION_SCHEMA.COLUMNS
64-
WHERE TABLE_SCHEMA = @schema AND TABLE_NAME = @table AND COLUMN_NAME NOT IN (SELECT UNNEST(@excludedColumns));
64+
WHERE TABLE_SCHEMA = @schema
65+
AND TABLE_NAME = @table
66+
AND COLUMN_NAME NOT IN (SELECT UNNEST(@excludedColumns))
67+
AND TABLE_SCHEMA || '.' || TABLE_NAME || '.' || COLUMN_NAME NOT IN (SELECT UNNEST(@excludedColumns));
6568
""";
6669

67-
var columns = await connection.QueryAsync<string>(query, new { schema = table.Schema, table = table.Name, ExcludedColumns = excludedColumns });
70+
var columns = await connection.QueryAsync<string>(query, new { schema = table.Schema, table = table.Name, excludedColumns });
6871
result.AppendLine($"CREATE TABLE [{table.Schema}].[{table.Name}] ({string.Join(", ", columns)});");
6972
}
7073

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="Dapper" Version="2.1.28" />
11+
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.1" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<ProjectReference Include="..\DatabaseGpt.Abstractions\DatabaseGpt.Abstractions.csproj" />
16+
</ItemGroup>
17+
18+
</Project>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using DatabaseGpt.Abstractions;
2+
using DatabaseGpt.Sqlite;
3+
4+
namespace DatabaseGpt;
5+
6+
public static class SqliteDatabaseGptExtensions
7+
{
8+
public static void UseSqlite(this IDatabaseGptSettings databaseGptSettings, string? connectionString)
9+
{
10+
databaseGptSettings.SetDatabaseGptProviderFactory(() => new SqliteDatabaseGptProvider(new()
11+
{
12+
ConnectionString = connectionString
13+
}));
14+
}
15+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
using System.Data;
2+
using System.Data.Common;
3+
using System.Text;
4+
using Dapper;
5+
using DatabaseGpt.Abstractions;
6+
using DatabaseGpt.Abstractions.Exceptions;
7+
using Microsoft.Data.Sqlite;
8+
9+
namespace DatabaseGpt.Sqlite;
10+
11+
public class SqliteDatabaseGptProvider(SqliteDatabaseGptProviderConfiguration settings) : IDatabaseGptProvider
12+
{
13+
private readonly SqliteConnection connection = new(settings.ConnectionString);
14+
15+
private bool disposedValue;
16+
17+
public string Name => "SQLite";
18+
19+
public string Language => "SQLite";
20+
21+
public async Task<IEnumerable<string>> GetTablesAsync(IEnumerable<string> includedTables, IEnumerable<string> excludedTables, CancellationToken cancellationToken = default)
22+
{
23+
ThrowIfDisposed();
24+
25+
var tables = await connection.QueryAsync<string>("""
26+
SELECT TBL_NAME AS Tables
27+
FROM sqlite_schema
28+
WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'
29+
""");
30+
31+
if (includedTables?.Any() ?? false)
32+
{
33+
tables = tables.Where(t => includedTables.Contains(t, StringComparer.InvariantCultureIgnoreCase));
34+
}
35+
else if (excludedTables?.Any() ?? false)
36+
{
37+
tables = tables.Where(t => !excludedTables.Contains(t, StringComparer.InvariantCultureIgnoreCase));
38+
}
39+
40+
return tables;
41+
}
42+
43+
public async Task<string> GetCreateTablesScriptAsync(IEnumerable<string> tables, IEnumerable<string> excludedColumns, CancellationToken cancellationToken = default)
44+
{
45+
ThrowIfDisposed();
46+
47+
var result = new StringBuilder();
48+
49+
foreach (var table in tables)
50+
{
51+
var query = $"""
52+
SELECT '[' || NAME || '] ' ||
53+
UPPER(TYPE) || ' ' ||
54+
CASE WHEN [NOTNULL] = 0 THEN 'NULL' ELSE 'NOT NULL' END
55+
FROM PRAGMA_TABLE_INFO(@table)
56+
WHERE NAME NOT IN (@excludedColumns)
57+
AND @table || '.' || NAME NOT IN (@excludedColumns);
58+
""";
59+
60+
var columns = await connection.QueryAsync<string>(query, new { table, excludedColumns });
61+
result.AppendLine($"CREATE TABLE [{table}] ({string.Join(", ", columns)});");
62+
}
63+
64+
return result.ToString();
65+
}
66+
67+
public Task<string?> GetQueryHintsAsync(CancellationToken cancellationToken = default)
68+
{
69+
ThrowIfDisposed();
70+
71+
return Task.FromResult<string?>(null);
72+
}
73+
74+
public Task<string> NormalizeQueryAsync(string query, CancellationToken cancellationToken = default)
75+
{
76+
ThrowIfDisposed();
77+
78+
return Task.FromResult(query);
79+
}
80+
81+
public async Task<DbDataReader> ExecuteQueryAsync(string query, CancellationToken cancellationToken = default)
82+
{
83+
ThrowIfDisposed();
84+
85+
try
86+
{
87+
return await connection.ExecuteReaderAsync(query);
88+
}
89+
catch (SqliteException ex)
90+
{
91+
throw new DatabaseGptException("An error occurred while executing the query. See the inner exception for details.", ex);
92+
}
93+
}
94+
95+
protected virtual void Dispose(bool disposing)
96+
{
97+
if (!disposedValue)
98+
{
99+
if (disposing)
100+
{
101+
connection.Dispose();
102+
}
103+
104+
disposedValue = true;
105+
}
106+
}
107+
108+
public void Dispose()
109+
{
110+
Dispose(disposing: true);
111+
GC.SuppressFinalize(this);
112+
}
113+
114+
private void ThrowIfDisposed()
115+
=> ObjectDisposedException.ThrowIf(disposedValue, this);
116+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace DatabaseGpt.Sqlite;
2+
3+
public class SqliteDatabaseGptProviderConfiguration
4+
{
5+
public string? ConnectionString { get; set; }
6+
}

0 commit comments

Comments
 (0)