Merge pull request #406 from stevenh/6c636d4084e1a15d053652f1125c167a4b60b2d3

Refactored IQueryBuilder extracting common code into the GenericQueryCreator
This commit is contained in:
Steven Hartland 2012-02-27 03:18:12 -08:00
commit b63cca0415

View file

@ -33,11 +33,12 @@ namespace TShockAPI.DB
string InsertValues(string table, List<SqlValue> values);
string ReadColumn(string table, List<SqlValue> wheres);
string DeleteRow(string table, List<SqlValue> wheres);
string RenameTable(string from, string to);
}
public class SqliteQueryCreator : IQueryBuilder
public class SqliteQueryCreator : GenericQueryCreator, IQueryBuilder
{
public string CreateTable(SqlTable table)
public override string CreateTable(SqlTable table)
{
var columns =
table.Columns.Select(
@ -45,129 +46,12 @@ namespace TShockAPI.DB
"'{0}' {1} {2} {3} {4} {5}".SFormat(c.Name, DbTypeToString(c.Type, c.Length), c.Primary ? "PRIMARY KEY" : "",
c.AutoIncrement ? "AUTOINCREMENT" : "", c.NotNull ? "NOT NULL" : "",
c.Unique ? "UNIQUE" : ""));
return "CREATE TABLE '{0}' ({1})".SFormat(table.Name, string.Join(", ", columns));
return "CREATE TABLE {0} ({1})".SFormat(EscapeTableName(table.Name), string.Join(", ", columns));
}
private static Random rand = new Random();
/// <summary>
/// Alter a table from source to destination
/// </summary>
/// <param name="from">Must have name and column names. Column types are not required</param>
/// <param name="to">Must have column names and column types.</param>
/// <returns></returns>
public string AlterTable(SqlTable from, SqlTable to)
public override string RenameTable(string from, string to)
{
var rstr = rand.NextString(20);
var alter = "ALTER TABLE '{0}' RENAME TO '{1}_{0}'".SFormat(from.Name, rstr);
var create = CreateTable(to);
//combine all columns in the 'from' variable excluding ones that aren't in the 'to' variable.
//exclude the ones that aren't in 'to' variable because if the column is deleted, why try to import the data?
var insert = "INSERT INTO '{0}' ({1}) SELECT {1} FROM {2}_{0}".SFormat(from.Name,
string.Join(", ",
from.Columns.Where(
c =>
to.Columns.Any(
c2 => c2.Name == c.Name)).Select
(c => c.Name)), rstr);
var drop = "DROP TABLE '{0}_{1}'".SFormat(rstr, from.Name);
return "{0}; {1}; {2}; {3};".SFormat(alter, create, insert, drop);
/*
ALTER TABLE "main"."Bans" RENAME TO "oXHFcGcd04oXHFcGcd04_Bans"
CREATE TABLE "main"."Bans" ("IP" TEXT PRIMARY KEY ,"Name" TEXT)
INSERT INTO "main"."Bans" SELECT "IP","Name" FROM "main"."oXHFcGcd04oXHFcGcd04_Bans"
DROP TABLE "main"."oXHFcGcd04oXHFcGcd04_Bans"
*
* Twitchy - Oh. I get it!
*/
}
public string DeleteRow(string table, List<SqlValue> wheres)
{
var sbwheres = new StringBuilder();
int count = 0;
foreach (SqlValue where in wheres)
{
sbwheres.Append(where.Name + "=" + where.Value);
if (count != wheres.Count - 1)
sbwheres.Append(" AND ");
count++;
}
if (wheres.Count > 0)
return "DELETE FROM '{0}' WHERE {1} ".SFormat(table, sbwheres.ToString());
else
return "DELETE FROM '{0}'".SFormat(table, sbwheres.ToString());
}
public string UpdateValue(string table, List<SqlValue> values, List<SqlValue> wheres)
{
var sbvalues = new StringBuilder();
var sbwheres = new StringBuilder();
int count = 0;
foreach (SqlValue value in values)
{
sbvalues.Append(value.Name + "=" + value.Value);
if (count != values.Count - 1)
sbvalues.Append(",");
count++;
}
count = 0;
foreach (SqlValue where in wheres)
{
sbwheres.Append(where.Name + "=" + where.Value);
if (count != wheres.Count - 1)
sbwheres.Append(" AND ");
count++;
}
if (wheres.Count > 0)
return "UPDATE '{0}' SET {1} WHERE {2}".SFormat(table, sbvalues.ToString(), sbwheres.ToString());
else
return "UPDATE '{0}' SET {1}".SFormat(table, sbvalues.ToString());
}
public string InsertValues(string table, List<SqlValue> values)
{
var sbnames = new StringBuilder();
var sbvalues = new StringBuilder();
int count = 0;
foreach (SqlValue name in values)
{
sbnames.Append(name.Name);
if (count != values.Count - 1)
sbnames.Append(", ");
count++;
}
count = 0;
foreach (SqlValue value in values)
{
sbvalues.Append(value.Value.ToString());
if (count != values.Count - 1)
sbvalues.Append(", ");
count++;
}
return "INSERT INTO '{0}' ({1}) VALUES ({2})".SFormat(table, sbnames.ToString(), sbvalues.ToString());
}
public string ReadColumn(string table, List<SqlValue> wheres)
{
var sbwheres = new StringBuilder();
int count = 0;
foreach (SqlValue where in wheres)
{
sbwheres.Append(where.Name + "=" + where.Value);
if (count != wheres.Count - 1)
sbwheres.Append(" AND ");
count++;
}
if (wheres.Count > 0)
return "SELECT * FROM {0} WHERE {1}".SFormat(table, sbwheres.ToString());
else
return "SELECT * FROM {0}".SFormat(table);
return "ALTER TABLE {0} RENAME TO {1}".SFormat(from, to);
}
private static readonly Dictionary<MySqlDbType, string> TypesAsStrings = new Dictionary<MySqlDbType, string>
@ -189,11 +73,16 @@ namespace TShockAPI.DB
return ret;
throw new NotImplementedException(Enum.GetName(typeof (MySqlDbType), type));
}
protected override string EscapeTableName(string table)
{
return table.SFormat("'{0}'", table);
}
}
public class MysqlQueryCreator : IQueryBuilder
public class MysqlQueryCreator : GenericQueryCreator, IQueryBuilder
{
public string CreateTable(SqlTable table)
public override string CreateTable(SqlTable table)
{
var columns =
table.Columns.Select(
@ -201,125 +90,15 @@ namespace TShockAPI.DB
"{0} {1} {2} {3} {4}".SFormat(c.Name, DbTypeToString(c.Type, c.Length), c.Primary ? "PRIMARY KEY" : "",
c.AutoIncrement ? "AUTO_INCREMENT" : "", c.NotNull ? "NOT NULL" : ""));
var uniques = table.Columns.Where(c => c.Unique).Select(c => c.Name);
return "CREATE TABLE {0} ({1} {2})".SFormat(table.Name, string.Join(", ", columns),
return "CREATE TABLE {0} ({1} {2})".SFormat(EscapeTableName(table.Name), string.Join(", ", columns),
uniques.Count() > 0
? ", UNIQUE({0})".SFormat(string.Join(", ", uniques))
: "");
}
private static Random rand = new Random();
/// <summary>
/// Alter a table from source to destination
/// </summary>
/// <param name="from">Must have name and column names. Column types are not required</param>
/// <param name="to">Must have column names and column types.</param>
/// <returns></returns>
public string AlterTable(SqlTable from, SqlTable to)
public override string RenameTable(string from, string to)
{
var rstr = rand.NextString(20);
var alter = "RENAME TABLE {0} TO {1}_{0}".SFormat(from.Name, rstr);
var create = CreateTable(to);
//combine all columns in the 'from' variable excluding ones that aren't in the 'to' variable.
//exclude the ones that aren't in 'to' variable because if the column is deleted, why try to import the data?
var insert = "INSERT INTO {0} ({1}) SELECT {1} FROM {2}_{0}".SFormat(from.Name,
string.Join(", ",
from.Columns.Where(
c =>
to.Columns.Any(
c2 => c2.Name == c.Name)).Select(
c => c.Name)), rstr);
var drop = "DROP TABLE {0}_{1}".SFormat(rstr, from.Name);
return "{0}; {1}; {2}; {3};".SFormat(alter, create, insert, drop);
}
public string DeleteRow(string table, List<SqlValue> wheres)
{
var sbwheres = new StringBuilder();
int count = 0;
foreach (SqlValue where in wheres)
{
sbwheres.Append(where.Name + "=" + where.Value);
if (count != wheres.Count - 1)
sbwheres.Append(" AND ");
count++;
}
if (wheres.Count > 0)
return "DELETE FROM {0} WHERE {1} ".SFormat(table, sbwheres.ToString());
else
return "DELETE FROM {0}".SFormat(table, sbwheres.ToString());
}
public string UpdateValue(string table, List<SqlValue> values, List<SqlValue> wheres)
{
var sbvalues = new StringBuilder();
var sbwheres = new StringBuilder();
int count = 0;
foreach (SqlValue value in values)
{
sbvalues.Append(value.Name + "=" + value.Value);
if (count != values.Count - 1)
sbvalues.Append("AND");
count++;
}
count = 0;
foreach (SqlValue where in wheres)
{
sbwheres.Append(where.Name + "=" + where.Value);
if (count != wheres.Count - 1)
sbwheres.Append(" AND ");
count++;
}
if (wheres.Count > 0)
return "UPDATE {0} SET {1} WHERE {2}".SFormat(table, sbvalues.ToString(), sbwheres.ToString());
else
return "UPDATE {0} SET {1}".SFormat(table, sbvalues.ToString());
}
public string InsertValues(string table, List<SqlValue> values)
{
var sbnames = new StringBuilder();
var sbvalues = new StringBuilder();
int count = 0;
foreach (SqlValue name in values)
{
sbnames.Append(name.Name);
if (count != values.Count - 1)
sbnames.Append(", ");
count++;
}
count = 0;
foreach (SqlValue value in values)
{
sbvalues.Append(value.Value.ToString());
if (count != values.Count - 1)
sbvalues.Append(", ");
count++;
}
return "INSERT INTO {0} ({1}) VALUES ({2})".SFormat(table, sbnames.ToString(), sbvalues.ToString());
}
public string ReadColumn(string table, List<SqlValue> wheres)
{
var sbwheres = new StringBuilder();
int count = 0;
foreach (SqlValue where in wheres)
{
sbwheres.Append(where.Name + "=" + where.Value);
if (count != wheres.Count - 1)
sbwheres.Append(" AND ");
count++;
}
if (wheres.Count > 0)
return "SELECT * FROM {0} WHERE {1}".SFormat(table, sbwheres.ToString());
else
return "SELECT * FROM {0}".SFormat(table);
return "RENAME TABLE {0} TO {1}".SFormat(from, to);
}
private static readonly Dictionary<MySqlDbType, string> TypesAsStrings = new Dictionary<MySqlDbType, string>
@ -340,5 +119,95 @@ namespace TShockAPI.DB
return ret + (length != null ? "({0})".SFormat((int) length) : "");
throw new NotImplementedException(Enum.GetName(typeof (MySqlDbType), type));
}
protected override string EscapeTableName(string table)
{
return table.SFormat("`{0}`", table);
}
}
}
public abstract class GenericQueryCreator
{
protected static Random rand = new Random();
protected abstract string EscapeTableName(string table);
public abstract string CreateTable(SqlTable table);
public abstract string RenameTable(string from, string to);
/// <summary>
/// Alter a table from source to destination
/// </summary>
/// <param name="from">Must have name and column names. Column types are not required</param>
/// <param name="to">Must have column names and column types.</param>
/// <returns></returns>
public string AlterTable(SqlTable from, SqlTable to)
{
/*
* Any example outpuf from this looks like:-
ALTER TABLE "main"."Bans" RENAME TO "oXHFcGcd04oXHFcGcd04_Bans"
CREATE TABLE "main"."Bans" ("IP" TEXT PRIMARY KEY ,"Name" TEXT)
INSERT INTO "main"."Bans" SELECT "IP","Name" FROM "main"."oXHFcGcd04oXHFcGcd04_Bans"
DROP TABLE "main"."oXHFcGcd04oXHFcGcd04_Bans"
*
* Twitchy - Oh. I get it!
*/
var rstr = rand.NextString(20);
var escapedTable = EscapeTableName(from.Name);
var tmpTable = EscapeTableName("{0}_{1}".SFormat(rstr, from.Name));
var alter = RenameTable(escapedTable, tmpTable);
var create = CreateTable(to);
// combine all columns in the 'from' variable excluding ones that aren't in the 'to' variable.
// exclude the ones that aren't in 'to' variable because if the column is deleted, why try to import the data?
var columns = string.Join(", ", from.Columns.Where(c => to.Columns.Any(c2 => c2.Name == c.Name)).Select(c => c.Name));
var insert = "INSERT INTO {0} ({1}) SELECT {1} FROM {2}".SFormat(escapedTable, columns, tmpTable);
var drop = "DROP TABLE {0}".SFormat(tmpTable);
return "{0}; {1}; {2}; {3};".SFormat(alter, create, insert, drop);
}
public string DeleteRow(string table, List<SqlValue> wheres)
{
return "DELETE FROM {0}{1}".SFormat(EscapeTableName(table), BuildWhere(wheres));
}
public string UpdateValue(string table, List<SqlValue> values, List<SqlValue> wheres)
{
if (0 == values.Count)
throw new ArgumentException("No values supplied");
return "UPDATE {0} SET {1}{2}".SFormat(EscapeTableName(table), string.Join(", ", values.Select(v => v.Name + " = " + v.Value)), BuildWhere(wheres));
}
public string ReadColumn(string table, List<SqlValue> wheres)
{
return "SELECT * FROM {0}{1}".SFormat(EscapeTableName(table), BuildWhere(wheres));
}
public string InsertValues(string table, List<SqlValue> values)
{
var sbnames = new StringBuilder();
var sbvalues = new StringBuilder();
int count = 0;
foreach (SqlValue value in values)
{
sbnames.Append(value.Name);
sbvalues.Append(value.Value.ToString());
if (count != values.Count - 1)
{
sbnames.Append(", ");
sbvalues.Append(", ");
}
count++;
}
return "INSERT INTO {0} ({1}) VALUES ({2})".SFormat(EscapeTableName(table), sbnames, sbvalues);
}
protected static string BuildWhere(List<SqlValue> wheres)
{
if (0 == wheres.Count)
return string.Empty;
return "WHERE {2}".SFormat(string.Join(", ", wheres.Select(v => v.Name + " = " + v.Value)));
}
}
}