Skip to content

Commit

Permalink
Make /server backup table work with double/blob columns
Browse files Browse the repository at this point in the history
  • Loading branch information
UnknownShadow200 committed Aug 13, 2022
1 parent 9922eae commit 01fc519
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 120 deletions.
10 changes: 8 additions & 2 deletions MCGalaxy/Database/Backends/Interfaces.cs
Expand Up @@ -65,11 +65,9 @@ public abstract class ISqlRecord
{
public abstract int FieldCount { get; }
public abstract string GetName(int i);
public abstract Type GetFieldType(int i);
public abstract int GetOrdinal(string name);

public abstract byte[] GetBytes(int i);
public abstract object GetValue(int i);
public abstract bool GetBoolean(int i);
public abstract int GetInt32(int i);
public abstract long GetInt64(int i);
Expand All @@ -78,8 +76,10 @@ public abstract class ISqlRecord
public abstract DateTime GetDateTime(int i);
public abstract bool IsDBNull(int i);

public abstract object GetValue(int i);
public abstract string RawGetDateTime(int col);
public abstract string GetStringValue(int col);
public abstract string DumpValue(int col);


public string GetText(int col) {
Expand All @@ -100,5 +100,11 @@ public abstract class ISqlRecord
int col = GetOrdinal(name);
return IsDBNull(col) ? 0 : GetInt64(col);
}

protected static string Quote(string value) {
if (value.IndexOf('\'') >= 0) // escape '
value = value.Replace("'", "''");
return "'" + value + "'";
}
}
}
25 changes: 18 additions & 7 deletions MCGalaxy/Database/Backends/MySQL.cs
Expand Up @@ -225,35 +225,46 @@ sealed class MySQLReader : ISqlReader

public override int FieldCount { get { return rdr.FieldCount; } }
public override string GetName(int i) { return rdr.GetName(i); }
public override Type GetFieldType(int i) { return rdr.GetFieldType(i); }
public override int GetOrdinal(string name) { return rdr.GetOrdinal(name); }

public override object GetValue(int i) { return rdr.GetValue(i); }

public override bool GetBoolean(int i) { return rdr.GetBoolean(i); }
public override byte[] GetBytes(int i) { return (byte[])rdr.GetValue(i); }
public override byte[] GetBytes(int i) { return (byte[])GetValue(i); }
public override int GetInt32(int i) { return rdr.GetInt32(i); }
public override long GetInt64(int i) { return rdr.GetInt64(i); }
public override double GetDouble(int i) { return rdr.GetDouble(i); }
public override string GetString(int i) { return rdr.GetString(i); }
public override DateTime GetDateTime(int i) { return rdr.GetDateTime(i); }
public override bool IsDBNull(int i) { return rdr.IsDBNull(i); }
public override object GetValue(int i) { return rdr.GetValue(i); }



public override string RawGetDateTime(int col) {
DateTime date = GetDateTime(col);
return date.ToString(Database.DateFormat);
}

public override string GetStringValue(int col) {
if (IsDBNull(col)) return "";
Type type = GetFieldType(col);
Type type = rdr.GetFieldType(col);

if (type == typeof(string)) return GetString(col);
if (type == typeof(DateTime)) return RawGetDateTime(col);

return GetValue(col).ToString();
}

public override string DumpValue(int col) {
if (IsDBNull(col)) return "NULL";
Type colType = rdr.GetFieldType(col);

// TODO doubles not exact? probably doesn't matter
if (colType == typeof(string)) {
return Quote(GetString(col));
} else if (colType == typeof(DateTime)) {
return Quote(RawGetDateTime(col));
}
return GetString(col);
}
}
}
#endif
107 changes: 14 additions & 93 deletions MCGalaxy/Database/Backends/SQLiteBackend.cs
Expand Up @@ -85,8 +85,6 @@ static class Interop
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
internal static extern TypeAffinity sqlite3_column_type(IntPtr stmt, int index);
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr sqlite3_column_decltype(IntPtr stmt, int index);
[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr sqlite3_column_name(IntPtr stmt, int index);

[DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
Expand Down Expand Up @@ -420,15 +418,6 @@ static class SQLiteConvert
}


internal static Type[] affinity_to_type = {
typeof(object), // Uninitialized (0)
typeof(Int64), // Int64 (1)
typeof(Double), // Double (2)
typeof(string), // Text (3)
typeof(byte[]), // Blob (4)
typeof(object), // Null (5)
};

internal static SqlType TypeToDbType(Type typ) {
TypeCode tc = Type.GetTypeCode(typ);
if (tc == TypeCode.Object) {
Expand Down Expand Up @@ -459,66 +448,6 @@ static class SQLiteConvert
SqlType.Object, // ?? (17)
SqlType.String // String (18)
};

internal static Type[] sqltype_to_type = {
typeof(float), typeof(double), typeof(decimal),
typeof(sbyte), typeof(Int16), typeof(Int32), typeof(Int64),
typeof(byte), typeof(UInt16), typeof(UInt32), typeof(UInt64),
typeof(bool), typeof(DateTime),
typeof(byte[]), typeof(string), typeof(object)
};

static bool TryParseDbType(string typeName, out SqlType type) {
string[] names = all_names;
for (int i = 0; i < names.Length; i++)
{
if (!typeName.Equals(names[i], StringComparison.OrdinalIgnoreCase)) continue;
type = all_types[i]; return true;
}
type = 0; return false;
}

internal static SqlType TypeNameToDbType(string typeName) {
if (typeName == null) return SqlType.Object;

SqlType value;
if (TryParseDbType(typeName, out value)) return value;

int i = typeName.IndexOf('(');
if (i > 0 && TryParseDbType(typeName.Substring(0, i).TrimEnd(), out value)) return value;

return SqlType.Object;
}

static string[] all_names = new string[] {
"BIGINT", "BIGUINT", "BINARY", "BLOB",
"BOOL", "BOOLEAN", "CHAR", "DATE",
"DATETIME", "DOUBLE", "FLOAT", "IDENTITY",
"INT", "INT8", "INT16", "INT32",
"INT64", "INTEGER", "INTEGER8", "INTEGER16",
"INTEGER32", "INTEGER64", "LONG", "MEDIUMINT",
"REAL", "SINGLE", "SMALLINT", "SMALLUINT",
"STRING", "TEXT", "TIME", "TINYINT",
"TINYSINT", "UINT", "UINT8", "UINT16",
"UINT32", "UINT64", "ULONG", "UNSIGNEDINTEGER",
"UNSIGNEDINTEGER8", "UNSIGNEDINTEGER16", "UNSIGNEDINTEGER32", "UNSIGNEDINTEGER64",
"VARCHAR",
};

static SqlType[] all_types = new SqlType[] {
SqlType.Int64, SqlType.UInt64, SqlType.Binary, SqlType.Binary,
SqlType.Boolean, SqlType.Boolean, SqlType.String, SqlType.DateTime,
SqlType.DateTime, SqlType.Double, SqlType.Double, SqlType.Int64,
SqlType.Int32, SqlType.SByte, SqlType.Int16, SqlType.Int32,
SqlType.Int64, SqlType.Int64, SqlType.SByte, SqlType.Int16,
SqlType.Int32, SqlType.Int64, SqlType.Int64, SqlType.Int32,
SqlType.Double, SqlType.Single, SqlType.Int16, SqlType.UInt16,
SqlType.String, SqlType.String, SqlType.DateTime, SqlType.Byte,
SqlType.SByte, SqlType.UInt32, SqlType.Byte, SqlType.UInt16,
SqlType.UInt32, SqlType.UInt64, SqlType.UInt64, SqlType.UInt64,
SqlType.Byte, SqlType.UInt16, SqlType.UInt32, SqlType.UInt64,
SqlType.String,
};
}

enum TypeAffinity
Expand All @@ -529,7 +458,6 @@ enum TypeAffinity
Text = 3,
Blob = 4,
Null = 5,
DateTime = 10,
}

public sealed class SQLiteDataReader : ISqlReader
Expand Down Expand Up @@ -602,38 +530,36 @@ public sealed class SQLiteDataReader : ISqlReader

public override string GetString(int i) { return stmt.GetText(i); }

public override object GetValue(int i) {
TypeAffinity affinity = GetAffinity(i);
return stmt.GetValue(i, affinity);
}

public override bool IsDBNull(int i) {
return GetAffinity(i) == TypeAffinity.Null;
}


public override object GetValue(int i) {
TypeAffinity affinity = GetAffinity(i);
return stmt.GetValue(i, affinity);
}

public override string RawGetDateTime(int col) {
return GetString(col); // GetDateTime is extremely slow so avoid it
}

public override string GetStringValue(int col) {
return GetString(col);
}

}

public override Type GetFieldType(int i) {
TypeAffinity affinity = stmt.ColumnAffinity(i);
public override string DumpValue(int col) {
TypeAffinity affinity = GetAffinity(col);
if (affinity == TypeAffinity.Null) return "NULL";

// Fetch the declared column datatype and attempt to convert it to a known DbType.
string typeName = stmt.ColumnType(i);
SqlType type = SQLiteConvert.TypeNameToDbType(typeName);
string value = GetString(col);
if (affinity == TypeAffinity.Text) return Quote(value);

if (type == SqlType.Object)
return SQLiteConvert.affinity_to_type[(int)affinity];
else
return SQLiteConvert.sqltype_to_type[(int)type];
// TODO doubles not exact? probably doesn't matter
return value;
}


public override string GetName(int i) { return stmt.ColumnName(i); }

public override int GetOrdinal(string name) {
Expand Down Expand Up @@ -832,11 +758,6 @@ sealed class SQLiteStatement : IDisposable
return Interop.sqlite3_column_type(handle, index);
}

internal string ColumnType(int index) {
IntPtr p = Interop.sqlite3_column_decltype(handle, index);
return SQLiteConvert.FromUTF8(p, -1);
}

internal void BindAll(List<string> names, List<object> values) {
if (paramNames == null || names.Count == 0) return;

Expand Down
20 changes: 2 additions & 18 deletions MCGalaxy/Database/TableDumper.cs
Expand Up @@ -26,7 +26,6 @@ public sealed class TableDumper
string table, insertCols;
internal StreamWriter sql;
string[] colNames;
Type[] colTypes;

public void DumpTable(StreamWriter sql, string table) {
gottenRows = false;
Expand All @@ -47,11 +46,9 @@ public sealed class TableDumper
sql.WriteLine();

colNames = new string[record.FieldCount];
colTypes = new Type[record.FieldCount];
for (int i = 0; i < record.FieldCount; i++)
{
colNames[i] = record.GetName(i);
colTypes[i] = record.GetFieldType(i);
}
insertCols = FormatInsertColumns(table);
gottenRows = true;
Expand All @@ -64,21 +61,8 @@ public sealed class TableDumper
//The values themselves can be integers or strings, or null
for (int col = 0; col < colNames.Length; col++)
{
if (record.IsDBNull(col)) {
sql.Write("NULL");
} else if (colTypes[col] == typeof(string)) {
string value = record.GetString(col);
if (value.IndexOf('\'') >= 0) // escape '
value = value.Replace("'", "''");
sql.Write("'" + value + "'");
} else if (colTypes[col] == typeof(DateTime)) {
string date = record.RawGetDateTime(col);
sql.Write("'" + date + "'");
} else {
long value = record.GetInt64(col); // TODO: try to use GetInt32 where possible
sql.Write(value);
}
sql.Write((col < colTypes.Length - 1 ? ", " : ");"));
sql.Write(record.DumpValue(col));
sql.Write((col < colNames.Length - 1 ? ", " : ");"));
}

sql.WriteLine();
Expand Down

0 comments on commit 01fc519

Please sign in to comment.