Proper rework attributes, creation functional

This commit is contained in:
Daniel_I_Am 2020-06-04 15:19:09 +02:00
parent f67999d67c
commit c8f174d3e8
No known key found for this signature in database
GPG Key ID: 80C428FCC9743E84
8 changed files with 143 additions and 36 deletions

View File

@ -2,6 +2,8 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using Antlr4.Runtime;
using ChaosBot.Database; using ChaosBot.Database;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
using NLog; using NLog;
@ -20,34 +22,66 @@ namespace ChaosBot.Attribute
{ {
if (type.GetCustomAttributes(typeof(DBEntity), true).Length > 0) if (type.GetCustomAttributes(typeof(DBEntity), true).Length > 0)
{ {
// type == all classes that have [DBEntity(...)]
// Get a reference to the attribute // Get a reference to the attribute
DBEntity dbEntity = type.GetCustomAttributes(typeof(DBEntity)).Cast<DBEntity>().First(); DBEntity dbEntity = type.GetCustomAttributes(typeof(DBEntity)).Cast<DBEntity>().First();
string table = dbEntity.Table; // Generate columns
// TODO: Generate this in one go instead of many separate commands // name, type, constraintName, constraints,
Controller.RawQuery($"CREATE TABLE IF NOT EXISTS {table} (id INTEGER NOT NULL CONSTRAINT {table}_pk PRIMARY KEY AUTOINCREMENT)"); List<Tuple<string, string, string, string>> columnList = new List<Tuple<string, string, string, string>>();
foreach (MethodInfo field in type.GetMethods()) // Get the table as an easy variable
string table = dbEntity.Table;
// 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 string constraintSuffix =
if (field.Name == "id") DBEntity.ConstrainNames.GetValueOrDefault(dBFieldAttribute.GetType(), null);
if (constraintSuffix != null)
{ {
Controller.RawQuery($"CREATE UNIQUE INDEX {table}_id_uindex ON {table} (id)", false, true); constraintNameBuilder.Append($"_{constraintSuffix}");
continue; constraintsList.Add($"{dBFieldAttribute.GetSQLiteQuery()}");
}
}
} }
string fieldname = field.Name.Substring(4); string constraintName = constraintNameBuilder.ToString();
string fieldType = DBEntity.DataTypes.GetValueOrDefault(field.ReturnType).ToString(); if (constraintsList.Count > 0)
string fieldModifiers = null; {
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));
}
string query = $"ALTER TABLE {table} ADD COLUMN {fieldname} {fieldType} {fieldModifiers}"; // Check table exists
Controller.RawQuery(query, false, true); 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) catch (Exception ex)
{ {
@ -55,14 +89,14 @@ namespace ChaosBot.Attribute
{ {
if (!sqliteException.Message.Contains("duplicate column name")) if (!sqliteException.Message.Contains("duplicate column name"))
{ {
_logger.Fatal($"AssemblyController.Register: Exception [{ex}] thrown, <[{ex.Message}]>."); _logger.Fatal(
$"AssemblyController.Register: Exception [{ex}] thrown, <[{ex.Message}]>.");
} }
} }
else else
{ {
_logger.Error($"AssemblyController.Register: Exception [{ex}] thrown, <[{ex.Message}]>."); _logger.Error(
} $"AssemblyController.Register: Exception [{ex}] thrown, <[{ex.Message}]>.");
}
} }
} }
} }

View File

@ -0,0 +1,13 @@
using System;
namespace ChaosBot.Attribute
{
[AttributeUsage(AttributeTargets.Property)]
public class DBAutoIncrement : DBFieldAttribute
{
public override string GetSQLiteQuery()
{
return "AUTOINCREMENT";
}
}
}

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Discord;
using Microsoft.Data.Sqlite; using Microsoft.Data.Sqlite;
namespace ChaosBot.Attribute namespace ChaosBot.Attribute
@ -9,6 +10,7 @@ namespace ChaosBot.Attribute
{ {
public readonly string Table; 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> public static readonly Dictionary<Type, SqliteType> DataTypes = new Dictionary<Type, SqliteType>
{ {
{typeof(bool), SqliteType.Integer}, {typeof(bool), SqliteType.Integer},
@ -32,6 +34,14 @@ namespace ChaosBot.Attribute
{typeof(UInt64), SqliteType.Integer} {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) public DBEntity(string table)
{ {
this.Table = table; this.Table = table;

View File

@ -0,0 +1,7 @@
namespace ChaosBot.Attribute
{
public abstract class DBFieldAttribute : System.Attribute
{
public abstract string GetSQLiteQuery();
}
}

View File

@ -0,0 +1,13 @@
using System;
namespace ChaosBot.Attribute
{
[AttributeUsage(AttributeTargets.Property)]
public class DBNotNull : DBFieldAttribute
{
public override string GetSQLiteQuery()
{
return "NOT NULL";
}
}
}

View File

@ -0,0 +1,13 @@
using System;
namespace ChaosBot.Attribute
{
[AttributeUsage(AttributeTargets.Property)]
public class DBPrimaryKey : DBFieldAttribute
{
public override string GetSQLiteQuery()
{
return "PRIMARY KEY";
}
}
}

View File

@ -0,0 +1,13 @@
using System;
namespace ChaosBot.Attribute
{
[AttributeUsage(AttributeTargets.Property)]
public class DBUnique : DBFieldAttribute
{
public override string GetSQLiteQuery()
{
return "UNIQUE";
}
}
}

View File

@ -5,6 +5,10 @@ namespace ChaosBot.Database.Entity
[DBEntity("RaffleTable")] [DBEntity("RaffleTable")]
public class Raffle public class Raffle
{ {
[DBPrimaryKey]
[DBAutoIncrement]
[DBNotNull]
[DBUnique]
public int id { get; } public int id { get; }
public string userId { get; private set; } public string userId { get; private set; }
public string guildId { get; private set; } public string guildId { get; private set; }