More work on native database backend.

This commit is contained in:
UnknownShadow200 2016-04-28 16:42:06 +10:00
parent b6f843c10c
commit 24229ae173
16 changed files with 181 additions and 159 deletions

View File

@ -25,8 +25,13 @@ namespace MCGalaxy.SQL {
protected IDbTransaction transaction;
public static BulkTransaction Create() {
if (Server.useMySQL) return MySQLBulkTransaction.Create(MySQL.connString);
else return SQLiteBulkTransaction.Create(SQLite.connString);
try {
if (Server.useMySQL) return new MySQLBulkTransaction(MySQL.connString);
else return new SQLiteBulkTransaction(SQLite.connString);
} catch (Exception ex) {
Server.ErrorLog(ex);
return null;
}
}
public abstract IDbCommand CreateCommand(string query);

View File

@ -32,7 +32,6 @@ namespace MCGalaxy.SQL {
else SQLite.AddParams(name, param);
}
[Obsolete("Use a ParameterisedQuery instance instead, which is threadsafe.")]
public static void executeQuery(string queryString, bool createDB = false) {
if (Server.useMySQL) executeQuery(MySQL.query, queryString, createDB);
else executeQuery(SQLite.query, queryString, createDB);
@ -55,7 +54,6 @@ namespace MCGalaxy.SQL {
query.ClearParams();
}
[Obsolete("Use a ParameterisedQuery instance instead, which is threadsafe.")]
public static DataTable fillData(string queryString, bool skipError = false) {
if (Server.useMySQL) return fillData(MySQL.query, queryString, skipError);
else return fillData(SQLite.query, queryString, skipError);
@ -82,4 +80,26 @@ namespace MCGalaxy.SQL {
}
}
}
public static class MySQL { //: Database //Extending for future improvement (Making it object oriented later)
static string connStringFormat = "Data Source={0};Port={1};User ID={2};Password={3};Pooling={4}";
public static string connString { get { return String.Format(connStringFormat, Server.MySQLHost, Server.MySQLPort, Server.MySQLUsername, Server.MySQLPassword, Server.DatabasePooling); } }
internal static ParameterisedQuery query = new MySQLParameterisedQuery();
public static void AddParams(string name, object param) { query.AddParam(name, param); }
public static void ClearParams() { query.ClearParams(); }
}
public static class SQLite {
static string connStringFormat = "Data Source =" + Server.apppath + "/MCGalaxy.db; Version =3; Pooling ={0}; Max Pool Size =1000;";
public static string connString { get { return String.Format(connStringFormat, Server.DatabasePooling); } }
internal static ParameterisedQuery query = new SQLiteParameterisedQuery();
public static void AddParams(string name, object param) { query.AddParam(name, param); }
public static void ClearParams() { query.ClearParams(); }
}
}

View File

@ -1,35 +0,0 @@
/*
Copyright 2010 MCSharp team (Modified for use with MCZall/MCLawl/MCGalaxy)
Dual-licensed under the Educational Community License, Version 2.0 and
the GNU General Public License, Version 3 (the "Licenses"); you may
not use this file except in compliance with the Licenses. You may
obtain a copy of the Licenses at
http://www.osedu.org/licenses/ECL-2.0
http://www.gnu.org/licenses/gpl-3.0.html
Unless required by applicable law or agreed to in writing,
software distributed under the Licenses are distributed on an "AS IS"
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied. See the Licenses for the specific language governing
permissions and limitations under the Licenses.
*/
using System;
using System.Data;
using MySql.Data.MySqlClient;
namespace MCGalaxy.SQL {
public static class MySQL { //: Database //Extending for future improvement (Making it object oriented later)
static string connStringFormat = "Data Source={0};Port={1};User ID={2};Password={3};Pooling={4}";
public static string connString { get { return String.Format(connStringFormat, Server.MySQLHost, Server.MySQLPort, Server.MySQLUsername, Server.MySQLPassword, Server.DatabasePooling); } }
internal static MySQLParameterisedQuery query = new MySQLParameterisedQuery();
public static void AddParams(string name, object param) { query.AddParam(name, param); }
public static void ClearParams() { query.ClearParams(); }
}
}

View File

@ -24,10 +24,6 @@ namespace MCGalaxy.SQL {
public sealed class MySQLBulkTransaction : BulkTransaction {
public MySQLBulkTransaction(string connString) {
Init(connString);
}
void Init(string connString) {
connection = new MySqlConnection(connString);
connection.Open();
connection.ChangeDatabase(Server.MySQLDatabaseName);
@ -35,15 +31,6 @@ namespace MCGalaxy.SQL {
transaction = connection.BeginTransaction();
}
public static BulkTransaction Create(string connString) {
try {
return new MySQLBulkTransaction(connString);
} catch (Exception ex) {
Server.ErrorLog(ex);
return null;
}
}
public override IDbCommand CreateCommand(string query) {
return new MySqlCommand(query, (MySqlConnection)connection, (MySqlTransaction)transaction);
}

View File

@ -23,25 +23,12 @@ namespace MCGalaxy.SQL.Native {
public partial class NativeBulkTransaction : BulkTransaction {
private NativeBulkTransaction(string connString) {
Init(connString);
}
void Init(string connString) {
public NativeBulkTransaction(string connString) {
connection = new NativeConnection();
connection.ConnectionString = SQLite.connString;
connection.Open();
transaction = connection.BeginTransaction();
}
public static BulkTransaction Create(string connString) {
try {
return new NativeBulkTransaction(connString);
} catch (Exception ex) {
Server.ErrorLog(ex);
return null;
}
}
public override IDbCommand CreateCommand(string query) {
IDbCommand cmd = new NativeCommand();

View File

@ -24,7 +24,7 @@ namespace MCGalaxy.SQL.Native {
unsafe sealed class NativeCommand : IDbCommand {
public IntPtr Statement;
NativeParamsList args = new NativeParamsList();
internal NativeParamsList args = new NativeParamsList();
public IDbConnection Connection { get; set; }
public IDbTransaction Transaction { get; set; }
@ -40,10 +40,10 @@ namespace MCGalaxy.SQL.Native {
public object ExecuteScalar() { return null; }
public void Prepare() {
byte[] sql = NativeUtils.MakeUTF8(CommandText);
byte[] sql = Interop.MakeUTF8(CommandText);
IntPtr db = ((NativeConnection)Connection).DB;
IntPtr tail;
int code = NativeUtils.sqlite3_prepare_v2(db, sql, sql.Length, out Statement, out tail);
int code = Interop.sqlite3_prepare_v2(db, sql, sql.Length, out Statement, out tail);
if (code > 0) throw new NativeException(code);
}
@ -51,15 +51,15 @@ namespace MCGalaxy.SQL.Native {
foreach (IDataParameter param in args)
BindParam(param);
int code = NativeUtils.sqlite3_step(Statement);
int code = Interop.sqlite3_step(Statement);
if (code > 0 && code != 101) throw new NativeException(code);
code = NativeUtils.sqlite3_reset(Statement);
code = Interop.sqlite3_reset(Statement);
if (code > 0) throw new NativeException(code);
return 0;
}
public void Dispose() {
int code = NativeUtils.sqlite3_finalize(Statement);
int code = Interop.sqlite3_finalize(Statement);
if (code > 0) throw new NativeException(code);
}
@ -70,25 +70,23 @@ namespace MCGalaxy.SQL.Native {
int code = 0;
switch (nParam.type) {
case DbType.AnsiStringFixedLength:
code = NativeUtils.sqlite3_bind_text(Statement, nParam.Index, nParam.StringPtr,
nParam.StringCount - 1, IntPtr.Zero);
break;
code = Interop.sqlite3_bind_text(Statement, nParam.Index, nParam.StringPtr,
nParam.StringCount - 1, IntPtr.Zero); break;
case DbType.Int32:
code = Interop.sqlite3_bind_int(Statement, nParam.Index, nParam.I32Value); break;
case DbType.UInt16:
code = NativeUtils.sqlite3_bind_int(Statement, nParam.Index, nParam.U16Value);
break;
code = Interop.sqlite3_bind_int(Statement, nParam.Index, nParam.U16Value); break;
case DbType.Byte:
code = NativeUtils.sqlite3_bind_int(Statement, nParam.Index, nParam.U8Value);
break;
code = Interop.sqlite3_bind_int(Statement, nParam.Index, nParam.U8Value); break;
case DbType.Boolean:
code = NativeUtils.sqlite3_bind_int(Statement, nParam.Index, nParam.BoolValue ? 1 : 0);
break;
code = Interop.sqlite3_bind_int(Statement, nParam.Index, nParam.BoolValue ? 1 : 0); break;
}
if (code > 0) throw new NativeException(code);
}
void BindIndex(NativeParameter nParam) {
byte[] name = NativeUtils.MakeUTF8(nParam.ParameterName);
nParam.Index = NativeUtils.sqlite3_bind_parameter_index(Statement, name);
byte[] name = Interop.MakeUTF8(nParam.ParameterName);
nParam.Index = Interop.sqlite3_bind_parameter_index(Statement, name);
}
}
}

View File

@ -37,7 +37,7 @@ namespace MCGalaxy.SQL.Native {
}
public void Close() {
int code = sqlite3_close(DB);
int code = Interop.sqlite3_close(DB);
DB = IntPtr.Zero;
if (code > 0) throw new NativeException(code);
}
@ -56,8 +56,8 @@ namespace MCGalaxy.SQL.Native {
string path;
public void Open() {
ParseConnectionString();
byte[] filename = NativeUtils.MakeUTF8(path);
int code = sqlite3_open_v2(filename, out DB, 0x2, IntPtr.Zero);
byte[] filename = Interop.MakeUTF8(path);
int code = Interop.sqlite3_open_v2(filename, out DB, 0x2, IntPtr.Zero);
if (code > 0) throw new NativeException(code);
}
@ -71,12 +71,6 @@ namespace MCGalaxy.SQL.Native {
if (key == "Data Source") path = value;
}
}
[DllImport("sqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int sqlite3_open_v2(byte[] filename, out IntPtr db, int flags, IntPtr vfs);
[DllImport("sqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int sqlite3_close(IntPtr db);
}
}
}

View File

@ -0,0 +1,60 @@
/*
Copyright 2011 MCForge
Dual-licensed under the Educational Community License, Version 2.0 and
the GNU General Public License, Version 3 (the "Licenses"); you may
not use this file except in compliance with the Licenses. You may
obtain a copy of the Licenses at
http://www.opensource.org/licenses/ecl2.php
http://www.gnu.org/licenses/gpl-3.0.html
Unless required by applicable law or agreed to in writing,
software distributed under the Licenses are distributed on an "AS IS"
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied. See the Licenses for the specific language governing
permissions and limitations under the Licenses.
*/
using System;
using System.Data;
namespace MCGalaxy.SQL.Native {
public sealed class NativeParameterisedQuery : ParameterisedQuery {
public override void Execute(string query, bool createDB = false) {
using (var conn = new NativeConnection()) {
conn.ConnectionString = SQLite.connString;
conn.Open();
using (NativeCommand cmd = new NativeCommand()) {
cmd.CommandText = query;
cmd.Connection = conn;
foreach (var param in parameters)
cmd.args.AddWithValue(param.Key, param.Value);
cmd.Prepare();
cmd.ExecuteNonQuery();
}
conn.Close();
}
}
public unsafe override void Fill(string query, DataTable results) {
using (var conn = new NativeConnection()) {
conn.ConnectionString = SQLite.connString;
conn.Open();
using (NativeCommand cmd = new NativeCommand()) {
cmd.CommandText = query;
cmd.Connection = conn;
foreach (var param in parameters)
cmd.args.AddWithValue(param.Key, param.Value);
cmd.Prepare();
NativeReader reader = new NativeReader();
reader.ReadColumns(cmd, results);
reader.ReadRows(cmd, results);
}
conn.Close();
}
}
}
}

View File

@ -89,7 +89,7 @@ namespace MCGalaxy.SQL.Native {
public IEnumerator GetEnumerator() { return args.GetEnumerator(); }
public void AddParamWithVaue(string key, object value) {
public void AddWithValue(string key, object value) {
NativeParameter arg = new NativeParameter();
arg.ParameterName = key;
Type type = value.GetType();
@ -103,6 +103,9 @@ namespace MCGalaxy.SQL.Native {
} else if (type == typeof(ushort)) {
arg.U16Value = (ushort)value;
arg.DbType = DbType.UInt16;
} else if (type == typeof(int)) {
arg.I32Value = (ushort)value;
arg.DbType = DbType.Int32;
} else {
throw new NotSupportedException("Unsupported type: " + type);
}

View File

@ -0,0 +1,47 @@
/*
Copyright 2015 MCGalaxy
Dual-licensed under the Educational Community License, Version 2.0 and
the GNU General Public License, Version 3 (the "Licenses"); you may
not use this file except in compliance with the Licenses. You may
obtain a copy of the Licenses at
http://www.opensource.org/licenses/ecl2.php
http://www.gnu.org/licenses/gpl-3.0.html
Unless required by applicable law or agreed to in writing,
software distributed under the Licenses are distributed on an "AS IS"
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied. See the Licenses for the specific language governing
permissions and limitations under the Licenses.
*/
using System;
using System.Data;
using System.Runtime.InteropServices;
using System.Text;
namespace MCGalaxy.SQL.Native {
unsafe sealed class NativeReader {
public void ReadColumns(NativeCommand cmd, DataTable results) {
int cols = Interop.sqlite3_column_count(cmd.Statement);
for (int i = 0; i < cols; i++) {
IntPtr namePtr = Interop.sqlite3_column_name(cmd.Statement, i);
string name = new String((sbyte*)namePtr);
int code = Interop.sqlite3_column_type(cmd.Statement, i);
Type type = typeof(object);
if (code == 1) type = typeof(long);
else if (code == 2) type = typeof(double);
else if (code == 3) type = typeof(string);
else if (code == 4) type = typeof(byte[]);
results.Columns.Add(new DataColumn(name, type));
}
}
public void ReadRows(NativeCommand cmd, DataTable results) {
}
}
}

View File

@ -58,6 +58,7 @@ namespace MCGalaxy.SQL.Native {
public DbType type;
public int Index = -1;
// Avoid boxing primitive types
public int I32Value;
public ushort U16Value;
public byte U8Value;
public bool BoolValue;
@ -82,7 +83,7 @@ namespace MCGalaxy.SQL.Native {
}
}
unsafe static class NativeUtils {
unsafe static class Interop {
static Encoding encoding = Encoding.UTF8;
public static byte[] MakeUTF8(string input) {
@ -92,6 +93,13 @@ namespace MCGalaxy.SQL.Native {
return chars;
}
[DllImport("sqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int sqlite3_open_v2(byte[] filename, out IntPtr db, int flags, IntPtr vfs);
[DllImport("sqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int sqlite3_close(IntPtr db);
[DllImport("sqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int sqlite3_bind_int(IntPtr stmt, int index, int value);
@ -119,6 +127,10 @@ namespace MCGalaxy.SQL.Native {
[DllImport("sqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int sqlite3_column_type(IntPtr stmt, int iCol);
[DllImport("sqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr sqlite3_column_name(IntPtr stmt, int iCol);
[DllImport("sqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern double sqlite3_column_double(IntPtr stmt, int iCol);
@ -134,11 +146,5 @@ namespace MCGalaxy.SQL.Native {
[DllImport("sqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr sqlite3_column_text16(IntPtr stmt, int iCol);
[DllImport("sqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr sqlite3_column_name(IntPtr stmt, int iCol);
[DllImport("sqlite3.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr sqlite3_column_name16(IntPtr stmt, int iCol);
}
}

View File

@ -1,34 +0,0 @@
/*
Copyright 2011 MCForge
Dual-licensed under the Educational Community License, Version 2.0 and
the GNU General Public License, Version 3 (the "Licenses"); you may
not use this file except in compliance with the Licenses. You may
obtain a copy of the Licenses at
http://www.opensource.org/licenses/ecl2.php
http://www.gnu.org/licenses/gpl-3.0.html
Unless required by applicable law or agreed to in writing,
software distributed under the Licenses are distributed on an "AS IS"
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied. See the Licenses for the specific language governing
permissions and limitations under the Licenses.
*/
using System;
using System.Data;
using System.Data.SQLite;
namespace MCGalaxy.SQL {
public static class SQLite {
static string connStringFormat = "Data Source =" + Server.apppath + "/MCGalaxy.db; Version =3; Pooling ={0}; Max Pool Size =1000;";
public static string connString { get { return String.Format(connStringFormat, Server.DatabasePooling); } }
internal static SQLiteParameterisedQuery query = new SQLiteParameterisedQuery();
public static void AddParams(string name, object param) { query.AddParam(name, param); }
public static void ClearParams() { query.ClearParams(); }
}
}

View File

@ -24,25 +24,11 @@ namespace MCGalaxy.SQL {
public sealed class SQLiteBulkTransaction : BulkTransaction {
private SQLiteBulkTransaction(string connString) {
Init(connString);
}
void Init(string connString) {
connection = new SQLiteConnection(connString);
public SQLiteBulkTransaction(string connString) {
connection = new SQLiteConnection(connString);
connection.Open();
//connection.ChangeDatabase(Server.MySQLDatabaseName);
transaction = connection.BeginTransaction();
}
public static BulkTransaction Create(string connString) {
try {
return new SQLiteBulkTransaction(connString);
} catch (Exception ex) {
Server.ErrorLog(ex);
return null;
}
}
public override IDbCommand CreateCommand(string query) {
return new SQLiteCommand(query, (SQLiteConnection)connection, (SQLiteTransaction)transaction);

View File

@ -450,7 +450,9 @@ namespace MCGalaxy
using (BulkTransaction transaction = BulkTransaction.Create()) {
fixed (char* ptr = date) {
ptr[4] = '-'; ptr[7] = '-'; ptr[10] = ' '; ptr[13] = ':'; ptr[16] = ':';
DateTime now = DateTime.UtcNow;
DoSaveChanges(tempCache, ptr, date, transaction);
Server.s.Log( "db save " + (DateTime.UtcNow - now).TotalSeconds );
}
}
tempCache.Clear();

View File

@ -413,17 +413,17 @@
<Compile Include="Config\StringAttributes.cs" />
<Compile Include="Database\Backup.cs" />
<Compile Include="Database\BlockDB.cs" />
<Compile Include="Database\MySQL\MySQL.cs" />
<Compile Include="Database\MySQL\MySQLBulkTransaction.cs" />
<Compile Include="Database\MySQL\MySQLParameterisedQuery.cs" />
<Compile Include="Database\Native\NativeParameterisedQuery.cs" />
<Compile Include="Database\Native\NativeParamsList.cs" />
<Compile Include="Database\Native\NativeReader.cs" />
<Compile Include="Database\ParameterisedQuery.cs" />
<Compile Include="Database\Native\NativeConnection.cs" />
<Compile Include="Database\Native\Utils.cs" />
<Compile Include="Database\Native\NativeBulkTransaction.cs" />
<Compile Include="Database\Native\NativeCommand.cs" />
<Compile Include="Database\Native\NativeException.cs" />
<Compile Include="Database\SQLite\SQLite.cs" />
<Compile Include="Database\SQLite\SQLiteBulkTransaction.cs" />
<Compile Include="Database\SQLite\SQLiteParameterisedQuery.cs" />
<Compile Include="Drawing\Brushes\Brush.cs" />

View File

@ -29,13 +29,9 @@ namespace MCGalaxy {
public static List<Player> GetPlayers() { return new List<Player>(players); }
public static Group GetGroup(string name) {
return Group.findPlayerGroup(name);
}
public static Group GetGroup(string name) { return Group.findPlayerGroup(name); }
public static string GetColor(string name) {
return GetGroup(name).color;
}
public static string GetColor(string name) { return GetGroup(name).color; }
const StringComparison comp = StringComparison.OrdinalIgnoreCase;
public static Player Find(string name) {