Proper rework attributes, creation functional
This commit is contained in:
parent
f67999d67c
commit
c8f174d3e8
@ -2,6 +2,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Antlr4.Runtime;
|
||||
using ChaosBot.Database;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using NLog;
|
||||
@ -20,50 +22,82 @@ namespace ChaosBot.Attribute
|
||||
{
|
||||
if (type.GetCustomAttributes(typeof(DBEntity), true).Length > 0)
|
||||
{
|
||||
// type == all classes that have [DBEntity(...)]
|
||||
|
||||
// Get a reference to the attribute
|
||||
DBEntity dbEntity = type.GetCustomAttributes(typeof(DBEntity)).Cast<DBEntity>().First();
|
||||
|
||||
// Generate columns
|
||||
// name, type, constraintName, constraints,
|
||||
List<Tuple<string, string, string, string>> columnList = new List<Tuple<string, string, string, string>>();
|
||||
|
||||
// Get the table as an easy variable
|
||||
string table = dbEntity.Table;
|
||||
// TODO: Generate this in one go instead of many separate commands
|
||||
Controller.RawQuery($"CREATE TABLE IF NOT EXISTS {table} (id INTEGER NOT NULL CONSTRAINT {table}_pk PRIMARY KEY AUTOINCREMENT)");
|
||||
|
||||
foreach (MethodInfo field in type.GetMethods())
|
||||
// Loop through all fields
|
||||
foreach (PropertyInfo prop in type.GetProperties())
|
||||
{
|
||||
if (field.Name.StartsWith("get_"))
|
||||
string columnName = prop.Name;
|
||||
string columnType = DBEntity.DataTypes.GetValueOrDefault(prop.PropertyType).ToString();
|
||||
StringBuilder constraintNameBuilder = new StringBuilder($"{table}_{columnName}");
|
||||
List<string> constraintsList = new List<string>();
|
||||
|
||||
// Go through every attribute
|
||||
foreach (object fieldAttribute in prop.GetCustomAttributes(true))
|
||||
{
|
||||
try
|
||||
if (fieldAttribute is DBFieldAttribute dBFieldAttribute)
|
||||
{
|
||||
// TODO: Use an attribute to detect primary autoincrement key
|
||||
if (field.Name == "id")
|
||||
string constraintSuffix =
|
||||
DBEntity.ConstrainNames.GetValueOrDefault(dBFieldAttribute.GetType(), null);
|
||||
if (constraintSuffix != null)
|
||||
{
|
||||
Controller.RawQuery($"CREATE UNIQUE INDEX {table}_id_uindex ON {table} (id)", false, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
string fieldname = field.Name.Substring(4);
|
||||
string fieldType = DBEntity.DataTypes.GetValueOrDefault(field.ReturnType).ToString();
|
||||
string fieldModifiers = null;
|
||||
|
||||
string query = $"ALTER TABLE {table} ADD COLUMN {fieldname} {fieldType} {fieldModifiers}";
|
||||
Controller.RawQuery(query, false, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is SqliteException sqliteException)
|
||||
{
|
||||
if (!sqliteException.Message.Contains("duplicate column name"))
|
||||
{
|
||||
_logger.Fatal($"AssemblyController.Register: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error($"AssemblyController.Register: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||
constraintNameBuilder.Append($"_{constraintSuffix}");
|
||||
constraintsList.Add($"{dBFieldAttribute.GetSQLiteQuery()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string constraintName = constraintNameBuilder.ToString();
|
||||
if (constraintsList.Count > 0)
|
||||
{
|
||||
constraintsList.Insert(0, "CONSTRAINT");
|
||||
constraintsList.Insert(1, constraintName);
|
||||
}
|
||||
string constraints = String.Join(" ", constraintsList);
|
||||
columnList.Add(new Tuple<string, string, string, string>(columnName, columnType, constraintName, constraints));
|
||||
}
|
||||
|
||||
// Check table exists
|
||||
bool tableExists =
|
||||
Controller.RawQuery($"SELECT name FROM sqlite_master WHERE type='table' AND name='{table}'")
|
||||
.Rows.Count > 0;
|
||||
|
||||
try
|
||||
{
|
||||
if (!tableExists)
|
||||
{
|
||||
string columnDefs = String.Join(", ", columnList.Select(c => $"{c.Item1} {c.Item2} {c.Item4}"));
|
||||
string query = $"CREATE TABLE {table} ({columnDefs})";
|
||||
Controller.RawQuery(query);
|
||||
}
|
||||
// // TODO: Generate this in one go instead of many separate commands
|
||||
// Controller.RawQuery($"CREATE TABLE IF NOT EXISTS {table} (id INTEGER NOT NULL CONSTRAINT {table}_pk PRIMARY KEY AUTOINCREMENT)");
|
||||
// Controller.RawQuery($"CREATE UNIQUE INDEX {table}_id_uindex ON {table} (id)", false, true);
|
||||
// string query = $"ALTER TABLE {table} ADD COLUMN {fieldname} {fieldType} {fieldModifiers}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is SqliteException sqliteException)
|
||||
{
|
||||
if (!sqliteException.Message.Contains("duplicate column name"))
|
||||
{
|
||||
_logger.Fatal(
|
||||
$"AssemblyController.Register: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error(
|
||||
$"AssemblyController.Register: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
13
ChaosBot/Attribute/DBAutoIncrement.cs
Normal file
13
ChaosBot/Attribute/DBAutoIncrement.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace ChaosBot.Attribute
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class DBAutoIncrement : DBFieldAttribute
|
||||
{
|
||||
public override string GetSQLiteQuery()
|
||||
{
|
||||
return "AUTOINCREMENT";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Discord;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace ChaosBot.Attribute
|
||||
@ -9,6 +10,7 @@ namespace ChaosBot.Attribute
|
||||
{
|
||||
public readonly string Table;
|
||||
|
||||
// Yeah... this table does not exist elsewhere except human-readable documentation
|
||||
public static readonly Dictionary<Type, SqliteType> DataTypes = new Dictionary<Type, SqliteType>
|
||||
{
|
||||
{typeof(bool), SqliteType.Integer},
|
||||
@ -32,6 +34,14 @@ namespace ChaosBot.Attribute
|
||||
{typeof(UInt64), SqliteType.Integer}
|
||||
};
|
||||
|
||||
public static readonly Dictionary<Type, string> ConstrainNames = new Dictionary<Type, string>
|
||||
{
|
||||
{typeof(DBNotNull), "nn"},
|
||||
{typeof(DBUnique), "uq"},
|
||||
{typeof(DBPrimaryKey), "pk"},
|
||||
{typeof(DBAutoIncrement), "ai"},
|
||||
};
|
||||
|
||||
public DBEntity(string table)
|
||||
{
|
||||
this.Table = table;
|
||||
|
||||
7
ChaosBot/Attribute/DBFieldAttribute.cs
Normal file
7
ChaosBot/Attribute/DBFieldAttribute.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace ChaosBot.Attribute
|
||||
{
|
||||
public abstract class DBFieldAttribute : System.Attribute
|
||||
{
|
||||
public abstract string GetSQLiteQuery();
|
||||
}
|
||||
}
|
||||
13
ChaosBot/Attribute/DBNotNull.cs
Normal file
13
ChaosBot/Attribute/DBNotNull.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace ChaosBot.Attribute
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class DBNotNull : DBFieldAttribute
|
||||
{
|
||||
public override string GetSQLiteQuery()
|
||||
{
|
||||
return "NOT NULL";
|
||||
}
|
||||
}
|
||||
}
|
||||
13
ChaosBot/Attribute/DBPrimaryKey.cs
Normal file
13
ChaosBot/Attribute/DBPrimaryKey.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace ChaosBot.Attribute
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class DBPrimaryKey : DBFieldAttribute
|
||||
{
|
||||
public override string GetSQLiteQuery()
|
||||
{
|
||||
return "PRIMARY KEY";
|
||||
}
|
||||
}
|
||||
}
|
||||
13
ChaosBot/Attribute/DBUnique.cs
Normal file
13
ChaosBot/Attribute/DBUnique.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace ChaosBot.Attribute
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class DBUnique : DBFieldAttribute
|
||||
{
|
||||
public override string GetSQLiteQuery()
|
||||
{
|
||||
return "UNIQUE";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,10 @@ namespace ChaosBot.Database.Entity
|
||||
[DBEntity("RaffleTable")]
|
||||
public class Raffle
|
||||
{
|
||||
[DBPrimaryKey]
|
||||
[DBAutoIncrement]
|
||||
[DBNotNull]
|
||||
[DBUnique]
|
||||
public int id { get; }
|
||||
public string userId { get; private set; }
|
||||
public string guildId { get; private set; }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user