2024-09-10 22:12:17 +00:00
|
|
|
using BotSharp.Plugin.SqlDriver.Models;
|
2024-09-17 11:32:11 +00:00
|
|
|
using Microsoft.Data.SqlClient;
|
2024-09-04 16:04:19 +00:00
|
|
|
using Microsoft.Extensions.Logging;
|
2024-08-22 15:15:05 +00:00
|
|
|
using MySqlConnector;
|
|
|
|
|
|
|
|
|
|
namespace BotSharp.Plugin.SqlDriver.Functions;
|
|
|
|
|
|
|
|
|
|
public class GetTableDefinitionFn : IFunctionCallback
|
|
|
|
|
{
|
2024-09-30 20:14:37 +00:00
|
|
|
public string Name => "sql_table_definition";
|
2024-09-18 02:27:47 +00:00
|
|
|
public string Indication => "Obtain the relevant data structure definitions.";
|
2024-08-22 15:15:05 +00:00
|
|
|
private readonly IServiceProvider _services;
|
2024-09-04 16:04:19 +00:00
|
|
|
private readonly ILogger<GetTableDefinitionFn> _logger;
|
2024-08-22 15:15:05 +00:00
|
|
|
|
2024-09-04 16:04:19 +00:00
|
|
|
public GetTableDefinitionFn(
|
|
|
|
|
IServiceProvider services,
|
|
|
|
|
ILogger<GetTableDefinitionFn> logger)
|
2024-08-22 15:15:05 +00:00
|
|
|
{
|
|
|
|
|
_services = services;
|
2024-09-04 16:04:19 +00:00
|
|
|
_logger = logger;
|
2024-08-22 15:15:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<bool> Execute(RoleDialogModel message)
|
|
|
|
|
{
|
2024-09-10 22:12:17 +00:00
|
|
|
var args = JsonSerializer.Deserialize<SqlStatement>(message.FunctionArgs);
|
2024-10-04 21:44:01 +00:00
|
|
|
var tables = args.Tables;
|
2024-08-22 15:15:05 +00:00
|
|
|
var agentService = _services.GetRequiredService<IAgentService>();
|
|
|
|
|
var settings = _services.GetRequiredService<SqlDriverSetting>();
|
2024-08-30 21:12:20 +00:00
|
|
|
|
|
|
|
|
// Get table DDL from database
|
2024-09-17 11:32:11 +00:00
|
|
|
var tableDdls = settings.DatabaseType switch
|
|
|
|
|
{
|
|
|
|
|
"MySql" => GetDdlFromMySql(tables),
|
|
|
|
|
"SqlServer" => GetDdlFromSqlServer(tables),
|
|
|
|
|
_ => throw new NotImplementedException($"Database type {settings.DatabaseType} is not supported.")
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
message.Content = string.Join("\r\n\r\n", tableDdls);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2024-09-04 16:04:19 +00:00
|
|
|
|
2024-09-17 11:32:11 +00:00
|
|
|
private List<string> GetDdlFromMySql(string[] tables)
|
|
|
|
|
{
|
|
|
|
|
var settings = _services.GetRequiredService<SqlDriverSetting>();
|
2024-08-30 21:12:20 +00:00
|
|
|
var tableDdls = new List<string>();
|
2024-10-14 22:25:55 +00:00
|
|
|
using var connection = new MySqlConnection(settings.MySqlMetaConnectionString ?? settings.MySqlConnectionString);
|
2024-09-03 20:41:12 +00:00
|
|
|
connection.Open();
|
2024-08-22 15:15:05 +00:00
|
|
|
|
2024-09-04 16:04:19 +00:00
|
|
|
foreach (var table in tables)
|
2024-08-22 15:15:05 +00:00
|
|
|
{
|
2024-09-04 16:04:19 +00:00
|
|
|
try
|
2024-09-03 20:41:12 +00:00
|
|
|
{
|
2024-09-04 16:04:19 +00:00
|
|
|
var escapedTableName = MySqlHelper.EscapeString(table);
|
2024-09-05 15:34:35 +00:00
|
|
|
var sql = $"SHOW CREATE TABLE `{escapedTableName}`";
|
2024-09-04 16:04:19 +00:00
|
|
|
|
|
|
|
|
using var command = new MySqlCommand(sql, connection);
|
|
|
|
|
using var reader = command.ExecuteReader();
|
|
|
|
|
if (reader.Read())
|
|
|
|
|
{
|
2024-09-05 15:34:35 +00:00
|
|
|
var result = reader.GetString(1);
|
2024-09-04 16:04:19 +00:00
|
|
|
tableDdls.Add(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reader.Close();
|
|
|
|
|
command.Dispose();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
2024-09-03 20:41:12 +00:00
|
|
|
{
|
2024-09-05 01:11:25 +00:00
|
|
|
_logger.LogWarning($"Error when getting ddl statement of table {table}. {ex.Message}\r\n{ex.InnerException}");
|
2024-09-03 20:41:12 +00:00
|
|
|
}
|
2024-08-22 15:15:05 +00:00
|
|
|
}
|
|
|
|
|
|
2024-09-03 20:41:12 +00:00
|
|
|
connection.Close();
|
2024-09-17 11:32:11 +00:00
|
|
|
return tableDdls;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private List<string> GetDdlFromSqlServer(string[] tables)
|
|
|
|
|
{
|
|
|
|
|
var settings = _services.GetRequiredService<SqlDriverSetting>();
|
|
|
|
|
var tableDdls = new List<string>();
|
|
|
|
|
using var connection = new SqlConnection(settings.SqlServerExecutionConnectionString ?? settings.SqlServerConnectionString);
|
|
|
|
|
connection.Open();
|
|
|
|
|
|
|
|
|
|
foreach (var table in tables)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var sql = @$"DECLARE @TableName NVARCHAR(128) = '{table}';
|
2024-09-30 23:25:32 +00:00
|
|
|
DECLARE @SQL NVARCHAR(MAX) = 'CREATE TABLE ' + @TableName + ' (';
|
|
|
|
|
|
|
|
|
|
SELECT @SQL = @SQL + '
|
|
|
|
|
' + COLUMN_NAME + ' ' +
|
|
|
|
|
DATA_TYPE +
|
|
|
|
|
CASE
|
|
|
|
|
WHEN CHARACTER_MAXIMUM_LENGTH IS NOT NULL AND DATA_TYPE LIKE '%char%'
|
|
|
|
|
THEN '(' + CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR(10)) + ')'
|
|
|
|
|
WHEN DATA_TYPE IN ('decimal', 'numeric')
|
|
|
|
|
THEN '(' + CAST(NUMERIC_PRECISION AS VARCHAR(10)) + ',' + CAST(NUMERIC_SCALE AS VARCHAR(10)) + ')'
|
|
|
|
|
ELSE ''
|
|
|
|
|
END + ' ' +
|
|
|
|
|
CASE WHEN IS_NULLABLE = 'NO' THEN 'NOT NULL' ELSE 'NULL' END + ','
|
|
|
|
|
FROM INFORMATION_SCHEMA.COLUMNS
|
|
|
|
|
WHERE TABLE_NAME = @TableName
|
|
|
|
|
ORDER BY ORDINAL_POSITION;
|
|
|
|
|
|
|
|
|
|
-- Remove the last comma and add closing parenthesis
|
|
|
|
|
SET @SQL = LEFT(@SQL, LEN(@SQL) - 1) + ');';
|
|
|
|
|
|
|
|
|
|
SELECT @SQL;";
|
2024-09-17 11:32:11 +00:00
|
|
|
|
|
|
|
|
using var command = new SqlCommand(sql, connection);
|
|
|
|
|
using var reader = command.ExecuteReader();
|
|
|
|
|
if (reader.Read())
|
|
|
|
|
{
|
|
|
|
|
var result = reader.GetString(0);
|
|
|
|
|
tableDdls.Add(result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogWarning($"Error when getting ddl statement of table {table}. {ex.Message}\r\n{ex.InnerException}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
connection.Close();
|
|
|
|
|
return tableDdls;
|
2024-08-22 15:15:05 +00:00
|
|
|
}
|
|
|
|
|
}
|